feat(gitea): add Kerberos SPNEGO proxy for git.prole.org SSO

Deploys an Apache + mod_auth_gssapi sidecar in the gitea namespace that
handles SPNEGO/Kerberos negotiation (HTTP/git.prole.org@PROLE.ORG) and
injects X-WEBAUTH-USER for Gitea reverse-proxy auto-login.

Identity chain:
  Browser → Traefik TLS → Kong → gitea-spnego-proxy:4000
    → GSSAPI negotiate → X-WEBAUTH-USER: <username>
    → gitea-http:3000 (reverse proxy auto-registration)

Changes:
- gitea-spnego-proxy.yaml: krb5.conf ConfigMap + Deployment + Service
- gitea/spnego-proxy/: Dockerfile and Apache vhost (build source)
- kong-configmap.yaml: route git.prole.org → gitea-spnego-proxy:4000

Gitea reverse proxy settings applied via helm upgrade:
  ENABLE_REVERSE_PROXY_AUTHENTICATION=true
  ENABLE_REVERSE_PROXY_AUTO_REGISTRATION=true
  REVERSE_PROXY_AUTHENTICATION_USER_HEADER=X-WEBAUTH-USER

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
chrisfu 2026-05-08 02:53:05 -07:00
parent 52667c1e5d
commit 2a2b16d0fa
4 changed files with 181 additions and 1 deletions

View File

@ -0,0 +1,126 @@
# gitea-spnego-proxy.yaml
# Apache + mod_auth_gssapi sidecar that handles SPNEGO/Kerberos negotiation for
# git.prole.org. Sits between Kong and Gitea; injects X-WEBAUTH-USER for reverse
# proxy auto-login. Gitea remains on port 3000 (cluster-internal); this proxy
# listens on port 4000 and is the Kong upstream target.
#
# Identity chain:
# Browser → Traefik TLS → Kong → gitea-spnego-proxy:4000
# → GSSAPI (HTTP/git.prole.org@PROLE.ORG keytab)
# → X-WEBAUTH-USER: <username>
# → gitea-http.gitea:3000
---
apiVersion: v1
kind: ConfigMap
metadata:
name: gitea-krb5-conf
namespace: gitea
data:
krb5.conf: |
[libdefaults]
default_realm = PROLE.ORG
dns_lookup_realm = false
dns_lookup_kdc = false
forwardable = true
renewable = true
rdns = false
[realms]
PROLE.ORG = {
kdc = prole-kerberos-ad-dc.knoe-system.svc.cluster.local:88
admin_server = prole-kerberos-ad-dc.knoe-system.svc.cluster.local:88
}
PROLE.LOCAL = {
kdc = authority-prole-auth.knoe-system.svc.cluster.local:88
admin_server = authority-prole-auth.knoe-system.svc.cluster.local:749
}
[domain_realm]
.prole.org = PROLE.ORG
prole.org = PROLE.ORG
.prole.local = PROLE.LOCAL
prole.local = PROLE.LOCAL
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitea-spnego-proxy
namespace: gitea
labels:
app: gitea-spnego-proxy
spec:
replicas: 1
selector:
matchLabels:
app: gitea-spnego-proxy
template:
metadata:
labels:
app: gitea-spnego-proxy
spec:
nodeSelector:
kubernetes.io/hostname: gandalf.prole.org
containers:
- name: proxy
image: myrddin.prole.org:5000/gitea-spnego-proxy:latest
imagePullPolicy: Always
ports:
- name: http
containerPort: 4000
protocol: TCP
env:
- name: KRB5_CONFIG
value: /etc/krb5.conf
- name: KRB5_KTNAME
value: /etc/krb5/http.keytab
volumeMounts:
- name: keytab
mountPath: /etc/krb5
readOnly: true
- name: krb5-conf
mountPath: /etc/krb5.conf
subPath: krb5.conf
readOnly: true
livenessProbe:
tcpSocket:
port: 4000
initialDelaySeconds: 10
periodSeconds: 30
failureThreshold: 3
readinessProbe:
tcpSocket:
port: 4000
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests:
cpu: 10m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
volumes:
- name: keytab
secret:
secretName: gitea-krb5-keytab
defaultMode: 0400
- name: krb5-conf
configMap:
name: gitea-krb5-conf
---
apiVersion: v1
kind: Service
metadata:
name: gitea-spnego-proxy
namespace: gitea
labels:
app: gitea-spnego-proxy
spec:
selector:
app: gitea-spnego-proxy
ports:
- name: http
port: 4000
targetPort: 4000
protocol: TCP
type: ClusterIP

View File

@ -77,8 +77,10 @@ data:
- /
strip_path: false
# Gitea: routed through gitea-spnego-proxy (Apache + mod_auth_gssapi) which
# negotiates SPNEGO/Kerberos and injects X-WEBAUTH-USER for reverse proxy login.
- name: gitea-http
url: http://gitea-http.gitea.svc.cluster.local:3000
url: http://gitea-spnego-proxy.gitea.svc.cluster.local:4000
routes:
- name: gitea-root
hosts:

View File

@ -0,0 +1,17 @@
FROM debian:bookworm-slim
RUN apt-get update && \
apt-get install -y --no-install-recommends \
apache2 \
libapache2-mod-auth-gssapi \
krb5-user \
ca-certificates && \
rm -rf /var/lib/apt/lists/* && \
a2enmod proxy proxy_http headers auth_gssapi rewrite
COPY gitea-spnego.conf /etc/apache2/sites-available/gitea-spnego.conf
RUN a2dissite 000-default && a2ensite gitea-spnego
EXPOSE 4000
CMD ["apache2ctl", "-D", "FOREGROUND"]

View File

@ -0,0 +1,35 @@
Listen 4000
<VirtualHost *:4000>
ServerName git.prole.org
LogLevel info
ErrorLog /proc/self/fd/2
CustomLog /proc/self/fd/1 combined
# Health check endpoint — no auth required (used by k8s probes)
<Location /_healthz>
AuthType None
Require all granted
</Location>
# GSSAPI/SPNEGO — all other paths require a valid Kerberos ticket
# Keytab contains HTTP/git.prole.org@PROLE.ORG (stored as gitea-krb5-keytab secret)
<Location />
AuthType GSSAPI
AuthName "Kerberos - PROLE.ORG"
GssapiCredStore keytab:/etc/krb5/http.keytab
GssapiLocalName on
Require valid-user
# Inject bare username into X-WEBAUTH-USER for Gitea reverse proxy login.
# Strip the @REALM suffix if GssapiLocalName didn't resolve it.
RequestHeader set X-WEBAUTH-USER "%{REMOTE_USER}e"
RequestHeader edit X-WEBAUTH-USER "@.*$" ""
</Location>
ProxyPreserveHost On
ProxyPass /_healthz !
ProxyPass / http://gitea-http.gitea.svc.cluster.local:3000/
ProxyPassReverse / http://gitea-http.gitea.svc.cluster.local:3000/
</VirtualHost>