import fnmatch import os import sys import urllib.parse import jwt from common import KEY_PATH, SUB_PREFIX, load_key token = open(sys.argv[1]).read().strip() role = "arn:aws:iam::123456789012:role/sandbox-document-reader" if not os.path.exists(KEY_PATH): print("no issuer-key.pem in this folder, so the signature cannot be checked: run issuer.py here first") sys.exit(1) try: claims = jwt.decode( token, load_key().public_key(), algorithms=["ES256"], leeway=300, options={"verify_aud": False, "require": ["exp", "aud", "sub", "iss"]}, ) except jwt.PyJWTError as e: print(f"STS would refuse this token before any trust policy check: {type(e).__name__}: {e}") sys.exit(1) print("signature and exp checked against the local issuer key, with the 300 s skew IAM allows") print() query = urllib.parse.urlencode({ "Action": "AssumeRoleWithWebIdentity", "Version": "2011-06-15", "RoleArn": role, "RoleSessionName": claims["sandbox_id"], "DurationSeconds": 900, "WebIdentityToken": token[:24] + "..." + token[-8:], }) print("request that would be sent, with no AWS credentials attached:") print("GET https://sts.amazonaws.com/?" + query.replace("&", "\n &")) print() print("the role trust policy then checks two claims:") aud_ok = claims["aud"] == "sts.amazonaws.com" sub_ok = fnmatch.fnmatchcase(claims["sub"], SUB_PREFIX + "*") print(f" StringEquals aud = sts.amazonaws.com -> {'pass' if aud_ok else 'fail'} (aud is {claims['aud']})") print(f" StringLike sub = {SUB_PREFIX}* -> {'pass' if sub_ok else 'fail'} (sub is {claims['sub']})") print() if aud_ok and sub_ok: print("response fields: AccessKeyId, SecretAccessKey, SessionToken, Expiration (900 s from now)") print("not sent: this script prints the request and stops") else: print("STS would refuse this request, so no credential comes back") sys.exit(1)