feat(ory): OIDC group-to-team mapping, social login, Gitea OIDC-only mode
Identity permissions flow from Kratos metadata_admin.groups through Hydra ID token claims to Gitea's OIDC group-to-team mapping: - super-admin → site admin + Owners + Employees teams - employee → Owners + Employees teams - community → Contributors team (social sign-up users) Kratos: Discord + GitHub social login providers, community identity schema, OIDC method enabled with env-var credential injection via VSO. Gitea: OIDC-only login (no local registration, no password form), APP_NAME, favicon, auto-registration with account linking. Also: messages-mta-in recreate strategy + liveness probe for milter.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -19,6 +19,9 @@ gitea:
|
||||
email: gitea@local.domain
|
||||
|
||||
config:
|
||||
DEFAULT:
|
||||
APP_NAME: "Sunbeam Studios Version Control"
|
||||
|
||||
ui:
|
||||
DEFAULT_THEME: sunbeam
|
||||
THEMES: sunbeam
|
||||
@@ -56,11 +59,24 @@ gitea:
|
||||
TYPE: redis
|
||||
CONN_STR: redis://valkey.data.svc.cluster.local:6379/2?pool_size=100&idle_timeout=180s
|
||||
|
||||
service:
|
||||
# Only allow registration through OIDC (Hydra/Kratos), not local accounts.
|
||||
DISABLE_REGISTRATION: "false"
|
||||
ALLOW_ONLY_EXTERNAL_REGISTRATION: "true"
|
||||
# Hide the password login form — show only the OIDC button.
|
||||
ENABLE_PASSWORD_SIGNIN_FORM: "false"
|
||||
|
||||
openid:
|
||||
ENABLE_OPENID_SIGNIN: "false"
|
||||
ENABLE_OPENID_SIGNUP: "false"
|
||||
|
||||
oauth2_client:
|
||||
# Auto-redirect to Hydra OIDC on login — makes OIDC the primary auth method.
|
||||
OAUTH2_AUTO_REDIRECT_TO_PROVIDER: Sunbeam
|
||||
# Register new OIDC users automatically.
|
||||
ENABLE_AUTO_REGISTRATION: "true"
|
||||
ACCOUNT_LINKING: auto
|
||||
USERNAME: preferred_username
|
||||
|
||||
storage:
|
||||
STORAGE_TYPE: minio
|
||||
@@ -112,6 +128,10 @@ extraContainerVolumeMounts:
|
||||
mountPath: /data/gitea/public/assets/img/logo.svg
|
||||
subPath: logo.svg
|
||||
readOnly: true
|
||||
- name: custom-theme
|
||||
mountPath: /data/gitea/public/assets/img/favicon.png
|
||||
subPath: favicon.png
|
||||
readOnly: true
|
||||
- name: mkcert-ca
|
||||
mountPath: /run/ca/ca.crt
|
||||
subPath: ca.crt
|
||||
|
||||
@@ -5,6 +5,10 @@ metadata:
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
# Recreate: hostPort 25 blocks RollingUpdate — the new pod can't
|
||||
# schedule while the old one still holds the port.
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: messages-mta-in
|
||||
@@ -31,6 +35,26 @@ spec:
|
||||
key: MDA_API_SECRET
|
||||
- name: MAX_INCOMING_EMAIL_SIZE
|
||||
value: "30000000"
|
||||
# Liveness: verify the delivery milter process is running and the
|
||||
# unix socket exists. The milter is a long-lived Python process that
|
||||
# can hang silently after days of uptime (COE-2026-002 addendum).
|
||||
# Without this probe, postfix returns 451 to all inbound mail and
|
||||
# nobody notices until senders complain.
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- "test -S /var/spool/postfix/milter/delivery.sock && kill -0 $(cat /var/run/milter.pid 2>/dev/null || pgrep -f delivery_milter.py)"
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 25
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 15
|
||||
securityContext:
|
||||
capabilities:
|
||||
add: ["NET_BIND_SERVICE"]
|
||||
|
||||
@@ -46,6 +46,25 @@ kratos:
|
||||
- https://auth.DOMAIN_SUFFIX
|
||||
lookup_secret:
|
||||
enabled: true
|
||||
oidc:
|
||||
enabled: true
|
||||
config:
|
||||
providers:
|
||||
- id: discord
|
||||
provider: discord
|
||||
client_id: $DISCORD_CLIENT_ID
|
||||
client_secret: $DISCORD_CLIENT_SECRET
|
||||
scope:
|
||||
- identify
|
||||
- email
|
||||
mapper_url: "base64://eyJpZCI6ICJ7eyBpZiAucHJvdmlkZXJfaWQgfX17eyAucHJvdmlkZXJfaWQgfX17eyBlbHNlIH19e3sgLnByb3ZpZGVyIH19e3sgZW5kIH19Ont7IC5zdWIgfX0iLCAidHJhaXRzIjogeyJlbWFpbCI6ICJ7eyAuZW1haWwgfX0iLCAibmlja25hbWUiOiAie3sgLnVzZXJuYW1lIH19IiwgInBpY3R1cmUiOiAie3sgaWYgLmF2YXRhciB9fWh0dHBzOi8vY2RuLmRpc2NvcmRhcHAuY29tL2F2YXRhcnMve3sgLnN1YiB9fS97eyAuYXZhdGFyIH19LnBuZ3t7IGVuZCB9fSJ9LCAibWV0YWRhdGFfcHVibGljIjogeyJwcm92aWRlciI6ICJkaXNjb3JkIn19"
|
||||
- id: github
|
||||
provider: github
|
||||
client_id: $GITHUB_CLIENT_ID
|
||||
client_secret: $GITHUB_CLIENT_SECRET
|
||||
scope:
|
||||
- user:email
|
||||
mapper_url: "base64://eyJpZCI6ICJ7eyBpZiAucHJvdmlkZXJfaWQgfX17eyAucHJvdmlkZXJfaWQgfX17eyBlbHNlIH19e3sgLnByb3ZpZGVyIH19e3sgZW5kIH19Ont7IC5zdWIgfX0iLCAidHJhaXRzIjogeyJlbWFpbCI6ICJ7eyAuZW1haWwgfX0iLCAibmlja25hbWUiOiAie3sgLmxvZ2luIH19IiwgImdpdmVuX25hbWUiOiAie3sgLm5hbWUgfX0iLCAicGljdHVyZSI6ICJ7eyAuYXZhdGFyX3VybCB9fSJ9LCAibWV0YWRhdGFfcHVibGljIjogeyJwcm92aWRlciI6ICJnaXRodWIifX0="
|
||||
flows:
|
||||
error:
|
||||
ui_url: https://auth.DOMAIN_SUFFIX/error
|
||||
@@ -78,6 +97,8 @@ kratos:
|
||||
url: base64://ewogICIkaWQiOiAiaHR0cHM6Ly9zY2hlbWFzLnN1bmJlYW0uc3R1ZGlvL2lkZW50aXR5Lmpzb24iLAogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInR5cGUiOiAib2JqZWN0IiwKICAidGl0bGUiOiAiUGVyc29uIChsZWdhY3kpIiwKICAicHJvcGVydGllcyI6IHsKICAgICJ0cmFpdHMiOiB7CiAgICAgICJ0eXBlIjogIm9iamVjdCIsCiAgICAgICJwcm9wZXJ0aWVzIjogewogICAgICAgICJlbWFpbCI6IHsKICAgICAgICAgICJ0eXBlIjogInN0cmluZyIsCiAgICAgICAgICAiZm9ybWF0IjogImVtYWlsIiwKICAgICAgICAgICJ0aXRsZSI6ICJFbWFpbCIsCiAgICAgICAgICAib3J5LnNoL2tyYXRvcyI6IHsKICAgICAgICAgICAgImNyZWRlbnRpYWxzIjogewogICAgICAgICAgICAgICJwYXNzd29yZCI6IHsKICAgICAgICAgICAgICAgICJpZGVudGlmaWVyIjogdHJ1ZQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgInJlY292ZXJ5IjogewogICAgICAgICAgICAgICJ2aWEiOiAiZW1haWwiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJ2ZXJpZmljYXRpb24iOiB7CiAgICAgICAgICAgICAgInZpYSI6ICJlbWFpbCIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgIm5hbWUiOiB7CiAgICAgICAgICAidHlwZSI6ICJvYmplY3QiLAogICAgICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgICAgICJmaXJzdCI6IHsKICAgICAgICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICAgICAgICJ0aXRsZSI6ICJGaXJzdCBuYW1lIgogICAgICAgICAgICB9LAogICAgICAgICAgICAibGFzdCI6IHsKICAgICAgICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICAgICAgICJ0aXRsZSI6ICJMYXN0IG5hbWUiCiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0sCiAgICAgICJyZXF1aXJlZCI6IFsKICAgICAgICAiZW1haWwiCiAgICAgIF0sCiAgICAgICJhZGRpdGlvbmFsUHJvcGVydGllcyI6IGZhbHNlCiAgICB9CiAgfQp9Cg==
|
||||
- id: external
|
||||
url: base64://ewogICIkaWQiOiAiaHR0cHM6Ly9zY2hlbWFzLnN1bmJlYW0uc3R1ZGlvL2V4dGVybmFsLmpzb24iLAogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInR5cGUiOiAib2JqZWN0IiwKICAidGl0bGUiOiAiRXh0ZXJuYWwgVXNlciIsCiAgInByb3BlcnRpZXMiOiB7CiAgICAidHJhaXRzIjogewogICAgICAidHlwZSI6ICJvYmplY3QiLAogICAgICAicHJvcGVydGllcyI6IHsKICAgICAgICAiZW1haWwiOiB7CiAgICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICAgImZvcm1hdCI6ICJlbWFpbCIsCiAgICAgICAgICAidGl0bGUiOiAiRW1haWwiLAogICAgICAgICAgIm9yeS5zaC9rcmF0b3MiOiB7CiAgICAgICAgICAgICJjcmVkZW50aWFscyI6IHsKICAgICAgICAgICAgICAicGFzc3dvcmQiOiB7CiAgICAgICAgICAgICAgICAiaWRlbnRpZmllciI6IHRydWUKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJyZWNvdmVyeSI6IHsKICAgICAgICAgICAgICAidmlhIjogImVtYWlsIgogICAgICAgICAgICB9LAogICAgICAgICAgICAidmVyaWZpY2F0aW9uIjogewogICAgICAgICAgICAgICJ2aWEiOiAiZW1haWwiCiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgICJnaXZlbl9uYW1lIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIiwKICAgICAgICAgICJ0aXRsZSI6ICJGaXJzdCBuYW1lIgogICAgICAgIH0sCiAgICAgICAgImZhbWlseV9uYW1lIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIiwKICAgICAgICAgICJ0aXRsZSI6ICJMYXN0IG5hbWUiCiAgICAgICAgfSwKICAgICAgICAibmlja25hbWUiOiB7CiAgICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICAgInRpdGxlIjogIk5pY2tuYW1lIgogICAgICAgIH0sCiAgICAgICAgInBpY3R1cmUiOiB7CiAgICAgICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAgICAgImZvcm1hdCI6ICJ1cmkiLAogICAgICAgICAgInRpdGxlIjogIlByb2ZpbGUgcGljdHVyZSIKICAgICAgICB9CiAgICAgIH0sCiAgICAgICJyZXF1aXJlZCI6IFsKICAgICAgICAiZW1haWwiCiAgICAgIF0sCiAgICAgICJhZGRpdGlvbmFsUHJvcGVydGllcyI6IGZhbHNlCiAgICB9CiAgfQp9Cg==
|
||||
- id: community
|
||||
url: base64://ewogICIkaWQiOiAiaHR0cHM6Ly9zY2hlbWFzLnN1bmJlYW0uc3R1ZGlvL2NvbW11bml0eS5qc29uIiwKICAiJHNjaGVtYSI6ICJodHRwOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LTA3L3NjaGVtYSMiLAogICJ0eXBlIjogIm9iamVjdCIsCiAgInRpdGxlIjogIkNvbW11bml0eSBNZW1iZXIiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgImVtYWlsIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIiwKICAgICAgICAgICJmb3JtYXQiOiAiZW1haWwiLAogICAgICAgICAgInRpdGxlIjogIkVtYWlsIiwKICAgICAgICAgICJvcnkuc2gva3JhdG9zIjogewogICAgICAgICAgICAiY3JlZGVudGlhbHMiOiB7CiAgICAgICAgICAgICAgInBhc3N3b3JkIjogewogICAgICAgICAgICAgICAgImlkZW50aWZpZXIiOiB0cnVlCiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAidG90cCI6IHsKICAgICAgICAgICAgICAgICJhY2NvdW50X25hbWUiOiB0cnVlCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICAicmVjb3ZlcnkiOiB7CiAgICAgICAgICAgICAgInZpYSI6ICJlbWFpbCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgInZlcmlmaWNhdGlvbiI6IHsKICAgICAgICAgICAgICAidmlhIjogImVtYWlsIgogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAiZ2l2ZW5fbmFtZSI6IHsKICAgICAgICAgICJ0eXBlIjogInN0cmluZyIsCiAgICAgICAgICAidGl0bGUiOiAiRmlyc3QgbmFtZSIKICAgICAgICB9LAogICAgICAgICJmYW1pbHlfbmFtZSI6IHsKICAgICAgICAgICJ0eXBlIjogInN0cmluZyIsCiAgICAgICAgICAidGl0bGUiOiAiTGFzdCBuYW1lIgogICAgICAgIH0sCiAgICAgICAgIm5pY2tuYW1lIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIiwKICAgICAgICAgICJ0aXRsZSI6ICJOaWNrbmFtZSIKICAgICAgICB9LAogICAgICAgICJwaWN0dXJlIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIiwKICAgICAgICAgICJmb3JtYXQiOiAidXJpIiwKICAgICAgICAgICJ0aXRsZSI6ICJQcm9maWxlIHBpY3R1cmUiCiAgICAgICAgfQogICAgICB9LAogICAgICAicmVxdWlyZWQiOiBbCiAgICAgICAgImVtYWlsIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiBmYWxzZQogICAgfQogIH0KfQo=
|
||||
|
||||
courier:
|
||||
smtp:
|
||||
@@ -133,6 +154,26 @@ deployment:
|
||||
secretKeyRef:
|
||||
name: kratos-db-creds
|
||||
key: dsn
|
||||
- name: DISCORD_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: kratos-social-discord
|
||||
key: client-id
|
||||
- name: DISCORD_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: kratos-social-discord
|
||||
key: client-secret
|
||||
- name: GITHUB_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: kratos-social-github
|
||||
key: client-id
|
||||
- name: GITHUB_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: kratos-social-github
|
||||
key: client-secret
|
||||
resources:
|
||||
limits:
|
||||
memory: 256Mi
|
||||
|
||||
@@ -157,3 +157,51 @@ spec:
|
||||
text: "{{ index .Secrets \"s3-access-key\" }}"
|
||||
s3-secret-key:
|
||||
text: "{{ index .Secrets \"s3-secret-key\" }}"
|
||||
---
|
||||
# Discord OAuth2 credentials for Kratos social sign-in.
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: kratos-social-discord
|
||||
namespace: ory
|
||||
spec:
|
||||
vaultAuthRef: vso-auth
|
||||
mount: secret
|
||||
type: kv-v2
|
||||
path: kratos-social-discord
|
||||
refreshAfter: 30s
|
||||
destination:
|
||||
name: kratos-social-discord
|
||||
create: true
|
||||
overwrite: true
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
templates:
|
||||
client-id:
|
||||
text: "{{ index .Secrets \"client-id\" }}"
|
||||
client-secret:
|
||||
text: "{{ index .Secrets \"client-secret\" }}"
|
||||
---
|
||||
# GitHub OAuth2 credentials for Kratos social sign-in.
|
||||
apiVersion: secrets.hashicorp.com/v1beta1
|
||||
kind: VaultStaticSecret
|
||||
metadata:
|
||||
name: kratos-social-github
|
||||
namespace: ory
|
||||
spec:
|
||||
vaultAuthRef: vso-auth
|
||||
mount: secret
|
||||
type: kv-v2
|
||||
path: kratos-social-github
|
||||
refreshAfter: 30s
|
||||
destination:
|
||||
name: kratos-social-github
|
||||
create: true
|
||||
overwrite: true
|
||||
transformation:
|
||||
excludeRaw: true
|
||||
templates:
|
||||
client-id:
|
||||
text: "{{ index .Secrets \"client-id\" }}"
|
||||
client-secret:
|
||||
text: "{{ index .Secrets \"client-secret\" }}"
|
||||
|
||||
Reference in New Issue
Block a user