Close RAILIANCE-WP-0015-T06 rapp credential-lane binding
Document the one recipe a new rapp uses to acquire runtime secrets: standing KV secrets bind through a CCR target.rapp, leases through grant rapp_id. Stamp the existing postgres grants and the qonto workload CCR. Gate, delivery, and revocation are unchanged.
This commit is contained in:
parent
6ab882cc44
commit
dfa6373985
10 changed files with 342 additions and 10 deletions
|
|
@ -63,6 +63,7 @@ FRONTDOOR_READINESS = {
|
|||
"compromised",
|
||||
}
|
||||
SAFE_ID_RE = re.compile(r"^[A-Z0-9][A-Z0-9_.-]*$")
|
||||
RAPP_SLUG_RE = re.compile(r"^rapp-[a-z0-9]+(-[a-z0-9]+)*$")
|
||||
TTL_RE = re.compile(r"^[1-9][0-9]*[smhd]$")
|
||||
LOWER_SAFE_ID_RE = re.compile(r"^[a-z0-9][a-z0-9-]*$")
|
||||
FIELD_NAME_RE = re.compile(r"^[A-Z][A-Z0-9_]*$")
|
||||
|
|
@ -191,6 +192,10 @@ def validate_workload_kv_read(ccr: dict[str, Any], errors: list[str], warnings:
|
|||
target = require_object(ccr.get("target"), "target", errors)
|
||||
for field in ("domain", "tenant", "workload", "environment", "purpose"):
|
||||
require_string(target.get(field), f"target.{field}", errors)
|
||||
rapp = target.get("rapp")
|
||||
if rapp is not None:
|
||||
if not isinstance(rapp, str) or not RAPP_SLUG_RE.match(rapp):
|
||||
errors.append("target.rapp must be a rapp-* slug when set")
|
||||
|
||||
openbao = require_object(ccr.get("openbao"), "openbao", errors)
|
||||
mount = require_string(openbao.get("mount"), "openbao.mount", errors)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ REQUIRED_DENIED_MODES = {
|
|||
}
|
||||
|
||||
ALLOWED_CREDENTIAL_TYPES = {"openbao-token", "openbao-database-credential"}
|
||||
RAPP_SLUG_RE = re.compile(r"^rapp-[a-z0-9]+(-[a-z0-9]+)*$")
|
||||
ALLOWED_GRANT_CLASSES = {"self-service", "approval-required", "break-glass"}
|
||||
ALLOWED_GRANT_STATUSES = {"pilot", "active", "deprecated", "disabled"}
|
||||
DISALLOWED_POLICIES = {"root", "platform-admin"}
|
||||
|
|
@ -84,6 +85,20 @@ def validate_grant(
|
|||
return ""
|
||||
|
||||
grant_id = require_nonempty_string(grant_obj.get("id"), f"{prefix}.id", errors)
|
||||
rapp_id = grant_obj.get("rapp_id")
|
||||
if rapp_id is not None:
|
||||
if not isinstance(rapp_id, str) or not RAPP_SLUG_RE.match(rapp_id):
|
||||
errors.append(f"{prefix}.rapp_id must be a rapp-* slug when set")
|
||||
if grant_id.startswith("rapp-"):
|
||||
prefix_id = grant_id.split("/", 1)[0]
|
||||
if not rapp_id:
|
||||
errors.append(
|
||||
f"{prefix}.rapp_id is required when id starts with rapp-"
|
||||
)
|
||||
elif isinstance(rapp_id, str) and rapp_id != prefix_id:
|
||||
errors.append(
|
||||
f"{prefix}.rapp_id must equal the grant id prefix {prefix_id!r}"
|
||||
)
|
||||
require_nonempty_string(grant_obj.get("title"), f"{prefix}.title", errors)
|
||||
require_nonempty_string(
|
||||
grant_obj.get("description"), f"{prefix}.description", errors
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue