0e6ecae26d
Rename all acdl-* AWS resources → nova-* across terraform (DynamoDB, Secrets Manager, Lambda, SNS, SG, KMS alias, ECS, ECR, IAM user/policy, state bucket, ALB, VPC/subnet names). Lambda default table names → nova-* (D-111). State bucket backend → nova-tfstate (-migrate-state documented). New docs/NOVA_AWS_MIGRATION.md runbook (staged migration + rollback). New scripts/migrate_dynamodb_data.py (scan+copy, dry-run default). acdl-deploy- → nova-deploy- role ARN in deploy workflows. Test fixtures updated; terraform validate + pytest + run_ci.sh PASS. ---ci--- project: acdl phase: 4 milestone: v1.15 status: execute ---/ci---
80 lines
3.1 KiB
Python
80 lines
3.1 KiB
Python
"""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() |