Token JWT
Esta tarea muestra cómo configurar una política de autorización de Istio para aplicar el acceso basado en un JSON Web Token (JWT). Una política de autorización de Istio admite claims JWT de tipo cadena, de tipo lista de cadenas y de tipo cadena delimitada por espacios.
Antes de empezar
Antes de comenzar esta tarea, haga lo siguiente:
Complete la tarea de autenticación de usuario final de Istio.
Lea los conceptos de autorización de Istio.
Instale Istio utilizando la guía de instalación de Istio.
Despliegue dos workloads:
httpbinycurl. Despliegue estos en un namespace, por ejemplofoo. Ambos workloads se ejecutan con un proxy Envoy delante de cada uno. Despliegue el namespace y los workloads de ejemplo utilizando estos comandos:$ kubectl create ns foo $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n foo $ kubectl apply -f <(istioctl kube-inject -f @samples/curl/curl.yaml@) -n fooVerifique que
curlse comunica correctamente conhttpbinutilizando este comando:$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl http://httpbin.foo:8000/ip -sS -o /dev/null -w "%{\n}" 200
Permitir solicitudes con JWT válido y claims de tipo lista
El siguiente comando crea la política de autenticación de solicitudes
jwt-examplepara el workloadhttpbinen el namespacefoo. Esta política para el workloadhttpbinacepta un JWT emitido portesting@secure.istio.io:$ kubectl apply -f - <<EOF apiVersion: security.istio.io/v1 kind: RequestAuthentication metadata: name: "jwt-example" namespace: foo spec: selector: matchLabels: app: httpbin jwtRules: - issuer: "testing@secure.istio.io" jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.32/security/tools/jwt/samples/jwks.json" EOFVerifique que una solicitud con un JWT inválido es denegada:
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer invalidToken" -w "%{\n}" 401Verifique que una solicitud sin un JWT es permitida porque no hay política de autorización:
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -w "%{\n}" 200El siguiente comando crea la política de autorización
require-jwtpara el workloadhttpbinen el namespacefoo. La política requiere que todas las solicitudes al workloadhttpbintengan un JWT válido conrequestPrincipalestablecido entesting@secure.istio.io/testing@secure.istio.io. Istio construye elrequestPrincipalcombinando elissysubdel token JWT con un separador/como se muestra:$ kubectl apply -f - <<EOF apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: require-jwt namespace: foo spec: selector: matchLabels: app: httpbin action: ALLOW rules: - from: - source: requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"] EOFObtenga el JWT que establece las claves
issysuben el mismo valor,testing@secure.istio.io. Esto hace que Istio genere el atributorequestPrincipalcon el valortesting@secure.istio.io/testing@secure.istio.io:$ TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.32/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode {"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"testing@secure.istio.io","sub":"testing@secure.istio.io"}Verifique que una solicitud con un JWT válido es permitida:
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer $TOKEN" -w "%{\n}" 200Verifique que una solicitud sin un JWT es denegada:
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -w "%{\n}" 403El siguiente comando actualiza la política de autorización
require-jwtpara también requerir que el JWT tenga un claim llamadogroupsque contenga el valorgroup1:$ kubectl apply -f - <<EOF apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: require-jwt namespace: foo spec: selector: matchLabels: app: httpbin action: ALLOW rules: - from: - source: requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"] when: - key: request.auth.claims[groups] values: ["group1"] EOFObtenga el JWT que establece el claim
groupsen una lista de cadenas:group1ygroup2:$ TOKEN_GROUP=$(curl https://raw.githubusercontent.com/istio/istio/release-1.32/security/tools/jwt/samples/groups-scope.jwt -s) && echo "$TOKEN_GROUP" | cut -d '.' -f2 - | base64 --decode {"exp":3537391104,"groups":["group1","group2"],"iat":1537391104,"iss":"testing@secure.istio.io","scope":["scope1","scope2"],"sub":"testing@secure.istio.io"}Verifique que una solicitud con el JWT que incluye
group1en el claimgroupses permitida:$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer $TOKEN_GROUP" -w "%{\n}" 200Verifique que una solicitud con un JWT, que no tiene el claim
groupses rechazada:$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer $TOKEN" -w "%{\n}" 403
Permitir solicitudes con JWT válido y claims delimitados por espacios
Algunos claims de JWT codifican múltiples valores como una única cadena delimitada por espacios
en lugar de un array JSON. El claim scope de OAuth2 es un ejemplo conocido de este patrón,
definido en RFC 6749 como una
lista separada por espacios.
Istio siempre trata los claims scope y permission como delimitados por espacios,
dividiéndolos en valores individuales que las políticas de autorización pueden comparar. Para
otros claims personalizados que usen la misma codificación, use el campo spaceDelimitedClaims
en su JWTRule para incluirlos explícitamente. Sin este campo, un valor de claim personalizado
como "admin editor" se compara como una única cadena exacta.
{"iss": "testing@secure.istio.io", "roles": "admin editor"}Descargue el script de generación de JWT y la clave de firma:
$ wget --no-verbose https://raw.githubusercontent.com/istio/istio/release-1.32/security/tools/jwt/samples/gen-jwt.py $ wget --no-verbose https://raw.githubusercontent.com/istio/istio/release-1.32/security/tools/jwt/samples/key.pemEl siguiente comando actualiza la política de autenticación de solicitudes
jwt-examplepara declarar que el claimroleses delimitado por espacios:$ kubectl apply -f - <<EOF apiVersion: security.istio.io/v1 kind: RequestAuthentication metadata: name: "jwt-example" namespace: foo spec: selector: matchLabels: app: httpbin jwtRules: - issuer: "testing@secure.istio.io" jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.32/security/tools/jwt/samples/jwks.json" spaceDelimitedClaims: ["roles"] EOFEl siguiente comando actualiza la política de autorización
require-jwtpara requerir que el claimrolesincluya el valoradmin:$ kubectl apply -f - <<EOF apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: require-jwt namespace: foo spec: selector: matchLabels: app: httpbin action: ALLOW rules: - from: - source: requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"] when: - key: request.auth.claims[roles] values: ["admin"] EOFObtenga un JWT cuyo claim
rolesesté establecido en la cadena delimitada por espacios"admin editor":$ TOKEN_ROLES=$(python3 ./gen-jwt.py ./key.pem --claims '{"roles":"admin editor"}')Verifique que una solicitud con ese JWT es permitida, porque
adminestá presente en el claimrolesdelimitado por espacios:$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer $TOKEN_ROLES" -w "%{\n}" 200Obtenga un JWT cuyo claim
rolesno incluyaadmin:$ TOKEN_NO_ADMIN=$(python3 ./gen-jwt.py ./key.pem --claims '{"roles":"editor"}')Verifique que la solicitud es denegada:
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer $TOKEN_NO_ADMIN" -w "%{\n}" 403
Limpieza
Elimine el namespace foo:
$ kubectl delete namespace fooSi descargaste gen-jwt.py y key.pem para la sección de claims delimitados por espacios,
elimínelos:
$ rm -f ./gen-jwt.py ./key.pem