2026-07-11 19:17:42 -07:00
|
|
|
# Temporal OAuth2-Proxy Setup (Authentik OIDC)
|
|
|
|
|
|
|
|
|
|
## Overview
|
|
|
|
|
|
|
|
|
|
Protects Temporal UI with Authentik OIDC authentication. Traffic flow:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Browser → Ingress (TLS) → oauth2-proxy (OIDC check) → temporal-web (internal)
|
|
|
|
|
↓
|
|
|
|
|
Redirects to Authentik login
|
|
|
|
|
↓
|
|
|
|
|
JWT cookie issued
|
|
|
|
|
↓
|
|
|
|
|
Forwards to temporal-web
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Prerequisites
|
|
|
|
|
|
|
|
|
|
✅ Authentik OIDC provider `temporal` already exists with:
|
|
|
|
|
- Client ID: `temporal`
|
|
|
|
|
- Client Secret: stored in Kubernetes secret `temporal-oidc` (key: `clientSecret`)
|
2026-07-19 09:29:17 -07:00
|
|
|
- Redirect URI: `https://temporal.riotpiao.com/oauth2/callback`
|
2026-07-11 19:17:42 -07:00
|
|
|
|
|
|
|
|
## Secrets
|
|
|
|
|
|
|
|
|
|
The `temporal-oidc` secret must contain:
|
|
|
|
|
|
|
|
|
|
| Key | Value | Source |
|
|
|
|
|
|-----|-------|--------|
|
|
|
|
|
| `clientSecret` | OAuth2 client secret from Authentik | Authentik → Applications → temporal |
|
|
|
|
|
| `cookieSecret` | Session encryption key (base64 32-byte) | Generate: `openssl rand -base64 32` |
|
|
|
|
|
|
|
|
|
|
### Check existing secret:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
kubectl get secret -n temporal temporal-oidc
|
|
|
|
|
kubectl describe secret -n temporal temporal-oidc
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### If missing, create it:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# Get client secret from Authentik UI
|
|
|
|
|
# Applications → temporal → copy "Client Secret"
|
|
|
|
|
CLIENT_SECRET="..."
|
|
|
|
|
|
|
|
|
|
# Generate cookie secret
|
|
|
|
|
COOKIE_SECRET=$(openssl rand -base64 32)
|
|
|
|
|
|
|
|
|
|
# Create secret
|
|
|
|
|
kubectl create secret generic temporal-oidc \
|
|
|
|
|
-n temporal \
|
|
|
|
|
--from-literal=clientSecret="${CLIENT_SECRET}" \
|
|
|
|
|
--from-literal=cookieSecret="${COOKIE_SECRET}"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Deployment Steps
|
|
|
|
|
|
|
|
|
|
### Step 1: Apply OAuth2-Proxy Manifests
|
|
|
|
|
```bash
|
|
|
|
|
kubectl apply -f k8s/temporal/oauth2-proxy.yaml
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Verify:
|
|
|
|
|
```bash
|
|
|
|
|
kubectl get deploy -n temporal oauth2-proxy
|
|
|
|
|
kubectl logs -n temporal deploy/oauth2-proxy
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Expected log:
|
|
|
|
|
```
|
|
|
|
|
[<timestamp>] [oauthproxy.go:...] Listening on 0.0.0.0:4180
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Step 2: Apply OAuth2-Proxy Ingress
|
|
|
|
|
```bash
|
|
|
|
|
kubectl apply -f k8s/temporal/temporal-ingress-oauth2.yaml
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Verify:
|
|
|
|
|
```bash
|
|
|
|
|
kubectl get ingress -n temporal
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Expected:
|
|
|
|
|
```
|
|
|
|
|
NAME CLASS HOSTS ADDRESS PORTS AGE
|
2026-07-19 09:29:17 -07:00
|
|
|
temporal nginx temporal.riotpiao.com ... 80, 443 10s
|
2026-07-11 19:17:42 -07:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Step 3: Test Access
|
|
|
|
|
|
|
|
|
|
1. **Open Temporal UI (unauthenticated):**
|
|
|
|
|
```bash
|
2026-07-19 09:29:17 -07:00
|
|
|
open https://temporal.riotpiao.com
|
2026-07-11 19:17:42 -07:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Expected: Redirects to Authentik login page
|
|
|
|
|
|
|
|
|
|
2. **Login with Authentik credentials**
|
|
|
|
|
- Username/email
|
|
|
|
|
- Password
|
2026-07-19 09:29:17 -07:00
|
|
|
- Should redirect back to `temporal.riotpiao.com` and display UI
|
2026-07-11 19:17:42 -07:00
|
|
|
|
|
|
|
|
3. **Verify auth:**
|
|
|
|
|
```bash
|
|
|
|
|
# Check for oauth2_proxy cookie
|
2026-07-19 09:29:17 -07:00
|
|
|
curl -v https://temporal.riotpiao.com 2>&1 | grep -i cookie
|
2026-07-11 19:17:42 -07:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
4. **Check oauth2-proxy logs:**
|
|
|
|
|
```bash
|
|
|
|
|
kubectl logs -n temporal deploy/oauth2-proxy -f
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Look for:
|
|
|
|
|
```
|
|
|
|
|
[timestamp] [auth_test.go:...] Authentication successful
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Troubleshooting
|
|
|
|
|
|
|
|
|
|
### Redirect URI mismatch
|
|
|
|
|
Error in oauth2-proxy logs:
|
|
|
|
|
```
|
|
|
|
|
redirect_uri_mismatch: The redirect_uri does not match the one registered in Authentik
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Fix:
|
2026-07-19 09:29:17 -07:00
|
|
|
- Verify Authentik application (Applications → temporal) has redirect URI: `https://temporal.riotpiao.com/oauth2/callback`
|
2026-07-11 19:17:42 -07:00
|
|
|
- Ensure HTTPS (not HTTP)
|
|
|
|
|
|
|
|
|
|
### Missing secret
|
|
|
|
|
Error:
|
|
|
|
|
```
|
|
|
|
|
clientSecret: key not found in temporal-oidc secret
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Fix:
|
|
|
|
|
```bash
|
|
|
|
|
kubectl get secret -n temporal temporal-oidc -o yaml
|
|
|
|
|
# If missing, create per "Secrets" section above
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Cookie secret expiration
|
|
|
|
|
OAuth2-Proxy won't start if `cookieSecret` is empty or invalid.
|
|
|
|
|
|
|
|
|
|
Fix:
|
|
|
|
|
```bash
|
|
|
|
|
COOKIE_SECRET=$(openssl rand -base64 32)
|
|
|
|
|
kubectl patch secret temporal-oidc -n temporal \
|
|
|
|
|
-p "{\"data\":{\"cookieSecret\":\"$(echo -n $COOKIE_SECRET | base64)\"}}}"
|
|
|
|
|
kubectl rollout restart deploy/oauth2-proxy -n temporal
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### oauth2-proxy crashes with "connection refused"
|
|
|
|
|
Error in logs:
|
|
|
|
|
```
|
|
|
|
|
upstream connect error or disconnect/reset before headers
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Likely cause: `temporal-web` service not accessible.
|
|
|
|
|
|
|
|
|
|
Check:
|
|
|
|
|
```bash
|
|
|
|
|
kubectl get svc -n temporal temporal-web
|
|
|
|
|
kubectl exec -n temporal deploy/oauth2-proxy -- curl http://temporal-web:8080
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## File Structure
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
k8s/temporal/
|
|
|
|
|
├── oauth2-proxy.yaml # oauth2-proxy Deployment + Service + SA
|
|
|
|
|
├── temporal-ingress-oauth2.yaml # Ingress routing to oauth2-proxy
|
|
|
|
|
├── oauth2-proxy-values.yaml # Helm values (reference only)
|
|
|
|
|
└── temporal-values.yaml # Modified: ingress.enabled=false
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Next: Add to Helmfile
|
|
|
|
|
|
|
|
|
|
If integrating with helmfile.yaml.gotmpl:
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
releases:
|
|
|
|
|
- name: temporal
|
|
|
|
|
# ... existing config ...
|
|
|
|
|
hooks:
|
|
|
|
|
postSync:
|
|
|
|
|
- events: ["success"]
|
|
|
|
|
showlogs: true
|
|
|
|
|
command: "sh"
|
|
|
|
|
args:
|
|
|
|
|
- -c
|
|
|
|
|
- |
|
|
|
|
|
kubectl apply -f k8s/temporal/oauth2-proxy.yaml
|
|
|
|
|
kubectl apply -f k8s/temporal/temporal-ingress-oauth2.yaml
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Or add separate releases:
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
- name: oauth2-proxy-temporal
|
|
|
|
|
namespace: temporal
|
|
|
|
|
chart: oauth2-proxy/oauth2-proxy
|
|
|
|
|
version: "6.x.x"
|
|
|
|
|
values:
|
|
|
|
|
- k8s/temporal/oauth2-proxy-values.yaml
|
|
|
|
|
set:
|
|
|
|
|
- name: config.clientSecret
|
|
|
|
|
value: "{{ (env "TEMPORAL_OIDC_CLIENT_SECRET") }}"
|
|
|
|
|
- name: config.cookieSecret
|
|
|
|
|
value: "{{ (env "TEMPORAL_OIDC_COOKIE_SECRET") }}"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Then add to `.env`:
|
|
|
|
|
```bash
|
|
|
|
|
TEMPORAL_OIDC_CLIENT_SECRET=<from Authentik>
|
|
|
|
|
TEMPORAL_OIDC_COOKIE_SECRET=$(openssl rand -base64 32)
|
|
|
|
|
```
|