0662ed26a3
---ci--- project: acdl phase: 4 milestone: v1.28 status: execute persona: backend-engineer ---
63 lines
2.0 KiB
Python
63 lines
2.0 KiB
Python
"""Nova IdP JWKS endpoint Lambda (REQ-338, D-230).
|
|
|
|
Serves the KMS public key as a JWK in a standard JWKS response. The
|
|
endpoint is a Lambda function URL with ``AuthType: NONE`` (JWKS is
|
|
public-key only — configured in CloudFormation, not in code).
|
|
|
|
Response:
|
|
* ``Content-Type: application/json``
|
|
* ``Cache-Control: public, max-age=3600`` (1h — clients cache the JWKS)
|
|
* ``Access-Control-Allow-Origin: *`` (JWKS is public)
|
|
* ``body: {"keys": [<jwk>]}``
|
|
|
|
The JWK is built via :func:`core.kms_signing.get_jwk` from the KMS
|
|
public key (DER SPKI → ``cryptography`` → JWK).
|
|
|
|
Dual-use (REQ-329): ``__main__`` CLI block for local testing
|
|
(``--print-jwks``).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
OIDC_KMS_KEY_ID = os.environ.get("NOVA_OIDC_KMS_KEY_ID", "alias/nova-oidc-signing")
|
|
|
|
|
|
def lambda_handler(event, context):
|
|
"""AWS Lambda handler — serve the JWKS response (REQ-338)."""
|
|
try:
|
|
from core.kms_signing import get_jwk
|
|
jwk = get_jwk(key_id=OIDC_KMS_KEY_ID)
|
|
return {
|
|
"statusCode": 200,
|
|
"headers": {
|
|
"Content-Type": "application/json",
|
|
"Cache-Control": "public, max-age=3600",
|
|
"Access-Control-Allow-Origin": "*",
|
|
},
|
|
"body": json.dumps({"keys": [jwk]}),
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
"statusCode": 500,
|
|
"headers": {"Content-Type": "application/json"},
|
|
"body": json.dumps({"error": str(e)}),
|
|
}
|
|
|
|
|
|
def cli_main(argv=None):
|
|
"""CLI entry point (REQ-329 dual-use). ``--print-jwks`` → stdout."""
|
|
raw = argv if argv is not None else sys.argv[1:]
|
|
if "--print-jwks" in raw:
|
|
resp = lambda_handler({}, None)
|
|
sys.stdout.write(resp["body"] + "\n")
|
|
return resp.get("statusCode", 200) - 200
|
|
print("Usage: python3 -m core.lambda.nova_idp_jwks --print-jwks", file=sys.stderr)
|
|
return 2
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover - CLI entry
|
|
sys.exit(cli_main()) |