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