Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
badra001 committed Apr 14, 2026
1 parent cff2214 commit 1f92cc4
Showing 1 changed file with 92 additions and 0 deletions.
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()

0 comments on commit 1f92cc4

Please sign in to comment.