diff --git a/local-app/python-tools/aws-service-linked-roles/aws-slr-generate.py b/local-app/python-tools/aws-service-linked-roles/aws-slr-generate.py index 914769d5..55c5b635 100755 --- a/local-app/python-tools/aws-service-linked-roles/aws-slr-generate.py +++ b/local-app/python-tools/aws-service-linked-roles/aws-slr-generate.py @@ -5,7 +5,7 @@ import sys from botocore.exceptions import ClientError, ProfileNotFound -VERSION = "1.0.1" +VERSION = "1.0.2" def get_account_id(session): sts = session.client('sts') @@ -17,6 +17,7 @@ def generate_slr_terraform(): parser.add_argument("--region", help="AWS region (e.g., us-gov-west-1)") parser.add_argument("--import-file", default="import.tf", help="Output filename for import blocks") parser.add_argument("--variables-file", default="variables.service-linked-roles.auto.tfvars", help="Output filename for tfvars") + parser.add_argument("--dry-run", action="store_true", help="Print the generated content to stdout without creating files") parser.add_argument("--version", action="version", version=f"%(prog)s {VERSION}") args = parser.parse_args() @@ -34,7 +35,6 @@ def generate_slr_terraform(): paginator = iam.get_paginator('list_roles') for page in paginator.paginate(PathPrefix='/aws-service-role/'): for role in page['Roles']: - # Extract the service principal from the Trust Policy trust_policy = role.get('AssumeRolePolicyDocument', {}) for statement in trust_policy.get('Statement', []): principal = statement.get('Principal', {}).get('Service') @@ -48,35 +48,48 @@ def generate_slr_terraform(): # De-duplicate and sort unique_services = sorted(list(set(service_names))) - # 1. Generate Import File - with open(args.import_file, 'w') as f: - f.write(f"# Generated by SLR-to-TF v{VERSION}\n") - for service in unique_services: - f.write(f'import {{\n') - f.write(f' to = aws_iam_service_linked_role.roles["{service}"]\n') - f.write(f' id = "arn:aws:iam::{account_id}:role/aws-service-role/{service}"\n') - f.write(f'}}\n\n') + # Prepare Content + import_content = [f"# Generated by SLR-to-TF v{VERSION}\n"] + for service in unique_services: + import_content.append(f'import {{\n') + import_content.append(f' to = aws_iam_service_linked_role.roles["{service}"]\n') + import_content.append(f' id = "arn:aws:iam::{account_id}:role/aws-service-role/{service}"\n') + import_content.append(f'}}\n\n') - # 2. Generate Variables File - with open(args.variables_file, 'w') as f: - f.write(f"# Generated by SLR-to-TF v{VERSION}\n") - f.write('service_linked_roles = [\n') - for service in unique_services: - f.write(f' "{service}",\n') - f.write(']\n') + vars_content = [f"# Generated by SLR-to-TF v{VERSION}\n", "service_linked_roles = [\n"] + for service in unique_services: + vars_content.append(f' "{service}",\n') + vars_content.append("]\n") + + # Output Logic + if args.dry_run: + print("\n" + "="*20 + " DRY RUN: IMPORT FILE " + "="*20) + print("".join(import_content)) + print("="*20 + " DRY RUN: VARIABLES FILE " + "="*20) + print("".join(vars_content)) + print("="*65 + "\n") + else: + with open(args.import_file, 'w') as f: + f.writelines(import_content) + with open(args.variables_file, 'w') as f: + f.writelines(vars_content) # Summary Output - print("-" * 40) + print("-" * 45) print(f"SLR-to-TF Generator v{VERSION}") - print("-" * 40) + print("-" * 45) print(f"AWS Account: {account_id}") - print(f"Region: {session.region_name}") + print(f"Region: {session.region_name or 'Default'}") print(f"Roles Found: {slr_count}") print(f"Unique Services: {len(unique_services)}") - print(f"Import File: {args.import_file}") - print(f"Variables File: {args.variables_file}") - print("-" * 40) - print("Success: Files generated. Run 'terraform plan' to verify imports.") + + if args.dry_run: + print(f"Mode: DRY RUN (No files created)") + else: + print(f"Import File: {args.import_file}") + print(f"Variables File: {args.variables_file}") + + print("-" * 45) except ProfileNotFound: print(f"Error: The profile '{args.profile}' was not found.")