-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
92 additions
and
0 deletions.
There are no files selected for viewing
92 changes: 92 additions & 0 deletions
92
local-app/python-tools/aws-service-linked-roles/aws-slr-generate.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| #!/bin/env python | ||
|
|
||
| import boto3 | ||
| import argparse | ||
| import sys | ||
| from botocore.exceptions import ClientError, ProfileNotFound | ||
|
|
||
| VERSION = "1.0.1" | ||
|
|
||
| def get_account_id(session): | ||
| sts = session.client('sts') | ||
| return sts.get_caller_identity()['Account'] | ||
|
|
||
| def generate_slr_terraform(): | ||
| parser = argparse.ArgumentParser(description="Audit AWS Service Linked Roles and generate Terraform import/vars files.") | ||
| parser.add_argument("--profile", help="AWS CLI profile to use") | ||
| 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("--version", action="version", version=f"%(prog)s {VERSION}") | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| try: | ||
| # Initialize Session | ||
| session = boto3.Session(profile_name=args.profile, region_name=args.region) | ||
| iam = session.client('iam') | ||
| account_id = get_account_id(session) | ||
|
|
||
| service_names = [] | ||
| slr_count = 0 | ||
|
|
||
| # Paginate through IAM roles with the SLR path | ||
| 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') | ||
| if principal: | ||
| slr_count += 1 | ||
| if isinstance(principal, list): | ||
| service_names.extend(principal) | ||
| else: | ||
| service_names.append(principal) | ||
|
|
||
| # 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') | ||
|
|
||
| # 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') | ||
|
|
||
| # Summary Output | ||
| print("-" * 40) | ||
| print(f"SLR-to-TF Generator v{VERSION}") | ||
| print("-" * 40) | ||
| print(f"AWS Account: {account_id}") | ||
| print(f"Region: {session.region_name}") | ||
| 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.") | ||
|
|
||
| except ProfileNotFound: | ||
| print(f"Error: The profile '{args.profile}' was not found.") | ||
| sys.exit(1) | ||
| except ClientError as e: | ||
| print(f"AWS Error: {e}") | ||
| sys.exit(1) | ||
| except Exception as e: | ||
| print(f"An unexpected error occurred: {e}") | ||
| sys.exit(1) | ||
|
|
||
| if __name__ == "__main__": | ||
| generate_slr_terraform() |