--- title: Basic Authentication Policy description: Shows you how to use Istio authentication policy to setup mutual TLS and basic end-user authentication. weight: 10 keywords: [security,authentication] aliases: - /docs/tasks/security/istio-auth.html --- Through this task, you will learn how to: * Use authentication policy to setup mutual TLS. * Use authentication policy to do end-user authentication. ## Before you begin * Understand Istio [authentication policy](/docs/concepts/security/authn-policy/) and related [mutual TLS authentication](/docs/concepts/security/mutual-tls/) concepts. * Have a Kubernetes cluster with Istio installed, without global mutual TLS enabled (e.g use `install/kubernetes/istio-demo.yaml` as described in [installation steps](/docs/setup/kubernetes/quick-start/#installation-steps), or set `global.mtls.enabled` to false using [Helm](/docs/setup/kubernetes/helm-install/)). * For demo, create two namespaces `foo` and `bar`, and deploy [httpbin](https://github.com/istio/istio/blob/{{}}/samples/httpbin) and [sleep](https://github.com/istio/istio/tree/master/samples/sleep) with sidecar on both of them. Also, run another httpbin and sleep app without sidecar (to keep it separate, run them in `legacy` namespace). In a regular system, a service can be both *server* (receiving traffic) for some services, and *client* for some others. For simplicity, in this demo, we only use `sleep` apps as clients, and `httpbin` as servers. ```command $ 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/sleep/sleep.yaml@) -n foo $ kubectl create ns bar $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n bar $ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@) -n bar $ kubectl create ns legacy $ kubectl apply -f @samples/httpbin/httpbin.yaml@ -n legacy $ kubectl apply -f @samples/sleep/sleep.yaml@ -n legacy ``` * Verifying setup by sending an HTTP request (using curl command) from any clients (i.e `sleep.foo`, `sleep.bar` and `sleep.legacy`) to any server (`httpbin.foo`, `httpbin.bar` or `httpbin.legacy`). All requests should success with HTTP code 200. For example, here is a command to check `sleep.bar` to `httpbin.foo` reachability: ```command $ 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" 200 ``` Conveniently, this one-liner command iterates through all combinations: ```command $ 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 sleep.foo to httpbin.foo: 200 sleep.foo to httpbin.bar: 200 sleep.foo to httpbin.legacy: 200 sleep.bar to httpbin.foo: 200 sleep.bar to httpbin.bar: 200 sleep.bar to httpbin.legacy: 200 sleep.legacy to httpbin.foo: 200 sleep.legacy to httpbin.bar: 200 sleep.legacy to httpbin.legacy: 200 ``` > If you have `curl` installed on istio-proxy container, you can also verify that it can reach `httpbin` services in from proxy: ```command $ kubectl exec $(kubectl get pod -l app=sleep -n bar -o jsonpath={.items..metadata.name}) -c istio-proxy -n bar -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n" 200 ``` * Last but not least, verify that there are no authentication policy: ```command $ kubectl get meshpolicies.authentication.istio.io No resources found. $ kubectl get policies.authentication.istio.io --all-namespaces No resources found. $ kubectl get destinationrules.networking.istio.io --all-namespaces ``` > You may see some policies and/or destination rules added by Istio installation, depends on installation mode. However, there should be none for `foo`, `bar` and `legacy` namespaces. ## Enable mutual TLS for all services in the mesh To enable mutual TLS for all services in the mesh, you can submit *mesh authentication policy* and destination rule as below: ```bash cat < The HTTP return code is not yet consistent. If request is sent in mutual TLS mode and server accept HTTP only, error code is 503. On the contrary, if request is sent in plain-text to server that use mutual TLS, the error code is 000 (with `curl` exit code 56, "failure with receiving network data"). To fix the connection from client-with-sidecar to server-without-sidecar, you can add destination rule specific for those server to overwrite TLS setting. ```bash cat < This approach can also be used to configure Kubernetes' API server, when mutual TLS is enabled globally. Following is an example configuration. ```bash cat < 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: ```bash cat < 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. ```command $ 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 sleep.foo to httpbin.foo: 200 sleep.foo to httpbin.bar: 200 sleep.foo to httpbin.legacy: 200 sleep.bar to httpbin.foo: 200 sleep.bar to httpbin.bar: 200 sleep.bar to httpbin.legacy: 200 sleep.legacy to httpbin.foo: 000 command terminated with exit code 56 sleep.legacy to httpbin.bar: 200 sleep.legacy to httpbin.legacy: 200 ``` ## Enable mutual TLS for single service `httpbin.bar` 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. ```bash cat < In this example, we do **not** specify namespace in metadata but put it in the command line (`-n bar`). They should work the same. > There is no restriction on the authentication policy and destination rule name. The example use 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. ```plain ... sleep.legacy to httpbin.bar: 000 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: ```bash cat <}}/security/tools/jwt) to create one. You can also use your own JWT/JWKS endpoint for the demo. Once you have that, export to some environment variables. ```command $ export SVC_ACCOUNT="example@my-project.iam.gserviceaccount.com" $ export JWKS=https://www.googleapis.com/service_accounts/v1/jwk/${SVC_ACCOUNT} $ export TOKEN= ``` Also, for convenience, expose `httpbin.foo` via ingress (for more details, see [ingress task](/docs/tasks/traffic-management/ingress/)). ```bash cat <