Access policy
Control access for workloads in your service mesh.
For example, you might want to enforce a “zero trust” network model for all of your services. In your workspace settings, you can enable service isolation so that only services within the same workspace (or imported workspaces) can communicate with each other. For even more control, you can set up access policies. With access policies, you can deny all access to a specific destination except for the clients that you explicitly allow.
This guide shows you how to set up Gloo access policies to restrict incoming or outgoing traffic on Layer 4 for an endpoint to a specific port and protocol. For example, you can allow incoming TCP traffic on port 3000 only.
For more information, see the following resources.
- Gloo Mesh (Gloo Platform APIs) API docs
- Getting started guide for service isolation
- Istio docs for authorization policy
Before you begin
Complete the multicluster getting started guide to set up the following testing environment.
- Three clusters along with environment variables for the clusters and their Kubernetes contexts.
- The Gloo
meshctlCLI, along with other CLI tools such askubectlandistioctl. - The Gloo management server in the management cluster, and the Gloo agents in the workload clusters.
- Istio installed in the workload clusters.
- A simple Gloo workspace setup.
- Install Bookinfo and other sample apps.
Configure access policies
You can apply an access policy at the workload or destination level. For more information, see Applying policies.
The following example is for a simple access policy that allows only the productpage app to access the ratings app. Keep in mind that the applyToWorkloads selector in the example does not work if you enable service isolation in your workspace.
apiVersion: security.policy.gloo.solo.io/v2
kind: AccessPolicy
metadata:
name: ratings-access
namespace: bookinfo
spec:
applyToWorkloads:
- selector:
labels:
app: ratings
config:
authn:
tlsMode: STRICT
authzList:
- allowedClients:
- serviceAccountSelector:
labels:
account: productpage
allowedPaths:
- /ratings*The following example is for a simple access policy that allows only the productpage app to access the ratings app. When comparing this access policy to the access policy that uses a workload selector, the destination selector also lets you specify the port number of the target app.
apiVersion: security.policy.gloo.solo.io/v2
kind: AccessPolicy
metadata:
name: ratings-access
namespace: bookinfo
spec:
applyToDestinations:
- port:
number: 9080
selector:
labels:
app: ratings
config:
authn:
tlsMode: STRICT
authzList:
- allowedClients:
- serviceAccountSelector:
labels:
account: productpage
allowedPaths:
- /ratings*The following access policy specifies the request headers that must be sent to allow or deny the communication between the productpage and ratings apps. For example, if you send a request with the X-Test-Header: match header from the productpage app to the ratings app, the request is matched and the communication between productpage and ratings is allowed. If you send the same request without a header or with the X-Test-Header: noMatch header, the request is not matched and the communication between the apps is denied.
apiVersion: security.policy.gloo.solo.io/v2
kind: AccessPolicy
metadata:
name: ratings-access
namespace: bookinfo
spec:
applyToDestinations:
- port:
number: 9080
selector:
labels:
app: ratings
config:
authn:
tlsMode: STRICT
authzList:
- allowedClients:
- serviceAccountSelector:
labels:
account: productpage
allowedPaths:
- /ratings*
match:
request:
headers:
X-Test-Header:
notValues:
- noMatch
- partial-blocked
values:
- match
- partial*The following example specifies the IP address that you want to allow access to the ratings app. When a client sends a request to ratings, the client’s IP address is matched against the IP addresses that are defined in the access policy. If the IP address matches, the request is forwarded to the ratings app. If the IP does not match, access to ratings is denied.
You can specify single IP addresses (e.g. 111.123.2.0) or an IP address CIDR block (e.g. 123.222.167.4/24).
Keep in mind that the applyToWorkloads selector in the example does not work if you enable service isolation in your workspace.
apiVersion: security.policy.gloo.solo.io/v2
kind: AccessPolicy
metadata:
name: ratings-access
namespace: bookinfo
spec:
applyToWorkloads:
- selector:
labels:
app: ratings
config:
authn:
tlsMode: STRICT
authzList:
- allowedIpBlocks:
- 112.114.230.1
allowedPaths:
- /ratings*You can have multiple authzList entries to configure access to workloads. A request is allowed when it matches at least one of the authzList entries (logically OR’d together).
For each entry, you can specify different requirements for allowed clients, paths, methods, IP blocks, and other configuration settings. Then, a request is allowed only when ALL of the requirements are met (logically AND’d together).
In the following example:
- The product page app is allowed to send GET requests to the ratings app along the
/ratings*wildcard path. - The product page app is allowed to send CREATE, DELETE, PATCH, and POST requests to the ratings app along the
/ratings/1*wildcard path. - The product page app is allowed to send PATCH requests to the ratings app along the
/ratings/2*wildcard path. - Keep in mind that the
applyToWorkloadsselector in the example does not work if you enable service isolation in your workspace.
apiVersion: security.policy.gloo.solo.io/v2
kind: AccessPolicy
metadata:
name: ratings-access
namespace: bookinfo
spec:
applyToWorkloads:
- selector:
labels:
app: ratings
config:
authn:
tlsMode: STRICT
authzList:
- allowedClients:
- serviceAccountSelector:
labels:
app: productpage
allowedPaths:
- /ratings*
allowedMethods:
- GET
- allowedClients:
- serviceAccountSelector:
labels:
app: productpage
allowedPaths:
- /ratings/1*
allowedMethods:
- CREATE
- DELETE
- PATCH
- POST
- allowedClients:
- serviceAccountSelector:
labels:
app: productpage
allowedPaths:
- /ratings/2*
allowedMethods:
- PATCHYou can have multiple allowed clients in the same access policy. A request is allowed when it matches at least one of the authzList entries (logically OR’d together).
For each client, you can specify different requirements for allowed paths, methods, IP blocks, and other configuration settings. Then, a request is allowed only when ALL of the requirements are met (logically AND’d together).
In the following example:
- The product page app is allowed to access the ratings app along the
/ratings*wildcard path. - The reviews app is allowed to access the ratings app for requests that use the PATCH method.
- Keep in mind that the
applyToWorkloadsselector in the example does not work if you enable service isolation in your workspace.
apiVersion: security.policy.gloo.solo.io/v2
kind: AccessPolicy
metadata:
name: ratings-access
namespace: bookinfo
spec:
applyToWorkloads:
- selector:
labels:
app: ratings
config:
authn:
tlsMode: STRICT
authzList:
- allowedClients:
- serviceAccountSelector:
labels:
app: productpage
allowedPaths:
- /ratings*
- allowedClients:
- serviceAccountSelector:
labels:
app: reviews
allowedMethods:
- PATCHReview the following table to understand this configuration. For more information, see the API docs.
| Setting | Description |
|---|---|
applyToDestinations or applyToWorkloads | Use labels to apply the policy to destinations. Destinations might be a Kubernetes service, VirtualDestination, or ExternalService (if supported by the policy). If you do not specify any destinations or routes, the policy applies to all destinations in the workspace by default. If you do not specify any destinations but you do specify a route, the policy applies to the route but to no destinations. Note that for security reasons, applyToWorkloads is preferred. However, the applyToWorkloads selector does not work if you enable service isolation in your workspace. |
authn | For authentication, set the type of TLS policy to enforce when connecting to the workload. STRICT secures connections to the upstream workload with mTLS by presenting client certificates for authentication. If you set up service isolation for the workspace, this setting is always set to STRICT. Other modes include PERMISSIVE to allow both TLS-secured and plain text connections to the upstream endpoint, or DISABLE to not set up a TLS connection to the upstream endpoint. |
authzList | Configure how clients are allowed to access the workload. You can have multiple allowed clients in the same access policy, as well as multiple configurations for the same client. A request is allowed when it matches at least one of the entries in this authzList field (logically OR’d together). |
allowedClients | Configure which clients are permitted to access the workload. In this example, the allowed clients are restricted to the product page app, as selected by the label of its Kubernetes service account. |
allowedIpBlocks | Specify the IP address or IP address CIDR that you want to allow access to the workload. |
allowedPaths | Optionally, you can restrict which path to allow. For HTTP paths, exact match, prefix match, and suffix match are supported. In this example, requests are restricted to the suffix match path /ratings*. |
allowedMethods | Optionally, you can restrict the HTTP methods to allow, such as GET or POST. If the request is made via gRPC, this value is ignored because the method is always POST. In this example, no method is set, so all methods are allowed by default. |
match | Define the requirements that must be met to match the request and enforce the policy. |
request.headers | Specify the request headers that must be sent to allow or deny communication between the allowedClients and the workload that you specified. If a header is sent that is specified in the values section, the header is matched and the request is allowed. Headers in the notValues section are not allowed, and requests that include this header are denied. |
Verify access policies
Create a temporary curl pod and send a request to the ratings app from your local machine. Use the
kubectl debugcommand to create an ephemeral curl container in the deployment. This way, the curl container inherits any permissions from the app that you want to test. The communication from your local machine to the ratings app is allowed as no access policy is applied yet.kubectl --context ${REMOTE_CONTEXT1} -n bookinfo debug -i pods/$(kubectl get pod --context ${REMOTE_CONTEXT1} -l app=reviews -A -o jsonpath='{.items[0].metadata.name}') --image=curlimages/curl -- curl -v http://ratings:9080/ratings/1Example output:
HTTP/1.1 200 OK ... {"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}If the output has an error about
EphemeralContainers, see Ephemeral containers don’t work when testing Bookinfo.Apply one of the access policies. The access policy allows access to the ratings app from the product page app. Requests from all other clients are denied.
kubectl apply -f policy.yamlVerify that requests from a temporary curl pod are now blocked. You get back a
403 Forbiddenresponse.kubectl --context ${REMOTE_CONTEXT1} -n bookinfo debug -i pods/$(kubectl get pod --context ${REMOTE_CONTEXT1} -l app=productpage -A -o jsonpath='{.items[0].metadata.name}') --image=curlimages/curl -- curl -v http://ratings:9080/ratings/1If the output has an error about
EphemeralContainers, see Ephemeral containers don’t work when testing Bookinfo.Verify that the productpage app can access the ratings app. Note that if you created an access policy with request header matching, you must provide the
X-Test-Header: <header-value>in your curl request.kubectl --context ${REMOTE_CONTEXT1} -n bookinfo debug -i pods/$(kubectl get pod --context ${REMOTE_CONTEXT1} -l app=productpage -A -o jsonpath='{.items[0].metadata.name}') --image=curlimages/curl -- curl -v http://ratings:9080/ratings/1Example output:
HTTP/1.1 200 OK ... {"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}Check the metrics to verify that the policy allowed or blocked requests.
- Open the Prometheus expression browser.
For more information, see the CLI documentation.
meshctl proxy prometheusPort-forward the
prometheus-serverdeployment on 9091.kubectl -n gloo-mesh port-forward deploy/prometheus-server 9091 - Open your browser and connect to localhost:9091/.
- In the Expression search bar, enter
rate(hubble_drop_total{destination_workload_id=~"ratings.+"}[5m]), then click Execute. - Verify that you can see requests from the temporary curl pod to the ratings app that were dropped because of the access policy.
- Open the Prometheus expression browser.
Cleanup
You can optionally remove the resources that you set up as part of this guide.
kubectl --context $REMOTE_CONTEXT1 -n bookinfo delete accesspolicy ratings-access