Skip to main content
logoTetrate Enterprise Gateway for Envoy (TEG)Version: v1.1.x

Secure Your App

OIDC

TEG offers seamless single sign-on (SSO) integration through OIDC. With TEG, you can effortlessly link your application to any OIDC identity provider using the straightforward SecurityPolicy. This enables instant authentication for your application, all without the need to make any code modifications. See the upstream guide for details.

Authorization

The upstream guide details authentication: users are required to prove who they are.

You may also wish to authorize users; to make access control decisions based on details provided by the OIDC IdP (Identity Provider). When the user has been authenticated by the gateway, several pieces of information are known about them, probably including their name and email address, and possibly custom info from the Identity Provider like group memberships or an admin flag. The OIDC provider sends this info to TEG in a format called a JWT. TEG forwards that JWT to your service so that your code can inspect it and make its own authorization decisions.

JWT

TEG can also authenticate using "raw" JWTs; if your clients provide JWTs in the Authentication header, rather than them being injected by an OIDC flow. See the upstream guide for details.

Authorization

As with OIDC-sourced JWTs, your apps are free to inspect them to make authorization decisions.

In addition, when directly configuring JWT authentication, there are a few more settings we can change. One of these causes headers to be injected into the request from values ("claims") in the JWT. This can make it easier for your apps to access these values, include them in access logs, etc. Header injection is configured in the SecurityPolicy resource thus:

kind: SecurityPolicy
...
spec:
...
jwt:
providers:
- ...
claimToHeaders:
- claim: sub
header: x-claim-subject
- claim: name
header: x-claim-name

Complex Authorization Policy with OPA

Open Policy Agent (OPA) is a powerful and flexible policy engine. It takes policy documents in the Rego language, applying their rules to any given input parameters to make policy decisions. TEG can defer to an OPA server to make complex authorization (authz) decisions, passing request info to OPA and encoding the authz policy in Rego.

This section will take you through configuring TEG to act in this way.

Prerequisites

Get a Kubernetes cluster, install TEG, deploy an example app, and expose it, following the instructions. Basic familiarity with OPA and Rego is assumed.

Install and Configure OPA

For this demo example, we'll be deploying our OPA Rego policy in a Secret and mounting that as a volume into the OPA Pod. This is not a production-grade setup, but will work for a demo. Because of this, we need to deploy the Secret first, so that the Pod can mount it at startup.

OPA Policy

This example policy allows only requests to the /headers path. Save it to your local machine as policy.rego (this name is important)

package envoy.authz

import input.attributes.request.http as http_request

default allow = false

allow {
action_allowed
}

action_allowed {
http_request.path == "/headers"
}

We'll now deploy that file to Kubernetes as a Secret resource.

kubectl create secret generic opa-policy --from-file policy.rego

OPA Server + Envoy Plugin

The following resources will run an OPA daemon, with the Envoy ext_authz API plugin pre-configured. This plugin serves policy decisions over the Envoy ext_authz API, which is not OPA's default, but is how the Envoy proxies in the TEG dataplane (ie the members of the gateways) talk to external authorization providers.

The resources also expose the OPA daemon as a Service within the cluster. Note how the Deployment mounts in our Rego policy.

apiVersion: apps/v1
kind: Deployment
metadata:
name: opa
labels:
app: opa
spec:
replicas: 1
selector:
matchLabels:
app: opa
template:
metadata:
labels:
app: opa
spec:
containers:
- name: opa
image: openpolicyagent/opa:0.62.1-envoy-5-rootless
volumeMounts:
- readOnly: true
mountPath: /policy
name: opa-policy
args:
- "run"
- "--server"
- "--addr=0.0.0.0:8181"
- "--set=plugins.envoy_ext_authz_grpc.addr=0.0.0.0:9191"
- "--set=plugins.envoy_ext_authz_grpc.query=data.envoy.authz.allow"
- "--set=decision_logs.console=true"
- "--ignore=.*"
- "/policy/policy.rego"
volumes:
- name: opa-policy
secret:
secretName: opa-policy
---
apiVersion: v1
kind: Service
metadata:
name: opa
spec:
selector:
app: opa
ports:
- name: grpc
protocol: TCP
port: 9191
targetPort: 9191

Apply OPA Policy-Enforcement to httpbin

Now we can tell EG to call out to that OPA service for auth decisions when clients request the httpbin service.

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: httpbin-opa-authz
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: httpbin
extAuth:
grpc:
backendRef:
name: opa
port: 9191

Test

We should now see that requests to the previously-working /get path are rejected as unauthorized:

curl -i localhost:8080/get

However we can still access the /headers path, which is within policy:

curl -i localhost:8080/headers

If you wish to dive further in, you can see OPA's logs of its authz decisions:

kubectl logs deployment/opa | jq