"""Create the Nova v1.1 spike IAM user + scoped inline policy + initial key. Idempotent: skips user creation if the user exists; creates an initial access key if none active exists. Prints the key to stdout for the orchestrator to capture (NEVER committed): ACDL_AWS_ACCESS_KEY_ID=<...> ACDL_AWS_SECRET_ACCESS_KEY=<...> Run with the bootstrap root key in env: ACDL_BOOTSTRAP_AWS_ACCESS_KEY_ID / ACDL_BOOTSTRAP_AWS_SECRET_ACCESS_KEY AWS_DEFAULT_REGION (defaults to us-east-1) The inline policy is read from spike_runner_policy.json (next to this file). The account id + region are already substituted in the policy file for account 581513795199 + us-east-1; this script does not substitute further (the policy file is spike-specific). Idempotent: re-running this script against an already-bootstrapped account exits 0 without duplicating resources. The IAM user is guarded by a get_user probe (skips creation if it exists), the inline policy is re-PUT on every run (PutUserPolicy overwrites in place), and the initial access key is created only when no active key exists (list_access_keys filters on Status=Active; if one is present the script returns without creating another, directing the operator to rotate_spike_key.sh). """ import json import os import sys import boto3 REGION = os.environ.get("AWS_DEFAULT_REGION", "us-east-1") USER_NAME = "nova-spike-runner" POLICY_NAME = "nova-spike-runner-policy" POLICY_FILE = os.path.join(os.path.dirname(__file__), "spike_runner_policy.json") def main(): session = boto3.Session( aws_access_key_id=os.environ["ACDL_BOOTSTRAP_AWS_ACCESS_KEY_ID"], aws_secret_access_key=os.environ["ACDL_BOOTSTRAP_AWS_SECRET_ACCESS_KEY"], region_name=REGION, ) iam = session.client("iam") # --- IAM user (idempotent) --- try: iam.get_user(UserName=USER_NAME) print(f"iam: user {USER_NAME} already exists") except iam.exceptions.NoSuchEntityException: iam.create_user(UserName=USER_NAME) print(f"iam: created user {USER_NAME}") # --- Inline policy (idempotent: put_user_policy overwrites) --- with open(POLICY_FILE, "r") as fh: policy_doc = fh.read() iam.put_user_policy( UserName=USER_NAME, PolicyName=POLICY_NAME, PolicyDocument=policy_doc, ) print(f"iam: inline policy {POLICY_NAME} attached to {USER_NAME}") # --- Initial access key (create only if no active key exists) --- keys = iam.list_access_keys(UserName=USER_NAME).get("AccessKeyMetadata", []) active = [k for k in keys if k["Status"] == "Active"] if active: print(f"iam: {USER_NAME} already has {len(active)} active key(s); not creating a new one") print(" (use scripts/rotate_spike_key.sh to rotate)") return new_key = iam.create_access_key(UserName=USER_NAME)["AccessKey"] print("ACDL_AWS_ACCESS_KEY_ID=" + new_key["AccessKeyId"]) print("ACDL_AWS_SECRET_ACCESS_KEY=" + new_key["SecretAccessKey"]) print(f"iam: created initial access key {new_key['AccessKeyId']} for {USER_NAME}", file=sys.stderr) if __name__ == "__main__": main()