mirror of
https://github.com/dredx/prole.git
synced 2026-09-23 11:03:59 +00:00
feat(auth): add Google Workspace OAuth (prole.org) for Grafana + Supabase Studio
- monitoring/kps-values-k3s.yaml: Grafana helm values for k3s homelab with dual auth (auth.proxy Kerberos + auth.google for prole.org Workspace) - grafana-proxy-configmap.yaml: nginx passthrough for /grafana/login/google and /grafana/login to allow Google OAuth flow without knoe-auth redirect - grafana-google-oidc-secret-prole.example.yaml: Secret template for Grafana Google OAuth client (svc.prole.org, Internal consent, prole.org Workspace) - oauth2-proxy-google-oidc-secret-prole.example.yaml: Secret template for oauth2-proxy gating db.prole.org Studio - oauth2-proxy-deployment-prole.yaml: k3s oauth2-proxy deployment for db.prole.org (prole.org domain, no BackendConfig) - init_grafana_oauth_prole.sh: Bootstrap script for Grafana OAuth secret - init_oauth2_proxy_prole.sh: Bootstrap script for Studio oauth2-proxy Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
52f4053718
commit
885fa99a29
29
deploy/gcp/gke/grafana-google-oidc-secret-prole.example.yaml
Normal file
29
deploy/gcp/gke/grafana-google-oidc-secret-prole.example.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: grafana-google-oidc
|
||||
namespace: monitoring
|
||||
labels:
|
||||
app: grafana
|
||||
app.kubernetes.io/managed-by: knoe-installer
|
||||
# Google OAuth 2.0 client credentials for Grafana's native Google sign-in
|
||||
# (Grafana auth.google plugin) on the prole.org k3s homelab cluster.
|
||||
# Mounted into kps-grafana via `envFromSecret: grafana-google-oidc` in
|
||||
# monitoring/kps-values-k3s.yaml. Grafana reads GF_AUTH_GOOGLE_CLIENT_ID /
|
||||
# GF_AUTH_GOOGLE_CLIENT_SECRET and uses them as auth.google.client_id / client_secret.
|
||||
#
|
||||
# Create the OAuth client at: https://console.cloud.google.com/apis/credentials
|
||||
# (in the prole.org GCP project — separate from the knoey.com project)
|
||||
# - Application type: Web application
|
||||
# - Name: prole.org Grafana
|
||||
# - Authorized JavaScript origins: https://svc.prole.org
|
||||
# - Authorized redirect URIs: https://svc.prole.org/grafana/login/google
|
||||
# - OAuth consent screen: Internal (prole.org Workspace only)
|
||||
# - Scopes: openid, email, profile
|
||||
#
|
||||
# Why a separate client from prole.org Studio: independent rotation surface.
|
||||
# Companion to oauth2-proxy-google-oidc-secret-prole.example.yaml.
|
||||
type: Opaque
|
||||
stringData:
|
||||
GF_AUTH_GOOGLE_CLIENT_ID: "${GRAFANA_GOOGLE_CLIENT_ID}"
|
||||
GF_AUTH_GOOGLE_CLIENT_SECRET: "${GRAFANA_GOOGLE_CLIENT_SECRET}"
|
||||
@ -0,0 +1,32 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: oauth2-proxy-google-oidc
|
||||
namespace: supabase
|
||||
labels:
|
||||
app: oauth2-proxy
|
||||
app.kubernetes.io/managed-by: knoe-installer
|
||||
# Google OAuth 2.0 client credentials + cookie secret for the oauth2-proxy
|
||||
# gating Supabase Studio at db.prole.org on the k3s homelab cluster.
|
||||
# Applied by etc/init_oauth2_proxy_prole.sh via envsubst from
|
||||
# etc/secrets/oauth2-proxy-{client-id,client-secret,cookie-secret}-prole.
|
||||
#
|
||||
# Create the OAuth client at: https://console.cloud.google.com/apis/credentials
|
||||
# (in the prole.org GCP project — separate from the knoey.com project)
|
||||
# - Application type: Web application
|
||||
# - Name: prole.org Studio
|
||||
# - Authorized JavaScript origins: https://db.prole.org
|
||||
# - Authorized redirect URIs: https://db.prole.org/oauth2/callback
|
||||
# - OAuth consent screen: Internal (prole.org Workspace only)
|
||||
# - Scopes: openid, email, profile
|
||||
#
|
||||
# cookie_secret: must be 32 bytes. Generate with:
|
||||
# openssl rand -base64 32
|
||||
#
|
||||
# Why a separate client from prole.org Grafana: independent rotation surface.
|
||||
# Companion to grafana-google-oidc-secret-prole.example.yaml.
|
||||
type: Opaque
|
||||
stringData:
|
||||
client_id: "${OAUTH2_PROXY_CLIENT_ID}"
|
||||
client_secret: "${OAUTH2_PROXY_CLIENT_SECRET}"
|
||||
cookie_secret: "${OAUTH2_PROXY_COOKIE_SECRET}"
|
||||
@ -30,6 +30,29 @@ data:
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
}
|
||||
|
||||
# Pass Google OAuth and Grafana login paths through without auth_request
|
||||
# so auth.google sign-in can complete. Kerberos users still reach Grafana
|
||||
# via the auth_request path below and get X-WEBAUTH-USER injected.
|
||||
location = /grafana/login/google {
|
||||
proxy_set_header X-WEBAUTH-USER "";
|
||||
proxy_set_header X-Knoe-Groups "";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_http_version 1.1;
|
||||
proxy_pass http://kps-grafana.monitoring.svc.cluster.local:80;
|
||||
}
|
||||
|
||||
location ~ ^/grafana/login(/.*)?$ {
|
||||
proxy_set_header X-WEBAUTH-USER "";
|
||||
proxy_set_header X-Knoe-Groups "";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_http_version 1.1;
|
||||
proxy_pass http://kps-grafana.monitoring.svc.cluster.local:80;
|
||||
}
|
||||
|
||||
location / {
|
||||
auth_request /_auth_verify;
|
||||
auth_request_set $knoe_user $upstream_http_x_knoe_user;
|
||||
|
||||
@ -0,0 +1,150 @@
|
||||
# oauth2-proxy gate in front of Supabase Studio at db.prole.org (k3s homelab).
|
||||
#
|
||||
# Sits between the Traefik ingress and supabase-kong; redirects unauthenticated
|
||||
# requests to Google Workspace (prole.org), allows any @prole.org identity through,
|
||||
# then proxies the request upstream to supabase-kong:8000.
|
||||
#
|
||||
# Bootstrap: ./etc/init_oauth2_proxy_prole.sh
|
||||
# Cluster: k3s homelab (myrddin/merlin/gandalf)
|
||||
# Namespace: supabase
|
||||
#
|
||||
# After this Deployment is Ready, patch the Traefik IngressRoute (or the
|
||||
# db.prole.org Ingress) to route through oauth2-proxy:80 instead of
|
||||
# supabase-kong:8000 directly.
|
||||
#
|
||||
# skip-auth-route rules mirror the knoe.dev deployment — Kong key-auth is
|
||||
# the enforcer on API paths; only the Studio UI at / is Google-gated.
|
||||
#
|
||||
# When knoe-auth Round 1 ships an OIDC OP, swap --provider=google to
|
||||
# --provider=oidc --oidc-issuer-url=https://api.prole.org/auth.
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: oauth2-proxy
|
||||
namespace: supabase
|
||||
labels:
|
||||
app: oauth2-proxy
|
||||
app.kubernetes.io/managed-by: knoe-installer
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: oauth2-proxy
|
||||
namespace: supabase
|
||||
labels:
|
||||
app: oauth2-proxy
|
||||
app.kubernetes.io/managed-by: knoe-installer
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: oauth2-proxy
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 4180
|
||||
protocol: TCP
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: oauth2-proxy
|
||||
namespace: supabase
|
||||
labels:
|
||||
app: oauth2-proxy
|
||||
app.kubernetes.io/managed-by: knoe-installer
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app: oauth2-proxy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: oauth2-proxy
|
||||
spec:
|
||||
serviceAccountName: oauth2-proxy
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: oauth2-proxy
|
||||
image: quay.io/oauth2-proxy/oauth2-proxy:v7.15.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- --provider=google
|
||||
- --email-domain=prole.org
|
||||
- --upstream=http://supabase-kong:8000
|
||||
- --http-address=0.0.0.0:4180
|
||||
- --reverse-proxy=true
|
||||
- --cookie-secure=true
|
||||
- --cookie-name=_prole_studio_oauth2
|
||||
- --cookie-domain=db.prole.org
|
||||
- --whitelist-domain=db.prole.org
|
||||
- --redirect-url=https://db.prole.org/oauth2/callback
|
||||
- --skip-provider-button=true
|
||||
- --scope=openid email profile
|
||||
# Do NOT set --pass-authorization-header / --set-authorization-header.
|
||||
# Those would clobber the Authorization: Bearer <apikey> that
|
||||
# supabase-py and Studio send to Kong's key-auth plugin.
|
||||
- --skip-auth-route=^/(auth|rest|realtime|storage|functions|graphql)/v1/.*
|
||||
- --skip-auth-route=^/pg/.*
|
||||
- --skip-auth-route=^/onboard\.html$
|
||||
- --skip-auth-route=^/support$
|
||||
- --request-logging=true
|
||||
- --auth-logging=true
|
||||
- --standard-logging=true
|
||||
env:
|
||||
- name: OAUTH2_PROXY_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oauth2-proxy-google-oidc
|
||||
key: client_id
|
||||
- name: OAUTH2_PROXY_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oauth2-proxy-google-oidc
|
||||
key: client_secret
|
||||
- name: OAUTH2_PROXY_COOKIE_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oauth2-proxy-google-oidc
|
||||
key: cookie_secret
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 4180
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /ping
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /ping
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
readOnlyRootFilesystem: true
|
||||
100
etc/init_grafana_oauth_prole.sh
Normal file
100
etc/init_grafana_oauth_prole.sh
Normal file
@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env bash
|
||||
# init_grafana_oauth_prole.sh
|
||||
#
|
||||
# Bootstrap the Google-OAuth secret for Grafana on the prole.org k3s homelab
|
||||
# cluster. Companion to the knoe.dev version (init_grafana_oauth.sh) but uses
|
||||
# prole.org GCP project credentials and targets the k3s kubecontext.
|
||||
#
|
||||
# Creates the grafana-google-oidc Secret in the monitoring namespace, which
|
||||
# kps-grafana mounts via envFromSecret to get GF_AUTH_GOOGLE_CLIENT_ID and
|
||||
# GF_AUTH_GOOGLE_CLIENT_SECRET for its auth.google sign-in flow.
|
||||
#
|
||||
# Auth model (monitoring/kps-values-k3s.yaml):
|
||||
# - Kerberos/knoe-auth users auto-login via auth.proxy (X-WEBAUTH-USER).
|
||||
# - chrisfu@prole.org (and any future @prole.org Workspace user) signs in
|
||||
# with the Google button on the Grafana login page.
|
||||
# - chrisfu@prole.org → Admin; all other @prole.org users → Editor.
|
||||
#
|
||||
# Usage:
|
||||
# ./etc/init_grafana_oauth_prole.sh
|
||||
#
|
||||
# Env vars (resolved from etc/secrets/* if not set in the shell):
|
||||
# GRAFANA_GOOGLE_CLIENT_ID ← from etc/secrets/grafana-google-oidc-client-id-prole
|
||||
# GRAFANA_GOOGLE_CLIENT_SECRET ← from etc/secrets/grafana-google-oidc-client-secret-prole
|
||||
#
|
||||
# Optional:
|
||||
# K3S_KUBECONTEXT (default: $KUBECONTEXT then ambient)
|
||||
# NAMESPACE (default: monitoring)
|
||||
#
|
||||
# Pre-reqs:
|
||||
# - OAuth 2.0 Web Application client created in the prole.org GCP project:
|
||||
# Authorized JS origins: https://svc.prole.org
|
||||
# Authorized redirect URI: https://svc.prole.org/grafana/login/google
|
||||
# Consent screen: Internal (prole.org Workspace)
|
||||
# Scopes: openid, email, profile
|
||||
# See deploy/gcp/gke/grafana-google-oidc-secret-prole.example.yaml for details.
|
||||
# - Client ID and secret saved (chmod 0600) to:
|
||||
# etc/secrets/grafana-google-oidc-client-id-prole
|
||||
# etc/secrets/grafana-google-oidc-client-secret-prole
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
MANIFEST_DIR="$REPO_ROOT/deploy/gcp/gke"
|
||||
|
||||
NAMESPACE="${NAMESPACE:-monitoring}"
|
||||
KCTX="${K3S_KUBECONTEXT:-${KUBECONTEXT:-}}"
|
||||
|
||||
if [[ -n "$KCTX" ]]; then
|
||||
KCTX_FLAG=(--context="$KCTX")
|
||||
else
|
||||
KCTX_FLAG=()
|
||||
fi
|
||||
|
||||
log() { printf "[%s] %s\n" "$(date +%H:%M:%S)" "$*"; }
|
||||
die() { log "ERROR: $*" >&2; exit 1; }
|
||||
|
||||
resolve_secret() {
|
||||
local var="$1" file="$2" val="${!1:-}"
|
||||
if [[ -z "$val" && -f "$REPO_ROOT/etc/secrets/$file" ]]; then
|
||||
val="$(cat "$REPO_ROOT/etc/secrets/$file")"
|
||||
fi
|
||||
if [[ -z "$val" ]]; then
|
||||
die "missing $var (set the env var, or save the value into etc/secrets/$file)"
|
||||
fi
|
||||
printf '%s' "$val"
|
||||
}
|
||||
|
||||
for tool in kubectl envsubst; do
|
||||
command -v "$tool" >/dev/null 2>&1 || die "required tool not found: $tool"
|
||||
done
|
||||
|
||||
GRAFANA_GOOGLE_CLIENT_ID="$(resolve_secret GRAFANA_GOOGLE_CLIENT_ID grafana-google-oidc-client-id-prole)"
|
||||
GRAFANA_GOOGLE_CLIENT_SECRET="$(resolve_secret GRAFANA_GOOGLE_CLIENT_SECRET grafana-google-oidc-client-secret-prole)"
|
||||
export GRAFANA_GOOGLE_CLIENT_ID GRAFANA_GOOGLE_CLIENT_SECRET
|
||||
|
||||
SECRET_TMPL="$MANIFEST_DIR/grafana-google-oidc-secret-prole.example.yaml"
|
||||
[[ -f "$SECRET_TMPL" ]] || die "missing manifest: $SECRET_TMPL"
|
||||
|
||||
log "==> grafana google-oauth bootstrap (prole.org / k3s)"
|
||||
log " namespace : $NAMESPACE"
|
||||
log " kubectx : ${KCTX:-<ambient>}"
|
||||
|
||||
log "Applying grafana-google-oidc Secret ..."
|
||||
envsubst '${GRAFANA_GOOGLE_CLIENT_ID} ${GRAFANA_GOOGLE_CLIENT_SECRET}' \
|
||||
< "$SECRET_TMPL" \
|
||||
| kubectl "${KCTX_FLAG[@]}" -n "$NAMESPACE" apply -f -
|
||||
|
||||
log "==> grafana google-oauth secret applied."
|
||||
echo ""
|
||||
echo " Next steps:"
|
||||
echo " 1. Helm upgrade kube-prometheus-stack with the k3s values:"
|
||||
echo " helm upgrade --reuse-values kps prometheus-community/kube-prometheus-stack \\"
|
||||
echo " --namespace $NAMESPACE \\"
|
||||
echo " -f $REPO_ROOT/monitoring/kps-values-k3s.yaml"
|
||||
echo " 2. Restart grafana-proxy to pick up the updated configmap:"
|
||||
echo " kubectl rollout restart deployment/knoe-grafana-proxy -n $NAMESPACE"
|
||||
echo " 3. Browser-test: https://svc.prole.org/grafana/login → Google sign-in button"
|
||||
echo " present; Kerberos users still auto-login via X-WEBAUTH-USER."
|
||||
echo ""
|
||||
116
etc/init_oauth2_proxy_prole.sh
Normal file
116
etc/init_oauth2_proxy_prole.sh
Normal file
@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env bash
|
||||
# init_oauth2_proxy_prole.sh
|
||||
#
|
||||
# Bootstrap the oauth2-proxy gate in front of Supabase Studio at db.prole.org
|
||||
# on the k3s homelab cluster. Companion to init_oauth2_proxy.sh (knoe.dev GKE)
|
||||
# but uses prole.org GCP project credentials and targets the k3s kubecontext.
|
||||
#
|
||||
# Gates access via Google Workspace OIDC (prole.org) so @prole.org identities
|
||||
# can sign in to Studio. Outside-domain users are rejected at this layer.
|
||||
#
|
||||
# Usage:
|
||||
# ./etc/init_oauth2_proxy_prole.sh
|
||||
#
|
||||
# Env vars (resolved from etc/secrets/* if not set in the shell):
|
||||
# OAUTH2_PROXY_CLIENT_ID ← from etc/secrets/oauth2-proxy-client-id-prole
|
||||
# OAUTH2_PROXY_CLIENT_SECRET ← from etc/secrets/oauth2-proxy-client-secret-prole
|
||||
# OAUTH2_PROXY_COOKIE_SECRET ← from etc/secrets/oauth2-proxy-cookie-secret-prole
|
||||
#
|
||||
# Optional:
|
||||
# K3S_KUBECONTEXT (default: $KUBECONTEXT then ambient)
|
||||
# NAMESPACE (default: supabase)
|
||||
#
|
||||
# Pre-reqs:
|
||||
# - OAuth 2.0 Web Application client created in the prole.org GCP project:
|
||||
# Authorized JS origins: https://db.prole.org
|
||||
# Authorized redirect URI: https://db.prole.org/oauth2/callback
|
||||
# Consent screen: Internal (prole.org Workspace)
|
||||
# Scopes: openid, email, profile
|
||||
# See deploy/gcp/gke/oauth2-proxy-google-oidc-secret-prole.example.yaml.
|
||||
# - Cookie secret generated with: openssl rand -base64 32
|
||||
# - Three values saved (chmod 0600) to:
|
||||
# etc/secrets/oauth2-proxy-client-id-prole
|
||||
# etc/secrets/oauth2-proxy-client-secret-prole
|
||||
# etc/secrets/oauth2-proxy-cookie-secret-prole
|
||||
#
|
||||
# After this script runs, patch the db.prole.org Ingress/IngressRoute to route
|
||||
# through oauth2-proxy:80 instead of supabase-kong:8000 directly (see next
|
||||
# steps printed at the end of this script).
|
||||
#
|
||||
# When knoe-auth Round 1 ships an OIDC OP at https://api.prole.org/auth, change
|
||||
# --provider=google to --provider=oidc --oidc-issuer-url=https://api.prole.org/auth
|
||||
# in deploy/opentofu/k3s/manifests/knoe/oauth2-proxy-deployment-prole.yaml and
|
||||
# re-run this script.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
MANIFEST_DIR="$REPO_ROOT/deploy/gcp/gke"
|
||||
K3S_MANIFEST_DIR="$REPO_ROOT/deploy/opentofu/k3s/manifests/knoe"
|
||||
|
||||
NAMESPACE="${NAMESPACE:-supabase}"
|
||||
KCTX="${K3S_KUBECONTEXT:-${KUBECONTEXT:-}}"
|
||||
|
||||
if [[ -n "$KCTX" ]]; then
|
||||
KCTX_FLAG=(--context="$KCTX")
|
||||
else
|
||||
KCTX_FLAG=()
|
||||
fi
|
||||
|
||||
log() { printf "[%s] %s\n" "$(date +%H:%M:%S)" "$*"; }
|
||||
die() { log "ERROR: $*" >&2; exit 1; }
|
||||
|
||||
resolve_secret() {
|
||||
local var="$1" file="$2" val="${!1:-}"
|
||||
if [[ -z "$val" && -f "$REPO_ROOT/etc/secrets/$file" ]]; then
|
||||
val="$(cat "$REPO_ROOT/etc/secrets/$file")"
|
||||
fi
|
||||
if [[ -z "$val" ]]; then
|
||||
die "missing $var (set the env var, or save the value into etc/secrets/$file)"
|
||||
fi
|
||||
printf '%s' "$val"
|
||||
}
|
||||
|
||||
for tool in kubectl envsubst; do
|
||||
command -v "$tool" >/dev/null 2>&1 || die "required tool not found: $tool"
|
||||
done
|
||||
|
||||
OAUTH2_PROXY_CLIENT_ID="$(resolve_secret OAUTH2_PROXY_CLIENT_ID oauth2-proxy-client-id-prole)"
|
||||
OAUTH2_PROXY_CLIENT_SECRET="$(resolve_secret OAUTH2_PROXY_CLIENT_SECRET oauth2-proxy-client-secret-prole)"
|
||||
OAUTH2_PROXY_COOKIE_SECRET="$(resolve_secret OAUTH2_PROXY_COOKIE_SECRET oauth2-proxy-cookie-secret-prole)"
|
||||
export OAUTH2_PROXY_CLIENT_ID OAUTH2_PROXY_CLIENT_SECRET OAUTH2_PROXY_COOKIE_SECRET
|
||||
|
||||
SECRET_TMPL="$MANIFEST_DIR/oauth2-proxy-google-oidc-secret-prole.example.yaml"
|
||||
DEPLOY_MANIFEST="$K3S_MANIFEST_DIR/oauth2-proxy-deployment-prole.yaml"
|
||||
|
||||
[[ -f "$SECRET_TMPL" ]] || die "missing manifest: $SECRET_TMPL"
|
||||
[[ -f "$DEPLOY_MANIFEST" ]] || die "missing manifest: $DEPLOY_MANIFEST"
|
||||
|
||||
log "==> oauth2-proxy bootstrap (prole.org / k3s)"
|
||||
log " namespace : $NAMESPACE"
|
||||
log " kubectx : ${KCTX:-<ambient>}"
|
||||
|
||||
log "Applying oauth2-proxy-google-oidc Secret ..."
|
||||
envsubst '${OAUTH2_PROXY_CLIENT_ID} ${OAUTH2_PROXY_CLIENT_SECRET} ${OAUTH2_PROXY_COOKIE_SECRET}' \
|
||||
< "$SECRET_TMPL" \
|
||||
| kubectl "${KCTX_FLAG[@]}" -n "$NAMESPACE" apply -f -
|
||||
|
||||
log "Applying oauth2-proxy ServiceAccount + Service + Deployment ..."
|
||||
kubectl "${KCTX_FLAG[@]}" -n "$NAMESPACE" apply -f "$DEPLOY_MANIFEST"
|
||||
|
||||
log "Waiting for oauth2-proxy Deployment to become Ready (timeout 180s) ..."
|
||||
kubectl "${KCTX_FLAG[@]}" -n "$NAMESPACE" rollout status deployment/oauth2-proxy --timeout=180s
|
||||
|
||||
log "==> oauth2-proxy bootstrap complete."
|
||||
echo ""
|
||||
echo " Next steps (NOT performed by this script):"
|
||||
echo " 1. Patch the db.prole.org Ingress/IngressRoute so traffic routes"
|
||||
echo " through oauth2-proxy:80 instead of supabase-kong:8000 directly."
|
||||
echo " Check current routing:"
|
||||
echo " kubectl -n supabase get ingress,ingressroute"
|
||||
echo " 2. Remove or disable any basic-auth plugin on the Studio route in"
|
||||
echo " the supabase-kong configmap; rollout-restart supabase-kong."
|
||||
echo " 3. Browser-test: https://db.prole.org/ → Google sign-in (prole.org"
|
||||
echo " account). Verify a non-prole.org account receives 403."
|
||||
echo ""
|
||||
146
monitoring/kps-values-k3s.yaml
Normal file
146
monitoring/kps-values-k3s.yaml
Normal file
@ -0,0 +1,146 @@
|
||||
# kube-prometheus-stack (kps) Helm values — k3s deploy mode (prole.org homelab).
|
||||
#
|
||||
# Apply with:
|
||||
# helm upgrade kps prometheus-community/kube-prometheus-stack \
|
||||
# --namespace monitoring \
|
||||
# -f monitoring/kps-values-k3s.yaml
|
||||
#
|
||||
# Auth model:
|
||||
# - Kerberos/knoe-auth users arrive via grafana-proxy nginx with X-WEBAUTH-USER
|
||||
# header → Grafana auth.proxy auto-login (no password prompt).
|
||||
# - Google Workspace users (chrisfu@prole.org etc.) use auth.google sign-in
|
||||
# button on the Grafana login page. The grafana-proxy nginx passes login
|
||||
# paths through unauthenticated so the OAuth flow can complete.
|
||||
# - chrisfu@prole.org → Admin; all other @prole.org users → Editor.
|
||||
# - Local break-glass login (adminPassword) remains available.
|
||||
#
|
||||
# Storage: uses local-path (k3s Rancher default). Override storageClassName if
|
||||
# the homelab has a different provisioner (NFS, Longhorn, etc.).
|
||||
---
|
||||
alertmanager:
|
||||
alertmanagerSpec:
|
||||
nodeSelector:
|
||||
prole.org/node-role: general
|
||||
storage:
|
||||
volumeClaimTemplate:
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
storageClassName: local-path
|
||||
|
||||
grafana:
|
||||
enabled: true
|
||||
# adminPassword is the local break-glass; primary auth is Google OAuth +
|
||||
# knoe-auth proxy (below). Stored in the prole.org vault.
|
||||
adminPassword: admin
|
||||
|
||||
nodeSelector:
|
||||
prole.org/node-role: general
|
||||
|
||||
initChownData:
|
||||
enabled: false
|
||||
|
||||
persistence:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
enabled: true
|
||||
size: 10Gi
|
||||
storageClassName: local-path
|
||||
type: sts
|
||||
|
||||
service:
|
||||
port: 80
|
||||
targetPort: 3000
|
||||
|
||||
sidecar:
|
||||
dashboards:
|
||||
enabled: true
|
||||
label: grafana_dashboard
|
||||
labelValue: "1"
|
||||
datasources:
|
||||
enabled: true
|
||||
label: grafana_datasource
|
||||
labelValue: "1"
|
||||
|
||||
# Mount Google OAuth client credentials from the grafana-google-oidc Secret.
|
||||
# Created by etc/init_grafana_oauth_prole.sh from
|
||||
# etc/secrets/grafana-google-oidc-client-{id,secret}-prole.
|
||||
# Provides GF_AUTH_GOOGLE_CLIENT_ID and GF_AUTH_GOOGLE_CLIENT_SECRET env vars.
|
||||
envFromSecret: grafana-google-oidc
|
||||
|
||||
grafana.ini:
|
||||
server:
|
||||
domain: svc.prole.org
|
||||
root_url: "https://svc.prole.org/grafana"
|
||||
serve_from_sub_path: true
|
||||
security:
|
||||
cookie_secure: true
|
||||
cookie_samesite: lax
|
||||
csrf_trusted_origins: svc.prole.org
|
||||
csrf_additional_headers: X-Forwarded-Host
|
||||
"live":
|
||||
allowed_origins: "https://svc.prole.org"
|
||||
auth:
|
||||
disable_login_form: false
|
||||
token_rotation_interval_minutes: 1440
|
||||
# Proxy auth: Kerberos/knoe-auth users arriving via grafana-proxy nginx.
|
||||
# The nginx proxy injects X-WEBAUTH-USER after verifying with knoe-auth;
|
||||
# Grafana trusts this header and auto-logs the user in without a password.
|
||||
"auth.proxy":
|
||||
enabled: true
|
||||
header_name: X-WEBAUTH-USER
|
||||
header_property: username
|
||||
auto_sign_up: true
|
||||
# Google OAuth: prole.org Workspace users sign in via the Google button on
|
||||
# the Grafana login page. Requires grafana-proxy nginx to pass /grafana/login
|
||||
# endpoints through unauthenticated (see grafana-proxy-configmap.yaml).
|
||||
"auth.google":
|
||||
enabled: true
|
||||
allowed_domains: prole.org
|
||||
scopes: "openid email profile"
|
||||
auth_url: https://accounts.google.com/o/oauth2/v2/auth
|
||||
token_url: https://oauth2.googleapis.com/token
|
||||
api_url: https://openidconnect.googleapis.com/v1/userinfo
|
||||
# JMESPath: chrisfu gets Admin; every other @prole.org user gets Editor.
|
||||
role_attribute_path: "contains(['chrisfu@prole.org'], email) && 'Admin' || 'Editor'"
|
||||
skip_org_role_sync: false
|
||||
users:
|
||||
auto_assign_org_role: Editor
|
||||
|
||||
kube-state-metrics:
|
||||
nodeSelector:
|
||||
prole.org/node-role: general
|
||||
|
||||
prometheus:
|
||||
prometheusSpec:
|
||||
nodeSelector:
|
||||
prole.org/node-role: general
|
||||
storageSpec:
|
||||
volumeClaimTemplate:
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 30Gi
|
||||
storageClassName: local-path
|
||||
|
||||
prometheus-node-exporter:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: NotIn
|
||||
values:
|
||||
- pi.prole.org
|
||||
nodeSelector:
|
||||
prole.org/node-role: general
|
||||
|
||||
prometheusOperator:
|
||||
nodeSelector:
|
||||
prole.org/node-role: general
|
||||
Loading…
Reference in New Issue
Block a user