You are browsing documentation for an older version. See the latest documentation here.
MeshOPA - OPA Policy Integration
Warning: This policy uses the new policy matching algorithm, it should not be mixed with the OPA Policy.
MeshOPA policy plugin
Kong Mesh integrates the Open Policy Agent (OPA) to provide access control for your services.
The agent is included in the data plane proxy sidecar, instead of the more common deployment as a separate sidecar.
When the MeshOPA
policy is applied, the control plane configures the following:
- The embedded policy agent, with the specified policy
- Envoy, to use External Authorization that points to the embedded policy agent
TargetRef support matrix
TargetRef type | top level | to | from |
---|---|---|---|
Mesh | ✅ | ❌ | ❌ |
MeshSubset | ✅ | ❌ | ❌ |
MeshService | ✅ | ❌ | ❌ |
MeshServiceSubset | ✅ | ❌ | ❌ |
MeshGatewayRoute | ❌ | ❌ | ❌ |
To learn more about the information in this table, see the matching docs.
Configuration
To apply a policy with MeshOPA, you must do the following:
- Specify the group of data plane proxies to apply the policy to with the
targetRef
property. - Provide a policy with the
appendPolicies
property. Policies are defined in the Rego language. -
Optionally provide custom configuration for the policy agent.
Note: You cannot currently apply multiple OPA policies. This limitation will be addressed in the future.
You must also specify the HTTP protocol in your mesh configuration:
For more information, see the Kong Mesh documentation about protocol support.
Inline
With secrets
Encoding the policy in a Secret provides some security for policies that contain sensitive data.
Configuration
Kong Mesh defines a default configuration for OPA, but you can adjust the configuration to meet your environment’s requirements.
The following environment variables are available:
Variable | Type | What it configures | Default value {:width=25%:} |
---|---|---|---|
KMESH_OPA_ADDR | string | Address OPA API server listens on | localhost:8181 |
KMESH_OPA_CONFIG_PATH | string | Path to file of initial config | N/A |
KMESH_OPA_DIAGNOSTIC_ADDR | string | Address of OPA diagnostics server | 0.0.0.0:8282 |
KMESH_OPA_ENABLED | bool | Whether kuma-dp starts embedded OPA |
true |
KMESH_OPA_EXT_AUTHZ_ADDR | string | Address of Envoy External AuthZ service | localhost:9191 |
KMESH_OPA_CONFIG_OVERRIDES | strings | Overrides for OPA configuration, in addition to config file(*) | [plugins.envoy_ext_authz_grpc. query=data.envoy.authz.allow] |
Configuring the authorization filter
You can configure the external authorization filter by adjusting the authConfig
section.
By default, the body will not be sent to the agent.
To send it, set authConfig.requestBody.maxSize
to the maximum size of your body.
If the request body is larger than this parameter, it will be truncated and the header x-envoy-auth-partial-body
will be set to true
.
Support for external API management servers
The agentConfig
field lets you define a custom configuration that points to an external management server:
Example
The following example shows how to deploy and test a sample MeshOPA policy on Kubernetes, using the kuma-demo application.
-
Deploy the example application:
kubectl apply -f https://bit.ly/demokuma
-
Make a request from the frontend to the backend:
kubectl exec -i -t $(kubectl get pod -l "app=kuma-demo-frontend" -o jsonpath='{.items[0].metadata.name}' -n kuma-demo) -n kuma-demo -c kuma-fe -- curl backend:3001 -v
The output looks like:
Defaulting container name to kuma-fe. Use 'kubectl describe pod/kuma-demo-app-6787b4f7f5-m428c -n kuma-demo' to see all of the containers in this pod. * Trying 10.111.108.218:3001... * TCP_NODELAY set * Connected to backend (10.111.108.218) port 3001 (#0) > GET / HTTP/1.1 > Host: backend:3001 > User-Agent: curl/7.67.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < x-powered-by: Express < cache-control: no-store, no-cache, must-revalidate, private < access-control-allow-origin: * < access-control-allow-methods: PUT, GET, POST, DELETE, OPTIONS < access-control-allow-headers: * < host: backend:3001 < user-agent: curl/7.67.0 < accept: */* < x-forwarded-proto: http < x-request-id: 1717af9c-2587-43b9-897f-f8061bba5ad4 < content-length: 90 < content-type: text/html; charset=utf-8 < date: Tue, 16 Mar 2021 15:33:18 GMT < x-envoy-upstream-service-time: 1521 < server: envoy < * Connection #0 to host backend left intact Hello World! Marketplace with sales and reviews made with <3 by the OCTO team at Kong Inc.
-
Apply a MeshOPA policy that requires a valid JWT token:
echo " apiVersion: kuma.io/v1alpha1 kind: MeshOPA metadata: namespace: kong-mesh-system name: mopa-1 labels: kuma.io/mesh: default spec: targetRef: kind: Mesh default: appendPolicies: - inlineString: | package envoy.authz import input.attributes.request.http as http_request default allow = false token = {\"valid\": valid, \"payload\": payload} { [_, encoded] := split(http_request.headers.authorization, \" \") [valid, _, payload] := io.jwt.decode_verify(encoded, {\"secret\": \"secret\"}) } allow { is_token_valid action_allowed } is_token_valid { token.valid now := time.now_ns() / 1000000000 token.payload.nbf <= now now < token.payload.exp } action_allowed { http_request.method == \"GET\" token.payload.role == \"admin\" } " | kubectl apply -f -
-
Make an invalid request from the frontend to the backend:
kubectl exec -i -t $(kubectl get pod -l "app=kuma-demo-frontend" -o jsonpath='{.items[0].metadata.name}' -n kuma-demo) -n kuma-demo -c kuma-fe -- curl backend:3001 -v
The output looks like:
Defaulting container name to kuma-fe. Use 'kubectl describe pod/kuma-demo-app-6787b4f7f5-bwvnb -n kuma-demo' to see all of the containers in this pod. * Trying 10.105.146.164:3001... * TCP_NODELAY set * Connected to backend (10.105.146.164) port 3001 (#0) > GET / HTTP/1.1 > Host: backend:3001 > User-Agent: curl/7.67.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 403 Forbidden < date: Tue, 09 Mar 2021 16:50:40 GMT < server: envoy < x-envoy-upstream-service-time: 2 < content-length: 0 < * Connection #0 to host backend left intact
Note the
HTTP/1.1 403 Forbidden
message. The application doesn’t allow a request without a valid token.The policy can take up to 30 seconds to propagate, so if this request succeeds the first time, wait and then try again.
-
Make a valid request from the frontend to the backend.
Export the token into an environment variable:
export ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYWRtaW4iLCJzdWIiOiJZbTlpIiwibmJmIjoxNTE0ODUxMTM5LCJleHAiOjI1MjQ2MDgwMDB9.H0-42LYzoWyQ_4MXAcED30u6lA5JE087eECV2nxDfXo"
Make the request:
kubectl exec -i -t $(kubectl get pod -l "app=kuma-demo-frontend" -o jsonpath='{.items[0].metadata.name}' -n kuma-demo) -n kuma-demo -c kuma-fe -- curl -H "Authorization: Bearer $ADMIN_TOKEN" backend:3001
The output looks like:
Defaulting container name to kuma-fe. Use 'kubectl describe pod/kuma-demo-app-6787b4f7f5-m428c -n kuma-demo' to see all of the containers in this pod. * Trying 10.111.108.218:3001... * TCP_NODELAY set * Connected to backend (10.111.108.218) port 3001 (#0) > GET / HTTP/1.1 > Host: backend:3001 > User-Agent: curl/7.67.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < x-powered-by: Express < cache-control: no-store, no-cache, must-revalidate, private < access-control-allow-origin: * < access-control-allow-methods: PUT, GET, POST, DELETE, OPTIONS < access-control-allow-headers: * < host: backend:3001 < user-agent: curl/7.67.0 < accept: */* < x-forwarded-proto: http < x-request-id: 8fd7b398-1ba2-4c2e-b229-5159d04d782e < content-length: 90 < content-type: text/html; charset=utf-8 < date: Tue, 16 Mar 2021 17:26:00 GMT < x-envoy-upstream-service-time: 261 < server: envoy < * Connection #0 to host backend left intact Hello World! Marketplace with sales and reviews made with <3 by the OCTO team at Kong Inc.
The request is valid again because the token is signed with the
secret
private key, its payload includes the admin role, and it is not expired.