Register rapp-qonto KeyCape client
This commit is contained in:
parent
9026d7f904
commit
11a14648c4
3 changed files with 44 additions and 18 deletions
|
|
@ -131,6 +131,15 @@ clients:
|
||||||
allowedScopes: ["openid", "profile", "email", "groups"]
|
allowedScopes: ["openid", "profile", "email", "groups"]
|
||||||
grantTypes: ["authorization_code"]
|
grantTypes: ["authorization_code"]
|
||||||
clientType: "public"
|
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
|
EOF
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ spec:
|
||||||
# 2026-05-24: direct-imported into railiance01 k3s for the
|
# 2026-05-24: direct-imported into railiance01 k3s for the
|
||||||
# bootstrap-console OIDC/MFA rollout. Use IfNotPresent while the
|
# bootstrap-console OIDC/MFA rollout. Use IfNotPresent while the
|
||||||
# HTTP registry push/pull path is being cleaned up.
|
# 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
|
imagePullPolicy: IfNotPresent
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
|
|
@ -65,6 +65,11 @@ spec:
|
||||||
env:
|
env:
|
||||||
- name: KEYCAPE_CONFIG
|
- name: KEYCAPE_CONFIG
|
||||||
value: /etc/keycape/config.yaml
|
value: /etc/keycape/config.yaml
|
||||||
|
- name: KEYCAPE_RAPP_QONTO_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: keycape-rapp-qonto-client
|
||||||
|
key: client-secret
|
||||||
|
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
# keycape-config Secret provides config.yaml and key.pem
|
# keycape-config Secret provides config.yaml and key.pem
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,18 @@ OPENBAO_CLIENT = {
|
||||||
"clientType": "public",
|
"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 = {
|
LLDAP_REQUIRED = {
|
||||||
"userOU": "ou=people",
|
"userOU": "ou=people",
|
||||||
"groupOU": "ou=groups",
|
"groupOU": "ou=groups",
|
||||||
|
|
@ -55,38 +67,38 @@ def load_config() -> dict[str, Any]:
|
||||||
return config
|
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")
|
clients = config.get("clients")
|
||||||
if not isinstance(clients, list):
|
if not isinstance(clients, list):
|
||||||
return ["clients must be a list"]
|
return ["clients must be a list"]
|
||||||
target = next(
|
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,
|
None,
|
||||||
)
|
)
|
||||||
if target is None:
|
if target is None:
|
||||||
return ["missing openbao-admin client"]
|
return [f"missing {required['clientId']} client"]
|
||||||
|
|
||||||
errors: list[str] = []
|
errors: list[str] = []
|
||||||
for key in ("displayName", "clientType"):
|
for key, expected in required.items():
|
||||||
if target.get(key) != OPENBAO_CLIENT[key]:
|
if key in ("redirectUris", "allowedScopes", "grantTypes", "roles"):
|
||||||
errors.append(f"{key} should be {OPENBAO_CLIENT[key]!r}")
|
missing = sorted(set(expected) - set(target.get(key) or []))
|
||||||
for key in ("redirectUris", "allowedScopes", "grantTypes"):
|
if missing:
|
||||||
missing = sorted(set(OPENBAO_CLIENT[key]) - set(target.get(key) or []))
|
errors.append(f"{required['clientId']}.{key} missing: {', '.join(missing)}")
|
||||||
if missing:
|
elif target.get(key) != expected:
|
||||||
errors.append(f"{key} missing: {', '.join(missing)}")
|
errors.append(f"{required['clientId']}.{key} should be {expected!r}")
|
||||||
return errors
|
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")
|
clients = config.get("clients")
|
||||||
if not isinstance(clients, list):
|
if not isinstance(clients, list):
|
||||||
clients = []
|
clients = []
|
||||||
config["clients"] = clients
|
config["clients"] = clients
|
||||||
for index, client in enumerate(clients):
|
for index, client in enumerate(clients):
|
||||||
if isinstance(client, dict) and client.get("clientId") == OPENBAO_CLIENT["clientId"]:
|
if isinstance(client, dict) and client.get("clientId") == required["clientId"]:
|
||||||
clients[index] = dict(OPENBAO_CLIENT)
|
clients[index] = dict(required)
|
||||||
return config
|
return config
|
||||||
clients.append(dict(OPENBAO_CLIENT))
|
clients.append(dict(required))
|
||||||
return config
|
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:
|
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)
|
config_text = yaml.safe_dump(updated, sort_keys=False)
|
||||||
encoded = base64.b64encode(config_text.encode("utf-8")).decode("ascii")
|
encoded = base64.b64encode(config_text.encode("utf-8")).decode("ascii")
|
||||||
json.dump({"data": {"config.yaml": encoded}}, sys.stdout, separators=(",", ":"))
|
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:
|
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:
|
if errors:
|
||||||
for error in errors:
|
for error in errors:
|
||||||
print(f"[FAIL] {error}")
|
print(f"[FAIL] {error}")
|
||||||
raise SystemExit(1)
|
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:
|
def main() -> None:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue