Provide me a list of unused Security Groups by all regions.
list-unused-security-groups-all · the answer aws-bench grades against: 4 attached to nothing
Below is what each tool's agent actually ran. The scores say which tools answered. This says how, and the how is where they differ most.
chant — answered
6 commands, from chant-g3.
cd /workspace/chant && chant search "kind:EC2::SecurityGroup" --at latest --env floci --explain --show GroupId,GroupName,region
cd /workspace/chant && chant search "kind:EC2::Instance" --at latest --env floci --show SecurityGroupIds
cd /workspace/chant && chant search "kind:EC2::SecurityGroup !<-kind:EC2::Instance" --at latest --env floci --show GroupId,GroupName,region,providerDefault
cd /workspace/chant && chant search "kind:EC2::SecurityGroup !<-kind:EC2::Instance !<-kind:EC2::NetworkInterface !<-kind:EC2::LaunchTemplate !<-kind:EC2::SecurityGroup" --at latest --env floci --show GroupId,GroupName,region,providerDefault --explain
cd /workspace/chant && chant search "kind:EC2::SecurityGroup !attr:providerDefault=true !<-kind:EC2::Instance !<-kind:EC2::NetworkInterface !<-kind:EC2::LaunchTemplate" --at latest --env floci --show GroupId,GroupName,region --explain
cd /workspace/chant && chant search "kind:EC2::SecurityGroup !<-kind:EC2::Instance !<-kind:EC2::NetworkInterface !<-kind:EC2::LaunchTemplate" --at latest --env floci --show GroupId,GroupName,region,providerDefault
No tool (AWS CLI) — answered
4 commands, from bare-g3.
# Get all security groups from all regions and check their usage for region in us-east-1 us-west-1 us-west-2; do echo "=== Region: $region ===" >&2 aws ec2 describe-security-groups \ --region $region \ --output json \ --query 'SecurityGroups[*].[GroupId,GroupName,VpcId]' > /tmp/sgs_${region}.json done # Now check instance usage for region in us-east-1 us-west-1 us-west-2; do echo "=== Checking instances in $region ===" >&2 aws ec2 describe-instances \ --region $region \ --output json \ --query 'Reservations[*].Instances[*].[InstanceId,SecurityGroups[*].GroupId]' > /tmp/instances_${region}.json done # Check launch templates for region in us-east-1 us-west-1 us-west-2; do echo "=== Checking launch templates in $region ===" >&2 aws ec2 describe-launch-templates \ --region $region \ --output json > /tmp/launch_templates_${region}.json 2>/dev/null || echo "[]" > /tmp/launch_templates_${region}.json done echo "Data collected"
# Create a comprehensive analysis script python3 << 'EOF' import json import sys from collections import defaultdict def get_sg_usage(region): """Analyze which security groups are in use in a region""" # Load security groups with open(f'/tmp/sgs_{region}.json') as f: sgs_data = json.load(f) # Load instances with open(f'/tmp/instances_{region}.json') as f: instances_data = json.load(f) # Load launch templates with open(f'/tmp/launch_templates_{region}.json') as f: lt_data = json.load(f) # Track which SGs are in use used_sgs = set() sg_info = {} # Parse security groups for sg_id, sg_name, vpc_id in sgs_data: sg_info[sg_id] = {'name': sg_name, 'vpc': vpc_id} # Check instance usage for reservation in instances_data: for instance in reservation: if instance[1]: # Has security groups for sg_id in instance[1]: used_sgs.add(sg_id) # Check launch template usage try: templates = lt_data.get('LaunchTemplates', []) for template in templates: # Get launch template versions try: lt_versions = json.loads(f""" {{ "LaunchTemplateVersions": [] }} """) # Try to get versions with security groups import subprocess result = subprocess.run( ['aws', 'ec2', 'describe-launch-template-versions', '--launch-template-id', template['LaunchTemplateId'], '--region', region, '--output', 'json'], capture_output=True, text=True ) if result.returncode == 0: versions = json.loads(result.stdout) for version in versions.get('LaunchTemplateVersions', []): if 'LaunchTemplateData' in version: sg_ids = version['LaunchTemplateData'].get('SecurityGroupIds', []) for sg_id in sg_ids: used_sgs.add(sg_id) sg_ids = version['LaunchTemplateData'].get('SecurityGroups', []) for sg_id in sg_ids: used_sgs.add(sg_id) except: pass except: pass # Check security group rules that reference other security groups # Reload full security groups data for detailed analysis try: result = json.loads(open(f'/tmp/sgs_{region}.json').read()) # This was just IDs, need full data except: pass return { 'all_sgs': set(sg_info.keys()), 'used_sgs': used_sgs, 'sg_info': sg_info } # Process all regions unused_by_region = {} for region in ['us-east-1', 'us-west-1', 'us-west-2']: print(f"Processing {region}...", file=sys.stderr) usage = get_sg_usage(region) unused = usage['all_sgs'] - usage['used_sgs'] unused_by_region[region] = { 'unused': sorted(list(unused)), 'sg_info': usage['sg_info'] } # Print results for region in ['us-east-1', 'us-west-1', 'us-west-2']: data = unused_by_region[region] print(f"\n{region}:") if data['unused']: for sg_id in data['unused']: info = data['sg_info'].get(sg_id, {}) print(f" {sg_id} ({info.get('name', 'N/A')}) - VPC: {info.get('vpc', 'N/A')}") else: print(" No unused security groups found") EOF
# Get full security group details to check for cross-references for region in us-east-1 us-west-1 us-west-2; do echo "Getting full SG details for $region" >&2 aws ec2 describe-security-groups \ --region $region \ --output json > /tmp/sgs_full_${region}.json done # Check for network interfaces using security groups for region in us-east-1 us-west-1 us-west-2; do echo "Getting network interfaces for $region" >&2 aws ec2 describe-network-interfaces \ --region $region \ --output json > /tmp/enis_${region}.json done # Check for DB security groups and other resources for region in us-east-1 us-west-1 us-west-2; do echo "Checking RDS for $region" >&2 aws rds describe-db-instances \ --region $region \ --output json > /tmp/rds_${region}.json 2>/dev/null || echo "{}" > /tmp/rds_${region}.json done echo "Full data collected" >&2
python3 << 'EOF' import json import sys def analyze_region(region): """Comprehensive analysis of unused security groups""" print(f"\n=== Analyzing {region} ===", file=sys.stderr) # Load all data with open(f'/tmp/sgs_full_{region}.json') as f: sgs_data = json.load(f) with open(f'/tmp/enis_{region}.json') as f: enis_data = json.load(f) with open(f'/tmp/rds_{region}.json') as f: rds_data = json.load(f) # Create SG mapping all_sgs = {} for sg in sgs_data.get('SecurityGroups', []): all_sgs[sg['GroupId']] = { 'id': sg['GroupId'], 'name': sg['GroupName'], 'vpc': sg.get('VpcId', 'EC2-Classic'), 'description': sg.get('Description', ''), 'is_default': sg['GroupName'] == 'default' } # Track which SGs are in use used_sgs = set() usage_reasons = {} # 1. Check ENIs (covers instances, ALBs, etc.) for eni in enis_data.get('NetworkInterfaces', []): for sg in eni.get('Groups', []): sg_id = sg['GroupId'] if sg_id not in usage_reasons: usage_reasons[sg_id] = [] eni_type = eni.get('Description', 'Unknown') if eni.get('Association', {}).get('IpOwnerId') == 'amazon': eni_type = 'AWS Service' usage_reasons[sg_id].append(f"Used by ENI {eni['NetworkInterfaceId']} ({eni_type})") used_sgs.add(sg_id) # 2. Check SG rules that reference other SGs for sg_id, sg in all_sgs.items(): # Get full SG details for rules for sg_full in sgs_data.get('SecurityGroups', []): if sg_full['GroupId'] == sg_id: # Check ingress rules for rule in sg_full.get('IpPermissions', []): for user_id_group_pair in rule.get('UserIdGroupPairs', []): ref_sg_id = user_id_group_pair.get('GroupId') if ref_sg_id and ref_sg_id != sg_id: if ref_sg_id not in usage_reasons: usage_reasons[ref_sg_id] = [] usage_reasons[ref_sg_id].append(f"Referenced in SG {sg_id} ingress rules") used_sgs.add(ref_sg_id) # Check egress rules for rule in sg_full.get('IpPermissionsEgress', []): for user_id_group_pair in rule.get('UserIdGroupPairs', []): ref_sg_id = user_id_group_pair.get('GroupId') if ref_sg_id and ref_sg_id != sg_id: if ref_sg_id not in usage_reasons: usage_reasons[ref_sg_id] = [] usage_reasons[ref_sg_id].append(f"Referenced in SG {sg_id} egress rules") used_sgs.add(ref_sg_id) # 3. Check RDS instances for db in rds_data.get('DBInstances', []): for vpc_sg in db.get('VpcSecurityGroups', []): sg_id = vpc_sg['VpcSecurityGroupId'] if sg_id not in usage_reasons: usage_reasons[sg_id] = [] usage_reasons[sg_id].append(f"Used by RDS instance {db['DBInstanceIdentifier']}") used_sgs.add(sg_id) # Find unused unused = {} for sg_id, sg_info in all_sgs.items(): if sg_id not in used_sgs: unused[sg_id] = sg_info return { 'all_sgs': all_sgs, 'used_sgs': used_sgs, 'unused': unused, 'usage_reasons': usage_reasons } # Analyze all regions results = {} for region in ['us-east-1', 'us-west-1', 'us-west-2']: results[region] = analyze_region(region) # Print summary print("\n\n" + "="*80) print("UNUSED SECURITY GROUPS BY REGION") print("="*80) total_unused = 0 for region in ['us-east-1', 'us-west-1', 'us-west-2']: data = results[region] unused = data['unused'] total_unused += len(unused) print(f"\n{region}:") print(f" Total Security Groups: {len(data['all_sgs'])}") print(f" Used: {len(data['used_sgs'])}") print(f" Unused: {len(unused)}") if unused: print("\n Unused Security Groups:") for sg_id, sg_info in sorted(unused.items()): print(f" • {sg_id}") print(f" Name: {sg_info['name']}") print(f" VPC: {sg_info['vpc']}") print(f" Description: {sg_info['description']}") if sg_info['is_default']: print(f" ** This is the DEFAULT security group **") else: print(" No unused security groups found") print(f"\n{'='*80}") print(f"Total Unused Security Groups (all regions): {total_unused}") print(f"{'='*80}") EOF
Terraform — missed
4 commands, from terraform-g3.
cd /workspace/terraform && ./terraform state list | grep -E "(aws_security_group|aws_instance|aws_launch_template|aws_autoscaling_group|aws_ecs_service|aws_rds_cluster|aws_elasticache_cluster|aws_elb|aws_alb|aws_lb)" | head -50
cd /workspace/terraform && ./terraform show -json | jq . > /tmp/terraform_state.json && wc -l /tmp/terraform_state.json
cd /workspace/terraform && cat > /tmp/analyze_sgs.py << 'EOF' import json import sys from collections import defaultdict # Load state with open('/tmp/terraform_state.json') as f: state = json.load(f) # Extract all resources resources = {} def extract_resources(module, path=""): if 'resources' in module: for res in module['resources']: addr = path + res['address'] if path else res['address'] resources[addr] = res if 'child_modules' in module: for child in module['child_modules']: child_path = path + child['address'] + "." if path else child['address'] + "." extract_resources(child, child_path) if 'values' in state and 'root_module' in state['values']: extract_resources(state['values']['root_module']) # Find all security groups security_groups = {} for addr, res in resources.items(): if res['type'] == 'aws_security_group': sg_id = res['values'].get('id', 'unknown') sg_name = res['values'].get('name', 'unknown') sg_region = res['values'].get('region', 'unknown') vpc_id = res['values'].get('vpc_id', 'default') security_groups[sg_id] = { 'address': addr, 'name': sg_name, 'region': sg_region, 'vpc_id': vpc_id, 'used_by': [] } # Find all references to security groups sg_references = defaultdict(set) # Check instances for addr, res in resources.items(): if res['type'] == 'aws_instance': vpc_sgs = res['values'].get('vpc_security_group_ids', []) for sg_id in vpc_sgs: if sg_id in security_groups: sg_references[sg_id].add(f"instance: {addr}") # Check launch templates for addr, res in resources.items(): if res['type'] == 'aws_launch_template': # Check network interfaces in the template ni_spec = res['values'].get('network_interfaces', []) if isinstance(ni_spec, list) and len(ni_spec) > 0: for ni in ni_spec: if isinstance(ni, dict): ni_sgs = ni.get('security_groups', []) for sg_id in ni_sgs: if sg_id in security_groups: sg_references[sg_id].add(f"launch_template: {addr}") # Check security group rules (referencing other SGs) for addr, res in resources.items(): if res['type'] == 'aws_security_group_rule': referenced_sg = res['values'].get('security_group_id') source_sg = res['values'].get('source_security_group_id') if referenced_sg and referenced_sg in security_groups: sg_references[referenced_sg].add(f"sg_rule: {addr}") if source_sg and source_sg in security_groups: sg_references[source_sg].add(f"sg_rule_source: {addr}") # Check autoscaling groups for addr, res in resources.items(): if res['type'] == 'aws_autoscaling_group': vpc_sgs = res['values'].get('vpc_zone_identifier', []) # ASGs reference through launch config/template launch_template = res['values'].get('launch_template', {}) if isinstance(launch_template, dict): # SGs would be in the launch template, already checked above pass # Check load balancers for addr, res in resources.items(): if res['type'] in ['aws_lb', 'aws_alb', 'aws_elb']: sgs = res['values'].get('security_groups', []) for sg_id in sgs: if sg_id in security_groups: sg_references[sg_id].add(f"lb: {addr}") # Check RDS for addr, res in resources.items(): if res['type'] in ['aws_db_instance', 'aws_rds_cluster', 'aws_rds_cluster_instance']: sgs = res['values'].get('vpc_security_group_ids', []) for sg_id in sgs: if sg_id in security_groups: sg_references[sg_id].add(f"rds: {addr}") # Check ElastiCache for addr, res in resources.items(): if res['type'] == 'aws_elasticache_cluster': sgs = res['values'].get('security_group_ids', []) for sg_id in sgs: if sg_id in security_groups: sg_references[sg_id].add(f"elasticache: {addr}") # Check network interfaces for addr, res in resources.items(): if res['type'] == 'aws_network_interface': sgs = res['values'].get('security_groups', []) for sg_id in sgs: if sg_id in security_groups: sg_references[sg_id].add(f"eni: {addr}") # Update used_by for sg_id, refs in sg_references.items(): if sg_id in security_groups: security_groups[sg_id]['used_by'] = list(refs) # Find unused unused = {sg_id: sg for sg_id, sg in security_groups.items() if not sg['used_by']} used = {sg_id: sg for sg_id, sg in security_groups.items() if sg['used_by']} # Group by region unused_by_region = defaultdict(list) for sg_id, sg in unused.items(): unused_by_region[sg['region']].append({ 'id': sg_id, 'name': sg['name'], 'vpc_id': sg['vpc_id'], 'address': sg['address'] }) print("=" * 80) print("SECURITY GROUP USAGE ANALYSIS") print("=" * 80) print(f"\nTotal Security Groups: {len(security_groups)}") print(f"Used: {len(used)}") print(f"Unused: {len(unused)}\n") if unused: print("\nUNUSED SECURITY GROUPS BY REGION:") print("=" * 80) for region in sorted(unused_by_region.keys()): sgs = unused_by_region[region] print(f"\n{region} ({len(sgs)} unused):") for sg in sgs: print(f" - {sg['id']} | Name: {sg['name']} | VPC: {sg['vpc_id']}") else: print("\nNo unused security groups found!") # Also save detailed output output = { 'summary': { 'total': len(security_groups), 'used': len(used), 'unused': len(unused) }, 'unused_by_region': dict(unused_by_region), 'all_security_groups': security_groups } with open('/tmp/sg_analysis.json', 'w') as f: json.dump(output, f, indent=2) EOF python3 /tmp/analyze_sgs.py
cat > /tmp/final_report.py << 'EOF' import json from collections import defaultdict # Load the analysis with open('/tmp/sg_analysis.json') as f: analysis = json.load(f) # Create detailed report report = [] report.append("=" * 80) report.append("AWS SECURITY GROUPS - UNUSED BY REGION") report.append("=" * 80) report.append("") report.append(f"Report Date: 2026-08-03") report.append(f"Data Source: Terraform State (/workspace/terraform)") report.append("") report.append("SUMMARY") report.append("-" * 80) report.append(f"Total Security Groups Managed: {analysis['summary']['total']}") report.append(f"Used Security Groups: {analysis['summary']['used']}") report.append(f"Unused Security Groups: {analysis['summary']['unused']}") report.append("") if analysis['summary']['unused'] == 0: report.append("✓ No unused security groups found. All security groups are in use.") else: report.append("UNUSED SECURITY GROUPS BY REGION") report.append("-" * 80) for region in sorted(analysis['unused_by_region'].keys()): sgs = analysis['unused_by_region'][region] report.append("") report.append(f"REGION: {region} ({len(sgs)} unused)") report.append("-" * 80) for sg in sgs: report.append(f"\n Security Group ID: {sg['id']}") report.append(f" Name: {sg['name']}") report.append(f" VPC ID: {sg['vpc_id']}") report.append(f" Terraform Address: {sg['address']}") report.append("") report.append("") report.append("RECOMMENDED ACTIONS") report.append("-" * 80) report.append("1. Review each unused security group to confirm it is no longer needed") report.append("2. Delete via Terraform: terraform destroy -target=<resource_address>") report.append("3. Or remove from state: terraform state rm <resource_address>") report.append("") report.append("=" * 80) # Write to output file output_text = "\n".join(report) with open('/logs/agent/agent-output.txt', 'w') as f: f.write(output_text) print(output_text) EOF python3 /tmp/final_report.py
Pulumi — missed
14 commands, from pulumi-g3.
cd /workspace/pulumi && ./pulumi-export > /tmp/pulumi-state.json && wc -l /tmp/pulumi-state.json
cd /workspace/pulumi && jq -r '.deployment.resources[] | select(.type == "aws:ec2/securityGroup:SecurityGroup") | {urn, groupId: .outputs.id, groupName: .outputs.name, region: .outputs.vpcId, inputs: .inputs}' /tmp/pulumi-state.json | head -100
cd /workspace/pulumi && jq -r '.deployment.resources[] | select(.type == "aws:ec2/securityGroup:SecurityGroup") | {urn, groupId: .outputs.id, groupName: .outputs.name, vpcId: .outputs.vpcId}' /tmp/pulumi-state.json > /tmp/sgs.json && cat /tmp/sgs.json
cd /workspace/pulumi && jq -r '.deployment.resources[] | select(.type == "aws:ec2/securityGroup:SecurityGroup") | {urn, groupId: .outputs.id, groupName: .outputs.name, region: (.outputs.tags.region // .inputs.region // "unknown"), vpcId: .outputs.vpcId}' /tmp/pulumi-state.json
cd /workspace/pulumi && jq '.deployment.resources[] | select(.type == "aws:ec2/securityGroup:SecurityGroup") | {groupId: .outputs.id, groupName: .outputs.name, outputs: .outputs | keys}' /tmp/pulumi-state.json
cd /workspace/pulumi && jq -r '.deployment.resources[] | select(.type == "aws:ec2/securityGroup:SecurityGroup") | {urn, groupId: .outputs.id, groupName: .outputs.name, arn: .outputs.arn}' /tmp/pulumi-state.json
cat > /tmp/find_unused_sgs.jq << 'EOF' # Extract all security groups with region information def extract_region: split(":")[3]; # Create a map of all SG IDs to their metadata def sg_map: [.deployment.resources[] | select(.type == "aws:ec2/securityGroup:SecurityGroup")] | map({ groupId: .outputs.id, urn, groupName: .outputs.name, description: .outputs.description, vpcId: .outputs.vpcId, region: (.outputs.arn | extract_region) }) | map({(.groupId): .}) | add; # Extract all SG references from all resources def collect_sg_references: .deployment.resources[] | (.outputs.securityGroupIds // [], .outputs.securityGroupId // [], .inputs.securityGroupIds // [], .inputs.securityGroupId // [], (.inputs.vpcSecurityGroupIds // []), (.outputs.vpcSecurityGroupIds // []), (.inputs.launchTemplate.versionNumber | . as $v | .deployment.resources[] | select(.type == "aws:ec2/launchTemplate:LaunchTemplate") | (.outputs.securityGroupIds // [])) ) | select(. != null); # Find which SGs are referenced by instances and other resources def referenced_sgs: (.deployment.resources[] | (.outputs.securityGroupIds // [], .outputs.securityGroupId // [], .inputs.securityGroupIds // [], .inputs.securityGroupId // [], .inputs.vpcSecurityGroupIds // [], .outputs.vpcSecurityGroupIds // [])) | select(. != null); # Main logic (sg_map) as $sgs | ((.deployment.resources | map( [(.outputs.securityGroupIds // []), (.outputs.securityGroupId // []), (.inputs.securityGroupIds // []), (.inputs.securityGroupId // []), (.inputs.vpcSecurityGroupIds // []), (.outputs.vpcSecurityGroupIds // []) ] | flatten | select(length > 0) ) | flatten | unique) as $referenced) | ($sgs | keys as $all_sgs) | { "all_security_groups": $sgs, "referenced_sgs": $referenced, "unused": ($all_sgs - $referenced) } EOF cat /tmp/find_unused_sgs.jq
cd /workspace/pulumi && jq -f /tmp/find_unused_sgs.jq /tmp/pulumi-state.json > /tmp/unused_analysis.json && jq . /tmp/unused_analysis.json 2>&1 | head -100
cat > /tmp/find_unused_sgs.jq << 'EOF' # Extract all security groups with region information def extract_region: split(":")[3]; # Get all SG IDs to their metadata [.deployment.resources[] | select(.type == "aws:ec2/securityGroup:SecurityGroup")] as $sgs | # Get all referenced SG IDs from all resources (.deployment.resources | map([ (.outputs.securityGroupIds // []), ((.outputs.securityGroupId | select(.) | [.]) // []), (.inputs.securityGroupIds // []), ((.inputs.securityGroupId | select(.) | [.]) // []), (.inputs.vpcSecurityGroupIds // []), (.outputs.vpcSecurityGroupIds // []) ] | flatten) | flatten | unique ) as $referenced | # Map SGs by ID for lookup ($sgs | map({(. | .outputs.id): .}) | add) as $sg_map | # Output { "total_security_groups": ($sg_map | keys | length), "total_referenced": ($referenced | length), "unused_security_groups": [ $sg_map | keys[] as $sgid | select(($referenced | index($sgid) | . == null)) | $sg_map[$sgid] | { group_id: .outputs.id, group_name: .outputs.name, region: (.outputs.arn | extract_region), vpc_id: .outputs.vpcId, description: .outputs.description, urn: .urn } ] } EOF cat /tmp/find_unused_sgs.jq
cd /workspace/pulumi && jq -f /tmp/find_unused_sgs.jq /tmp/pulumi-state.json 2>&1
cat > /tmp/verify_refs.jq << 'EOF' # Extract all security groups [.deployment.resources[] | select(.type == "aws:ec2/securityGroup:SecurityGroup")] as $sgs | # Map SGs by ID ($sgs | map({(. | .outputs.id): {name: .outputs.name, arn: .outputs.arn}}) | add) as $sg_map | # For each resource, collect SG references [ .deployment.resources[] | select( (.outputs.securityGroupIds // [] | length > 0) or (.outputs.securityGroupId // null) or (.inputs.securityGroupIds // [] | length > 0) or (.inputs.securityGroupId // null) or (.inputs.vpcSecurityGroupIds // [] | length > 0) or (.outputs.vpcSecurityGroupIds // [] | length > 0) ) | { type: .type, id: (.outputs.id // .outputs.name // "unknown"), security_group_ids: ( [ (.outputs.securityGroupIds // []), ((.outputs.securityGroupId | select(.) | [.]) // []), (.inputs.securityGroupIds // []), ((.inputs.securityGroupId | select(.) | [.]) // []), (.inputs.vpcSecurityGroupIds // []), (.outputs.vpcSecurityGroupIds // []) ] | flatten | unique ) } ] | # Group by SG ID reduce .[] as $ref ( {}; .[$ref.security_group_ids[]] |= (. // []) + [$ref] ) | # Format output [ to_entries[] | { sg_id: .key, sg_name: ($sg_map[.key].name // "unknown"), references: [.value[] | {type: .type, id: .id}] } ] EOF jq -f /tmp/verify_refs.jq /tmp/pulumi-state.json
cd /workspace/pulumi && cat > /tmp/final_unused_report.jq << 'EOF' # Extract all security groups with metadata def extract_region: split(":")[3]; [.deployment.resources[] | select(.type == "aws:ec2/securityGroup:SecurityGroup")] as $sgs | # Collect all SG references across all resources reduce .deployment.resources[] as $resource ( {}; . as $acc | ( [ ($resource.outputs.securityGroupIds // []), (($resource.outputs.securityGroupId | select(.) | [.]) // []), ($resource.inputs.securityGroupIds // []), (($resource.inputs.securityGroupId | select(.) | [.]) // []), ($resource.inputs.vpcSecurityGroupIds // []), ($resource.outputs.vpcSecurityGroupIds // []) ] | flatten | unique ) as $sgids | reduce $sgids[] as $sgid ($acc; .[$sgid] = true) ) as $referenced_map | # Group unused SGs by region [ $sgs[] | select(.outputs.id as $id | $referenced_map[$id] != true) | { region: (.outputs.arn | extract_region), group_id: .outputs.id, group_name: .outputs.name, vpc_id: .outputs.vpcId, description: .outputs.description } ] | # Sort by region then group name sort_by([.region, .group_name]) | # Group by region group_by(.region) | map({ region: .[0].region, security_groups: map({group_id, group_name, vpc_id, description}) }) | # Final output { summary: { total_unused: (. | map(.security_groups | length) | add // 0), regions_affected: (. | length), }, unused_security_groups_by_region: . } EOF jq -f /tmp/final_unused_report.jq /tmp/pulumi-state.json
# … 2 more
AWS CDK — missed
9 commands, from cdk-g3.
cd /workspace/cdk_app && npx cdk ls
cd /workspace/cdk_app && npx cdk synth ec2-multiregion-QARoles-us-east-1 --json 2>/dev/null | jq -r '.Resources | keys[] | select(contains("SecurityGroup")) | .' > /tmp/sg_us_east_1_qa.txt && cat /tmp/sg_us_east_1_qa.txt
cd /workspace/cdk_app && for stack in $(npx cdk ls 2>/dev/null | grep -v WARNING | grep -v '\[Warning\]' | grep -v npm); do echo "=== Stack: $stack ===" npx cdk synth $stack --json 2>/dev/null | jq -r '.Resources | to_entries[] | select(.value.Type == "AWS::EC2::SecurityGroup" or .value.Type == "AWS::EC2::SecurityGroupIngress" or .value.Type == "AWS::EC2::SecurityGroupEgress") | .key + " (" + .value.Type + ")"' done
cd /workspace/cdk_app && cat > /tmp/analyze_sg.sh << 'EOF' #!/bin/bash # Store all security groups and their usages declare -A sg_defined declare -A sg_used for stack in $(npx cdk ls 2>/dev/null | grep -v WARNING | grep -v '\[Warning\]' | grep -v npm); do region=$(echo $stack | grep -o -E '(us-east-1|us-west-1|us-west-2|eu-west-1)$') echo "Processing stack: $stack (region: $region)" template=$(npx cdk synth $stack --json 2>/dev/null) # Get all security groups defined echo "$template" | jq -r --arg region "$region" --arg stack "$stack" '.Resources | to_entries[] | select(.value.Type == "AWS::EC2::SecurityGroup") | .key + "|SG_DEF|" + .value.Type + "|" + $stack + "|" + $region' >> /tmp/sgs.txt # Find all references to security groups in resources echo "$template" | jq -r --arg region "$region" --arg stack "$stack" '.Resources | to_entries[] | select(.value | strings | contains("SecurityGroup") or (.Properties.SecurityGroupIds != null) or (.Properties.SecurityGroups != null)) | .key + "|RESOURCE|" + .value.Type + "|" + $stack + "|" + $region' >> /tmp/sg_resources.txt done echo "=== Security Groups Defined ===" cat /tmp/sgs.txt 2>/dev/null || echo "None found" echo -e "\n=== Resources that use Security Groups ===" cat /tmp/sg_resources.txt 2>/dev/null | sort | uniq || echo "None found" EOF chmod +x /tmp/analyze_sg.sh /tmp/analyze_sg.sh
cd /workspace/cdk_app && npx cdk synth ec2-multiregion-EC2-ks84v1fh12-us-east-1 --json 2>/dev/null | jq '.Resources | to_entries[] | select(.value.Type | startswith("AWS::EC2")) | {key: .key, type: .value.Type, sgRefs: (.value.Properties.SecurityGroupIds // .value.Properties.SecurityGroups // .value.Properties.SecurityGroup // empty)}' | head -100
cd /workspace/cdk_app && cat > /tmp/comprehensive_sg_analysis.py << 'PYTHON' import json import subprocess import re from collections import defaultdict # Get all stacks result = subprocess.run(['npx', 'cdk', 'ls'], capture_output=True, text=True, cwd='/workspace/cdk_app') stacks = [line.strip() for line in result.stdout.split('\n') if line.strip() and 'WARNING' not in line and 'Warning' not in line and 'npm' not in line] all_sgs = {} # {stack: {sg_id: sg_details}} sg_usage = defaultdict(list) # {sg_id: [list of resources using it]} for stack in stacks: print(f"Analyzing stack: {stack}") # Synthesize the stack result = subprocess.run(['npx', 'cdk', 'synth', stack, '--json'], capture_output=True, text=True, cwd='/workspace/cdk_app', stderr=subprocess.DEVNULL) try: template = json.loads(result.stdout) except: print(f" Failed to parse template for {stack}") continue resources = template.get('Resources', {}) # Find all security groups sgs_in_stack = {} for resource_id, resource_def in resources.items(): if resource_def.get('Type') == 'AWS::EC2::SecurityGroup': sgs_in_stack[resource_id] = resource_def all_sgs[resource_id] = { 'stack': stack, 'region': stack.split('-')[-1], 'definition': resource_def } # Find all references to security groups for resource_id, resource_def in resources.items(): props = resource_def.get('Properties', {}) # Check SecurityGroupIds sg_ids = props.get('SecurityGroupIds', []) for sg_ref in sg_ids: if isinstance(sg_ref, dict) and 'Fn::GetAtt' in sg_ref: sg_name = sg_ref['Fn::GetAtt'][0] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) # Check SecurityGroups (for Classic/VPC) sgs = props.get('SecurityGroups', []) for sg_ref in sgs: if isinstance(sg_ref, dict) and 'Fn::GetAtt' in sg_ref: sg_name = sg_ref['Fn::GetAtt'][0] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) elif isinstance(sg_ref, dict) and 'Ref' in sg_ref: sg_name = sg_ref['Ref'] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) # Now find unused SGs print("\n" + "="*80) print("SECURITY GROUPS ANALYSIS") print("="*80) unused_sgs = [] used_sgs = [] for sg_id, sg_info in all_sgs.items(): stack = sg_info['stack'] region = sg_info['region'] if sg_id in sg_usage and len(sg_usage[sg_id]) > 0: used_sgs.append((sg_id, sg_info, sg_usage[sg_id])) else: unused_sgs.append((sg_id, sg_info)) print(f"\nTotal Security Groups Defined: {len(all_sgs)}") print(f"Used Security Groups: {len(used_sgs)}") print(f"UNUSED Security Groups: {len(unused_sgs)}") if unused_sgs: print("\n" + "="*80) print("UNUSED SECURITY GROUPS") print("="*80) for sg_id, sg_info in sorted(unused_sgs, key=lambda x: (x[1]['region'], x[0])): print(f"\nLogical ID: {sg_id}") print(f" Stack: {sg_info['stack']}") print(f" Region: {sg_info['region']}") if 'GroupDescription' in sg_info['definition'].get('Properties', {}): print(f" Description: {sg_info['definition']['Properties']['GroupDescription']}") if used_sgs: print("\n" + "="*80) print("USED SECURITY GROUPS") print("="*80) for sg_id, sg_info, usages in sorted(used_sgs, key=lambda x: (x[1]['region'], x[0])): print(f"\nLogical ID: {sg_id}") print(f" Stack: {sg_info['stack']}") print(f" Region: {sg_info['region']}") print(f" Used by ({len(usages)}):") for usage in usages: print(f" - {usage['resource']} ({usage['type']})") PYTHON python3 /tmp/comprehensive_sg_analysis.py
cd /workspace/cdk_app && cat > /tmp/comprehensive_sg_analysis.py << 'PYTHON' import json import subprocess import re from collections import defaultdict # Get all stacks result = subprocess.run(['npx', 'cdk', 'ls'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd='/workspace/cdk_app') stacks = [line.strip() for line in result.stdout.split('\n') if line.strip() and 'WARNING' not in line and 'Warning' not in line and 'npm' not in line] all_sgs = {} # {stack: {sg_id: sg_details}} sg_usage = defaultdict(list) # {sg_id: [list of resources using it]} for stack in stacks: print(f"Analyzing stack: {stack}") # Synthesize the stack result = subprocess.run(['npx', 'cdk', 'synth', stack, '--json'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd='/workspace/cdk_app') try: template = json.loads(result.stdout) except: print(f" Failed to parse template for {stack}") continue resources = template.get('Resources', {}) # Find all security groups sgs_in_stack = {} for resource_id, resource_def in resources.items(): if resource_def.get('Type') == 'AWS::EC2::SecurityGroup': sgs_in_stack[resource_id] = resource_def all_sgs[resource_id] = { 'stack': stack, 'region': stack.split('-')[-1], 'definition': resource_def } # Find all references to security groups for resource_id, resource_def in resources.items(): props = resource_def.get('Properties', {}) # Check SecurityGroupIds sg_ids = props.get('SecurityGroupIds', []) for sg_ref in sg_ids: if isinstance(sg_ref, dict) and 'Fn::GetAtt' in sg_ref: sg_name = sg_ref['Fn::GetAtt'][0] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) # Check SecurityGroups (for Classic/VPC) sgs = props.get('SecurityGroups', []) for sg_ref in sgs: if isinstance(sg_ref, dict) and 'Fn::GetAtt' in sg_ref: sg_name = sg_ref['Fn::GetAtt'][0] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) elif isinstance(sg_ref, dict) and 'Ref' in sg_ref: sg_name = sg_ref['Ref'] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) # Now find unused SGs print("\n" + "="*80) print("SECURITY GROUPS ANALYSIS") print("="*80) unused_sgs = [] used_sgs = [] for sg_id, sg_info in all_sgs.items(): stack = sg_info['stack'] region = sg_info['region'] if sg_id in sg_usage and len(sg_usage[sg_id]) > 0: used_sgs.append((sg_id, sg_info, sg_usage[sg_id])) else: unused_sgs.append((sg_id, sg_info)) print(f"\nTotal Security Groups Defined: {len(all_sgs)}") print(f"Used Security Groups: {len(used_sgs)}") print(f"UNUSED Security Groups: {len(unused_sgs)}") if unused_sgs: print("\n" + "="*80) print("UNUSED SECURITY GROUPS") print("="*80) for sg_id, sg_info in sorted(unused_sgs, key=lambda x: (x[1]['region'], x[0])): print(f"\nLogical ID: {sg_id}") print(f" Stack: {sg_info['stack']}") print(f" Region: {sg_info['region']}") if 'GroupDescription' in sg_info['definition'].get('Properties', {}): print(f" Description: {sg_info['definition']['Properties']['GroupDescription']}") if used_sgs: print("\n" + "="*80) print("USED SECURITY GROUPS") print("="*80) for sg_id, sg_info, usages in sorted(used_sgs, key=lambda x: (x[1]['region'], x[0])): print(f"\nLogical ID: {sg_id}") print(f" Stack: {sg_info['stack']}") print(f" Region: {sg_info['region']}") print(f" Used by ({len(usages)}):") for usage in usages: print(f" - {usage['resource']} ({usage['type']})") PYTHON python3 /tmp/comprehensive_sg_analysis.py
cd /workspace/cdk_app && cat > /tmp/detailed_sg_analysis.py << 'PYTHON' import json import subprocess import re from collections import defaultdict # Get all stacks result = subprocess.run(['npx', 'cdk', 'ls'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd='/workspace/cdk_app') stacks = [line.strip() for line in result.stdout.split('\n') if line.strip() and 'WARNING' not in line and 'Warning' not in line and 'npm' not in line] all_sgs = {} # {sg_id: sg_details} sg_usage = defaultdict(list) # {sg_id: [list of resources using it]} for stack in stacks: print(f"Analyzing stack: {stack}") # Extract region from stack name (it's always the last component after splitting by -) stack_parts = stack.split('-') region = None for part in reversed(stack_parts): if part in ['us-east-1', 'us-west-1', 'us-west-2', 'eu-west-1', 'ap-southeast-1']: region = part break # Synthesize the stack result = subprocess.run(['npx', 'cdk', 'synth', stack, '--json'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd='/workspace/cdk_app') try: template = json.loads(result.stdout) except: print(f" Failed to parse template for {stack}") continue resources = template.get('Resources', {}) # Find all security groups for resource_id, resource_def in resources.items(): if resource_def.get('Type') == 'AWS::EC2::SecurityGroup': all_sgs[resource_id] = { 'stack': stack, 'region': region if region else 'unknown', 'definition': resource_def, 'logical_id': resource_id } # Find all references to security groups for resource_id, resource_def in resources.items(): props = resource_def.get('Properties', {}) # Check SecurityGroupIds sg_ids = props.get('SecurityGroupIds', []) for sg_ref in sg_ids: if isinstance(sg_ref, dict) and 'Fn::GetAtt' in sg_ref: sg_name = sg_ref['Fn::GetAtt'][0] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) # Check SecurityGroups (for Classic/VPC) sgs = props.get('SecurityGroups', []) for sg_ref in sgs: if isinstance(sg_ref, dict) and 'Fn::GetAtt' in sg_ref: sg_name = sg_ref['Fn::GetAtt'][0] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) elif isinstance(sg_ref, dict) and 'Ref' in sg_ref: sg_name = sg_ref['Ref'] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) # Categorize SGs unused_sgs = [] used_sgs = [] for sg_id, sg_info in all_sgs.items(): if sg_id in sg_usage and len(sg_usage[sg_id]) > 0: used_sgs.append((sg_id, sg_info, sg_usage[sg_id])) else: unused_sgs.append((sg_id, sg_info)) # Create output output = [] output.append("="*100) output.append("UNUSED SECURITY GROUPS BY REGION - AWS CDK Analysis") output.append("="*100) output.append("") output.append(f"SUMMARY:") output.append(f" Total Security Groups Defined: {len(all_sgs)}") output.append(f" Used Security Groups: {len(used_sgs)}") output.append(f" UNUSED Security Groups: {len(unused_sgs)}") output.append("") if unused_sgs: # Group by region by_region = {} for sg_id, sg_info in unused_sgs: region = sg_info['region'] if region not in by_region: by_region[region] = [] by_region[region].append((sg_id, sg_info)) output.append("="*100) output.append("UNUSED SECURITY GROUPS (Grouped by Region)") output.append("="*100) for region in sorted(by_region.keys()): output.append("") output.append(f"REGION: {region}") output.append("-" * 100) for sg_id, sg_info in sorted(by_region[region], key=lambda x: x[0]): output.append(f"\n Logical ID: {sg_id}") output.append(f" Stack: {sg_info['stack']}") output.append(f" Region: {sg_info['region']}") props = sg_info['definition'].get('Properties', {}) if 'GroupDescription' in props: output.append(f" Description: {props['GroupDescription']}") if 'VpcId' in props: output.append(f" VPC: {props.get('VpcId', 'N/A')}") if 'Tags' in props: output.append(f" Tags: {props['Tags']}") else: output.append("No unused security groups found!") output.append("") output.append("="*100) output.append("USED SECURITY GROUPS (For Reference)") output.append("="*100) by_region_used = {} for sg_id, sg_info, usages in used_sgs: region = sg_info['region'] if region not in by_region_used: by_region_used[region] = [] by_region_used[region].append((sg_id, sg_info, usages)) for region in sorted(by_region_used.keys()): output.append("") output.append(f"REGION: {region}") output.append("-" * 100) for sg_id, sg_info, usages in sorted(by_region_used[region], key=lambda x: x[0]): output.append(f"\n Logical ID: {sg_id}") output.append(f" Stack: {sg_info['stack']}") output.append(f" Region: {sg_info['region']}") output.append(f" Used by ({len(usages)} resource(s)):") for usage in usages: output.append(f" - {usage['resource']} ({usage['type']})") # Print and save result_text = "\n".join(output) print(result_text) # Save to file with open('/logs/agent/agent-output.txt', 'w') as f: f.write(result_text) print("\n✓ Results saved to /logs/agent/agent-output.txt") PYTHON python3 /tmp/detailed_sg_analysis.py
cd /workspace/cdk_app && cat > /tmp/final_sg_analysis.py << 'PYTHON' import json import subprocess import re from collections import defaultdict # Get all stacks result = subprocess.run(['npx', 'cdk', 'ls'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd='/workspace/cdk_app') stacks = [line.strip() for line in result.stdout.split('\n') if line.strip() and 'WARNING' not in line and 'Warning' not in line and 'npm' not in line] all_sgs = {} # {sg_id: sg_details} sg_usage = defaultdict(list) # {sg_id: [list of resources using it]} for stack in stacks: print(f"Analyzing stack: {stack}") # Extract region from stack name - look for AWS region patterns at the end region_match = re.search(r'(us-east-1|us-west-1|us-west-2|eu-west-1|eu-central-1|ap-southeast-1|ap-northeast-1)$', stack) region = region_match.group(1) if region_match else 'unknown' # Synthesize the stack result = subprocess.run(['npx', 'cdk', 'synth', stack, '--json'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd='/workspace/cdk_app') try: template = json.loads(result.stdout) except: print(f" Failed to parse template for {stack}") continue resources = template.get('Resources', {}) # Find all security groups for resource_id, resource_def in resources.items(): if resource_def.get('Type') == 'AWS::EC2::SecurityGroup': all_sgs[resource_id] = { 'stack': stack, 'region': region, 'definition': resource_def, 'logical_id': resource_id } # Find all references to security groups for resource_id, resource_def in resources.items(): props = resource_def.get('Properties', {}) # Check SecurityGroupIds sg_ids = props.get('SecurityGroupIds', []) for sg_ref in sg_ids: if isinstance(sg_ref, dict) and 'Fn::GetAtt' in sg_ref: sg_name = sg_ref['Fn::GetAtt'][0] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) # Check SecurityGroups (for Classic/VPC) sgs = props.get('SecurityGroups', []) for sg_ref in sgs: if isinstance(sg_ref, dict) and 'Fn::GetAtt' in sg_ref: sg_name = sg_ref['Fn::GetAtt'][0] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) elif isinstance(sg_ref, dict) and 'Ref' in sg_ref: sg_name = sg_ref['Ref'] sg_usage[sg_name].append({ 'resource': resource_id, 'type': resource_def.get('Type'), 'stack': stack }) # Categorize SGs unused_sgs = [] used_sgs = [] for sg_id, sg_info in all_sgs.items(): if sg_id in sg_usage and len(sg_usage[sg_id]) > 0: used_sgs.append((sg_id, sg_info, sg_usage[sg_id])) else: unused_sgs.append((sg_id, sg_info)) # Create output output = [] output.append("="*100) output.append("UNUSED SECURITY GROUPS BY REGION - AWS CDK Analysis") output.append("="*100) output.append("") output.append(f"SUMMARY:") output.append(f" Total Security Groups Defined: {len(all_sgs)}") output.append(f" Used Security Groups: {len(used_sgs)}") output.append(f" UNUSED Security Groups: {len(unused_sgs)}") output.append("") if unused_sgs: # Group by region by_region = {} for sg_id, sg_info in unused_sgs: region = sg_info['region'] if region not in by_region: by_region[region] = [] by_region[region].append((sg_id, sg_info)) output.append("="*100) output.append("UNUSED SECURITY GROUPS (Grouped by Region)") output.append("="*100) for region in sorted(by_region.keys()): output.append("") output.append(f"REGION: {region}") output.append("-" * 100) for sg_id, sg_info in sorted(by_region[region], key=lambda x: x[0]): output.append(f"\n Logical ID: {sg_id}") output.append(f" Stack: {sg_info['stack']}") output.append(f" Region: {sg_info['region']}") props = sg_info['definition'].get('Properties', {}) if 'GroupDescription' in props: output.append(f" Description: {props['GroupDescription']}") if 'VpcId' in props: vpc_ref = props.get('VpcId', {}) if isinstance(vpc_ref, dict): output.append(f" VPC: {json.dumps(vpc_ref)}") else: output.append(f" VPC: {vpc_ref}") if 'Tags' in props: output.append(f" Tags: {props['Tags']}") else: output.append("No unused security groups found!") output.append("") output.append("="*100) output.append("USED SECURITY GROUPS (For Reference)") output.append("="*100) by_region_used = {} for sg_id, sg_info, usages in used_sgs: region = sg_info['region'] if region not in by_region_used: by_region_used[region] = [] by_region_used[region].append((sg_id, sg_info, usages)) for region in sorted(by_region_used.keys()): output.append("") output.append(f"REGION: {region}") output.append("-" * 100) for sg_id, sg_info, usages in sorted(by_region_used[region], key=lambda x: x[0]): output.append(f"\n Logical ID: {sg_id}") output.append(f" Stack: {sg_info['stack']}") output.append(f" Region: {sg_info['region']}") output.append(f" Used by ({len(usages)} resource(s)):") for usage in usages: output.append(f" - {usage['resource']} ({usage['type']})") # Print and save result_text = "\n".join(output) print(result_text) # Save to file with open('/logs/agent/agent-output.txt', 'w') as f: f.write(result_text) print("\n✓ Results saved to /logs/agent/agent-output.txt") PYTHON python3 /tmp/final_sg_analysis.py
Alchemy — missed
30 commands, from alchemy-g3.
cd /workspace/alchemy && alchemy state list | grep -i securitygroup | head -20
cd /workspace/alchemy && alchemy state tree
cd /workspace/alchemy && alchemy state list | grep -i 'securitygroup\|sg'
cd /workspace/alchemy && alchemy state get alchemy-ec2-multiregion/bench/exp-UnusedSecurityGroupId
cd /workspace/alchemy && alchemy state get alchemy-ec2-multiregion/bench/exp-SecurityGroupId
find /workspace/alchemy/.alchemy -name "*.json" -type f | head -5
cd /workspace/alchemy && alchemy state list | sort
cd /workspace/alchemy && alchemy state get alchemy-ec2-multiregion/bench/unused
grep -r '"kind".*"aws::SecurityGroup"' /workspace/alchemy/.alchemy --include="*.json" 2>/dev/null
cd /workspace/alchemy && alchemy state get alchemy-ec2-multiregion/bench/web
grep -r '"kind"' /workspace/alchemy/.alchemy/alchemy-ec2-multiregion/bench/*.json 2>/dev/null | grep -o '"kind":"[^"]*"' | sort | uniq -c
grep '"kind"' /workspace/alchemy/.alchemy/alchemy-ec2-multiregion/bench/*.json 2>/dev/null | cut -d'"' -f4 | sort | uniq -c | sort -rn
# … 18 more
Alchemy v2 (Effect) — missed
18 commands, from alchemy-effect-g2.
cd /workspace/alchemy && alchemy state stacks us-west-1.run.ts --local
cd /workspace/alchemy && alchemy state stages us-west-1.run.ts --local
cd /workspace/alchemy && alchemy state resources --stack alchemy-effect-ec2-multiregion-us-east-1 us-west-1.run.ts --local 2>&1 | head -50
cd /workspace/alchemy && alchemy state tree us-west-1.run.ts --local 2>&1 | head -100
cd /workspace/alchemy && alchemy state resources --stack alchemy-effect-ec2-multiregion-us-east-1 --stage bench us-west-1.run.ts --local
cd /workspace/alchemy && alchemy state get --stack alchemy-effect-ec2-multiregion-us-east-1 --stage bench --fqn WebSecurityGroup us-west-1.run.ts --local
cd /workspace/alchemy && alchemy state get --stack alchemy-effect-ec2-multiregion-us-east-1 --stage bench --fqn UnusedSecurityGroup us-west-1.run.ts --local
cd /workspace/alchemy && for region in us-west-1 us-west-2; do stack="alchemy-effect-ec2-multiregion-$region" echo "=== $region ($stack) ===" alchemy state resources --stack "$stack" --stage bench us-west-1.run.ts --local 2>&1 | grep -i "security\|group" || echo "No security groups" done
cd /workspace/alchemy && for stack in "alchemy-effect-ec2-multiregion-us-east-1" "alchemy-effect-ec2-multiregion-us-west-1" "alchemy-effect-ec2-multiregion-us-west-2"; do echo "=== $stack ===" alchemy state resources --stack "$stack" --stage bench us-west-1.run.ts --local 2>&1 done 2>&1 | tee /tmp/all_resources.txt
cd /workspace/alchemy && alchemy state get --stack alchemy-effect-ec2-multiregion-us-east-1 --stage bench --fqn WebServer us-west-1.run.ts --local
cd /workspace/alchemy && alchemy state get --stack alchemy-effect-ec2-multiregion-us-east-1 --stage bench --fqn LaunchTemplateServer us-west-1.run.ts --local
cd /workspace/alchemy && alchemy state get --stack alchemy-effect-ec2-multiregion-us-east-1 --stage bench --fqn WebLaunchTemplate us-west-1.run.ts --local
# … 6 more