security(hermes): canary current oauth proxy
This commit is contained in:
parent
a9b86d4cc4
commit
bd7c1640ee
@ -29,6 +29,12 @@ resources:
|
||||
- agent-ingress.yaml
|
||||
|
||||
configMapGenerator:
|
||||
- name: hermes-chat-oauth-templates
|
||||
namespace: hermes
|
||||
files:
|
||||
- error.html=oauth2-proxy-templates/error.html
|
||||
options:
|
||||
disableNameSuffixHash: true
|
||||
- name: hermes-operator-guide
|
||||
namespace: hermes
|
||||
files:
|
||||
|
||||
29
services/hermes/oauth2-proxy-templates/error.html
Normal file
29
services/hermes/oauth2-proxy-templates/error.html
Normal file
@ -0,0 +1,29 @@
|
||||
{{define "error.html"}}
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>{{.StatusCode}} {{.Title}}</title>
|
||||
{{if or (eq .StatusCode 500) (eq .Message "Login Failed: Unable to find a valid CSRF token. Please try again.")}}<meta http-equiv="refresh" content="0;url={{.ProxyPrefix}}/sign_in?rd=/">{{end}}
|
||||
<style>
|
||||
body{margin:0;min-height:100vh;display:grid;place-items:center;background:#f5f5f5;color:#333;font:16px/1.5 system-ui,sans-serif}
|
||||
main{width:min(560px,calc(100% - 40px));box-sizing:border-box;padding:36px;border:1px solid #ddd;border-radius:14px;background:#fff;text-align:center;box-shadow:0 12px 45px #0002}
|
||||
h1{font-size:3rem;margin:.2rem}.detail{color:#666}a{display:inline-block;margin-top:18px;padding:10px 16px;border-radius:8px;background:#00bfa5;color:#fff;text-decoration:none}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
{{if or (eq .StatusCode 500) (eq .Message "Login Failed: Unable to find a valid CSRF token. Please try again.")}}
|
||||
<h1>Signing you back in…</h1>
|
||||
<p class="detail">The previous one-time login callback expired or was already used. Hermes is starting a fresh sign-in automatically.</p>
|
||||
<a href="{{.ProxyPrefix}}/sign_in?rd=/">Continue now</a>
|
||||
{{else}}
|
||||
<h1>{{.StatusCode}} {{.Title}}</h1>
|
||||
{{if .Message}}<p class="detail">{{.Message}}</p>{{end}}
|
||||
<a href="{{.ProxyPrefix}}/sign_in?rd=/">Sign in again</a>
|
||||
{{end}}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@ -9,43 +9,6 @@ data:
|
||||
brad@bstein.dev
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: hermes-chat-oauth-templates
|
||||
namespace: hermes
|
||||
data:
|
||||
error.html: |
|
||||
{{define "error.html"}}
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>{{.StatusCode}} {{.Title}}</title>
|
||||
{{if or (eq .StatusCode 500) (eq .Message "Login Failed: Unable to find a valid CSRF token. Please try again.")}}<meta http-equiv="refresh" content="0;url={{.ProxyPrefix}}/sign_in?rd=/">{{end}}
|
||||
<style>
|
||||
body{margin:0;min-height:100vh;display:grid;place-items:center;background:#f5f5f5;color:#333;font:16px/1.5 system-ui,sans-serif}
|
||||
main{width:min(560px,calc(100% - 40px));box-sizing:border-box;padding:36px;border:1px solid #ddd;border-radius:14px;background:#fff;text-align:center;box-shadow:0 12px 45px #0002}
|
||||
h1{font-size:3rem;margin:.2rem}.detail{color:#666}a{display:inline-block;margin-top:18px;padding:10px 16px;border-radius:8px;background:#00bfa5;color:#fff;text-decoration:none}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
{{if or (eq .StatusCode 500) (eq .Message "Login Failed: Unable to find a valid CSRF token. Please try again.")}}
|
||||
<h1>Signing you back in…</h1>
|
||||
<p class="detail">The previous one-time login callback expired or was already used. Hermes is starting a fresh sign-in automatically.</p>
|
||||
<a href="{{.ProxyPrefix}}/sign_in?rd=/">Continue now</a>
|
||||
{{else}}
|
||||
<h1>{{.StatusCode}} {{.Title}}</h1>
|
||||
{{if .Message}}<p class="detail">{{.Message}}</p>{{end}}
|
||||
<a href="{{.ProxyPrefix}}/sign_in?rd=/">Sign in again</a>
|
||||
{{end}}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: oauth2-proxy-hermes-agent
|
||||
@ -276,7 +239,7 @@ spec:
|
||||
labels:
|
||||
app: oauth2-proxy-hermes-chat
|
||||
annotations:
|
||||
ai.bstein.dev/config-rev: "20260809-expired-callback-recovery"
|
||||
ai.bstein.dev/config-rev: "20260809-oauth2-proxy-7-15-canary"
|
||||
vault.hashicorp.com/agent-inject: "true"
|
||||
vault.hashicorp.com/agent-pre-populate-only: "true"
|
||||
vault.hashicorp.com/role: hermes-chat
|
||||
@ -292,7 +255,7 @@ spec:
|
||||
automountServiceAccountToken: true
|
||||
containers:
|
||||
- name: oauth2-proxy
|
||||
image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0@sha256:dcb6ff8dd21bf3058f6a22c6fa385fa5b897a9cd3914c88a2cc2bb0a85f8065d
|
||||
image: quay.io/oauth2-proxy/oauth2-proxy:v7.15.3@sha256:10a1165743a192e1940b4708fb9647027185ce11a681a1c5519b442ff7f1f561
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- --provider=oidc
|
||||
@ -311,6 +274,9 @@ spec:
|
||||
- --cookie-path=/
|
||||
- --cookie-secure=true
|
||||
- --cookie-samesite=lax
|
||||
- --cookie-csrf-expire=10m
|
||||
- --cookie-csrf-per-request=true
|
||||
- --cookie-csrf-per-request-limit=8
|
||||
- --cookie-refresh=1h
|
||||
- --cookie-expire=8h
|
||||
- --custom-templates-dir=/etc/oauth2-proxy/templates
|
||||
@ -319,6 +285,7 @@ spec:
|
||||
- --http-address=0.0.0.0:4180
|
||||
- --skip-provider-button=true
|
||||
- --reverse-proxy=true
|
||||
- --trusted-proxy-ip=10.42.0.0/16
|
||||
ports:
|
||||
- {name: http, containerPort: 4180}
|
||||
readinessProbe:
|
||||
|
||||
@ -104,16 +104,16 @@ def test_chat_oauth_allows_stale_service_worker_retirement():
|
||||
assert "--skip-auth-route=GET=^/sw[.]js([?].*)?$" in args
|
||||
assert "--custom-templates-dir=/etc/oauth2-proxy/templates" in args
|
||||
|
||||
template = next(
|
||||
document
|
||||
for document in documents
|
||||
if document["kind"] == "ConfigMap"
|
||||
and document["metadata"]["name"] == "hermes-chat-oauth-templates"
|
||||
)["data"]["error.html"]
|
||||
template = (HERMES / "oauth2-proxy-templates" / "error.html").read_text()
|
||||
assert 'http-equiv="refresh"' in template
|
||||
assert "Unable to find a valid CSRF token" in template
|
||||
assert "expired or was already used" in template
|
||||
assert "/sign_in?rd=/" in template
|
||||
container = deployment["spec"]["template"]["spec"]["containers"][0]
|
||||
assert "v7.15.3@sha256:10a1165743a192e" in container["image"]
|
||||
assert "--cookie-csrf-per-request=true" in args
|
||||
assert "--cookie-csrf-per-request-limit=8" in args
|
||||
assert "--trusted-proxy-ip=10.42.0.0/16" in args
|
||||
|
||||
|
||||
def test_chat_auth_file_mount_survives_atomic_provider_refresh():
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user