summaryrefslogtreecommitdiff
path: root/share/man/ENVOY.md
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-05-26 13:25:15 -0600
committermo khan <mo@mokhan.ca>2025-05-26 13:25:15 -0600
commit33a50904d80028fa06915987570800c5957e3167 (patch)
tree1f30ce1c7b1875281c503097d44da8d6673abb21 /share/man/ENVOY.md
parent1880ebcc4a59adfc8f16378cc10955bbbb52ed73 (diff)
docs: add a sequence diagram of the envoy architecture
Diffstat (limited to 'share/man/ENVOY.md')
-rw-r--r--share/man/ENVOY.md77
1 files changed, 75 insertions, 2 deletions
diff --git a/share/man/ENVOY.md b/share/man/ENVOY.md
index cbbf8ff..2eaa141 100644
--- a/share/man/ENVOY.md
+++ b/share/man/ENVOY.md
@@ -177,7 +177,7 @@ and send that message to me. Only I can decrypt that message using my private
key. This ensures confidentiality so that the ciphertext produced can be snooped
by anyone but only the recipient can convert the ciphertext back into plaintext.
-### Authenticity
+#### Authenticity
To ensure that a message originated from the entity that claims to have sent the
message an additional signature can be appended to the message. The signature
@@ -188,7 +188,7 @@ then they can decrypt the signature using the public key of the sender. If
signature can be decrypted without an error then we can trust that the message
did in fact originate from the sender. This authenticates the message.
-### Integrity
+#### Integrity
When a recipient receives a message from a sender the recipient also needs to
verify that the message wasn't altered. If the signature of the message includes
@@ -268,3 +268,76 @@ across services to allow the service to know who is logged in but each service
should have its own access token for each user based on the permissions that the
service declares that it needs and the permissions that the user agrees to give
it. I need to say this again because understanding this is crucial!
+
+## Envoy Architecture
+
+Given all the concerns listed above this is where Envoy shines. It can be used
+to take care of Authentication via an OpenID Connect transaction by slightly
+abusing the built-in `envoy.filters.http.oauth2` HTTP filter. It can also be
+used to validate any incoming JWTs via the `envoy.filters.http.jwt_authn` HTTP
+filter. Finally, we can use the `envoy.filters.http.ext_authz` HTTP filter to
+delegate authorization decisions to an external policy decision point (PDP).
+
+I wrote Sparkle as a proof-of-concept to model these ideas using Envoy. Before
+we dive into the configuration I want to quickly go over the high level
+architecture of how these pieces work together.
+
+```mermaid
+sequenceDiagram
+ participant User
+ participant Envoy
+ participant authzd
+ participant sparkled
+ participant OIDC Provider
+
+ Note over User,OIDC Provider: Initial Authentication Flow
+ User->>Envoy: GET /dashboard (no auth)
+ Envoy->>Envoy: OAuth2 filter detects no auth
+ Envoy->>User: Redirect to OIDC Provider
+ User->>OIDC Provider: Login
+ OIDC Provider->>User: Redirect to /callback with code
+ User->>Envoy: GET /callback?code=...
+ Envoy->>OIDC Provider: Exchange code for tokens
+ OIDC Provider->>Envoy: Return tokens (ID, access, refresh)
+ Envoy->>User: Set cookies & redirect to /dashboard
+
+ Note over User,sparkled: Authenticated Request Flow
+ User->>Envoy: GET /dashboard (with cookies)
+ Envoy->>Envoy: Extract ID token from cookie
+ Envoy->>Envoy: JWT filter validates & extracts claims
+ Note right of Envoy: Sets headers:<br/>x-jwt-payload<br/>x-jwt-claim-sub
+
+ Envoy->>authzd: Check authorization (gRPC)
+ Note right of authzd: Request includes:<br/>- Method & Path<br/>- Headers (inc. cookies)<br/>- JWT claims
+ authzd->>authzd: Evaluate authorization rules
+ authzd->>Envoy: Return OK/Denied decision
+
+ alt Authorization OK
+ Envoy->>sparkled: Forward request with JWT headers
+ sparkled->>sparkled: Extract user from x-jwt-claim-sub
+ sparkled->>User: Return dashboard content
+ else Authorization Denied
+ Envoy->>User: Return 401 Unauthorized
+ end
+
+ Note over User,sparkled: Public Endpoint Flow
+ User->>Envoy: GET /health
+ Envoy->>authzd: Check authorization (gRPC)
+ authzd->>authzd: Recognize public endpoint
+ authzd->>Envoy: Return OK (no auth required)
+ Envoy->>sparkled: Forward request
+ sparkled->>User: Return health status
+```
+
+Request Flow Summary
+
+1. Initial Authentication: Unauthenticated users are redirected to the OIDC provider
+1. Token Validation: Envoy validates ID tokens and extracts claims as headers
+1. Authorization Check: Every request goes through `authzd` for authorization decisions
+1. Application Layer: `sparkled` receives pre-authorized requests with user information in headers
+
+This architecture ensures that authorization decisions are made consistently at the edge before requests reach the application.
+
+## Envoy Configuration
+
+Let's dive into the envoy configuration.