Access

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.

For more information, see the following resources.

If you import or export resources across workspaces, your policies might not apply. For more information, see Import and export policies.

Before you begin

This guide assumes that you use the same names for components like clusters, workspaces, and namespaces as in the getting started. If you have different names, make sure to update the sample configuration files in this guide.
  1. 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 Platform CLI, meshctl, along with other CLI tools such as kubectl and istioctl.
    • 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.
  2. Install Bookinfo and other sample apps.

Configure access policies

You can apply an access policy at the destination or workload level. For more information, see Applying policies.

When you create the policy with a destination selector, only Kubernetes services can be specified in the applyToDestination section. Gloo virtual destinations or Gloo external services are not supported.

Note that the applyToWorkloads selector does not work when you enable service isolation in your workspace.

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
    authz:
      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
    authz:
      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
    authz:
      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
    authz:
      allowedIpBlocks:
      - 112.114.230.1
      allowedPaths:
      - /ratings*

Review the following table to understand this configuration. For more information, see the API docs.

Setting Description
applyToDestinations or applyToWorkloads Configure which destinations to apply the policy to, by using labels. Destinations can be a Kubernetes service, VirtualDestination, or ExternalService. 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 destination. 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.
authz Set up which clients are permitted to access the destination.
allowedClients Configure which clients are permitted to access the destination. 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 destination.
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 destination 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

  1. Create a temporary curl or debug pod and send a request to the ratings app from your local machine. The communication from your local machine to the ratings app is allowed as no access policy is applied yet.

    Create a temporary curl pod in the bookinfo namespace, so that you can test the app setup. You can also use this method in Kubernetes 1.23 or later, but an ephemeral container might be simpler, as shown in the other tab.

    1. Create the curl pod.

      kubectl run -it -n bookinfo --context $REMOTE_CONTEXT1 curl \
        --image=curlimages/curl:7.73.0 --rm  -- sh
      
    2. Send a request to the ratings app.

      curl http://ratings:9080/ratings/1 -w "${http_code}"
      

      Example output:

      {"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}200
      
    3. Exit the temporary pod. The pod deletes itself.

      exit
      

    Use the kubernetes debug command 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. If you don't run Kubernetes 1.23 or later, you can deploy a separate curl pod or manually add the curl container as shown in the other tab.

    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/1
    

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

  2. Apply one of the access policies. The access policy allows access to the ratings app from only the product page app. Requests from all other clients are denied.

    kubectl apply -f policy.yaml
    
  3. Verify that requests from a temporary curl or debug pod are now blocked. You get back a 403 Forbidden response.

    Create a temporary curl pod in the bookinfo namespace, so that you can test the app setup. You can also use this method in Kubernetes 1.23 or later, but an ephemeral container might be simpler, as shown in the other tab.

    1. Create the curl pod.

      kubectl run -it -n bookinfo --context $REMOTE_CONTEXT1 curl \
        --image=curlimages/curl:7.73.0 --rm  -- sh
      
    2. Send a request to the ratings app.

      curl http://ratings:9080/ratings/1 -w "${http_code}"
      

      Example output:

      RBAC: access denied
      
    3. Exit the temporary pod. The pod deletes itself.

      exit
      

    Use the kubernetes debug command 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. If you don't run Kubernetes 1.23 or later, you can deploy a separate curl pod or manually add the curl container as shown in the other tab.

    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/1
    

    If the output has an error about EphemeralContainers, see Ephemeral containers don’t work when testing Bookinfo.

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

    Add a curl container to your app deployment so that you can test the app setup. You can also use this method in Kubernetes 1.23 or later, but an ephemeral container might be simpler, as shown in the other tab.

    1. Create the curl container.
      kubectl apply --context ${REMOTE_CONTEXT1} -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/productpage-with-curl.yaml
      
    2. Verify that requests now succeed. You get back a 200 response.
      kubectl exec $(kubectl get pod -l app=productpage -A --context ${REMOTE_CONTEXT1}  -o jsonpath='{.items[0].metadata.name}') -n bookinfo -c curl --context ${REMOTE_CONTEXT1} -- curl -v http://ratings:9080/ratings/1
      
    3. Exit the temporary pod. The pod deletes itself.
      exit
      

    Use the kubernetes debug command 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. If you don't run Kubernetes 1.23 or later, you can deploy a separate curl pod or manually add the curl container as shown in the other tab.

    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/1
    

    Example output:

    HTTP/1.1 200 OK
    ...
    {"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}
    

Cleanup

You can optionally clean up the resources that you created.

kubectl --context $REMOTE_CONTEXT1 -n bookinfo delete accesspolicy ratings-access