mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-10 15:47:36 +02:00
docs: add JWT Verification w/Envoy guide (#1974)
* docs: add JWT Verification w/Envoy guide * add sentence about usage, fix formatting of config
This commit is contained in:
parent
c99ceaef1d
commit
00a1cb7456
3 changed files with 231 additions and 2 deletions
|
@ -156,6 +156,7 @@ module.exports = {
|
||||||
"argo",
|
"argo",
|
||||||
"cloud-run",
|
"cloud-run",
|
||||||
"istio",
|
"istio",
|
||||||
|
"jwt-verification",
|
||||||
"kubernetes",
|
"kubernetes",
|
||||||
"kubernetes-dashboard",
|
"kubernetes-dashboard",
|
||||||
"local-oidc",
|
"local-oidc",
|
||||||
|
|
227
docs/guides/jwt-verification.md
Normal file
227
docs/guides/jwt-verification.md
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
---
|
||||||
|
title: JWT Verification
|
||||||
|
lang: en-US
|
||||||
|
meta:
|
||||||
|
- name: keywords
|
||||||
|
content: pomerium identity-access-proxy envoy jwt
|
||||||
|
description: >-
|
||||||
|
This example demonstrates how to verify the Pomerium JWT assertion header using Envoy.
|
||||||
|
---
|
||||||
|
|
||||||
|
# JWT Verification
|
||||||
|
This example demonstrates how to verify the [Pomerium JWT assertion header](https://www.pomerium.io/reference/#pass-identity-headers) using [Envoy](https://www.envoyproxy.io/). This is useful for legacy or 3rd party applications which can't be modified to perform verification themselves.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
- [Docker](https://www.docker.com/)
|
||||||
|
- [Docker Compose](https://docs.docker.com/compose/)
|
||||||
|
- [mkcert](https://github.com/FiloSottile/mkcert)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
Two services are configured in a `docker-compose.yaml` file:
|
||||||
|
|
||||||
|
- `pomerium` running an all-in-one deployment of Pomerium on `*.localhost.pomerium.io`
|
||||||
|
- `envoy-jwt-checker` running envoy with a JWT Authn filter
|
||||||
|
|
||||||
|
Once running, the user visits [verify.localhost.pomerium.io](https://verify.localhost.pomerium.io), is authenticated through [authenticate.localhost.pomerium.io](https://authenticate.localhost.pomerium.io), and then the HTTP request is sent to envoy which proxies it to [`verify.pomerium.com`](https://verify.pomerium.com).
|
||||||
|
|
||||||
|
Before allowing the request Envoy will verify the signed JWT assertion header using the public key defined by [authenticate.localhost.pomerium.io/.well-known/pomerium/jwks.json](https://authenticate.int.example.com/.well-known/pomerium/jwks.json).
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
### 1. Docker Compose
|
||||||
|
Create a `docker-compose.yaml` file containing:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: "3.8"
|
||||||
|
services:
|
||||||
|
pomerium:
|
||||||
|
image: pomerium/pomerium:latest
|
||||||
|
ports:
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ./cfg/pomerium.yaml
|
||||||
|
target: /pomerium/config.yaml
|
||||||
|
- type: bind
|
||||||
|
source: ./certs/_wildcard.localhost.pomerium.io.pem
|
||||||
|
target: /pomerium/_wildcard.localhost.pomerium.io.pem
|
||||||
|
- type: bind
|
||||||
|
source: ./certs/_wildcard.localhost.pomerium.io-key.pem
|
||||||
|
target: /pomerium/_wildcard.localhost.pomerium.io-key.pem
|
||||||
|
|
||||||
|
envoy-jwt-checker:
|
||||||
|
image: envoyproxy/envoy:v1.17.1
|
||||||
|
ports:
|
||||||
|
- "10000:10000"
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ./cfg/envoy.yaml
|
||||||
|
target: /etc/envoy/envoy.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Certificates
|
||||||
|
Using [`mkcert`](https://github.com/FiloSottile/mkcert) generate a certificate for `*.localhost.pomerium.io` in a `certs` directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir certs
|
||||||
|
cd certs
|
||||||
|
mkcert '*.localhost.pomerium.io'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Envoy Configuration
|
||||||
|
Create a `cfg` directory containing the following `envoy.yaml` file:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
admin:
|
||||||
|
access_log_path: /dev/null
|
||||||
|
address:
|
||||||
|
socket_address: { address: 127.0.0.1, port_value: 9901 }
|
||||||
|
|
||||||
|
static_resources:
|
||||||
|
listeners:
|
||||||
|
- name: ingress-http
|
||||||
|
address:
|
||||||
|
socket_address: { address: 0.0.0.0, port_value: 10000 }
|
||||||
|
filter_chains:
|
||||||
|
- filters:
|
||||||
|
- name: envoy.filters.network.http_connection_manager
|
||||||
|
typed_config:
|
||||||
|
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
|
||||||
|
stat_prefix: ingress_http
|
||||||
|
codec_type: AUTO
|
||||||
|
route_config:
|
||||||
|
name: verify
|
||||||
|
virtual_hosts:
|
||||||
|
- name: verify
|
||||||
|
domains: ["*"]
|
||||||
|
routes:
|
||||||
|
- match:
|
||||||
|
prefix: "/"
|
||||||
|
route:
|
||||||
|
cluster: egress-verify
|
||||||
|
auto_host_rewrite: true
|
||||||
|
http_filters:
|
||||||
|
- name: envoy.filters.http.jwt_authn
|
||||||
|
typed_config:
|
||||||
|
"@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
|
||||||
|
providers:
|
||||||
|
pomerium:
|
||||||
|
issuer: authenticate.localhost.pomerium.io
|
||||||
|
audiences:
|
||||||
|
- verify.localhost.pomerium.io
|
||||||
|
from_headers:
|
||||||
|
- name: X-Pomerium-Jwt-Assertion
|
||||||
|
remote_jwks:
|
||||||
|
http_uri:
|
||||||
|
uri: https://authenticate.localhost.pomerium.io/.well-known/pomerium/jwks.json
|
||||||
|
cluster: egress-authenticate
|
||||||
|
timeout: 1s
|
||||||
|
rules:
|
||||||
|
- match:
|
||||||
|
prefix: /
|
||||||
|
requires:
|
||||||
|
provider_name: pomerium
|
||||||
|
- name: envoy.filters.http.router
|
||||||
|
clusters:
|
||||||
|
- name: egress-verify
|
||||||
|
connect_timeout: 0.25s
|
||||||
|
type: STRICT_DNS
|
||||||
|
lb_policy: ROUND_ROBIN
|
||||||
|
load_assignment:
|
||||||
|
cluster_name: verify
|
||||||
|
endpoints:
|
||||||
|
- lb_endpoints:
|
||||||
|
- endpoint:
|
||||||
|
address:
|
||||||
|
socket_address:
|
||||||
|
address: verify.pomerium.com
|
||||||
|
port_value: 443
|
||||||
|
transport_socket:
|
||||||
|
name: tls
|
||||||
|
typed_config:
|
||||||
|
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
|
||||||
|
sni: verify.pomerium.com
|
||||||
|
- name: egress-authenticate
|
||||||
|
connect_timeout: '0.25s'
|
||||||
|
type: STRICT_DNS
|
||||||
|
lb_policy: ROUND_ROBIN
|
||||||
|
load_assignment:
|
||||||
|
cluster_name: authenticate
|
||||||
|
endpoints:
|
||||||
|
- lb_endpoints:
|
||||||
|
- endpoint:
|
||||||
|
address:
|
||||||
|
socket_address:
|
||||||
|
address: pomerium
|
||||||
|
port_value: 443
|
||||||
|
transport_socket:
|
||||||
|
name: tls
|
||||||
|
typed_config:
|
||||||
|
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
|
||||||
|
sni: authenticate.localhost.pomerium.io
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Envoy configuration can be quite verbose, but the crucial bit is the HTTP filter:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: envoy.filters.http.jwt_authn
|
||||||
|
typed_config:
|
||||||
|
"@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
|
||||||
|
providers:
|
||||||
|
pomerium:
|
||||||
|
issuer: authenticate.localhost.pomerium.io
|
||||||
|
audiences:
|
||||||
|
- verify.localhost.pomerium.io
|
||||||
|
from_headers:
|
||||||
|
- name: X-Pomerium-Jwt-Assertion
|
||||||
|
remote_jwks:
|
||||||
|
http_uri:
|
||||||
|
uri: https://authenticate.localhost.pomerium.io/.well-known/pomerium/jwks.json
|
||||||
|
cluster: egress-authenticate
|
||||||
|
timeout: 1s
|
||||||
|
rules:
|
||||||
|
- match:
|
||||||
|
prefix: /
|
||||||
|
requires:
|
||||||
|
provider_name: pomerium
|
||||||
|
```
|
||||||
|
|
||||||
|
This configuration pulls the JWT out of the `X-Pomerium-Jwt-Assertion` header, verifies the `iss` and `aud` claims and checks the signature via the public key defined at the `jwks.json` endpoint. Documentation for additional configuration options is available here: [Envoy JWT Authentication](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter#config-http-filters-jwt-authn).
|
||||||
|
|
||||||
|
### 4. Pomerium Configuration
|
||||||
|
Create a `pomerium.yaml` file in the `cfg` directory containing:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
authenticate_service_url: https://authenticate.localhost.pomerium.io
|
||||||
|
|
||||||
|
certificate_file: "/pomerium/_wildcard.localhost.pomerium.io.pem"
|
||||||
|
certificate_key_file: "/pomerium/_wildcard.localhost.pomerium.io-key.pem"
|
||||||
|
|
||||||
|
idp_provider: google
|
||||||
|
idp_client_id: REPLACE_ME
|
||||||
|
idp_client_secret: REPLACE_ME
|
||||||
|
|
||||||
|
cookie_secret: WwMtDXWaRDMBQCylle8OJ+w4kLIDIGd8W3cB4/zFFtg=
|
||||||
|
shared_secret: WwMtDXWaRDMBQCylle8OJ+w4kLIDIGd8W3cB4/zFFtg=
|
||||||
|
signing_key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUdxWllpVzJycVo3TUdKTGp4bnNZVWJJcmZxNFdwR044RlgzQVh2UnRjSHdvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFYVd1UkNKMjFrL2JvUjNNRytPOVlHQjNXR0R1anVXMHFLVWhucUVwVS9JKzFoZmhuZEJ0WApDZGFpaGVGb0FOWXVCRUp3MFZhRml6QnVZb3l5RVAzOXBRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
|
||||||
|
|
||||||
|
policy:
|
||||||
|
- from: https://verify.localhost.pomerium.io
|
||||||
|
to: http://envoy-jwt-checker:10000
|
||||||
|
allowed_domains:
|
||||||
|
- pomerium.com
|
||||||
|
pass_identity_headers: true
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
You will need to replace the identity provider credentials for this to work.
|
||||||
|
|
||||||
|
## Run
|
||||||
|
You should now be able to run the example with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
Visit [verify.localhost.pomerium.io](https://verify.localhost.pomerium.io), login and you see the Pomerium verify page. However, visiting Envoy directly via [localhost:10000](http://localhost:10000) should return a `Jwt is missing` error, thus requiring Pomerium to access Envoy.
|
|
@ -5,9 +5,10 @@ This section contains applications, and scenario specific guides for Pomerium.
|
||||||
- The [ad-guard](./ad-guard.md) recipe demonstrates how pomerium can be used to augment web applications that only support simplistic authorization mechanisms like basic-auth with single-sign-on driven access policy.
|
- The [ad-guard](./ad-guard.md) recipe demonstrates how pomerium can be used to augment web applications that only support simplistic authorization mechanisms like basic-auth with single-sign-on driven access policy.
|
||||||
- The [argo](./argo.md) guide demonstrates how pomerium can be used to add access control to [Argo](https://argoproj.github.io/projects/argo).
|
- The [argo](./argo.md) guide demonstrates how pomerium can be used to add access control to [Argo](https://argoproj.github.io/projects/argo).
|
||||||
- The [Cloud Run](./cloud-run.md) recipe demonstrates deploying pomerium to Google Cloud Run as well as using it to Authorize users to protected Cloud Run endpoints.
|
- The [Cloud Run](./cloud-run.md) recipe demonstrates deploying pomerium to Google Cloud Run as well as using it to Authorize users to protected Cloud Run endpoints.
|
||||||
- The [Kubernetes Dashboard](./kubernetes-dashboard.md) guide covers how to secure Kubernetes dashboard using Pomerium.
|
- The [JWT Verification](./jwt-verification.md) guide demonstrates how to verify the Pomerium JWT assertion header using Envoy.
|
||||||
|
- The [Kubernetes Dashboard](./kubernetes-dashboard.md) guide covers how to secure Kubernetes dashboard using Pomerium.
|
||||||
- The [kubernetes](./kubernetes.md) guide covers how to add authentication and authorization to kubernetes dashboard using helm, and letsencrypt certificates. This guide also shows how third party reverse-proxies like nginx/traefik can be used in conjunction with pomerium using forward-auth.
|
- The [kubernetes](./kubernetes.md) guide covers how to add authentication and authorization to kubernetes dashboard using helm, and letsencrypt certificates. This guide also shows how third party reverse-proxies like nginx/traefik can be used in conjunction with pomerium using forward-auth.
|
||||||
- The [local OIDC](./local-oidc.md) guide demonstrates how pomerium can be used with local OIDC server for dev/testing.
|
- The [local OIDC](./local-oidc.md) guide demonstrates how pomerium can be used with local OIDC server for dev/testing.
|
||||||
- The [mTLS](./mtls.md) guide demonstrates how pomerium can be used to add mutual authentication using client certificates and a custom certificate authority.
|
- The [mTLS](./mtls.md) guide demonstrates how pomerium can be used to add mutual authentication using client certificates and a custom certificate authority.
|
||||||
- The [TiddlyWiki](./tiddlywiki.md) guide demonstrates how pomerium can be used to add authentication and authorization to web application using authenticated header.
|
- The [TiddlyWiki](./tiddlywiki.md) guide demonstrates how pomerium can be used to add authentication and authorization to web application using authenticated header.
|
||||||
- The [visual studio code](./vs-code-server.md) guide demonstrates how pomerium can be used to add access control to third-party applications that don't ship with [fine-grained access control](https://github.com/cdr/code-server/issues/905).
|
- The [visual studio code](./vs-code-server.md) guide demonstrates how pomerium can be used to add access control to third-party applications that don't ship with [fine-grained access control](https://github.com/cdr/code-server/issues/905).
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue