fix(v02): wire Keycloak OIDC runtime

This commit is contained in:
Codex Agent
2026-06-04 11:36:55 +08:00
parent 36b264f212
commit e70dab1f88
11 changed files with 319 additions and 44 deletions
+3
View File
@@ -155,6 +155,9 @@
"HWLAB_BOOTSTRAP_ADMIN_USERNAME": "admin",
"HWLAB_BOOTSTRAP_ADMIN_DISPLAY_NAME": "HWLAB v0.2 Admin",
"HWLAB_BOOTSTRAP_ADMIN_PASSWORD_HASH": "secretRef:hwlab-v02-bootstrap-admin/password-hash",
"HWLAB_KEYCLOAK_ISSUER": "https://auth.74-48-78-17.nip.io/realms/hwlab",
"HWLAB_KEYCLOAK_CLIENT_ID": "hwlab-cloud-web",
"HWLAB_KEYCLOAK_CLIENT_SECRET": "secretRef:hwlab-cloud-web-client/client-secret",
"HWLAB_CODE_AGENT_ADAPTER": "agentrun-v01",
"AGENTRUN_MGR_URL": "http://agentrun-mgr.agentrun-v01.svc.cluster.local:8080",
"HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID": "G14",
+93 -44
View File
@@ -1,15 +1,3 @@
apiVersion: v1
kind: Secret
metadata:
name: hwlab-cloud-web-client
namespace: keycloak
labels:
app.kubernetes.io/name: hwlab-cloud-web-client
hwlab.pikastech.local/component: identity
type: Opaque
stringData:
client-secret: kc-client-secret-placeholder
---
apiVersion: batch/v1
kind: Job
metadata:
@@ -19,14 +7,15 @@ metadata:
app.kubernetes.io/name: keycloak-bootstrap-realm
hwlab.pikastech.local/component: identity
spec:
backoffLimit: 3
backoffLimit: 1
activeDeadlineSeconds: 600
template:
metadata:
labels:
app.kubernetes.io/name: keycloak-bootstrap-realm
hwlab.pikastech.local/component: identity
spec:
restartPolicy: OnFailure
restartPolicy: Never
initContainers:
- name: wait-for-keycloak
image: curlimages/curl:8.10.1
@@ -50,7 +39,7 @@ spec:
exit 1
containers:
- name: bootstrap
image: curlimages/curl:8.10.1
image: quay.io/keycloak/keycloak:25.0
env:
- name: PASSWORD
valueFrom:
@@ -62,41 +51,101 @@ spec:
secretKeyRef:
name: hwlab-cloud-web-client
key: client-secret
- name: KEYCLOAK_BASE_URL
value: http://keycloak.keycloak.svc.cluster.local:8080
- name: REALM
value: hwlab
- name: CLIENT_ID
value: hwlab-cloud-web
- name: REDIRECT_URI_DEV
value: http://74.48.78.17:19667/auth/oidc/callback
- name: WEB_ORIGIN_DEV
value: http://74.48.78.17:19666
- name: ACCESS_TOKEN_LIFESPAN
value: "1440"
- name: SSO_SESSION_MAX_LIFESPAN
value: "86400"
command:
- /bin/sh
- -c
- |
set -eu
KC=http://keycloak.keycloak.svc.cluster.local:8080
REALM=hwlab
echo fetching-admin-token
curl -sf -X POST $KC/realms/master/protocol/openid-connect/token \
-H 'content-type: application/x-www-form-urlencoded' \
--data-urlencode 'username=admin' \
--data-urlencode "password=$PASSWORD" \
--data-urlencode 'grant_type=password' \
--data-urlencode 'client_id=admin-cli' > /tmp/token.json
TOKEN=$(grep -oE '"access_token":"[^"]+' /tmp/token.json | head -1 | cut -d'"' -f4)
if [ -z "$TOKEN" ]; then
echo no-token
cat /tmp/token.json
exit 1
fi
echo token-ok
code=$(curl -s -o /tmp/realm.json -w '%{http_code}' -H "Authorization: Bearer $TOKEN" $KC/admin/realms/$REALM)
if [ "$code" = "200" ]; then
echo realm-already-exists
KC="$KEYCLOAK_BASE_URL"
KCADM=/opt/keycloak/bin/kcadm.sh
CONFIG=/tmp/kcadm.config
echo "fetching-admin-token"
"$KCADM" config credentials \
--config "$CONFIG" \
--server "$KC" \
--realm master \
--user admin \
--password "$PASSWORD" \
--client admin-cli >/tmp/kcadm-login.log
echo "token-ok"
if "$KCADM" get "realms/$REALM" --config "$CONFIG" >/tmp/realm.json 2>/tmp/realm.err; then
echo "realm-already-exists"
"$KCADM" update "realms/$REALM" \
--config "$CONFIG" \
-s enabled=true \
-s registrationAllowed=true \
-s verifyEmail=false \
-s loginWithEmailAllowed=true \
-s duplicateEmailsAllowed=false \
-s resetPasswordAllowed=false \
-s editUsernameAllowed=false \
-s bruteForceProtected=false \
-s accessTokenLifespan="$ACCESS_TOKEN_LIFESPAN" \
-s ssoSessionIdleTimeout="$SSO_SESSION_MAX_LIFESPAN" \
-s ssoSessionMaxLifespan="$SSO_SESSION_MAX_LIFESPAN"
echo "realm-updated"
else
echo creating-realm
curl -sf -X POST $KC/admin/realms -H "Authorization: Bearer $TOKEN" -H 'content-type: application/json' -d '{"realm":"hwlab","enabled":true,"registrationAllowed":true,"verifyEmail":false,"loginWithEmailAllowed":true,"duplicateEmailsAllowed":false,"resetPasswordAllowed":false,"editUsernameAllowed":false,"bruteForceProtected":false,"accessTokenLifespan":1440,"ssoSessionIdleTimeout":86400,"ssoSessionMaxLifespan":86400}'
echo realm-created
echo "creating-realm"
"$KCADM" create realms \
--config "$CONFIG" \
-s realm="$REALM" \
-s enabled=true \
-s registrationAllowed=true \
-s verifyEmail=false \
-s loginWithEmailAllowed=true \
-s duplicateEmailsAllowed=false \
-s resetPasswordAllowed=false \
-s editUsernameAllowed=false \
-s bruteForceProtected=false \
-s accessTokenLifespan="$ACCESS_TOKEN_LIFESPAN" \
-s ssoSessionIdleTimeout="$SSO_SESSION_MAX_LIFESPAN" \
-s ssoSessionMaxLifespan="$SSO_SESSION_MAX_LIFESPAN"
echo "realm-created"
fi
client_code=$(curl -s -o /tmp/clients.json -w '%{http_code}' -H "Authorization: Bearer $TOKEN" "$KC/admin/realms/$REALM/clients?clientId=hwlab-cloud-web")
if [ "$client_code" = "200" ] && grep -q '"clientId":"hwlab-cloud-web"' /tmp/clients.json; then
echo client-already-exists
CLIENT_UUID=$("$KCADM" get clients \
--config "$CONFIG" \
-r "$REALM" \
-q clientId="$CLIENT_ID" \
--fields id \
--format csv \
--noquotes | head -1 | tr -d '\r')
if [ -n "$CLIENT_UUID" ]; then
echo "client-already-exists"
"$KCADM" update "clients/$CLIENT_UUID" \
--config "$CONFIG" \
-r "$REALM" \
-s clientId="$CLIENT_ID" \
-s secret="$CLIENT_SECRET" \
-s 'redirectUris=["'"$REDIRECT_URI_DEV"'"]' \
-s 'webOrigins=["'"$WEB_ORIGIN_DEV"'"]' \
-s standardFlowEnabled=true \
-s directAccessGrantsEnabled=true
echo "client-updated"
else
echo creating-client
curl -sf -X POST $KC/admin/realms/$REALM/clients -H "Authorization: Bearer $TOKEN" -H 'content-type: application/json' -d "{\"clientId\":\"hwlab-cloud-web\",\"secret\":\"$CLIENT_SECRET\",\"redirectUris\":[\"http://74.48.78.17:19667/auth/oidc/callback\",\"https://auth.74-48-78-17.nip.io/auth/oidc/callback\"],\"webOrigins\":[\"+\"],\"standardFlowEnabled\":true,\"directAccessGrantsEnabled\":true}"
echo client-created
echo "creating-client"
"$KCADM" create clients \
--config "$CONFIG" \
-r "$REALM" \
-s clientId="$CLIENT_ID" \
-s secret="$CLIENT_SECRET" \
-s 'redirectUris=["'"$REDIRECT_URI_DEV"'"]' \
-s 'webOrigins=["'"$WEB_ORIGIN_DEV"'"]' \
-s standardFlowEnabled=true \
-s directAccessGrantsEnabled=true
echo "client-created"
fi
echo keycloak-bootstrap-complete
echo "keycloak-bootstrap-complete"
+56
View File
@@ -0,0 +1,56 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: keycloak-frpc-config
namespace: keycloak
labels:
app.kubernetes.io/name: keycloak-frpc
hwlab.pikastech.local/component: identity
data:
frpc.toml: |
serverAddr = "74.48.78.17"
serverPort = 7000
loginFailExit = true
[[proxies]]
name = "keycloak-public-https"
type = "tcp"
localIP = "keycloak.keycloak.svc.cluster.local"
localPort = 8080
remotePort = 28443
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak-frpc
namespace: keycloak
labels:
app.kubernetes.io/name: keycloak-frpc
hwlab.pikastech.local/component: identity
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: keycloak-frpc
template:
metadata:
labels:
app.kubernetes.io/name: keycloak-frpc
hwlab.pikastech.local/component: identity
spec:
containers:
- name: frpc
image: fatedier/frpc:v0.68.1
args:
- -c
- /etc/frp/frpc.toml
volumeMounts:
- name: config
mountPath: /etc/frp
readOnly: true
volumes:
- name: config
configMap:
name: keycloak-frpc-config
+1
View File
@@ -6,6 +6,7 @@ resources:
- postgres.yaml
- keycloak.yaml
- keycloak-bootstrap-job.yaml
- keycloak-frpc.yaml
commonLabels:
app.kubernetes.io/part-of: hwlab
hwlab.pikastech.local/profile: dev
+39
View File
@@ -0,0 +1,39 @@
# Caddyfile for auth.74-48-78-17.nip.io (HWLAB Keycloak public HTTPS)
# This Caddyfile runs on the master server and reverse-proxies HTTPS to
# the G14 keycloak Service via master frps (port 28443).
#
# Master-side dependency tree:
#
# client browser
# -> 74.48.78.17:443 (Caddy, this file)
# -> 127.0.0.1:28443 (master frps remotePort, see frps.dev.toml)
# -> G14:/root/hwlab-v02/.worktree/.../deploy/k8s/keycloak/keycloak-frpc.yaml
# -> keycloak.keycloak.svc.cluster.local:8080
#
# Install: download caddy 2.x from https://github.com/caddyserver/caddy/releases
# Put binary at /usr/local/bin/caddy and Caddyfile at /etc/caddy/Caddyfile.
# The systemd unit caddy.service goes to /etc/systemd/system/caddy.service.
# Run `systemctl daemon-reload && systemctl enable --now caddy`.
# Caddy will auto-request a Let's Encrypt production cert for the first
# domain in the config (auth.74-48-78-17.nip.io).
# To validate the chain end-to-end first, point acme_ca to staging:
#
# acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
#
# Then remove the line to switch to production.
{
email ops@pikas.tech
}
auth.74-48-78-17.nip.io {
encode zstd gzip
reverse_proxy 127.0.0.1:28443 {
header_up Host {host}
header_up X-Real-IP {remote_host}
transport http {
dial_timeout 5s
response_header_timeout 30s
}
}
}
+26
View File
@@ -0,0 +1,26 @@
[Unit]
Description=Caddy (HWLAB Keycloak public HTTPS reverse proxy)
Documentation=https://caddyserver.com/docs/
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/caddy run --environ --config /etc/caddy/Caddyfile --adapter caddyfile
ExecReload=/usr/local/bin/caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
PrivateDevices=yes
PrivateTmp=yes
ProtectSystem=full
ProtectHome=read-only
ReadWritePaths=/var/lib/caddy /var/log/caddy /root/.local/share/caddy
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=yes
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
+18
View File
@@ -0,0 +1,18 @@
# Master-side frps container launch equivalent.
# The actual running container is `hwlab-frps-dev` (fatedier/frps:v0.68.1)
# started by the existing flow with restart policy `unless-stopped`.
# It bind-mounts /opt/hwlab-frp/frps.dev.toml -> /etc/frp/frps.toml (ro).
# To recreate from scratch:
#
# mkdir -p /opt/hwlab-frp
# cp deploy/master/frp/frps.dev.toml /opt/hwlab-frp/
# docker run -d --name hwlab-frps-dev --restart unless-stopped \
# -v /opt/hwlab-frp/frps.dev.toml:/etc/frp/frps.toml:ro \
# -p 7000:7000 \
# -p 16666:16666 -p 16667:16667 \
# -p 17666:17666 -p 17667:17667 \
# -p 18666:18666 -p 18667:18667 \
# -p 19666:19666 -p 19667:19667 \
# -p 7402:7402 \
# -p 28443:28443 \
# fatedier/frps:v0.68.1 -c /etc/frp/frps.toml
+41
View File
@@ -0,0 +1,41 @@
bindPort = 7000
[[allowPorts]]
start = 16666
end = 16666
[[allowPorts]]
start = 16667
end = 16667
[[allowPorts]]
start = 17666
end = 17666
[[allowPorts]]
start = 17667
end = 17667
[[allowPorts]]
start = 18666
end = 18666
[[allowPorts]]
start = 18667
end = 18667
[[allowPorts]]
start = 19666
end = 19666
[[allowPorts]]
start = 19667
end = 19667
[[allowPorts]]
start = 7402
end = 7402
[[allowPorts]]
start = 28443
end = 28443