feat: update plan 16 sec14-26
This commit is contained in:
@@ -22,6 +22,9 @@ set -uo pipefail
|
||||
# CASAN_APPROVAL_JWT (optional RS256 IdP token)
|
||||
# CASAN_IDP_PUBLIC_KEY (default central-governance/idp-public.pem)
|
||||
# CASAN_IDP_JWKS_URL (optional OIDC JWKS endpoint; overrides public key)
|
||||
# CASAN_TRUSTED_TIME / CASAN_TRUSTED_TIME_FILE (SEC-22/ARCH-06: trusted time
|
||||
# source for JWT `exp` instead of the manipulable local clock; file
|
||||
# unreadable = fail-closed)
|
||||
# Exit: 0 ok (prints "APPROVAL_OK role=<role>"), 3 deny (reason on stderr), 64 usage.
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
@@ -109,7 +112,27 @@ header = json.loads(b64u_decode(parts[0]))
|
||||
claims = json.loads(b64u_decode(parts[1]))
|
||||
if header.get("alg") != "RS256":
|
||||
die("jwt_alg_not_allowed")
|
||||
if int(claims.get("exp", 0)) <= int(time.time()):
|
||||
|
||||
# SEC-22 (ARCH-06): do NOT trust the local system clock alone for expiry. When a
|
||||
# trusted time source is provided (CASAN_TRUSTED_TIME seconds, or
|
||||
# CASAN_TRUSTED_TIME_FILE containing seconds from a trusted timestamp authority),
|
||||
# use it; an unreadable/invalid source is fail-closed (deny).
|
||||
def _trusted_now():
|
||||
v = os.environ.get("CASAN_TRUSTED_TIME")
|
||||
if v:
|
||||
try:
|
||||
return int(v)
|
||||
except Exception:
|
||||
die("trusted_time_invalid")
|
||||
f = os.environ.get("CASAN_TRUSTED_TIME_FILE")
|
||||
if f:
|
||||
try:
|
||||
return int(open(f).read().strip())
|
||||
except Exception:
|
||||
die("trusted_time_file_unreadable")
|
||||
return int(time.time())
|
||||
|
||||
if int(claims.get("exp", 0)) <= _trusted_now():
|
||||
die("jwt_expired")
|
||||
if claims.get("sub") != approver:
|
||||
die("jwt_sub_mismatch")
|
||||
|
||||
Reference in New Issue
Block a user