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 tanto claims JWT de tipo cadena como de tipo lista de cadenas.

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: httpbin y curl. Despliegue estos en un namespace, por ejemplo foo. Ambos workloads se ejecutan con un proxy Envoy delante de cada uno. Despliegue el namespace y los workloads de ejemplo utilizando estos comandos:

    ZipZip
    $ 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 foo
  • Verifique que curl se comunica correctamente con httpbin utilizando 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

  1. El siguiente comando crea la política de autenticación de solicitudes jwt-example para el workload httpbin en el namespace foo. Esta política para el workload httpbin acepta un JWT emitido por testing@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.27/security/tools/jwt/samples/jwks.json"
    EOF
  2. Verifique 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}"
    401
  3. Verifique 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}"
    200
  4. El siguiente comando crea la política de autorización require-jwt para el workload httpbin en el namespace foo. La política requiere que todas las solicitudes al workload httpbin tengan un JWT válido con requestPrincipal establecido en testing@secure.istio.io/testing@secure.istio.io. Istio construye el requestPrincipal combinando el iss y sub del 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"]
    EOF
  5. Obtenga el JWT que establece las claves iss y sub en el mismo valor, testing@secure.istio.io. Esto hace que Istio genere el atributo requestPrincipal con el valor testing@secure.istio.io/testing@secure.istio.io:

    $ TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.27/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"}
  6. 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}"
    200
  7. Verifique 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}"
    403
  8. El siguiente comando actualiza la política de autorización require-jwt para también requerir que el JWT tenga un claim llamado groups que contenga el valor group1:

    $ 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"]
    EOF
  9. Obtenga el JWT que establece el claim groups en una lista de cadenas: group1 y group2:

    $ TOKEN_GROUP=$(curl https://raw.githubusercontent.com/istio/istio/release-1.27/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"}
  10. Verifique que una solicitud con el JWT que incluye group1 en el claim groups 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_GROUP" -w "%{\n}"
    200
  11. Verifique que una solicitud con un JWT, que no tiene el claim groups es 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

Limpieza

Elimine el namespace foo:

$ kubectl delete namespace foo
¿Fue útil esta información?
¿Tienes alguna sugerencia para mejorar?

¡Gracias por tus comentarios!