Register rapp-qonto KeyCape client
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s

This commit is contained in:
tegwick 2026-07-27 20:17:56 +02:00
parent 9026d7f904
commit 11a14648c4
3 changed files with 44 additions and 18 deletions

View file

@ -131,6 +131,15 @@ clients:
allowedScopes: ["openid", "profile", "email", "groups"]
grantTypes: ["authorization_code"]
clientType: "public"
- clientId: "rapp-qonto-client"
displayName: "rapp-qonto workload"
allowedScopes: ["qonto:read"]
grantTypes: ["client_credentials"]
clientType: "confidential"
secretRef: "env:KEYCAPE_RAPP_QONTO_CLIENT_SECRET"
serviceSubject: "rapp-qonto"
tenant: "tenant:friendly:binky"
roles: ["qonto-reader"]
EOF
)

View file

@ -54,7 +54,7 @@ spec:
# 2026-05-24: direct-imported into railiance01 k3s for the
# bootstrap-console OIDC/MFA rollout. Use IfNotPresent while the
# HTTP registry push/pull path is being cleaned up.
image: 92.205.130.254:32166/coulomb/key-cape:main-nonce-0601
image: 92.205.130.254:32166/coulomb/key-cape:main-e877d27-2
imagePullPolicy: IfNotPresent
ports:
@ -65,6 +65,11 @@ spec:
env:
- name: KEYCAPE_CONFIG
value: /etc/keycape/config.yaml
- name: KEYCAPE_RAPP_QONTO_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: keycape-rapp-qonto-client
key: client-secret
volumeMounts:
# keycape-config Secret provides config.yaml and key.pem

View file

@ -34,6 +34,18 @@ OPENBAO_CLIENT = {
"clientType": "public",
}
RAPP_QONTO_CLIENT = {
"clientId": "rapp-qonto-client",
"displayName": "rapp-qonto workload",
"allowedScopes": ["qonto:read"],
"grantTypes": ["client_credentials"],
"clientType": "confidential",
"secretRef": "env:KEYCAPE_RAPP_QONTO_CLIENT_SECRET",
"serviceSubject": "rapp-qonto",
"tenant": "tenant:friendly:binky",
"roles": ["qonto-reader"],
}
LLDAP_REQUIRED = {
"userOU": "ou=people",
"groupOU": "ou=groups",
@ -55,38 +67,38 @@ def load_config() -> dict[str, Any]:
return config
def client_errors(config: dict[str, Any]) -> list[str]:
def client_errors(config: dict[str, Any], required: dict[str, Any]) -> list[str]:
clients = config.get("clients")
if not isinstance(clients, list):
return ["clients must be a list"]
target = next(
(client for client in clients if isinstance(client, dict) and client.get("clientId") == OPENBAO_CLIENT["clientId"]),
(client for client in clients if isinstance(client, dict) and client.get("clientId") == required["clientId"]),
None,
)
if target is None:
return ["missing openbao-admin client"]
return [f"missing {required['clientId']} client"]
errors: list[str] = []
for key in ("displayName", "clientType"):
if target.get(key) != OPENBAO_CLIENT[key]:
errors.append(f"{key} should be {OPENBAO_CLIENT[key]!r}")
for key in ("redirectUris", "allowedScopes", "grantTypes"):
missing = sorted(set(OPENBAO_CLIENT[key]) - set(target.get(key) or []))
if missing:
errors.append(f"{key} missing: {', '.join(missing)}")
for key, expected in required.items():
if key in ("redirectUris", "allowedScopes", "grantTypes", "roles"):
missing = sorted(set(expected) - set(target.get(key) or []))
if missing:
errors.append(f"{required['clientId']}.{key} missing: {', '.join(missing)}")
elif target.get(key) != expected:
errors.append(f"{required['clientId']}.{key} should be {expected!r}")
return errors
def upsert_client(config: dict[str, Any]) -> dict[str, Any]:
def upsert_client(config: dict[str, Any], required: dict[str, Any]) -> dict[str, Any]:
clients = config.get("clients")
if not isinstance(clients, list):
clients = []
config["clients"] = clients
for index, client in enumerate(clients):
if isinstance(client, dict) and client.get("clientId") == OPENBAO_CLIENT["clientId"]:
clients[index] = dict(OPENBAO_CLIENT)
if isinstance(client, dict) and client.get("clientId") == required["clientId"]:
clients[index] = dict(required)
return config
clients.append(dict(OPENBAO_CLIENT))
clients.append(dict(required))
return config
@ -111,7 +123,7 @@ def enforce_lldap_defaults(config: dict[str, Any]) -> dict[str, Any]:
def render_patch(config: dict[str, Any]) -> None:
updated = enforce_lldap_defaults(upsert_client(config))
updated = enforce_lldap_defaults(upsert_client(upsert_client(config, OPENBAO_CLIENT), RAPP_QONTO_CLIENT))
config_text = yaml.safe_dump(updated, sort_keys=False)
encoded = base64.b64encode(config_text.encode("utf-8")).decode("ascii")
json.dump({"data": {"config.yaml": encoded}}, sys.stdout, separators=(",", ":"))
@ -119,12 +131,12 @@ def render_patch(config: dict[str, Any]) -> None:
def verify(config: dict[str, Any]) -> None:
errors = client_errors(config) + lldap_errors(config)
errors = client_errors(config, OPENBAO_CLIENT) + client_errors(config, RAPP_QONTO_CLIENT) + lldap_errors(config)
if errors:
for error in errors:
print(f"[FAIL] {error}")
raise SystemExit(1)
print("[PASS] openbao-admin client and LLDAP OU lookup settings are present")
print("[PASS] openbao-admin and rapp-qonto clients and LLDAP OU lookup settings are present")
def main() -> None: