Microservices communicate with each other by using HTTP requests in plaintext. However, the communication is insecure. Once an internal microservice is intruded, border security measures are all for nothing, much like the Maginot Line. Attackers can take the machine where the intruded microservice runs as a stepping stone to attack the internal network. Zero trust is a security system that requires explicit authentication for all requests and applies the principle of least privilege to restrict access to resources. This topic shows you how to use resources such as workload identities, peer authentication policies, and request authentication policies to build a zero-trust security system and improve application security in Alibaba Cloud Service Mesh (ASM).

Background information

Microservices deliver various benefits such as scalability, agility, independent scaling, business logic isolation, independent lifecycle management, and easier distributed development. However, a large number of distributed microservices increase security risks because each microservice is an object that may be attacked. Once an internal microservice is intruded, attackers can take the machine where the intruded microservice runs as a stepping stone to attack the internal network.

ASM reduces the scope where attacks can be launched in the cloud-native environment and provides a basic framework for building a zero-trust application network. ASM also provides peer authentication policies, request authentication policies, Istio authorization policies, and Open Policy Agent (OPA)-based fine-grained access control policies. ASM allows you to implement end-to-end service encryption, service-level identity authentication, and fine-grained authorization policies. This ensures service-to-service security and achieves security objectives such as strong identity authentication for all requests and context-based authorization.

The zero-trust security system of ASM provides the following benefits compared with traditional security systems built in application code:
  • The lifecycle of the policies that are attached to ASM sidecar proxies is independent of applications. This helps you manage the sidecar proxies with ease.
  • ASM supports dynamic configuration of policies, which makes it easier to update policies. Updated policies immediately take effect without requiring you to redeploy applications.
  • ASM provides capabilities, such as JSON Web Token (JWT), to authenticate user credentials in requests.
  • The centralized control architecture of ASM allows the security team of an enterprise to build, manage, and deploy security policies that are applicable throughout the enterprise. This ensures the security of business applications that are built by application developers. The deployed security policies immediately take effect without requiring extra efforts.
  • ASM allows you to deploy identity authentication and authorization systems as services in ASM instances. Like other services in ASM instances, these security systems also benefit from the security measures provided by ASM instances, such as encrypted transmission, identity authentication, policy enforcement point (PEP), and authentication and authorization of user credentials.

View workload identities

An ASM instance assigns a unique ID to each microservice that runs in the ASM instance. A microservice needs to provide its unique ID before the microservice communicates with other microservices that run in the same ASM instance as the microservice. The unique IDs are used in peer authentication policies, request authentication policies, and authorization policies to check whether access between microservices is allowed.

When you use ASM to manage workloads that run in Kubernetes clusters or define workload identities for VMs based on workload entries, ASM assigns a service identity to each workload based on the service tokens of workloads.

Service identities in ASM follow the Secure Production Identity Framework for Everyone (SPIFFE) standard and are in the following format: spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>.

The following content describes how to view the workload identities of the services that reside in Kubernetes clusters in ASM and the VMs that are defined based on workload entries.

  1. Log on to the ASM console.
  2. In the left-side navigation pane, choose Service Mesh > Mesh Management.
  3. On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column of the ASM instance.
  4. On the details page of the ASM instance, choose Zero Trust Security > Workload Identity in the left-side navigation pane.
  5. View workload identities on the Workload Identity page.
    • At the top of the Workload Identity page, select WorkloadEntry from the Data Plane drop-down list and then select a namespace from the Namespace drop-down list. Then, you can view the workload identities of the VMs that are defined in the specified namespace based on workload entries.
    • At the top of the Workload Identity page, select a cluster ID from the Data Plane drop-down list and then select a namespace from the Namespace drop-down list. Then, you can view the workload identities of the services that reside in the specified Kubernetes cluster and namespace in ASM.

Use a peer authentication policy to implement mutual Transport Layer Security (mTLS) encryption

When two microservices communicate with each other, you can use a peer authentication policy to implement mTLS encryption for the communication between the two microservices.

  1. Deploy an application in an ASM instance. For more information, see Deploy an application in an ASM instance.
  2. Run the following command to access the details service by sending an HTTP request in plaintext:
    kubectl exec $(kubectl get pod -l app=productpage -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl http://details:9080/details/1 -o /dev/null -s -w '%{http_code}\n'

    Expected output:

    200

    By default, the details service can be accessed by using TLS-secured HTTP requests or HTTP requests in plaintext. Access the pods of the Productpage service by sending an HTTP request in plaintext. If a value of 200 is returned, the service is accessed as expected.

  3. Implement mTLS encryption for the communication with the details service.
    1. Log on to the ASM console.
    2. In the left-side navigation pane, choose Service Mesh > Mesh Management.
    3. On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column of the ASM instance.
    4. In the Create mTLS Mode panel, set the parameters as needed and click OK.
      Parameter Description
      Namespace The name of the namespace to which the peer authentication policy belongs.
      Name The name of the peer authentication policy.
      mTLS Mode (Namespace-wide) The mTLS mode. Select STRICT - Strictly Enforce mTLS from the drop-down list.
      Workload Label Selection Specifies whether to enable workload label selection. Turn on Workload Label Selection, click Add Matching Label, and then add a label with the name of app and the value of details.
  4. Run the following command to access the details service by sending an HTTP request in plaintext again:
    kubectl exec $(kubectl get pod -l app=productpage -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl http://details:9080/details/1 -o /dev/null -s -w '%{http_code}\n'

    Expected output:

    000
    command terminated with exit code 56

    The preceding results indicate that the details service fails to be accessed by sending an HTTP request in plaintext. After you create a peer authentication policy for a service, the service can be accessed only if the corresponding requests are authenticated by the TLS certificate. Otherwise, the service cannot be accessed.

Use a request authentication policy to implement JWT-based authentication

You can create a request authentication policy for a microservice to implement JWT-based authentication for requests that come to the microservice. If a request contains a JWT, the request authentication policy is used to check whether the JWT is valid. The microservice can be accessed only if the JWT is valid. If a request does not contain a JWT, the request is not checked, and the microservice can be accessed by the request as expected.
Note You can use an authorization policy and a request authentication policy to specify that the microservice can be accessed only if the requests contain a valid JWT. In this case, requests that contain an invalid JWT or do not contain a JWT cannot access the microservice.
  1. Deploy an application in an ASM instance. For more information, see Deploy an application in an ASM instance.
  2. Log on to the ASM console.
  3. In the left-side navigation pane, choose Service Mesh > Mesh Management.
  4. On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column of the ASM instance.
  5. On the details page of the ASM instance, choose Zero Trust Security > RequestAuthentication in the left-side navigation pane. On the RequestAuthentication page, click Create RequestAuthentication.
  6. In the Create panel, set the parameters as needed and click OK.
    Parameter Description
    Namespace The name of the namespace to which the request authentication policy belongs. In this example, select default.
    Name The name of the request authentication policy.
    Matching Label

    The label that is used to specify the service to which the request authentication policy applies. In this example, specify the details service.

    Click Add Matching Label and add a label with the name of app and the value of details.

    JWT Rule Set The JWT rules. Click Add next to JWT Rule Set and set the following parameters:
    • issuer: the issuer of the JWT. In this example, set the value to testing@secure.istio.io.
    • audiences: the audiences of the JWT. This parameter specifies the services that can use the JWT to access the destination service. If you do not set this parameter, all services can access the destination service.
    • jwks: the JWT request information. In this example, set the value to the following content:
      null
  7. Use a JWT tool to encode JWT request information into a JWT string.
    null

    Expected JWT string after encoding:

    eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg
  8. Verify that the request authentication policy takes effect as expected.
    1. Send a request that contains the encoded JWT to access the details service.
      export TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg
      kubectl exec $(kubectl get pod -l app=productpage -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl http://details:9080/details/1 -o /dev/null --header "Authorization: Bearer $TOKEN" -s -w '%{http_code}\n'                    

      Expected output:

      200

      A value of 200 is returned, which indicates that the details service is accessed as expected.

    2. Send a request that contains an invalid JWT to access the details service.
      kubectl exec $(kubectl get pod -l app=productpage -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl http://details:9080/details/1 -o /dev/null --header "Authorization: Bearer badtoken" -s -w '%{http_code}\n'

      Expected output:

      403

      A value of 403 is returned, which indicates that the details service fails to be accessed.

    3. Send a request that does not contain a JWT to access the details service.
      kubectl exec $(kubectl get pod -l app=productpage -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl http://details:9080/details/1 -o /dev/null  -s -w '%{http_code}\n'

      Expected output:

      200

      A value of 200 is returned, which indicates that the details service is accessed as expected.

    The preceding results indicate that a request can access the details service if the request contains a valid JWT or does not contain a JWT, and a request that contains an invalid JWT cannot access the details service. This indicates that the request authentication policy takes effect as expected.

Use an authorization policy to authenticate the source of requests

You can create an authorization policy for a microservice to specify that only requests that meet specified requirements can access the microservice. For example, you can set the port, IP address, and source of valid requests. In this example, use an authorization policy to specify that a request can access the destination service only if the request contains a JWT that is issued by the specified issuer.

  1. Deploy an application in an ASM instance. For more information, see Deploy an application in an ASM instance.
  2. Log on to the ASM console.
  3. In the left-side navigation pane, choose Service Mesh > Mesh Management.
  4. On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column of the ASM instance.
  5. On the details page of the ASM instance, choose Zero Trust Security > AuthorizationPolicy in the left-side navigation pane. On the AuthorizationPolicy page, click Create AuthorizationPolicy.
  6. In the Create panel, set the parameters as needed and click OK.
    Parameter Description
    Namespace The name of the namespace to which the authorization policy belongs. In this example, select default.
    Name The name of the authorization policy.
    Policies The policy. In this example, select RULES.
    Workload Label Selection Specifies whether to enable workload label selection. Turn on Workload Label Selection, click Add Matching Label, and then add a label with the name of app and the value of details.
    Action The action on requests that meet specified requirements. In this example, select ALLOW.
    Request Source Specifies whether to authenticate the sources of requests. Turn on Request Source, click Add Request Source to List, and then click Add Request Source. Then, select requestPrincipals from the Request Source Domain drop-down list and set the Value parameter to testing@secure.istio.io/testing@secure.istio.io.
  7. Run the following command to send a request that does not contain a JWT to access the details service:
     kubectl exec $(kubectl get pod -l app=productpage -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl http://details:9080/details/1 -o /dev/null  -s -w '%{http_code}\n'

    Expected output:

    403
    The request that does not contain a JWT fails to access the details service, which indicates that the authorization policy takes effect as expected. The authorization policy restricts that a request can access the details service only if the request contains a JWT that is issued by testing@secure.istio.io.

Use an OPA policy to implement fine-grained access control

OPA is a policy engine that you can use to implement fine-grained access control on your applications. You can deploy OPA as a standalone service along with microservices. To protect an application, make sure that each request to a microservice of the application is authorized before the request is processed. To check the authorization, the microservice makes an API call to OPA to decide whether the request is authorized.

ASM integrates with OPA. You can use OPA to define access control policies to implement fine-grained access control on your applications. For more information, see Use OPA to implement fine-grained access control in ASM.