arrow

Experiment On Improving Application Security In ASM

1. Experiment

1.1 Knowledge points

This experiment is performed on Alibaba Cloud Service Mesh (ASM). This experiment 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 ASM.

Microservices communicate with each other by using HTTP requests in plaintext. However, the communication is insecure. If an internal microservice is intruded, border security tools are all useless. Attackers can take the machine on which 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 control access to resources.

ASM reduces the attack surface 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.

1.2 Experiment process

  • Prepare for the experiment.
  • Deploy sample applications.
  • Verify zero-trust authentication.
  • Verify OPA policy authentication.

1.3 Lab environment architecture

image desc

1.4 Alibaba Cloud resources required

  • ASM
  • Container Service for Kubernetes (ACK)

1.5 Prerequisites

  • An Elastic Compute Service (ECS) instance is running Ubuntu 16.04. This is required if you use your own Alibaba Cloud account instead of the account provided by the experiment. This ensures that the experiment can be smoothly run.
  • The previous experiment is normally closed and exited.

2. Start the experiment environment

On the experiment platform, click Start Lab in the upper-right corner of the page to start the experiment.

image desc.

After the experiment environment is started, the system has deployed resources needed during the experiment in the background. For example, an ECS instance, an ApsaraDB RDS instance, a Server Load Balancer (SLB) instance, and an Object Storage Service (OSS) bucket are created. A RAM user is also created, and the username and password of the RAM user for logging on to the Alibaba Cloud Management Console are provided.

image desc

After the experiment environment is started and relevant resources are properly deployed, the experiment starts a countdown. You have an hour to perform experimental operations. After the countdown ends, the experiment stops, and relevant resources are released. During the experiment, pay attention to the remaining time and arrange your time wisely. Then, use the username and password provided by the system to log on to the Alibaba Cloud Management Console and view relevant resources.

image desc

Go to the logon page of the Alibaba Cloud Management console.

image desc

Enter the username of the RAM user and click Next.

image desc

Enter the password of the RAM user and click Login.

image desc

After you log on to the Alibaba Cloud Management Console, the homepage appears, as shown in the following figure.

image desc

3. Prepare for the experiment

3.1 Create an ACK cluster

Select Container Service for Kubernetes to go to the ACK console, as shown in the following figure.

image desc

Create an ACK cluster, as shown in the following figure.

image desc

Select Managed Kubernetes.

image desc

Enter the cluster name, select the Singapore (Singapore) region, select a virtual private cloud (VPC) and a vSwitch in which you want to create the ACK cluster, and then click Next.

image desc

Configure the worker nodes.

Select the instance type of the worker nodes, as shown in the following figure.

image desc

The number of worker nodes is set to 3.

image desc

Enter the password and click Next:Component Configurations.

image desc

Configure components and click Next:Confirm Order.

image desc

Click Create Cluster.

image desc

It requires approximately 10 minutes to create an ACK cluster. Please wait.

image desc

image desc

3.2 Create an ASM instance

Go to the ASM console, as shown in the following figure.

image desc

Click Create ASM Instance, as shown in the following figure.

image desc

Enter the instance name, select the Singapore (Singapore) region, select a VPC and a vSwitch in which you want to create the ASM instance, and then click Create Service Mesh.

image desc

image desc

Wait for the system to initialize the ASM instance, which takes approximately 3 minutes.

image desc

The ASM instance is created.

image desc

3.3 Add the ACK cluster to the ASM instance

Click Manage, as shown in the following figure.

image desc

Add the created ACK cluster to the ASM instance, as shown in the following figure.

image desc

image desc

The ACK cluster is added.

image desc

3.4 Create an ASM gateway

Click Create, as shown in the following figure.

image desc

Configure parameters, as shown in the following figure.

image desc

Click Create, as shown in the following figure.

image desc

Wait for approximately 1 minute until the ASM gateway is created.

image desc

4. Deploy sample applications

4.1 Connect to the ACK cluster

Click Elastic Compute Service, as shown in the following picture.

image desc

Copy the public IP address of the ECS instance and remotely log on to the ECS instance that runs the Ubuntu operating system. For more information about remote logon, see How to Remotely Log in to Alibaba Cloud’s ECS Server.

If multiple ECS instances are available in the ECS console, the cluster just created is creating ECS instances. Select the ECS instance with a public IP address to log on.

image desc

The default username and password of the ECS instance:

Username: root

Password: nkYHG890..

Run the following command to download the latest version of the kubectl client:

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

image desc

Run the following commands to grant the execute permissions to the downloaded client and move the client to the /usr/bin directory:

chmod +x kubectl
mv kubectl /usr/bin/

image desc

Run the following command to create a directory named .kube:

mkdir -p .kube

image desc

Log on to the ACK console, and click **Clusters in the left-side navigation pane. On the Clusters** page, click the cluster name.

image desc

On the Basic Information page, click Copy to copy the certificate information of the ACK cluster.

image desc

Return to the CLI and run the vim .kube/config command to create a file named config. Copy the certificate information of the ACK cluster that you created to the file. Save the file and exit.

image desc

Run the following command to view the node information:

kubectl get node

image desc

The command output shows that the worker nodes are connected to the ACK cluster.

4.3 Deploy applications

Go to the ASM console, and enable automatic sidecar injection in the default namespace.

image desc

image desc

Automatic sidecar injection is enabled.

image desc

Go to the CLI of the ECS instance.

Run the following commands to download the configuration files of the sample applications:

wget https://labex-ali-data-ap.oss-ap-southeast-1.aliyuncs.com/ASM/bookinfo.yaml

wget https://labex-ali-data-ap.oss-ap-southeast-1.aliyuncs.com/ASM/sleep.yaml

image desc

Run the following commands to create applications based on the configuration files:

kubectl apply -f bookinfo.yaml -n default

kubectl apply -f sleep.yaml  -n default

image desc

Run the following command to view the created sources:

kubectl get all -n default

image desc

5. Verify zero-trust authentication

5.1 Peer authentication policy

Run the following command to access the details application from the productpage application. By default, the details service can be accessed by using TLS-secured HTTP requests or HTTP requests 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'

image desc

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

Go to the ASM console.

image desc

Configure parameters to create a peer authentication policy, and click Create, as shown in the following figure.

image desc

The peer authentication policy is created.

image desc

Go to the CLI of the ECS instance and run the following command:

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'

image desc

The preceding results indicate that the details service fails to be accessed by using 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.

5.2 Request authentication policy

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.

Go to the ASM console. Click Create, as shown in the following figure.

image desc

Configure parameters to create a JWT rule, as shown in the following figure.

issuer: testing@secure.istio.io
jwks: { "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"}]}

image desc

The JWT rule is created.

image desc

Use the JWT tool to encode JWT request information into a JWT.

{ "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"}]}

Expected JWT string after encoding (the JWT string is already encoded, and you do not need to encode it again):

eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg

Go to the CLI of the ECS instance. Run the following command to send a request that contains a 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=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null --header "Authorization: Bearer $TOKEN" -s -w '%{http_code}\n'

image desc

Run the following command to send a request that contains an invalid JWT to access the details service.

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null --header "Authorization: Bearer badtoken" -s -w '%{http_code}\n'

image desc

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=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null  -s -w '%{http_code}\n'

image desc

The preceding results show 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.

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, the requests that contain an invalid JWT or do not contain a JWT cannot access the microservice.

The following section describes how to use an authorization policy.

5.3 Authorization policy

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 specify 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.

Go to the ASM console. Click Create, as shown in the following figure.

image desc

Configure parameters, as shown in the following figure. Set the value of Request Source Domain to testing@secure.istio.io/testing@secure.istio.io

image desc

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=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl http://details:9080/details/1 -o /dev/null  -s -w '%{http_code}\n'

image desc

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.

6. Verify OPA policy authentication

6.1 Enable OPA

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 for 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.

Go to the ASM console. Click Settings, as shown in the following figure.

image desc

Select Enable Open Policy Agent (OPA) Plug-in, and click OK, as shown in the following figure.

image desc

Wait for approximately 1 minute until the ASM instance is updated.

image desc

image desc

6.2 Create an OPA policy

Click Create, as shown in the following figure.

image desc

On the Create page, select default from the Namespace drop-down list, set a policy name, click Add Matching Label, add a label with the name of version and the value of v1, copy the following content to the code editor, and then click Create.

package istio.authz
import input.attributes.request.http as http_request
allow {
    roles_for_user[r]
    required_roles[r]
}
roles_for_user[r] {
    r := user_roles[user_name][_]
}
required_roles[r] {
    perm := role_perms[r][_]
    perm.method = http_request.method
    perm.path = http_request.path
}
user_name = parsed {
    [_, encoded] := split(http_request.headers.authorization, " ")
    [parsed, _] := split(base64url.decode(encoded), ":")
}
user_roles = {
    "guest1": ["guest"],
    "admin1": ["admin"]
}
role_perms = {
    "guest": [
        {"method": "GET",  "path": "/productpage"},
    ],
    "admin": [
        {"method": "GET",  "path": "/productpage"},
        {"method": "GET",  "path": "/api/v1/products"},
    ],
}

image desc

This policy defines the rule for authenticating access requests to the /productpage path. The guest role is assigned to the guest1 user, and the admin role is assigned to the admin1 user. Access rules are also defined for the roles in the configurations.

Go to the CLI of the ECS instance. Run the following command to add the opa-istio-injection=enabled label to the default namespace. OPA sidecar proxies are injected into the pods in a namespace to which the opa-istio-injection=enabled label is added.

kubectl label namespace default opa-istio-injection=enabled --overwrite

image desc

Next, restart the productpage application by deleting pods. After the application is restarted, OPA sidecar proxies are automatically injected.

Go to the ACK console. Select all pods in the default namespace and click Batch Delete, as shown in the following figure.

image desc

After the pods are deleted, new pods are immediately created. Wait for approximately 3 minutes.

image desc

OPA sidecar proxies are automatically injected into the new pods.

6.3 Create an ingress gateway and a virtual service for the productpage application

Go to the ASM console. Click Create from YAML, as shown in the following figure.

image desc

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"

image desc

Click Create from YAML to create a virtual service, as shown in the following figure.

image desc

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - "*"
  gateways:
  - bookinfo-gateway
  http:
  - match:
    - uri:
        exact: /productpage
    - uri:
        prefix: /static
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    route:
    - destination:
        host: productpage
        port:
          number: 9080

image desc

View the IP address of the ingress gateway.

image desc

Run the following command to access the application by using a URL that contains /productpage. Replace YOUR-GATEWAY-IP with the IP address of the ingress gateway.

curl -X GET http://YOUR-GATEWAY-IP/productpage --user guest1:password -I

image desc

Run the following command to access the application by using a URL that contains /api/v1/products. Replace YOUR-GATEWAY-IP with the IP address of the ingress gateway.

curl -X GET http://YOUR-GATEWAY-IP/api/v1/products --user guest1:password -I

image desc

The results indicate that the guest role is assigned to the guest1 user. In addition, the guest1 user has the permissions to access the application by using a URL that contains /productpage, but not /api/v1/products.

Next, use the admin1 user to access the application.

Run the following command to access the application by using a URL that contains /productpage. Replace YOUR-GATEWAY-IP with the IP address of the ingress gateway.

curl -X GET http://YOUR-GATEWAY-IP/productpage --user admin1:password -I

image desc

Run the following command to access the application by using a URL that contains /api/v1/products. Replace YOUR-GATEWAY-IP with the IP address of the ingress gateway.

curl -X GET http://YOUR-GATEWAY-IP/api/v1/products --user admin1:password -I

image desc

The results indicate that the admin role is assigned to the admin1 user. In addition, the admin1 user has the permissions to access the application by using a URL that contains /productpage or /api/v1/products.

6.4 Dynamically update an OPA policy

Go to the ASM console. Click YAML, as shown in the following figure.

image desc

Add the admin role to the role list of the guest1 user, and click OK, as shown in the following figure.

image desc

Run the following command to access the application as the guest1 user by using a URL that contains /api/v1/products. Replace YOUR-GATEWAY-IP with the IP address of the ingress gateway.

curl -X GET http://YOUR-GATEWAY-IP/api/v1/products --user guest1:password -I

image desc

Before the OPA policy is updated, the guest1 user can access the application by using a URL that contains /productpage, but not /api/v1/products. After the OPA policy is updated, the guest1 user can access the application by using a URL that contains /productpage or /api/v1/products. The results indicate that the OPA policy is dynamically updated.

Reminder:
Before you leave this lab, log out as the RAM user and click the Stop button of your lab session. Otherwise, issues may occur when you open a new lab session in the same browser.

image descimage desc

7. Experiment summary

This experiment 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 ASM. ASM is available for commercial use. ASM is a fully managed platform for service meshes and is compatible with the open source Istio service mesh. ASM allows you to manage services in a simplified manner and helps reduce your development and O&M costs. For example, you can use ASM to route and split inter-service traffic, secure inter-service communication based on authentication, and observe the behavior of services in meshes.