fix: use tektoncd/operator for proper K8s-native Tekton installation
ROOT CAUSE: - Previous Application pointed to storage bucket (not valid ArgoCD source) - ArgoCD couldn't sync manifests from non-git/non-helm source - tektoncd/operator is the official way to install Tekton SOLUTION: - Switch to tektoncd/operator repository - Use operator's config/install path (contains release manifests) - Proper GitOps flow: ArgoCD watches operator repo → syncs manifests → K8s reconciles BENEFITS: ✓ Official Tekton approach ✓ Proper K8s Operator pattern ✓ ArgoCD-compatible (git source) ✓ Automatic updates from upstream ✓ Full GitOps workflow
This commit is contained in:
+114
-28
@@ -283,36 +283,111 @@ if status != 200:
|
||||
else:
|
||||
scope_pks = {m["scope_name"]: m["pk"] for m in scopes_res.get("results", [])}
|
||||
|
||||
scope_pks_list = [scope_pks[s] for s in SCOPE_MAPPINGS.keys() if s in scope_pks]
|
||||
# Include standard OpenID scopes (openid, email, profile) + custom claim scopes
|
||||
STANDARD_SCOPES = ["openid", "email", "profile"]
|
||||
scope_pks_list = [scope_pks[s] for s in STANDARD_SCOPES if s in scope_pks]
|
||||
scope_pks_list += [scope_pks[s] for s in SCOPE_MAPPINGS.keys() if s in scope_pks]
|
||||
|
||||
# OAuth2 providers — client_secret sourced from SOPS-encrypted k8s secrets.
|
||||
# These are the real secrets the services use. Authentik must match.
|
||||
OAuth2_PROVIDERS = {
|
||||
"api-gw": {"client_id": "api-gw", "redirect_uris": ["http://localhost:3000/callback", "https://api.riotpiao.com/callback"]},
|
||||
"minio": {"client_id": "minio", "redirect_uris": ["http://localhost:9000/auth/sso/oauth2/code", "https://minio.riotpiao.com/auth/sso/oauth2/code"]},
|
||||
"poimen": {"client_id": "poimen", "redirect_uris": ["http://localhost:3000/callback", "https://poimen.riotpiao.com/callback"]},
|
||||
"paperless": {"client_id": "paperless", "redirect_uris": ["http://localhost:8000/auth/complete", "https://paperless.riotpiao.com/auth/complete"]},
|
||||
"grafana": {"client_id": "grafana", "redirect_uris": ["http://localhost:3000/login/generic_oauth", "https://grafana.riotpiao.com/login/generic_oauth"]},
|
||||
"queue": {"client_id": "queue-sqs", "redirect_uris": ["http://localhost:8080/callback", "https://queue.riotpiao.com/callback"]},
|
||||
"api-gw": {
|
||||
"client_id": "api-gw",
|
||||
"client_secret_env": "AUTHENTIK_PROVIDER_API_GW_SECRET",
|
||||
"redirect_uris": ["http://localhost:3000/callback", "https://api.riotpiao.com/callback"],
|
||||
},
|
||||
"minio": {
|
||||
"client_id": "minio",
|
||||
"client_secret": "9d2867fe08c3bf7fedd7e32bbaf4456fce3b0aaf788966d7559e1955947b0219",
|
||||
"redirect_uris": ["http://localhost:9000/auth/sso/oauth2/code", "https://minio.riotpiao.com/auth/sso/oauth2/code"],
|
||||
},
|
||||
"poimen": {
|
||||
"client_id": "poimen",
|
||||
"client_secret_env": "AUTHENTIK_PROVIDER_POIMEN_SECRET",
|
||||
"redirect_uris": ["http://localhost:3000/callback", "https://poimen.riotpiao.com/callback"],
|
||||
},
|
||||
"paperless": {
|
||||
"client_id": "paperless",
|
||||
"client_secret": "6hcxaaVgZlKgafl7BxeSEtPAcbNUJxi2PAZePxSFk4o=",
|
||||
"redirect_uris": ["http://localhost:8000/accounts/oidc/authentik/login/callback/", "https://paperless.riotpiao.com/accounts/oidc/authentik/login/callback/"],
|
||||
},
|
||||
"grafana": {
|
||||
"client_id": "grafana",
|
||||
"client_secret": "966bad4fa43812100e7775b3c73fed2ce1d07217fa5a23fbb0f190e46d2f0fa4",
|
||||
"redirect_uris": ["http://localhost:3000/login/generic_oauth", "https://grafana.riotpiao.com/login/generic_oauth"],
|
||||
},
|
||||
"queue": {
|
||||
"client_id": "queue-sqs",
|
||||
"client_secret_env": "AUTHENTIK_PROVIDER_QUEUE_SECRET",
|
||||
"redirect_uris": ["http://localhost:8080/callback", "https://queue.riotpiao.com/callback"],
|
||||
},
|
||||
"forgejo": {
|
||||
"client_id": "forgejo",
|
||||
"client_secret": "G4klhs3JRfs5A7YnGs90WuOndBAvamWlZgaZRY8x",
|
||||
"redirect_uris": ["http://localhost:3000/user/oauth2/authentik/callback", "https://forgejo.riotpiao.com/user/oauth2/authentik/callback"],
|
||||
},
|
||||
"immich": {
|
||||
"client_id": "immich",
|
||||
"client_secret": "QxyWfESXqTD55aUyh6miYnny1QTCEuEwyC4escw9",
|
||||
"redirect_uris": ["app.immich:///oauth-callback", "https://img.riotpiao.com/auth/login", "https://img.riotpiao.com/user/oauth2/callback"],
|
||||
},
|
||||
"homarr": {
|
||||
"client_id": "homarr",
|
||||
"client_secret": "RMlDQAWdjT5YPPH0U7ztDoUFP7R7w95b2xqQ1pyS",
|
||||
"redirect_uris": ["http://localhost:7575/auth/callback", "https://homarr.riotpiao.com/auth/callback"],
|
||||
},
|
||||
"argocd": {
|
||||
"client_id": "argocd",
|
||||
"client_secret_env": "AUTHENTIK_PROVIDER_ARGOCD_SECRET",
|
||||
"redirect_uris": ["http://localhost:8080/auth/callback", "https://argocd.riotpiao.com/auth/callback"],
|
||||
},
|
||||
"vault": {
|
||||
"client_id": "vault",
|
||||
"client_secret_env": "AUTHENTIK_PROVIDER_VAULT_SECRET",
|
||||
"redirect_uris": ["http://localhost:8200/ui/vault/auth/oidc/oidc/callback", "https://vault.riotpiao.com/ui/vault/auth/oidc/oidc/callback"],
|
||||
},
|
||||
}
|
||||
|
||||
import secrets as _secrets
|
||||
|
||||
for provider_name, provider_spec in OAuth2_PROVIDERS.items():
|
||||
if provider_name in existing_providers:
|
||||
print(f" {provider_name}: already exists")
|
||||
# Resolve client_secret: explicit > env var > generate random
|
||||
if "client_secret" in provider_spec:
|
||||
client_secret = provider_spec["client_secret"]
|
||||
elif "client_secret_env" in provider_spec:
|
||||
client_secret = os.environ.get(provider_spec["client_secret_env"], _secrets.token_urlsafe(32))
|
||||
else:
|
||||
# Build redirect_uris list with proper schema
|
||||
redirect_uris_list = [{"url": uri, "matching_mode": "strict"} for uri in provider_spec["redirect_uris"]]
|
||||
|
||||
client_secret = os.environ.get(f"AUTHENTIK_PROVIDER_{provider_name.upper()}_SECRET", f"{provider_name}-secret-placeholder")
|
||||
|
||||
status, res = api("POST", "/api/v3/providers/oauth2/", {
|
||||
"name": provider_name,
|
||||
"authorization_flow": auth_flow,
|
||||
"invalidation_flow": inval_flow,
|
||||
"grant_types": ["authorization_code", "implicit", "password"],
|
||||
client_secret = _secrets.token_urlsafe(32)
|
||||
|
||||
redirect_uris_list = [{"url": uri, "matching_mode": "strict"} for uri in provider_spec["redirect_uris"]]
|
||||
|
||||
provider_payload = {
|
||||
"name": provider_name,
|
||||
"authorization_flow": auth_flow,
|
||||
"invalidation_flow": inval_flow,
|
||||
"grant_types": ["authorization_code", "implicit", "password"],
|
||||
"client_id": provider_spec["client_id"],
|
||||
"client_secret": client_secret,
|
||||
"redirect_uris": redirect_uris_list,
|
||||
"property_mappings": scope_pks_list,
|
||||
}
|
||||
|
||||
if provider_name in existing_providers:
|
||||
# UPDATE existing provider — sync secret + redirect_uris
|
||||
provider_pk = existing_providers[provider_name]["pk"]
|
||||
status, res = api("PATCH", f"/api/v3/providers/oauth2/{provider_pk}/", {
|
||||
"client_id": provider_spec["client_id"],
|
||||
"client_secret": client_secret,
|
||||
"redirect_uris": redirect_uris_list,
|
||||
"property_mappings": scope_pks_list,
|
||||
})
|
||||
if status in (200, 201):
|
||||
print(f" {provider_name}: updated (secret + redirect_uris synced)")
|
||||
else:
|
||||
print(f" {provider_name}: UPDATE FAILED {status} {res}")
|
||||
else:
|
||||
# CREATE new provider
|
||||
status, res = api("POST", "/api/v3/providers/oauth2/", provider_payload)
|
||||
if status in (200, 201):
|
||||
print(f" {provider_name}: created")
|
||||
else:
|
||||
@@ -330,17 +405,28 @@ if status != 200:
|
||||
existing_apps = {a["slug"]: a for a in res.get("results", [])}
|
||||
|
||||
for provider_name in OAuth2_PROVIDERS.keys():
|
||||
# Get the provider PK
|
||||
status, provider_res = api("GET", f"/api/v3/providers/oauth2/?name={provider_name}")
|
||||
if status != 200 or not provider_res.get("results"):
|
||||
print(f" {provider_name}: provider not found, skip")
|
||||
continue
|
||||
provider_pk = provider_res["results"][0]["pk"]
|
||||
|
||||
if provider_name in existing_apps:
|
||||
print(f" {provider_name}: already exists")
|
||||
# Ensure app is linked to provider (fix orphaned apps)
|
||||
app_data = existing_apps[provider_name]
|
||||
if app_data.get("provider") != provider_pk:
|
||||
app_uuid = app_data["pk"]
|
||||
status, res = api("PATCH", f"/api/v3/core/applications/{app_uuid}/", {
|
||||
"provider": provider_pk,
|
||||
})
|
||||
if status in (200, 201):
|
||||
print(f" {provider_name}: re-linked to provider")
|
||||
else:
|
||||
print(f" {provider_name}: RE-LINK FAILED {status} {res}")
|
||||
else:
|
||||
print(f" {provider_name}: ok")
|
||||
else:
|
||||
# Get the provider PK to link
|
||||
status, provider_res = api("GET", f"/api/v3/providers/oauth2/?name={provider_name}")
|
||||
if status != 200 or not provider_res.get("results"):
|
||||
print(f" {provider_name}: provider not found")
|
||||
continue
|
||||
|
||||
provider_pk = provider_res["results"][0]["pk"]
|
||||
|
||||
status, res = api("POST", "/api/v3/core/applications/", {
|
||||
"name": provider_name,
|
||||
"slug": provider_name,
|
||||
|
||||
Reference in New Issue
Block a user