• Authentication Policy
    • Before you begin
      • Setup
    • Globally enabling Istio mutual TLS
      • Request from non-Istio services to Istio services
      • Request from Istio services to non-Istio services
      • Request from Istio services to Kubernetes API server
      • Cleanup part 1
    • Enable mutual TLS per namespace or service
      • Namespace-wide policy
      • Service-specific policy
      • Policy precedence
      • Cleanup part 2
    • End-user authentication
      • End-user authentication with per-path requirements
        • Disable End-user authentication for specific paths
        • Enable End-user authentication for specific paths
      • End-user authentication with mutual TLS
      • Cleanup part 3
    • 相关内容

    Authentication Policy

    This task covers the primary activities you might need to perform when enabling, configuring, and using Istio authentication policies. Find out more aboutthe underlying concepts in the authentication overview.

    Before you begin

    • Understand Istio authentication policy and relatedmutual TLS authentication concepts.

    • Install Istio on a Kubernetes cluster with global mutual TLS disabled (e.g, use the demo configuration profile, as described ininstallation steps, or set the global.mtls.enabled installation option to false).

    Setup

    Our examples use two namespaces foo and bar, with two services, httpbin and sleep, both running with an Envoy sidecar proxy. We also use secondinstances of httpbin and sleep running without the sidecar in the legacy namespace. If you’d like to use the same examples when trying the tasks,run the following:

    ZipZipZipZipZipZip

    1. $ kubectl create ns foo
    2. $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n foo
    3. $ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@) -n foo
    4. $ kubectl create ns bar
    5. $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n bar
    6. $ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@) -n bar
    7. $ kubectl create ns legacy
    8. $ kubectl apply -f @samples/httpbin/httpbin.yaml@ -n legacy
    9. $ kubectl apply -f @samples/sleep/sleep.yaml@ -n legacy

    You can verify setup by sending an HTTP request with curl from any sleep pod in the namespace foo, bar or legacy to either httpbin.foo,httpbin.bar or httpbin.legacy. All requests should succeed with HTTP code 200.

    For example, here is a command to check sleep.bar to httpbin.foo reachability:

    1. $ kubectl exec $(kubectl get pod -l app=sleep -n bar -o jsonpath={.items..metadata.name}) -c sleep -n bar -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n"
    2. 200

    This one-liner command conveniently iterates through all reachability combinations:

    1. $ for from in "foo" "bar" "legacy"; do for to in "foo" "bar" "legacy"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
    2. sleep.foo to httpbin.foo: 200
    3. sleep.foo to httpbin.bar: 200
    4. sleep.foo to httpbin.legacy: 200
    5. sleep.bar to httpbin.foo: 200
    6. sleep.bar to httpbin.bar: 200
    7. sleep.bar to httpbin.legacy: 200
    8. sleep.legacy to httpbin.foo: 200
    9. sleep.legacy to httpbin.bar: 200
    10. sleep.legacy to httpbin.legacy: 200

    You should also verify that there is a default mesh authentication policy in the system, which you can do as follows:

    1. $ kubectl get policies.authentication.istio.io --all-namespaces
    2. No resources found.
    1. $ kubectl get meshpolicies.authentication.istio.io
    2. NAME AGE
    3. default 3m

    Last but not least, verify that there are no destination rules that apply on the example services. You can do this by checking the host: value ofexisting destination rules and make sure they do not match. For example:

    1. $ kubectl get destinationrules.networking.istio.io --all-namespaces -o yaml | grep "host:"
    2. host: istio-policy.istio-system.svc.cluster.local
    3. host: istio-telemetry.istio-system.svc.cluster.local

    Depending on the version of Istio, you may see destination rules for hosts other then those shown. However, there should be none with hosts in the foo,bar and legacy namespace, nor is the match-all wildcard *

    Globally enabling Istio mutual TLS

    To set a mesh-wide authentication policy that enables mutual TLS, submit mesh authentication policy like below:

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: "authentication.istio.io/v1alpha1"
    3. kind: "MeshPolicy"
    4. metadata:
    5. name: "default"
    6. spec:
    7. peers:
    8. - mtls: {}
    9. EOF

    The mesh authentication policy uses the regular authentication policy APIit is defined in the cluster-scoped MeshPolicy CRD.

    This policy specifies that all workloads in the mesh will only accept encrypted requests using TLS. As you can see, this authentication policy has the kind:MeshPolicy. The name of the policy must be default, and it contains no targets specification (as it is intended to apply to all services in the mesh).

    At this point, only the receiving side is configured to use mutual TLS. If you run the curl command between Istio services (i.e those with sidecars), allrequests will fail with a 503 error code as the client side is still using plain-text.

    1. $ for from in "foo" "bar"; do for to in "foo" "bar"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
    2. sleep.foo to httpbin.foo: 503
    3. sleep.foo to httpbin.bar: 503
    4. sleep.bar to httpbin.foo: 503
    5. sleep.bar to httpbin.bar: 503

    To configure the client side, you need to set destination rules to use mutual TLS. It’s possible to usemultiple destination rules, one for each applicable service (or namespace). However, it’s more convenient to use a rule with the * wildcard to match allservices so that it is on par with the mesh-wide authentication policy.

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: "networking.istio.io/v1alpha3"
    3. kind: "DestinationRule"
    4. metadata:
    5. name: "default"
    6. namespace: "istio-system"
    7. spec:
    8. host: "*.local"
    9. trafficPolicy:
    10. tls:
    11. mode: ISTIO_MUTUAL
    12. EOF
    • Starting with Istio 1.1, only destination rules in the client namespace, server namespace and global namespace (default is istio-system) will be considered for a service, in that order.
    • Host value *.local to limit matches only to services in cluster, as opposed to external services. Also note, there is no restriction on the name ornamespace for destination rule.
    • With ISTIO_MUTUAL TLS mode, Istio will set the path for key and certificates (e.g client certificate, private key and CA certificates) according toits internal implementation.

    Don’t forget that destination rules are also used for non-auth reasons such as setting up canarying, but the same order of precedence applies. So if a servicerequires a specific destination rule for any reason - for example, for a configuration load balancer - the rule must contain a similar TLS block withISTIO_MUTUAL mode, as otherwise it will override the mesh- or namespace-wide TLS settings and disable TLS.

    Re-running the testing command as above, you will see all requests between Istio-services are now completed successfully:

    1. $ for from in "foo" "bar"; do for to in "foo" "bar"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
    2. sleep.foo to httpbin.foo: 200
    3. sleep.foo to httpbin.bar: 200
    4. sleep.bar to httpbin.foo: 200
    5. sleep.bar to httpbin.bar: 200

    Request from non-Istio services to Istio services

    The non-Istio service, e.g sleep.legacy doesn’t have a sidecar, so it cannot initiate the required TLS connection to Istio services. As a result,requests from sleep.legacy to httpbin.foo or httpbin.bar will fail:

    1. $ for from in "legacy"; do for to in "foo" "bar"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
    2. sleep.legacy to httpbin.foo: 000
    3. command terminated with exit code 56
    4. sleep.legacy to httpbin.bar: 000
    5. command terminated with exit code 56

    Due to the way Envoy rejects plain-text requests, you will see curl exit code 56 (failure with receiving network data) in this case.

    This works as intended, and unfortunately, there is no solution for this without reducing authentication requirements for these services.

    Request from Istio services to non-Istio services

    Try to send requests to httpbin.legacy from sleep.foo (or sleep.bar). You will see requests fail as Istio configures clients as instructed in ourdestination rule to use mutual TLS, but httpbin.legacy does not have a sidecar so it’s unable to handle it.

    1. $ for from in "foo" "bar"; do for to in "legacy"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
    2. sleep.foo to httpbin.legacy: 503
    3. sleep.bar to httpbin.legacy: 503

    To fix this issue, we can add a destination rule to overwrite the TLS setting for httpbin.legacy. For example:

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: networking.istio.io/v1alpha3
    3. kind: DestinationRule
    4. metadata:
    5. name: "httpbin-legacy"
    6. namespace: "legacy"
    7. spec:
    8. host: "httpbin.legacy.svc.cluster.local"
    9. trafficPolicy:
    10. tls:
    11. mode: DISABLE
    12. EOF

    This destination rule is in the namespace of the server (httpbin.legacy), so it will be preferred over the global destination rule defined in istio-system

    Request from Istio services to Kubernetes API server

    The Kubernetes API server doesn’t have a sidecar, thus request from Istio services such as sleep.foo will fail due to the same problem as when sendingrequests to any non-Istio service.

    1. $ TOKEN=$(kubectl describe secret $(kubectl get secrets | grep default-token | cut -f1 -d ' ' | head -1) | grep -E '^token' | cut -f2 -d':' | tr -d '\t')
    2. $ kubectl exec $(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name}) -c sleep -n foo -- curl https://kubernetes.default/api --header "Authorization: Bearer $TOKEN" --insecure -s -o /dev/null -w "%{http_code}\n"
    3. 000
    4. command terminated with exit code 35

    Again, we can correct this by overriding the destination rule for the API server (kubernetes.default)

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: networking.istio.io/v1alpha3
    3. kind: DestinationRule
    4. metadata:
    5. name: "api-server"
    6. namespace: istio-system
    7. spec:
    8. host: "kubernetes.default.svc.cluster.local"
    9. trafficPolicy:
    10. tls:
    11. mode: DISABLE
    12. EOF

    This rule, along with the global authentication policy and destination rule, above,is automatically injected into the system when you install Istio with mutual TLS enabled.

    Re-run the testing command above to confirm that it returns 200 after the rule is added:

    1. $ TOKEN=$(kubectl describe secret $(kubectl get secrets | grep default-token | cut -f1 -d ' ' | head -1) | grep -E '^token' | cut -f2 -d':' | tr -d '\t')
    2. $ kubectl exec $(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name}) -c sleep -n foo -- curl https://kubernetes.default/api --header "Authorization: Bearer $TOKEN" --insecure -s -o /dev/null -w "%{http_code}\n"
    3. 200

    Cleanup part 1

    Remove global authentication policy and destination rules added in the session:

    1. $ kubectl delete meshpolicy default
    2. $ kubectl delete destinationrules httpbin-legacy -n legacy
    3. $ kubectl delete destinationrules api-server -n istio-system
    4. $ kubectl delete destinationrules default -n istio-system

    Enable mutual TLS per namespace or service

    In addition to specifying an authentication policy for your entire mesh, Istio also lets you specify policies for particular namespaces or services. Anamespace-wide policy takes precedence over the mesh-wide policy, while a service-specific policy has higher precedence still.

    Namespace-wide policy

    The example below shows the policy to enable mutual TLS for all services in namespace foo. As you can see, it uses kind: Policy rather than MeshPolicy,and specifies a namespace, in this case, foo. If you don’t specify a namespace value the policy will apply to the default namespace.

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: "authentication.istio.io/v1alpha1"
    3. kind: "Policy"
    4. metadata:
    5. name: "default"
    6. namespace: "foo"
    7. spec:
    8. peers:
    9. - mtls: {}
    10. EOF

    Similar to mesh-wide policy, namespace-wide policy must be named default, and doesn’t restrict any specific service (no targets section)

    Add corresponding destination rule:

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: "networking.istio.io/v1alpha3"
    3. kind: "DestinationRule"
    4. metadata:
    5. name: "default"
    6. namespace: "foo"
    7. spec:
    8. host: "*.foo.svc.cluster.local"
    9. trafficPolicy:
    10. tls:
    11. mode: ISTIO_MUTUAL
    12. EOF

    Host *.foo.svc.cluster.local limits the matches to services in foo namespace only.

    As these policy and destination rule are applied on services in namespace foo only, you should see only request from client-without-sidecar (sleep.legacy) to httpbin.foo start to fail.

    1. $ for from in "foo" "bar" "legacy"; do for to in "foo" "bar" "legacy"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
    2. sleep.foo to httpbin.foo: 200
    3. sleep.foo to httpbin.bar: 200
    4. sleep.foo to httpbin.legacy: 200
    5. sleep.bar to httpbin.foo: 200
    6. sleep.bar to httpbin.bar: 200
    7. sleep.bar to httpbin.legacy: 200
    8. sleep.legacy to httpbin.foo: 000
    9. command terminated with exit code 56
    10. sleep.legacy to httpbin.bar: 200
    11. sleep.legacy to httpbin.legacy: 200

    Service-specific policy

    You can also set authentication policy and destination rule for a specific service. Run this command to set another policy only for httpbin.bar service.

    1. $ cat <<EOF | kubectl apply -n bar -f -
    2. apiVersion: "authentication.istio.io/v1alpha1"
    3. kind: "Policy"
    4. metadata:
    5. name: "httpbin"
    6. spec:
    7. targets:
    8. - name: httpbin
    9. peers:
    10. - mtls: {}
    11. EOF

    And a destination rule:

    1. $ cat <<EOF | kubectl apply -n bar -f -
    2. apiVersion: "networking.istio.io/v1alpha3"
    3. kind: "DestinationRule"
    4. metadata:
    5. name: "httpbin"
    6. spec:
    7. host: "httpbin.bar.svc.cluster.local"
    8. trafficPolicy:
    9. tls:
    10. mode: ISTIO_MUTUAL
    11. EOF
    • In this example, we do not specify namespace in metadata but put it in the command line (-n bar), which has an identical effect.
    • There is no restriction on the authentication policy and destination rule name. This example uses the name of the service itself for simplicity.

    Again, run the probing command. As expected, request from sleep.legacy to httpbin.bar starts failing with the same reasons.

    1. ...
    2. sleep.legacy to httpbin.bar: 000
    3. command terminated with exit code 56

    If we have more services in namespace bar, we should see traffic to them won’t be affected. Instead of adding more services to demonstrate this behavior,we edit the policy slightly to apply on a specific port:

    1. $ cat <<EOF | kubectl apply -n bar -f -
    2. apiVersion: "authentication.istio.io/v1alpha1"
    3. kind: "Policy"
    4. metadata:
    5. name: "httpbin"
    6. spec:
    7. targets:
    8. - name: httpbin
    9. ports:
    10. - number: 1234
    11. peers:
    12. - mtls: {}
    13. EOF

    And a corresponding change to the destination rule:

    1. $ cat <<EOF | kubectl apply -n bar -f -
    2. apiVersion: "networking.istio.io/v1alpha3"
    3. kind: "DestinationRule"
    4. metadata:
    5. name: "httpbin"
    6. spec:
    7. host: httpbin.bar.svc.cluster.local
    8. trafficPolicy:
    9. tls:
    10. mode: DISABLE
    11. portLevelSettings:
    12. - port:
    13. number: 1234
    14. tls:
    15. mode: ISTIO_MUTUAL
    16. EOF

    This new policy will apply only to the httpbin service on port 1234. As a result, mutual TLS is disabled (again) on port 8000 and requests fromsleep.legacy will resume working.

    1. $ kubectl exec $(kubectl get pod -l app=sleep -n legacy -o jsonpath={.items..metadata.name}) -c sleep -n legacy -- curl http://httpbin.bar:8000/ip -s -o /dev/null -w "%{http_code}\n"
    2. 200

    Policy precedence

    To illustrate how a service-specific policy takes precedence over namespace-wide policy, you can add a policy to disable mutual TLS for httpbin.foo as below.Note that you’ve already created a namespace-wide policy that enables mutual TLS for all services in namespace foo and observe that requests fromsleep.legacy to httpbin.foo are failing (see above).

    1. $ cat <<EOF | kubectl apply -n foo -f -
    2. apiVersion: "authentication.istio.io/v1alpha1"
    3. kind: "Policy"
    4. metadata:
    5. name: "overwrite-example"
    6. spec:
    7. targets:
    8. - name: httpbin
    9. EOF

    and destination rule:

    1. $ cat <<EOF | kubectl apply -n foo -f -
    2. apiVersion: "networking.istio.io/v1alpha3"
    3. kind: "DestinationRule"
    4. metadata:
    5. name: "overwrite-example"
    6. spec:
    7. host: httpbin.foo.svc.cluster.local
    8. trafficPolicy:
    9. tls:
    10. mode: DISABLE
    11. EOF

    Re-running the request from sleep.legacy, you should see a success return code again (200), confirming service-specific policy overrides the namespace-wide policy.

    1. $ kubectl exec $(kubectl get pod -l app=sleep -n legacy -o jsonpath={.items..metadata.name}) -c sleep -n legacy -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n"
    2. 200

    Cleanup part 2

    Remove policies and destination rules created in the above steps:

    1. $ kubectl delete policy default overwrite-example -n foo
    2. $ kubectl delete policy httpbin -n bar
    3. $ kubectl delete destinationrules default overwrite-example -n foo
    4. $ kubectl delete destinationrules httpbin -n bar

    End-user authentication

    To experiment with this feature, you need a valid JWT. The JWT must correspond to the JWKS endpoint you want to use for the demo. Inthis tutorial, we use this JWT test and thisJWKS endpoint from the Istio code base.

    Also, for convenience, expose httpbin.foo via ingressgateway (for more details, see the ingress task).

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: networking.istio.io/v1alpha3
    3. kind: Gateway
    4. metadata:
    5. name: httpbin-gateway
    6. namespace: foo
    7. spec:
    8. selector:
    9. istio: ingressgateway # use Istio default gateway implementation
    10. servers:
    11. - port:
    12. number: 80
    13. name: http
    14. protocol: HTTP
    15. hosts:
    16. - "*"
    17. EOF
    1. $ kubectl apply -f - <<EOF
    2. apiVersion: networking.istio.io/v1alpha3
    3. kind: VirtualService
    4. metadata:
    5. name: httpbin
    6. namespace: foo
    7. spec:
    8. hosts:
    9. - "*"
    10. gateways:
    11. - httpbin-gateway
    12. http:
    13. - route:
    14. - destination:
    15. port:
    16. number: 8000
    17. host: httpbin.foo.svc.cluster.local
    18. EOF

    Get ingress IP

    1. $ export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

    And run a test query

    1. $ curl $INGRESS_HOST/headers -s -o /dev/null -w "%{http_code}\n"
    2. 200

    Now, add a policy that requires end-user JWT for httpbin.foo. The next command assumes there is no service-specific policy for httpbin.foo (which shouldbe the case if you run cleanup as described). You can run kubectl get policies.authentication.istio.io -n foo to confirm.

    1. $ cat <<EOF | kubectl apply -n foo -f -
    2. apiVersion: "authentication.istio.io/v1alpha1"
    3. kind: "Policy"
    4. metadata:
    5. name: "jwt-example"
    6. spec:
    7. targets:
    8. - name: httpbin
    9. origins:
    10. - jwt:
    11. issuer: "testing@secure.istio.io"
    12. jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/jwks.json"
    13. principalBinding: USE_ORIGIN
    14. EOF

    The same curl command from before will return with 401 error code, as a result of server is expecting JWT but none was provided:

    1. $ curl $INGRESS_HOST/headers -s -o /dev/null -w "%{http_code}\n"
    2. 401

    Attaching the valid token generated above returns success:

    1. $ TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/demo.jwt -s)
    2. $ curl --header "Authorization: Bearer $TOKEN" $INGRESS_HOST/headers -s -o /dev/null -w "%{http_code}\n"
    3. 200

    To observe other aspects of JWT validation, use the script gen-jwt.py togenerate new tokens to test with different issuer, audiences, expiry date, etc. The script can be downloaded from the Istio repository:

    1. $ wget https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/gen-jwt.py
    2. $ chmod +x gen-jwt.py

    You also need the key.pem file:

    1. $ wget https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/key.pem

    Download the jwcrypto library,if you haven’t installed it on your system.

    For example, the command below creates a token thatexpires in 5 seconds. As you see, Istio authenticates requests using that token successfully at first but rejects them after 5 seconds:

    1. $ TOKEN=$(./gen-jwt.py ./key.pem --expire 5)
    2. $ for i in `seq 1 10`; do curl --header "Authorization: Bearer $TOKEN" $INGRESS_HOST/headers -s -o /dev/null -w "%{http_code}\n"; sleep 1; done
    3. 200
    4. 200
    5. 200
    6. 200
    7. 200
    8. 401
    9. 401
    10. 401
    11. 401
    12. 401

    You can also add a JWT policy to an ingress gateway (e.g., service istio-ingressgateway.istio-system.svc.cluster.local).This is often used to define a JWT policy for all services bound to the gateway, instead of for individual services.

    End-user authentication with per-path requirements

    End-user authentication can be enabled or disabled based on request path. This is useful if you want todisable authentication for some paths, for example, the path used for health check or status report.You can also specify different JWT requirements on different paths.

    The end-user authentication with per-path requirements is an experimental feature in Istio 1.1 andis NOT recommended for production use.

    Disable End-user authentication for specific paths

    Modify the jwt-example policy to disable End-user authentication for path /user-agent:

    1. $ cat <<EOF | kubectl apply -n foo -f -
    2. apiVersion: "authentication.istio.io/v1alpha1"
    3. kind: "Policy"
    4. metadata:
    5. name: "jwt-example"
    6. spec:
    7. targets:
    8. - name: httpbin
    9. origins:
    10. - jwt:
    11. issuer: "testing@secure.istio.io"
    12. jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/jwks.json"
    13. trigger_rules:
    14. - excluded_paths:
    15. - exact: /user-agent
    16. principalBinding: USE_ORIGIN
    17. EOF

    Confirm it’s allowed to access the path /user-agent without JWT tokens:

    1. $ curl $INGRESS_HOST/user-agent -s -o /dev/null -w "%{http_code}\n"
    2. 200

    Confirm it’s denied to access paths other than /user-agent without JWT tokens:

    1. $ curl $INGRESS_HOST/headers -s -o /dev/null -w "%{http_code}\n"
    2. 401

    Enable End-user authentication for specific paths

    Modify the jwt-example policy to enable End-user authentication only for path /ip:

    1. $ cat <<EOF | kubectl apply -n foo -f -
    2. apiVersion: "authentication.istio.io/v1alpha1"
    3. kind: "Policy"
    4. metadata:
    5. name: "jwt-example"
    6. spec:
    7. targets:
    8. - name: httpbin
    9. origins:
    10. - jwt:
    11. issuer: "testing@secure.istio.io"
    12. jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/jwks.json"
    13. trigger_rules:
    14. - included_paths:
    15. - exact: /ip
    16. principalBinding: USE_ORIGIN
    17. EOF

    Confirm it’s allowed to access paths other than /ip without JWT tokens:

    1. $ curl $INGRESS_HOST/user-agent -s -o /dev/null -w "%{http_code}\n"
    2. 200

    Confirm it’s denied to access the path /ip without JWT tokens:

    1. $ curl $INGRESS_HOST/ip -s -o /dev/null -w "%{http_code}\n"
    2. 401

    Confirm it’s allowed to access the path /ip with a valid JWT token:

    1. $ TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/demo.jwt -s)
    2. $ curl --header "Authorization: Bearer $TOKEN" $INGRESS_HOST/ip -s -o /dev/null -w "%{http_code}\n"
    3. 200

    End-user authentication with mutual TLS

    End-user authentication and mutual TLS can be used together. Modify the policy above to define both mutual TLS and end-user JWT authentication:

    1. $ cat <<EOF | kubectl apply -n foo -f -
    2. apiVersion: "authentication.istio.io/v1alpha1"
    3. kind: "Policy"
    4. metadata:
    5. name: "jwt-example"
    6. spec:
    7. targets:
    8. - name: httpbin
    9. peers:
    10. - mtls: {}
    11. origins:
    12. - jwt:
    13. issuer: "testing@secure.istio.io"
    14. jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/jwks.json"
    15. principalBinding: USE_ORIGIN
    16. EOF

    And add a destination rule:

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: "networking.istio.io/v1alpha3"
    3. kind: "DestinationRule"
    4. metadata:
    5. name: "httpbin"
    6. namespace: "foo"
    7. spec:
    8. host: "httpbin.foo.svc.cluster.local"
    9. trafficPolicy:
    10. tls:
    11. mode: ISTIO_MUTUAL
    12. EOF

    If you already enable mutual TLS mesh-wide or namespace-wide, the host httpbin.foo is already covered by the other destination rule.Therefore, you do not need adding this destination rule. On the other hand, you still need to add the mtls stanza to the authentication policy as the service-specific policy will override the mesh-wide (or namespace-wide) policy completely.

    After these changes, traffic from Istio services, including ingress gateway, to httpbin.foo will use mutual TLS. The test command above will still work. Requests from Istio services directly to httpbin.foo also work, given the correct token:

    1. $ TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/demo.jwt -s)
    2. $ kubectl exec $(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name}) -c sleep -n foo -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n" --header "Authorization: Bearer $TOKEN"
    3. 200

    However, requests from non-Istio services, which use plain-text will fail:

    1. $ kubectl exec $(kubectl get pod -l app=sleep -n legacy -o jsonpath={.items..metadata.name}) -c sleep -n legacy -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n" --header "Authorization: Bearer $TOKEN"
    2. 000
    3. command terminated with exit code 56

    Cleanup part 3

    • Remove authentication policy:
    1. $ kubectl -n foo delete policy jwt-example
    • Remove destination rule:
    1. $ kubectl -n foo delete destinationrule httpbin
    • If you are not planning to explore any follow-on tasks, you can remove all resources simply by deleting test namespaces.
    1. $ kubectl delete ns foo bar legacy

    相关内容

    Mutual TLS Migration

    Shows you how to incrementally migrate your Istio services to mutual TLS.

    安全

    描述 Istio 的授权与鉴权功能。

    Multi-mesh deployments for isolation and boundary protection

    Deploy environments that require isolation into separate meshes and enable inter-mesh communication by mesh federation.

    App Identity and Access Adapter

    Using Istio to secure multi-cloud Kubernetes applications with zero code changes.

    Change in Secret Discovery Service in Istio 1.3

    Taking advantage of Kubernetes trustworthy JWTs to issue certificates for workload instances more securely.

    Istio 1.2.4 sidecar image vulnerability

    An erroneous 1.2.4 sidecar image was available due to a faulty release operation.