135 lines
4.7 KiB
Python
135 lines
4.7 KiB
Python
#!/usr/bin/env python3
|
|||
|
|
"""
|
||
|
|
Example: Register 'dashboard-service' with OAuth + Vault JWT auth.
|
||
|
|
|
||
|
|
This is a complete working example that demonstrates:
|
||
|
|
1. Creating an Authentik OAuth2 provider and application
|
||
|
|
2. Creating Kubernetes secrets for OIDC credentials
|
||
|
|
3. Creating a Vault JWT role for service authentication
|
||
|
|
4. Group-based RBAC
|
||
|
|
|
||
|
|
To use this example:
|
||
|
|
|
||
|
|
# 1. Ensure prerequisites
|
||
|
|
kubectl port-forward -n iam svc/authentik-server 7000:80 &
|
||
|
|
kubectl port-forward -n storage svc/vault 8200:8200 &
|
||
|
|
|
||
|
|
# 2. Generate and store credentials
|
||
|
|
DASHBOARD_OIDC_CLIENT_SECRET=$(openssl rand -hex 32)
|
||
|
|
export DASHBOARD_OIDC_CLIENT_SECRET="$DASHBOARD_OIDC_CLIENT_SECRET"
|
||
|
|
talos put cluster/DASHBOARD_OIDC_CLIENT_SECRET DASHBOARD_OIDC_CLIENT_SECRET="$DASHBOARD_OIDC_CLIENT_SECRET"
|
||
|
|
|
||
|
|
# 3. Run registration
|
||
|
|
python3 register_oauth_app.py \\
|
||
|
|
--service-name dashboard-service \\
|
||
|
|
--namespace apps \\
|
||
|
|
--redirect-uri "https://dashboard.riotpiao.homelab.com/oauth2/callback" \\
|
||
|
|
--service-name-in-vault DASHBOARD \\
|
||
|
|
--vault-jwt-policy shell-secrets \\
|
||
|
|
--add-group dashboard-admins \\
|
||
|
|
--vault-jwt-bound-claims '{"groups":["dashboard-admins"]}'
|
||
|
|
|
||
|
|
# 4. Verify registration
|
||
|
|
curl -s -H "Authorization: Bearer $AUTHENTIK_BOOTSTRAP_TOKEN" \\
|
||
|
|
http://localhost:7000/api/v3/core/applications/?slug=dashboard-service | jq .
|
||
|
|
|
||
|
|
# 5. Test OAuth callback (requires app running)
|
||
|
|
# Browser: http://dashboard.riotpiao.homelab.com/login
|
||
|
|
# Should redirect to Authentik → back to dashboard with session
|
||
|
|
"""
|
||
|
|
|
||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
import os
|
||
|
|
|
||
|
|
|
||
|
|
def example_dashboard_service():
|
||
|
|
"""Register the example 'dashboard-service' with full RBAC."""
|
||
|
|
|
||
|
|
# Check prerequisites
|
||
|
|
print("Checking prerequisites...")
|
||
|
|
|
||
|
|
required_env = [
|
||
|
|
"AUTHENTIK_BOOTSTRAP_TOKEN",
|
||
|
|
"DASHBOARD_OIDC_CLIENT_SECRET",
|
||
|
|
]
|
||
|
|
|
||
|
|
missing = [v for v in required_env if not os.environ.get(v)]
|
||
|
|
if missing:
|
||
|
|
print(f"❌ Missing environment variables: {', '.join(missing)}")
|
||
|
|
print("\nSet them:")
|
||
|
|
print(" talos get cluster/AUTHENTIK_BOOTSTRAP_TOKEN --key AUTHENTIK_BOOTSTRAP_TOKEN | source")
|
||
|
|
print(" talos get cluster/DASHBOARD_OIDC_CLIENT_SECRET --key DASHBOARD_OIDC_CLIENT_SECRET | source")
|
||
|
|
return False
|
||
|
|
|
||
|
|
# Call the registration script
|
||
|
|
cmd = [
|
||
|
|
"python3",
|
||
|
|
"register_oauth_app.py",
|
||
|
|
"--service-name", "dashboard-service",
|
||
|
|
"--namespace", "apps",
|
||
|
|
"--redirect-uri", "https://dashboard.riotpiao.homelab.com/oauth2/callback",
|
||
|
|
"--service-name-in-vault", "DASHBOARD",
|
||
|
|
"--vault-jwt-policy", "shell-secrets",
|
||
|
|
"--add-group", "dashboard-admins",
|
||
|
|
"--vault-jwt-bound-claims", '{"groups":["dashboard-admins"]}',
|
||
|
|
]
|
||
|
|
|
||
|
|
print(f"\nRunning: {' '.join(cmd)}\n")
|
||
|
|
|
||
|
|
result = subprocess.run(cmd, check=False)
|
||
|
|
return result.returncode == 0
|
||
|
|
|
||
|
|
|
||
|
|
def verify_example():
|
||
|
|
"""Verify that the dashboard-service was registered correctly."""
|
||
|
|
print("\n" + "="*70)
|
||
|
|
print("Verification Steps")
|
||
|
|
print("="*70 + "\n")
|
||
|
|
|
||
|
|
print("✅ Check Authentik provider:")
|
||
|
|
print(" curl -s -H 'Authorization: Bearer $AUTHENTIK_BOOTSTRAP_TOKEN' \\")
|
||
|
|
print(" http://localhost:7000/api/v3/providers/oauth2/?name=dashboard-service \\")
|
||
|
|
print(" | jq '.results[0] | {name, client_id, redirect_uris}'")
|
||
|
|
print()
|
||
|
|
|
||
|
|
print("✅ Check Authentik application:")
|
||
|
|
print(" curl -s -H 'Authorization: Bearer $AUTHENTIK_BOOTSTRAP_TOKEN' \\")
|
||
|
|
print(" http://localhost:7000/api/v3/core/applications/?slug=dashboard-service \\")
|
||
|
|
print(" | jq '.results[0] | {name, slug, provider}'")
|
||
|
|
print()
|
||
|
|
|
||
|
|
print("✅ Check Kubernetes secret:")
|
||
|
|
print(" kubectl get secret dashboard-service-oidc -n apps -o jsonpath='{.data}' \\")
|
||
|
|
print(" | base64 -d | jq .")
|
||
|
|
print()
|
||
|
|
|
||
|
|
print("✅ Check Vault JWT role:")
|
||
|
|
print(" vault read auth/jwt/role/dashboard-service")
|
||
|
|
print()
|
||
|
|
|
||
|
|
print("✅ Test Vault JWT authentication:")
|
||
|
|
print(" # Get ID token from Authentik")
|
||
|
|
print(" ID_TOKEN=$(curl -s -X POST \\")
|
||
|
|
print(" http://localhost:7000/application/o/dashboard-service/token/ \\")
|
||
|
|
print(" -d 'grant_type=client_credentials&client_id=dashboard-service&client_secret=...' \\")
|
||
|
|
print(" | jq -r '.access_token')")
|
||
|
|
print()
|
||
|
|
print(" # Authenticate to Vault with JWT")
|
||
|
|
print(" vault write auth/jwt/login \\")
|
||
|
|
print(" role=dashboard-service \\")
|
||
|
|
print(" jwt=\"$ID_TOKEN\"")
|
||
|
|
print()
|
||
|
|
|
||
|
|
print("✅ Test OAuth redirect (requires app running):")
|
||
|
|
print(" curl -L https://dashboard.riotpiao.homelab.com/login")
|
||
|
|
print(" # Should redirect to Authentik, then back to dashboard")
|
||
|
|
print()
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
if not example_dashboard_service():
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
verify_example()
|