feat: authentik jwt + sops encryption for prod secrets & llm auth
CI / CI (pull_request) Successful in 3m40s
CI / CI (pull_request) Successful in 3m40s
SECURITY: - Add authentik_jwt.rs: OAuth2 client credentials flow with caching - SOPS encrypt secrets with age key (SOPS_AGE_KEY_FILE) - JWT tokens for LLM gateway, S3, and API gateway access - Token auto-refresh when expired (60s before expiry) - No hardcoded credentials in code or config ENTITY EXTRACTION: - LlmEntityExtractor now uses Authentik JWT instead of mock - Fallback to env var if Authentik not configured - Reflection verification still enabled - WikiLink extraction as Stage 0 (always active) DEPLOYMENT: - ConfigMap: LLM_ENDPOINT, LLM_MODEL, timeouts - Secret: AUTHENTIK_ISSUER, CLIENT_ID, CLIENT_SECRET, S3 keys - envFrom mounts both ConfigMap and Secret - KSOPS plugin for ArgoCD auto-decryption DOCUMENTATION: - docs/AUTHENTIK_SOPS_SETUP.md: Complete integration guide - Service account creation in Authentik - SOPS encryption/decryption workflow - JWT token exchange flow - Troubleshooting guide FILES: - crates/mem-ingest/src/authentik_jwt.rs (new, 180 LOC) - crates/mem-ingest/src/entity_extractor.rs (updated, JWT auth) - crates/mem-ingest/Cargo.toml (add reqwest) - k8s/app/poimen-memory-secrets.yaml (new, unencrypted template) - k8s/app/deployment.yaml (add secrets envFrom) - k8s/app/config.yaml (add LLM config) - k8s/.sops.yaml (encryption rules) - docs/AUTHENTIK_SOPS_SETUP.md (new, 350 LOC) NEXT: 1. Create Authentik service account (manual) 2. Encrypt secrets with SOPS 3. Deploy to poimen namespace 4. Test JWT token exchange with LLM endpoint
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
creation_rules:
|
||||
- path_regex: .*\.enc\.ya?ml$
|
||||
encrypted_regex: '^(stringData|data)$'
|
||||
age: age1e5fq3hwxy78psus2nfvmtmua36g0u3suk78ephw6246l974d2utsvn0hla
|
||||
@@ -21,3 +21,8 @@ data:
|
||||
OPENSEARCH_HOST: "opensearch.poimen.svc.cluster.local:9200"
|
||||
# Obsidian
|
||||
OBSIDIAN_URL: "http://obsidian-server.poimen.svc.cluster.local:8080"
|
||||
# LLM Configuration (for entity extraction)
|
||||
LLM_ENDPOINT: "http://api-internal.riotpiao.com:8000/v1/chat/completions"
|
||||
LLM_MODEL: "qwen:7b"
|
||||
LLM_TIMEOUT_SECS: "30"
|
||||
ENABLE_LLM_EXTRACTION: "true"
|
||||
|
||||
@@ -76,6 +76,8 @@ spec:
|
||||
name: poimen-memory-config
|
||||
- secretRef:
|
||||
name: poimen-memory-auth
|
||||
- secretRef:
|
||||
name: poimen-memory-secrets
|
||||
args:
|
||||
- serve
|
||||
- --port
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: poimen-memory-auth
|
||||
namespace: poimen
|
||||
labels:
|
||||
app.kubernetes.io/name: poimen-memory
|
||||
type: Opaque
|
||||
stringData:
|
||||
# Authentik Service Account - OAuth2 client credentials
|
||||
# These are obtained from Authentik admin panel:
|
||||
# Settings → Applications → poimen-memory → Service Account
|
||||
AUTHENTIK_ISSUER: "https://authentik.riotpiao.com/application/o/memory"
|
||||
AUTHENTIK_AUDIENCE: "poimen-memory"
|
||||
AUTHENTIK_CLIENT_ID: "${AUTHENTIK_SERVICE_ACCOUNT_CLIENT_ID}"
|
||||
AUTHENTIK_CLIENT_SECRET: "${AUTHENTIK_SERVICE_ACCOUNT_SECRET}"
|
||||
|
||||
# LLM API Key
|
||||
# Generated by Authentik service account with permissions to LLM gateway
|
||||
LLM_API_KEY: "${LLM_API_KEY_FROM_AUTHENTIK}"
|
||||
|
||||
# S3 Credentials for backups (Velero)
|
||||
S3_ACCESS_KEY: "${MINIO_ACCESS_KEY}"
|
||||
S3_SECRET_KEY: "${MINIO_SECRET_KEY}"
|
||||
Reference in New Issue
Block a user