You are viewing archived v1.24 Service Mesh documentation.
Available versions
Cloud Service Mesh latest
Cloud Service Mesh 1.26 archive
Cloud Service Mesh 1.24 archive
Cloud Service Mesh 1.24 archive
Cloud Service Mesh 1.23 archive
Cloud Service Mesh 1.22 archive
Cloud Service Mesh 1.21 archive
Cloud Service Mesh 1.20 archive
Anthos Service Mesh 1.19 archive
Cloud Service Mesh by example: mTLS Stay organized with collections Save and categorize content based on your preferences.
In Cloud Service Mesh 1.5 and later, auto mutual TLS (auto mTLS) is enabled bydefault. With auto mTLS, a client sidecar proxy automatically detects if theserver has a sidecar. The client sidecar sends mTLS to workloads with sidecarsand sends plaintext to workloads without sidecars. Note, however, servicesaccept both plaintext and mTLS traffic. As youinject sidecar proxies to your Pods, werecommend that you also configure your services to only accept mTLS traffic.
With Cloud Service Mesh, you can enforce mTLS, outside of your application code, byapplying a single YAML file. Cloud Service Mesh gives you the flexibility to apply anauthentication policy to the entire service mesh, to a namespace, or to anindividual workload.
Costs
In this document, you use the following billable components of Google Cloud:
To generate a cost estimate based on your projected usage, use thepricing calculator.
When you finish this tutorial, you can avoid ongoing costs by deleting theresources you created. For more information, seeClean up.
Before you begin
Make sure that billing is enabled for your Cloud project.Learn how toconfirm that billing is enabled for your project.
Install Cloud Service Mesh on a GKE cluster and deploy an ingressgateway. If you need to set up a cluster for this tutorial, see theCloud Service Mesh quickstart,which walks you through:
- Creating a GKE cluster.
- Provisions managed Cloud Service Mesh.
- Deploying an ingress gateway.
- Deploying the Online Boutique sample application from the
anthos-service-mesh-packagesrepo, which is modified from the original set of manifests in themicroservices-demorepo. Following best practices, each service is deployed in a separate namespacewith a unique service account.
Create a TestCurl pod to send plaintext traffic for testing.
apiVersion: v1 kind: Pod metadata: name: testcurl namespace: default annotations: sidecar.istio.io/inject: "false" spec: containers: - name: curl image: curlimages/curl command: ["sleep", "600"]
Access Online Boutique
Set the current context for
kubectlto the cluster where you deployedOnline Boutique:gcloud container clusters get-credentialsCLUSTER_NAME \ --project=PROJECT_ID \ --zone=CLUSTER_LOCATIONList the services in the
frontendnamespace:kubectl get services -n frontendNotice that
frontend-externalis aLoadBalancer, and it has anexternal IP address. The sample application includes a service that is aload balancer so that it can be deployed on GKE withoutCloud Service Mesh.Visit the application in your browser using the external IP address of the
frontend-externalservice:http://FRONTEND_EXTERNAL_IP/Cloud Service Mesh provides you the ability to deploy an ingress gateway. You canalso access the Online Boutique using the external IP address of the ingressgateway. Get the external IP of the gateway. Replace the placeholders withthe following information:
- GATEWAY_SERVICE_NAME : The name of the ingress gatewayservice. If you deployed the sample gateway without modification, or ifyou deployed thedefault ingress gateway,the name is
istio-ingressgateway. - GATEWAY_NAMESPACE: The namespace in which you deployedthe ingress gateway. If you deployed the default ingress gateway, thenamespace is
istio-system.
kubectl get serviceGATEWAY_NAME -nGATEWAY_NAMESPACE- GATEWAY_SERVICE_NAME : The name of the ingress gatewayservice. If you deployed the sample gateway without modification, or ifyou deployed thedefault ingress gateway,the name is
Open another tab in your browser and visit the application using theexternal IP address of the ingress gateway:
http://INGRESS_GATEWAY_EXTERNAL_IP/Run the following command to
curlthefrontendservice with plain HTTPfrom another Pod. Because the services are in different namespaces, youneed to curl theDNS name of thefrontendservice.kubectl debug --image istio/base --target istio-proxy -it \ $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \ -n product-catalog -- \ curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'Your request succeeds with status
200, because by default, both TLS andplaintext traffic are accepted.
Enable mutual TLS per namespace
You enforce mTLS by applying aPeerAuthentication policy withkubectl.
Save the following authentication policy as
mtls-namespace.yaml.cat <<EOF > mtls-namespace.yamlapiVersion: "security.istio.io/v1beta1"kind: "PeerAuthentication"metadata: name: "namespace-policy"spec: mtls: mode: STRICTEOFThe line
mode: STRICTin the YAML configures the services to onlyaccept mTLS. By default, themodeisPERMISSIVE, which configuresservices to accept both plaintext and mTLS.Apply the authentication policy to configure all Online Boutiqueservices to only accept mTLS:
fornsinadcartcheckoutcurrencyemailfrontendloadgenerator\paymentproduct-catalogrecommendationshipping;dokubectlapply-n$ns-fmtls-namespace.yamldoneExpected output:
peerauthentication.security.istio.io/namespace-policy createdpeerauthentication.security.istio.io/namespace-policy createdpeerauthentication.security.istio.io/namespace-policy createdpeerauthentication.security.istio.io/namespace-policy createdpeerauthentication.security.istio.io/namespace-policy createdpeerauthentication.security.istio.io/namespace-policy createdpeerauthentication.security.istio.io/namespace-policy createdpeerauthentication.security.istio.io/namespace-policy createdpeerauthentication.security.istio.io/namespace-policy createdpeerauthentication.security.istio.io/namespace-policy createdpeerauthentication.security.istio.io/namespace-policy created
Go to the tab in your browser that accesses the Online Boutique using theexternal IP address of the
frontend-externalservice:http://FRONTEND_EXTERNAL_IP/Refresh the page. The browser displays the following error:

Refreshing the page causes plaintext to be sent to the
frontendservice.Because of theSTRICTauthentication policy, the sidecar proxy blocks therequest to the service.Go to the tab in your browser that accesses the Online Boutique using theexternal IP address of the
istio-ingressgateway, and refresh the page,which displays successfully. When you access Online Boutique using theingress gateway, the request takes the following path:mTLS authentication flow:
- The browser sends a plaintext HTTP request to the server.
- The ingress gateway proxy container intercepts the request.
- The ingress gateway proxy performs a TLS handshake with theserver-side proxy (the frontend service in this example). This handshakeincludes an exchange of certificates. These certs are pre-loaded intothe proxy containers by Cloud Service Mesh.
- The ingress gateway proxy performs a secure naming check on theserver's certificate, verifying that an authorized identity is runningthe server.
- The ingress gateway and server proxies establish a mutual TLSconnection, and the server proxy forwards the request to the serverapplication container (the frontend service).
Run the following command to
curlthefrontendservice with plain HTTPfrom another Pod.kubectl exec testcurl -n default -- curl \ http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'Your request fails as we are sending plaintext traffic from sidecar-less workload where STRICT
peerAuthenticationpolicy is applied.
Find and delete authentication policies
For a list of all the
PeerAuthenticationpolicies in the service mesh:kubectl get peerauthentication --all-namespacesThe output is similar to the following:
NAMESPACE NAME MODE AGEad namespace-policy STRICT 17mcart namespace-policy STRICT 17mcheckout namespace-policy STRICT 17mcurrency namespace-policy STRICT 17memail namespace-policy STRICT 17mfrontend namespace-policy STRICT 17mloadgenerator namespace-policy STRICT 17mpayment namespace-policy STRICT 17mproduct-catalog namespace-policy STRICT 17mrecommendation namespace-policy STRICT 17mshipping namespace-policy STRICT 17mDelete the authentication policy from all of the Online Boutiquenamespaces:
fornsinadcartcheckoutcurrencyemailfrontendloadgeneratorpayment\product-catalogrecommendationshipping;dokubectldeletepeerauthentication-n$nsnamespace-policydone;Expected output:
peerauthentication.security.istio.io "namespace-policy" deletedpeerauthentication.security.istio.io "namespace-policy" deletedpeerauthentication.security.istio.io "namespace-policy" deletedpeerauthentication.security.istio.io "namespace-policy" deletedpeerauthentication.security.istio.io "namespace-policy" deletedpeerauthentication.security.istio.io "namespace-policy" deletedpeerauthentication.security.istio.io "namespace-policy" deletedpeerauthentication.security.istio.io "namespace-policy" deletedpeerauthentication.security.istio.io "namespace-policy" deletedpeerauthentication.security.istio.io "namespace-policy" deletedpeerauthentication.security.istio.io "namespace-policy" deletedAccess the Online Boutique using the external IP address of the
frontend-externalservice, and refresh the page. The page displays asexpected.Run the following command to
curlthefrontendservice with plain HTTPfrom another Pod.kubectl debug --image istio/base --target istio-proxy -it \ $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \ -n product-catalog -- \ curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'Your request succeeds with status
200, because by default, both TLS andplaintext traffic are accepted.
If you refresh the page in the Google Cloud console that displays theWorkloads list, it now shows that the mTLS status isPermissive.
Enable mutual TLS per workload
To set aPeerAuthentication policy for a specific workload, you must configuretheselector section and specify the labels that match the desired workload.However, Cloud Service Mesh can't aggregate workload-level policies for outboundmTLS traffic to a service. You need to configure a destination rule to managethat behavior.
Apply an authentication policy to a specific workload. Notice how thefollowing policy uses labels and selectors to target the specific
frontenddeployment.cat <<EOF | kubectl apply -n frontend -f -apiVersion: "security.istio.io/v1beta1"kind: "PeerAuthentication"metadata: name: "frontend" namespace: "frontend"spec: selector: matchLabels: app: frontend mtls: mode: STRICTEOFExpected output:
peerauthentication.security.istio.io/frontend created
Configure a matching destination rule.
cat <<EOF | kubectl apply -n frontend -f -apiVersion: "networking.istio.io/v1alpha3"kind: "DestinationRule"metadata: name: "frontend"spec: host: "frontend.demo.svc.cluster.local" trafficPolicy: tls: mode: ISTIO_MUTUALEOFExpected output:
destinationrule.networking.istio.io/frontend created
Access the Online Boutique using the external IP address of the
frontend-externalservice, and refresh the page. The page doesn'tdisplay because because thefrontend serviceis set toSTRICTmTLS, and the sidecar proxy blocks the request.Run the following command to
curlthefrontendservice with plain HTTPfrom another Pod.kubectl exec testcurl -n default -- curl \ http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'Your request fails as we are sending plaintext traffic from sidecar-less workload where STRICT
peerAuthenticationpolicy is applied.Delete the authentication policy:
kubectl delete peerauthentication -n frontend frontendExpected output:
peerauthentication.security.istio.io "frontend" deletedDelete the destination rule:
kubectl delete destinationrule -n frontend frontendExpected output:
destinationrule.networking.istio.io "frontend" deleted
Enforcing mesh-wide mTLS
To prevent all your services in the mesh from accepting plaintext traffic, seta mesh-widePeerAuthentication policy with the mTLS mode set toSTRICT.The mesh-widePeerAuthentication policy shouldn't have a selector and must beapplied in the root namespace,istio-system. When you deploy the policy, thecontrol plane automatically provisions TLS certificates so that workloads canauthenticate with each other.
Enforce mesh-wide mTLS:
kubectl apply -f - <<EOFapiVersion: "security.istio.io/v1beta1"kind: "PeerAuthentication"metadata: name: "mesh-wide" namespace: "istio-system"spec: mtls: mode: STRICTEOFExpected output:
peerauthentication.security.istio.io/mesh-wide created
Access the Online Boutique using the external IP address of the
frontend-externalservice, and refresh the page. The page doesn'tdisplay.Run the following command to
curlthefrontendservice with plain HTTPfrom another Pod.kubectl exec testcurl -n default -- curl \ http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'Your request fails as we are sending plaintext traffic from sidecar-less workload where STRICT
peerAuthenticationpolicy is applied.Delete the
mesh-widepolicy:kubectl delete peerauthentication -n istio-system mesh-wideExpected output:
peerauthentication.security.istio.io "mesh-wide" deleted
Clean up
To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, either delete the project that contains the resources, or keep the project and delete the individual resources.
If you want to prevent additional charges, delete the cluster:
gcloud container clusters deleteCLUSTER_NAME \ --project=PROJECT_ID \ --zone=CLUSTER_LOCATIONIf you want to keep your cluster and remove the Online Boutique sample:
- Delete the application namespaces:
kubectl delete -f online-boutique/kubernetes-manifests/namespacesExpected output:
namespace "ad" deletednamespace "cart" deletednamespace "checkout" deletednamespace "currency" deletednamespace "email" deletednamespace "frontend" deletednamespace "loadgenerator" deletednamespace "payment" deletednamespace "product-catalog" deletednamespace "recommendation" deletednamespace "shipping" deleted- Delete the service entries:
kubectl delete -f online-boutique/istio-manifests/allow-egress-googleapis.yamlExpected output:
serviceentry.networking.istio.io "allow-egress-googleapis" deletedserviceentry.networking.istio.io "allow-egress-google-metadata" deleted
What's next
- For a general guide on configuring
PeerAuthenticationpolicies, seeConfiguring transport security.
Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2026-02-19 UTC.