Alibaba Cloud Service Mesh (ASM) integrates with Open Policy Agent (OPA). You can
use OPA to define access control policies to implement fine-grained access control
on your applications. ASM instances of v1.8.6.41 and later allow you to create ConfigMaps
to automatically push OPA policies to containers. This way, the OPA policies can be
dynamically updated. This topic describes how to dynamically update OPA policies in
ASM.
Background information
OPA is an incubation-level project that is managed by
Cloud Native Computing Foundation (CNCF). As a policy engine, OPA can be used 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 each request coming to a microservice is authorized
before the request can be processed. To check the authorization, the microservice
makes an API call to OPA to decide whether the request is authorized.

Step 1: Enable OPA
- Log on to the ASM console.
- In the left-side navigation pane, choose .
- 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.
- In the Basic Information section, click Settings in the upper-right corner.
- In the Settings Update panel, select Enable OPA Plug-in.
- Click OK.
In the Basic Information section, you can find that the status in the OPA Plug-in field changes to Enabled.
Step 2: Create ConfigMaps
ASM supports the dynamic update of OPA policies. You can create a ConfigMap that contains
the
openpolicyagent.org/policy=rego
label to define an OPA policy. The OPA policy is then automatically pushed to the
pods that are injected with an OPA sidecar container in all namespaces. If you delete
the ConfigMap, the OPA policy is also deleted from the pods.
Notice
- When you define OPA policies for a pod, make sure that only one OPA policy contains
the
default allow
field. If the ConfigMaps of multiple OPA policies apply to a pod and the default allow
field is defined in each OPA policy, the OPA policies fail to be dynamically updated
due to the multiple default allow
fields.
- The startup of an OPA sidecar container relies on a ConfigMap that is named opa-policy.
If you delete the ConfigMap, the OPA policy that the ConfigMap defines is also deleted
from the OPA sidecar container. If you recreate the ConfigMap, the deleted OPA policy
is not restored. To use the OPA policy again, you must recreate the pods to which
the OPA policy is originally pushed.
- Specify the KubeConfig credential type. For more information, see Connect to an ACK cluster by using kubectl.
- Create a ConfigMap that is named opa-policy.
The startup of an OPA sidecar container relies on a ConfigMap that is named opa-policy.
The ConfigMap supports the dynamic update of OPA policies. We recommend that you configure
only basic policy settings in the ConfigMap. You can create other ConfigMaps to configure
complex policy settings.
- Use the following content to create a YAML file that is named opa-policy:
apiVersion: v1
kind: ConfigMap
metadata:
name: opa-policy
data:
policy.rego: | ### The dynamic push of OPA policies relies on the paths that are allowed in the ConfigMap. If you do not specify the paths in the ConfigMap, OPA policies fail to be dynamically updated.
package istio.authz
import input.parsed_path
allow {
parsed_path[0] = "v1"
parsed_path[1] = "policies"
}
- Run the following command to create the ConfigMap:
kubectl apply -f opa-policy.yaml
- Create a ConfigMap that is named opa-policy-add.
Use the ConfigMap to define an OPA policy.
- Use the following content to create a YAML file that is named opa-policy-add:
apiVersion: v1
kind: ConfigMap
metadata:
name: opa-policy-add
labels:
### You must configure the following label in the ConfigMap. Otherwise, the OPA policy that the ConfigMap defines cannot be dynamically updated.
openpolicyagent.org/policy: rego
data:
policy.rego: | ### The following code shows the definition of a sample policy. Define a policy based on your actual needs.
package istio.authz
import input.attributes.request.http as http_request
default allow = false
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"},
],
}
- user_roles: assigns roles to users. In this example, assign the guest role to the
guest1 user and the admin role to the admin1 user.
- role_perms: specifies the permissions of each role. In this example, grant the guest
role the permissions to access an application by using a URL that contains /productpage, and grant the admin role the permissions to access an application by using a URL
that contains /productpage or /api/v1/products.
- Run the following command to create the ConfigMap:
kubectl apply -f opa-policy-add.yaml
- Run the following command to view the policy push result:
The policy push result is recorded in the
annotations
parameter in the ConfigMap.
kubectl get configmap opa-policy-add -o yaml
View the ConfigMap in the command output:
Step 3: Inject an OPA sidecar
Deploy the sample application Bookinfo in the ASM instance and check whether an OPA
sidecar is injected into each pod of the Bookinfo application.
- Deploy the Bookinfo application in the ASM instance. For more information, see Deploy an application in an ASM instance.
- Define Istio virtual services and an ingress gateway service as required. For more
information, see Define Istio resources.
- Check whether an OPA sidecar is injected into the pods of each application in the
Bookinfo application.
- Log on to the ACK console.
- In the left-side navigation pane of the ACK console, click Clusters.
- On the Clusters page, find the cluster that you want to manage and click the name of the cluster
or click Details in the Actions column. The details page of the cluster appears.
- In the left-side navigation pane of the details page, choose .
- At the top of the Pods page, select default from the Namespace drop-down list. Click the pod name of an application.
On the
Container tab, you can find that a sidecar proxy that is named istio-proxy and an OPA sidecar
that is named opa-istio are injected into each container. Check the containers of
each application in turn to ensure that the sidecar proxy and OPA sidecar are injected
into each container.

Step 4: Verify that an OPA policy implements access control as expected
- Run the following cURL commands. 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.
curl -X GET http://{{The IP address of the ingress gateway service}}/productpage --user guest1:password -I
The following output is expected:
HTTP/1.1 200 OK
curl -X GET http://{{The IP address of the ingress gateway service}}/api/v1/products --user guest1:password -I
The following output is expected:
HTTP/1.1 403 Forbidden
- Run the following cURL commands. 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.
curl -X GET http://{{The IP address of the ingress gateway service}}/productpage --user admin1:password -I
The following output is expected:
HTTP/1.1 200 OK
curl -X GET http://{{The IP address of the ingress gateway service}}/api/v1/products --user admin1:password -I
The following output is expected:
HTTP/1.1 200 OK
The preceding results indicate that the defined OPA policy implements access control
as expected.
Step 5: Dynamically update an OPA policy
- Run the following command on the ACK cluster to update the ConfigMap that is named
opa-policy-add:
kubectl replace -n {The namespace where the ACK cluster resides} -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: opa-policy-add
labels:
### You must configure the following label in the ConfigMap. Otherwise, the OPA policy that the ConfigMap defines cannot be dynamically updated.
openpolicyagent.org/policy: rego
data:
policy.rego: | ### The following code shows the definition of a sample policy. Define a policy based on your actual needs.
package istio.authz
import input.attributes.request.http as http_request
default allow = false
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", "admin"],
"admin1": ["admin"]
}
role_perms = {
"guest": [
{"method": "GET", "path": "/productpage"},
],
"admin": [
{"method": "GET", "path": "/productpage"},
{"method": "GET", "path": "/api/v1/products"},
],
}
EOF
- user_roles: assigns roles to users. In this example, assign the guest and admin roles
to the guest1 user and the admin role to the admin1 user.
- role_perms: specifies the permissions of each role. In this example, grant the guest
role the permissions to access an application by using a URL that contains /productpage, and grant the admin role the permissions to access an application by using a URL
that contains /productpage or /api/v1/products.
- Run the following command to view the policy push result:
The policy push result is recorded in the
annotations
parameter in the ConfigMap.
kubectl get configmap opa-policy-add -o yaml
View the ConfigMap in the command output:
Step 6: Verify that an OPA policy is dynamically updated
Run the following cURL commands. The results indicate that the admin 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 or /api/v1/products.
curl -X GET http://{{The IP address of the ingress gateway service}}/productpage --user guest1:password -I
The following output is expected:
HTTP/1.1 200 OK
curl -X GET http://{{The IP address of the ingress gateway service}}/api/v1/products --user guest1:password -I
The following output is expected:
HTTP/1.1 200 OK
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 result indicates that the OPA policy is dynamically updated.