About

Gloo Mesh Enterprise can deploy an Open Policy Agent (OPA) server to run as a sidecar to its external auth service. After, you are responsible for administering the server per OPA best practices. You might choose this approach for larger scale environments and extended use cases such as bundling and caching.

With bundling, your Rego rules can live as a signed bundle in an external, central location, such as an AWS S3 bucket to meet your internal security requirements. This sidecar approach increases the resources needed in the external auth server pod, but works better at scale and provides more OPA-native support for teams familiar with administering an OPA server. You also get the OPA-Envoy plugin API as part of the Gloo external auth service.

For different setup options such as the default OPA or bring your own OPA, see OPA implementation optionsOPA implementation options.

Architecture

The following diagram and the steps in the rest of this guide show how you can set up an OPA server sidecar.

Figure: Architecture for deploying an OPA server sidecar.
Figure: Architecture for deploying an OPA server sidecar.
Figure: Architecture for deploying an OPA server sidecar.
Figure: Architecture for deploying an OPA server sidecar.

  1. A user sends a request that the ingress gateway receives. The request matches a route that is protected by an ExtAuthPolicy that uses OPA.
  2. The ingress gateway sends the request to the external auth service for an authorization decision.
  3. The external auth service passes the request through to the OPA server sidecar to make an authorization decision.
  4. The OPA server sidecar loads the OPA config of Rego rules from a bundle in a cloud provider. The OPA server uses these Rego rules to make an authorization decision on the request. You can provide the OPA config via a YAML file during the Helm installation, or subsequently in a Kubernetes config map. Note that the request does not trigger loading the rules. You must restart the OPA server each time that you update the OPA config.
  5. The OPA server returns the authorization decision to the external auth service, which returns the authorization decision to the ingress gateway.
  6. The ingress gateway handles the request per the authorization decision.
    • If unauthorized, the ingress gateway denies the request.
    • If authorized, the ingress gateway forwards the request to the destination workload.

Clear route cache

The Envoy proxy in your sidecar instance keeps a route cache in memory of precomputed routing decisions to help speed up performance. When the sidecar gets a request, it can check the route cache to decide where to send the request. When the route cache is cleared, Gloo recomputes the routing rules. This way, any old and potentially conflicting data from the initial request is cleared.

Before you begin

  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 meshctl CLI, 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.
  1. Install Bookinfo and other sample apps.

  2. Make sure that the external auth service is installed and running. If not, install the external auth service in your Gloo environment.

      kubectl get pods --context $REMOTE_CONTEXT1 -A -l app=ext-auth-service
      
  3. Download the opa CLI tool.

Bundle Rego rules

Prepare OPA configuration for the OPA server by creating, bundling, and referring to a Rego policy with the rules you want to enforce.

  1. Create a Rego policy file in a rego directory with the rules you want to enforce with OPA. The following policy allows GET and POST HTTP requests and denies requests to the /status endpoint.

      mkdir rego
    cat <<EOF > rego/policy.rego
    package httpbin
    
    import input.http_request
    
    # deny requests by default
    default allowed = false
    
    # set allowed to true if no error message
    allowed {
        not body
    }
    
    # return result and error message
    allow["allowed"] = allowed
    allow["body"] = body
    
    # main policy logic, with error message per rule
    body = "HTTP verb is not allowed" { not http_verb_allowed }
    else = "Path is not allowed" { not path_allowed }
    
    # allow only GET and POST requests
    http_verb_allowed {
       {"GET", "POST"}[_] == http_request.method
    }
    
    # deny requests to /status endpoint
    path_allowed {
       not startswith(http_request.path, "/status")
    }
    EOF
      
  2. Create another Rego policy. The following policy uses metadata that is enabled by the OPA-Envoy plugin API. This example shows how you can use OPA to evaluate and transform responses based on request metadata.

  • Check requests for an api-key header, with valid API keys either set to the test value of test-apikey or located in data.apikeys. The API keys in data.apikeys are loaded as part of the data bundle.
  • If the request is authorized, the api-key header is removed.
  • If the request is not authorized, the body is set to Unauthorized Request and returned to the client with a 403 status code, along with a reject-reason response header.
  • In both cases, the x-response-header is added.
  cat <<EOF > rego/apikey_policies.rego
package apikey_policies

import future.keywords.if

default allow := false

allow { api_key_allowed }

api_key_allowed { api_key == "test-apikey" } api_key_allowed { has_key(data.apikeys, api_key) }

api_key := input.http_request.headers["api-key"]

http_status := 200 { allow }

http_status := 403 { not allow }

body := "Unauthorized Request" { http_status == 403 }

headers["x-ext-auth-allow"] := "yes" if api_key_allowed headers["x-validated-by"] := "security-checkpoint" if api_key_allowed

request_headers_to_remove := ["api-key"]

response_headers_to_add["x-response-header"] := "for-client-only" response_headers_to_add["reject-reason"] := "unauthorized" if not allow

Helper function to check if a dictionary has a key

has_key(dict, k) { dict[k] } EOF

Use the `opa` CLI to bundle your Rego rules. The output of the command is a `bundle.tar.gz` compressed file in your current directory. For more information, see the [OPA docs](https://www.openpolicyagent.org/docs/latest/management-bundles/).