docs(P10): complete contract-ingestor-identity-validation phase (v1.13.13)
---ci--- project: acdl phase: 10 milestone: v1.14 status: complete requirements: covered: [REQ-144] partial: [] ---/ci---
This commit is contained in:
@@ -238,21 +238,42 @@ def _validate_caller_identity(event, payload):
|
||||
|
||||
If the identity is not available (e.g. local testing or non-IAM auth), the
|
||||
check is skipped (the ABAC policy at the IAM layer enforces the scope).
|
||||
|
||||
v1.14 (REQ-144): also validates contractId format, environment enum, and
|
||||
error length. The ABAC reliance is documented here: the Function URL IAM
|
||||
identity does not expose principal tags in the event, so full enforcement
|
||||
of consumerRepo ownership is at the IAM layer (ABAC via
|
||||
aws:PrincipalTag/acdl:owner). This function validates format only, not
|
||||
ownership.
|
||||
"""
|
||||
identity = event.get("requestContext", {}).get("identity", {})
|
||||
caller_arn = identity.get("userArn", "")
|
||||
if not caller_arn:
|
||||
return # no identity available — rely on IAM ABAC enforcement
|
||||
pass # no identity available — rely on IAM ABAC enforcement
|
||||
payload_repo = payload.get("consumerRepo", "")
|
||||
if not payload_repo:
|
||||
return
|
||||
# Extract the session name or principal tag from the ARN. The ABAC policy
|
||||
# scopes via aws:PrincipalTag/acdl:owner = <consumerRepo>. The Function URL
|
||||
# IAM identity does not expose principal tags in the event, so we do a
|
||||
# best-effort check: the consumerRepo must not be empty and must be a valid
|
||||
# repo identifier (org/repo format). Full enforcement is at the IAM layer.
|
||||
if "/" not in payload_repo or len(payload_repo) > 128:
|
||||
raise ValueError(f"invalid consumerRepo format: {payload_repo!r}")
|
||||
if payload_repo:
|
||||
# consumerRepo must be org/repo format, <=128 chars
|
||||
if "/" not in payload_repo or len(payload_repo) > 128:
|
||||
raise ValueError(f"invalid consumerRepo format: {payload_repo!r}")
|
||||
|
||||
# v1.14 (REQ-144): contractId format validation
|
||||
contract_id = payload.get("contractId", "")
|
||||
if contract_id:
|
||||
import re
|
||||
if not re.match(r'^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$', contract_id):
|
||||
raise ValueError(f"invalid contractId format: {contract_id!r} (alphanumeric, hyphen, underscore; max 64 chars)")
|
||||
|
||||
# v1.14 (REQ-144): environment enum validation
|
||||
environment = payload.get("environment", "")
|
||||
if environment:
|
||||
valid_envs = {"dev", "qa", "prod", "dr"}
|
||||
if environment not in valid_envs:
|
||||
raise ValueError(f"invalid environment: {environment!r} (must be one of {valid_envs})")
|
||||
|
||||
# v1.14 (REQ-144): error length cap (for report_error action)
|
||||
error_msg = payload.get("error", "")
|
||||
if error_msg and len(str(error_msg)) > 10000:
|
||||
payload["error"] = str(error_msg)[:10000]
|
||||
|
||||
|
||||
def _validate_change_request(payload):
|
||||
|
||||
Reference in New Issue
Block a user