From 358b82a1a5f5f9a0a813491821c4bc095ee4f32e Mon Sep 17 00:00:00 2001 From: n0mad1k Date: Sat, 3 May 2025 00:36:37 -0400 Subject: [PATCH] working on aws still but deployment works --- AWS/c2.yml | 40 +++++- AWS/cleanup.yml | 226 +++++++++++++++++-------------- AWS/infrastructure.yml | 27 +++- AWS/process_vpc.yml | 252 +++++++++++++++-------------------- AWS/redirector.yml | 5 +- tasks/security_hardening.yml | 15 ++- 6 files changed, 308 insertions(+), 257 deletions(-) diff --git a/AWS/c2.yml b/AWS/c2.yml index 1c8bf07..fb6f89a 100644 --- a/AWS/c2.yml +++ b/AWS/c2.yml @@ -15,7 +15,8 @@ deployment_id: "{{ deployment_id | default('') }}" c2_name: "{{ c2_name | default('s-' + deployment_id) }}" # Check for shared infrastructure - use_shared_infra: "{{ not (c2_region is defined and redirector_region is defined and c2_region != redirector_region) }}" + # Only use shared when C2 and redirector are in the same region + use_shared_infra: "{{ not (c2_region is defined and redirector_region is defined and c2_region != redirector_region) and not c2_only | default(false) | bool and not redirector_only | default(false) | bool }}" tasks: - name: Validate AWS credentials @@ -53,11 +54,16 @@ ami_id: "{{ ami_map[aws_c2_region] }}" when: ami_map is defined and aws_c2_region in ami_map - # Add AMI username mapping + # Add AMI username mapping - improved with better detection - name: Determine correct SSH user for the AMI set_fact: - ami_ssh_user: >- - {% if ami_id == 'ami-061b17d332829ab1c' %}kali{% else %}ubuntu{% endif %} + ami_ssh_user: "{{ 'kali' if (ami_id is defined and ami_id is search('-kali-')) or (ami_id is defined and ami_id == 'ami-061b17d332829ab1c') else 'ubuntu' }}" + + - name: Display AMI and user information for debugging + debug: + msg: + - "Using AMI ID: {{ ami_id | default('AMI not defined') }}" + - "Detected SSH user: {{ ami_ssh_user }}" - name: Create EC2 key pair amazon.aws.ec2_key: @@ -130,12 +136,14 @@ set_fact: vpc_id: "{{ shared_infra.vpc_id }}" subnet_id: "{{ shared_infra.subnet_id }}" + c2_vpc_id: "{{ shared_infra.vpc_id }}" # Store for cleanup reference when: use_shared_infra | bool and infra_state_file.stat.exists | default(false) - name: Set VPC ID from created infrastructure set_fact: vpc_id: "{{ vpc_result.vpc.id }}" subnet_id: "{{ subnet_result.subnet.id }}" + c2_vpc_id: "{{ vpc_result.vpc.id }}" # Store for cleanup reference when: not (use_shared_infra | bool and infra_state_file.stat.exists | default(false)) # Create security group @@ -189,6 +197,13 @@ c2_ip: "{{ c2_instance.instances[0].public_ip_address }}" c2_instance_id: "{{ c2_instance.instances[0].instance_id }}" + - name: Display C2 instance details for debugging + debug: + msg: + - "C2 IP: {{ c2_ip }}" + - "C2 Instance ID: {{ c2_instance_id }}" + - "SSH User to use: {{ ami_ssh_user }}" + - name: Wait for C2 instance initialization pause: seconds: 180 @@ -212,7 +227,7 @@ name: "c2" groups: "c2servers" ansible_host: "{{ c2_ip }}" - ansible_user: "{{ ami_ssh_user | default('kali') }}" + ansible_user: "{{ ami_ssh_user }}" ansible_ssh_private_key_file: "~/.ssh/{{ c2_name }}.pem" ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes" ansible_python_interpreter: "/usr/bin/python3" @@ -225,6 +240,21 @@ redirector_ip: "{{ hostvars['localhost']['redirector_ip'] | default('127.0.0.1') }}" c2_subdomain: "{{ c2_subdomain | default('mail') }}" tasks: + - name: Install python3 if it doesn't exist on target + raw: test -e /usr/bin/python3 || (apt-get update && apt-get install -y python3) + args: + executable: /bin/bash + register: python_install + ignore_errors: yes + + - name: Debug connection information + debug: + msg: + - "Connected to C2 server successfully" + - "Host: {{ ansible_host }}" + - "User: {{ ansible_user }}" + - "Python version: {{ ansible_python_version | default('unknown') }}" + - name: Download Kali archive keyring to temporary location get_url: url: https://archive.kali.org/archive-keyring.gpg diff --git a/AWS/cleanup.yml b/AWS/cleanup.yml index 0eff18d..34274e4 100644 --- a/AWS/cleanup.yml +++ b/AWS/cleanup.yml @@ -9,8 +9,10 @@ - vars.yaml vars: delete_results: {} + vpc_cleanup_list: [] tasks: + # Confirmation prompts - name: Confirm cleanup pause: prompt: "This will delete all AWS resources for deployment ID {{ deployment_id }}. Continue? (yes/no)" @@ -23,7 +25,32 @@ fail_msg: "Cleanup cancelled by user" when: confirm_cleanup | default(true) | bool - # C2 server cleanup + # Check for and load shared infrastructure file + - name: Check for shared infrastructure state + stat: + path: "infrastructure_state.json" + register: infra_state_file + + - name: Load shared infrastructure state + include_vars: + file: "infrastructure_state.json" + name: shared_infra + when: infra_state_file.stat.exists | default(false) + + # Initialize cleaned resources tracking + - name: Initialize cleaned resources tracking + set_fact: + cleaned_resources: + instances: [] + key_pairs: [] + security_groups: [] + network_interfaces: [] + route_tables: [] + subnets: [] + internet_gateways: [] + vpcs: [] + + # EC2 Instance cleanup - name: Terminate C2 instances amazon.aws.ec2_instance: state: absent @@ -33,7 +60,11 @@ register: c2_instances_result when: cleanup_c2 | default(true) | bool - # Redirector cleanup + - name: Update cleaned instances list for C2 + set_fact: + cleaned_resources: "{{ cleaned_resources | combine({'instances': cleaned_resources.instances + c2_instances_result.instance_ids}, recursive=true) }}" + when: cleanup_c2 | default(true) | bool and c2_instances_result.instance_ids is defined + - name: Terminate redirector instances amazon.aws.ec2_instance: state: absent @@ -42,8 +73,12 @@ "tag:Name": "{{ redirector_name }}" register: redirector_instances_result when: cleanup_redirector | default(true) | bool + + - name: Update cleaned instances list for redirector + set_fact: + cleaned_resources: "{{ cleaned_resources | combine({'instances': cleaned_resources.instances + redirector_instances_result.instance_ids}, recursive=true) }}" + when: cleanup_redirector | default(true) | bool and redirector_instances_result.instance_ids is defined - # Tracker cleanup - name: Terminate tracker instances amazon.aws.ec2_instance: state: absent @@ -52,14 +87,21 @@ "tag:Name": "{{ tracker_name | default('t-' + deployment_id) }}" register: tracker_instances_result when: cleanup_tracker | default(true) | bool and track_deployment | default(false) | bool + + - name: Update cleaned instances list for tracker + set_fact: + cleaned_resources: "{{ cleaned_resources | combine({'instances': cleaned_resources.instances + tracker_instances_result.instance_ids}, recursive=true) }}" + when: cleanup_tracker | default(true) | bool and track_deployment | default(false) | bool and tracker_instances_result.instance_ids is defined - # We need to wait a bit for instances to terminate before we can clean up security groups + # Wait for all instances to terminate before attempting to clean up dependent resources - name: Wait for instances to terminate pause: seconds: 30 - when: cleanup_c2 | default(true) | bool or cleanup_redirector | default(true) | bool or (cleanup_tracker | default(true) | bool and track_deployment | default(false) | bool) + when: (cleanup_c2 | default(true) | bool and c2_instances_result.changed | default(false)) or + (cleanup_redirector | default(true) | bool and redirector_instances_result.changed | default(false)) or + (cleanup_tracker | default(true) | bool and track_deployment | default(false) | bool and tracker_instances_result.changed | default(false)) - # Delete key pairs + # Key pair cleanup - name: Delete C2 EC2 key pair amazon.aws.ec2_key: name: "{{ c2_name }}" @@ -68,6 +110,11 @@ register: c2_key_result when: cleanup_c2 | default(true) | bool + - name: Update cleaned key pairs list for C2 + set_fact: + cleaned_resources: "{{ cleaned_resources | combine({'key_pairs': cleaned_resources.key_pairs + [c2_name]}, recursive=true) }}" + when: cleanup_c2 | default(true) | bool and c2_key_result.changed | default(false) + - name: Delete redirector EC2 key pair amazon.aws.ec2_key: name: "{{ redirector_name }}" @@ -76,6 +123,11 @@ register: redirector_key_result when: cleanup_redirector | default(true) | bool + - name: Update cleaned key pairs list for redirector + set_fact: + cleaned_resources: "{{ cleaned_resources | combine({'key_pairs': cleaned_resources.key_pairs + [redirector_name]}, recursive=true) }}" + when: cleanup_redirector | default(true) | bool and redirector_key_result.changed | default(false) + - name: Delete tracker EC2 key pair amazon.aws.ec2_key: name: "{{ tracker_name | default('t-' + deployment_id) }}" @@ -84,7 +136,12 @@ register: tracker_key_result when: cleanup_tracker | default(true) | bool and track_deployment | default(false) | bool - # Security Groups + - name: Update cleaned key pairs list for tracker + set_fact: + cleaned_resources: "{{ cleaned_resources | combine({'key_pairs': cleaned_resources.key_pairs + [tracker_name | default('t-' + deployment_id)]}, recursive=true) }}" + when: cleanup_tracker | default(true) | bool and track_deployment | default(false) | bool and tracker_key_result.changed | default(false) + + # Security group cleanup - name: Delete C2 security group amazon.aws.ec2_security_group: name: "{{ c2_name }}-sg" @@ -94,6 +151,11 @@ ignore_errors: yes when: cleanup_c2 | default(true) | bool + - name: Update cleaned security groups list for C2 + set_fact: + cleaned_resources: "{{ cleaned_resources | combine({'security_groups': cleaned_resources.security_groups + [c2_sg_result.group_id | default('')]}, recursive=true) }}" + when: cleanup_c2 | default(true) | bool and c2_sg_result.changed | default(false) and c2_sg_result.group_id is defined + - name: Delete redirector security group amazon.aws.ec2_security_group: name: "{{ redirector_name }}-sg" @@ -103,6 +165,11 @@ ignore_errors: yes when: cleanup_redirector | default(true) | bool + - name: Update cleaned security groups list for redirector + set_fact: + cleaned_resources: "{{ cleaned_resources | combine({'security_groups': cleaned_resources.security_groups + [redirector_sg_result.group_id | default('')]}, recursive=true) }}" + when: cleanup_redirector | default(true) | bool and redirector_sg_result.changed | default(false) and redirector_sg_result.group_id is defined + - name: Delete tracker security group amazon.aws.ec2_security_group: name: "{{ tracker_name | default('t-' + deployment_id) }}-sg" @@ -112,97 +179,62 @@ ignore_errors: yes when: cleanup_tracker | default(true) | bool and track_deployment | default(false) | bool - # VPC Resources - - name: Get VPCs + - name: Update cleaned security groups list for tracker + set_fact: + cleaned_resources: "{{ cleaned_resources | combine({'security_groups': cleaned_resources.security_groups + [tracker_sg_result.group_id | default('')]}, recursive=true) }}" + when: cleanup_tracker | default(true) | bool and track_deployment | default(false) | bool and tracker_sg_result.changed | default(false) and tracker_sg_result.group_id is defined + + # Identify VPCs to clean up + - name: Get VPCs by deployment tag amazon.aws.ec2_vpc_net_info: region: "{{ aws_region }}" filters: "tag:deployment_id": "{{ deployment_id }}" - register: vpc_info - - - name: Get subnets - amazon.aws.ec2_vpc_subnet_info: - region: "{{ aws_region }}" - filters: - "tag:deployment_id": "{{ deployment_id }}" - register: subnet_info - - - name: Get route tables - amazon.aws.ec2_vpc_route_table_info: - region: "{{ aws_region }}" - filters: - "tag:deployment_id": "{{ deployment_id }}" - register: route_table_info - - - name: Get internet gateways - amazon.aws.ec2_vpc_igw_info: - region: "{{ aws_region }}" - filters: - "tag:deployment_id": "{{ deployment_id }}" - register: igw_info + register: tagged_vpcs - # Get and delete any remaining network interfaces in these VPCs - - name: Get network interfaces in VPCs - amazon.aws.ec2_eni_info: - region: "{{ aws_region }}" - filters: - vpc-id: "{{ item.vpc_id }}" - loop: "{{ vpc_info.vpcs }}" - register: eni_info - - - name: Delete network interfaces - amazon.aws.ec2_eni: - region: "{{ aws_region }}" - eni_id: "{{ item.1.network_interface_id }}" + - name: Add tagged VPCs to cleanup list + set_fact: + vpc_cleanup_list: "{{ vpc_cleanup_list + [item.vpc_id] }}" + with_items: "{{ tagged_vpcs.vpcs }}" + when: tagged_vpcs.vpcs | length > 0 + + - name: Add shared VPC to cleanup if both C2 and redirector being cleaned + set_fact: + vpc_cleanup_list: "{{ vpc_cleanup_list + [shared_infra.vpc_id] }}" + when: > + infra_state_file.stat.exists | default(false) and + shared_infra.vpc_id is defined and + cleanup_c2 | default(true) | bool and + cleanup_redirector | default(true) | bool + + # Make the VPC cleanup list unique + - name: Deduplicate VPC cleanup list + set_fact: + vpc_cleanup_list: "{{ vpc_cleanup_list | unique }}" + when: vpc_cleanup_list | length > 0 + + # Process each VPC - direct inline implementation instead of temporary files + - name: Process VPCs for cleanup + block: + - name: Process each VPC + include_tasks: "../tasks/process_vpc.yml" + vars: + vpc_id: "{{ item }}" + with_items: "{{ vpc_cleanup_list | unique }}" + when: vpc_cleanup_list | length > 0 + + # Clean up infrastructure state file if both C2 and redirector are being cleaned + - name: Remove infrastructure state file if cleaning up shared infrastructure + file: + path: "infrastructure_state.json" state: absent - force_detach: true - loop: "{{ eni_info.results | subelements('network_interfaces', skip_missing=true) }}" - register: eni_deleted - ignore_errors: yes - - # Delete VPC resources - - name: Delete route tables - amazon.aws.ec2_vpc_route_table: - region: "{{ aws_region }}" - vpc_id: "{{ item.vpc_id }}" - route_table_id: "{{ item.id }}" - state: absent - loop: "{{ route_table_info.route_tables }}" - register: route_tables_deleted - ignore_errors: yes - - - name: Delete internet gateways - amazon.aws.ec2_vpc_igw: - region: "{{ aws_region }}" - vpc_id: "{{ item.attachments[0].vpc_id }}" - state: absent - loop: "{{ igw_info.internet_gateways }}" - register: igws_deleted - ignore_errors: yes - - - name: Delete subnets - amazon.aws.ec2_vpc_subnet: - region: "{{ aws_region }}" - vpc_id: "{{ item.vpc_id }}" - cidr: "{{ item.cidr_block }}" - state: absent - loop: "{{ subnet_info.subnets }}" - register: subnets_deleted - ignore_errors: yes - - # Wait before trying to delete VPCs to allow AWS to catch up on dependency deletions - - name: Wait for AWS to process subnet and gateway deletions - pause: - seconds: 15 - - - name: Delete VPCs - amazon.aws.ec2_vpc_net: - region: "{{ aws_region }}" - vpc_id: "{{ item.id }}" - state: absent - loop: "{{ vpc_info.vpcs }}" - register: vpcs_deleted - ignore_errors: yes + when: > + infra_state_file.stat.exists | default(false) and + ((cleanup_c2 | default(true) | bool and cleanup_redirector | default(true) | bool) or + (cleanup_c2 | default(true) | bool and not cleanup_redirector | default(true) | bool and + c2_region | default(aws_region) == shared_infra.region) or + (cleanup_redirector | default(true) | bool and not cleanup_c2 | default(true) | bool and + redirector_region | default(aws_region) == shared_infra.region)) # Create summary of deleted resources - name: Collect all deleted resources @@ -221,11 +253,11 @@ redirector: "{{ redirector_sg_result.group_id | default('') | ternary([redirector_sg_result.group_id], []) }}" tracker: "{{ tracker_sg_result.group_id | default('') | ternary([tracker_sg_result.group_id], []) }}" vpc_resources: - route_tables: "{{ route_tables_deleted.results | default([]) | map(attribute='item.id', default='') | select() | list }}" - internet_gateways: "{{ igws_deleted.results | default([]) | map(attribute='gateway_id', default='') | select() | list }}" - subnets: "{{ subnets_deleted.results | default([]) | map(attribute='subnet.id', default='') | select() | list }}" - network_interfaces: "{{ eni_deleted.results | default([]) | map(attribute='interface.id', default='') | select() | list }}" - vpcs: "{{ vpcs_deleted.results | default([]) | map(attribute='vpc.id', default='') | select() | list }}" + route_tables: "{{ cleaned_resources.route_tables | default([]) }}" + internet_gateways: "{{ cleaned_resources.internet_gateways | default([]) }}" + subnets: "{{ cleaned_resources.subnets | default([]) }}" + network_interfaces: "{{ cleaned_resources.network_interfaces | default([]) }}" + vpcs: "{{ cleaned_resources.vpcs | default([]) }}" when: not disable_summary | default(false) # Display summary of deleted resources diff --git a/AWS/infrastructure.yml b/AWS/infrastructure.yml index 943e5f3..f4a4af5 100644 --- a/AWS/infrastructure.yml +++ b/AWS/infrastructure.yml @@ -12,8 +12,11 @@ deployment_id: "{{ deployment_id | default('') }}" infra_name: "infra-{{ deployment_id }}" # Region settings - split_regions: "{{ c2_region is defined and redirector_region is defined and c2_region != redirector_region }}" deployment_region: "{{ aws_region | default(aws_region_choices | random) }}" + # Check if using split regions (C2 and redirector in different regions) + split_regions: "{{ c2_region is defined and redirector_region is defined and c2_region != redirector_region }}" + # Check if only deploying one component (C2 only or redirector only) + single_component: "{{ c2_only | default(false) | bool or redirector_only | default(false) | bool }}" tasks: - name: Validate AWS credentials @@ -26,6 +29,20 @@ - name: Skip shared infrastructure if using split regions meta: end_play when: split_regions | bool + + - name: Print infrastructure deployment info + debug: + msg: "Deploying shared infrastructure in {{ deployment_region }}" + when: not split_regions | bool and not single_component | bool + + - name: Check if deploying just C2 or just redirector + debug: + msg: "Skipping shared infrastructure for single component deployment ({{ 'C2 only' if c2_only | default(false) else 'Redirector only' }})" + when: single_component | bool + + - name: Skip shared infrastructure for single component deployment + meta: end_play + when: single_component | bool - name: Create shared VPC amazon.aws.ec2_vpc_net: @@ -37,10 +54,12 @@ deployment_id: "{{ deployment_id }}" state: present register: vpc_result + when: not split_regions | bool and not single_component | bool - name: Store shared VPC ID set_fact: shared_vpc_id: "{{ vpc_result.vpc.id }}" + when: not split_regions | bool and not single_component | bool and vpc_result is defined - name: Create internet gateway amazon.aws.ec2_vpc_igw: @@ -51,6 +70,7 @@ Name: "{{ infra_name }}-igw" deployment_id: "{{ deployment_id }}" register: igw_result + when: not split_regions | bool and not single_component | bool and shared_vpc_id is defined - name: Create subnet amazon.aws.ec2_vpc_subnet: @@ -63,6 +83,7 @@ Name: "{{ infra_name }}-subnet" deployment_id: "{{ deployment_id }}" register: subnet_result + when: not split_regions | bool and not single_component | bool and shared_vpc_id is defined - name: Create routing table amazon.aws.ec2_vpc_route_table: @@ -77,6 +98,7 @@ subnets: - "{{ subnet_result.subnet.id }}" register: route_table_result + when: not split_regions | bool and not single_component | bool and shared_vpc_id is defined and igw_result is defined and subnet_result is defined - name: Write infrastructure info to state file copy: @@ -89,4 +111,5 @@ "deployment_id": "{{ deployment_id }}" } dest: "infrastructure_state.json" - mode: "0600" \ No newline at end of file + mode: "0600" + when: not split_regions | bool and not single_component | bool and shared_vpc_id is defined and subnet_result is defined and igw_result is defined \ No newline at end of file diff --git a/AWS/process_vpc.yml b/AWS/process_vpc.yml index 2fdff03..d71186d 100644 --- a/AWS/process_vpc.yml +++ b/AWS/process_vpc.yml @@ -1,206 +1,164 @@ --- # VPC Cleanup Process -# Step 1: Route Tables +# Step 1: Network Interfaces +- name: Find network interfaces in VPC {{ vpc_id }} + amazon.aws.ec2_eni_info: + region: "{{ aws_region }}" + filters: + vpc-id: "{{ vpc_id }}" + register: eni_info + failed_when: false + changed_when: false + +- name: Delete network interfaces + amazon.aws.ec2_eni: + region: "{{ aws_region }}" + eni_id: "{{ item.id }}" + state: absent + force_detach: true + loop: "{{ eni_info.network_interfaces }}" + register: eni_deleted + ignore_errors: yes + when: eni_info.network_interfaces | length > 0 + +- name: Update cleaned network interfaces + set_fact: + cleaned_resources: "{{ cleaned_resources | combine({'network_interfaces': cleaned_resources.network_interfaces + [item.id]}, recursive=True) }}" + with_items: "{{ eni_info.network_interfaces }}" + when: eni_info.network_interfaces | length > 0 + +# Step 2: Route Tables - name: Find all route tables for VPC {{ vpc_id }} - command: > - aws ec2 describe-route-tables - --filters "Name=vpc-id,Values={{ vpc_id }}" - --query "RouteTables[?Associations[0].Main != `true`].RouteTableId" - --output text - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - register: rt_ids + amazon.aws.ec2_vpc_route_table_info: + region: "{{ aws_region }}" + filters: + vpc-id: "{{ vpc_id }}" + register: rt_info failed_when: false changed_when: false - name: Process route tables - when: rt_ids.stdout | trim != "" + when: rt_info.route_tables | length > 0 block: - - name: Find route table associations - command: > - aws ec2 describe-route-tables - --route-table-id {{ item }} - --query "RouteTables[].Associations[].RouteTableAssociationId" - --output text - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - register: rt_assocs - with_items: "{{ rt_ids.stdout.split() }}" - failed_when: false - changed_when: false - - - name: Disassociate route tables - command: > - aws ec2 disassociate-route-table - --association-id {{ item.1 }} - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - with_subelements: - - "{{ rt_assocs.results }}" - - stdout_lines - when: item.0.stdout | trim != "" - failed_when: false - ignore_errors: true - - - name: Delete route tables - command: > - aws ec2 delete-route-table - --route-table-id {{ item }} - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - with_items: "{{ rt_ids.stdout.split() }}" + - name: Delete non-main route tables + amazon.aws.ec2_vpc_route_table: + region: "{{ aws_region }}" + vpc_id: "{{ vpc_id }}" + route_table_id: "{{ item.id }}" + state: absent + loop: "{{ rt_info.route_tables }}" + when: not item.associations or not item.associations[0].main | default(false) register: deleted_rts - failed_when: false - ignore_errors: true + ignore_errors: yes - name: Update cleaned route tables set_fact: - cleaned_resources: "{{ cleaned_resources | combine({'route_tables': cleaned_resources.route_tables + rt_ids.stdout.split()}, recursive=True) }}" - when: rt_ids.stdout | trim != "" + cleaned_resources: "{{ cleaned_resources | combine({'route_tables': cleaned_resources.route_tables + [item.id]}, recursive=True) }}" + with_items: "{{ rt_info.route_tables }}" + when: not item.associations or not item.associations[0].main | default(false) -# Step 2: Internet Gateways +# Step 3: Internet Gateways - name: Find internet gateways for VPC {{ vpc_id }} - command: > - aws ec2 describe-internet-gateways - --filters "Name=attachment.vpc-id,Values={{ vpc_id }}" - --query "InternetGateways[].InternetGatewayId" - --output text - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - register: igw_ids + amazon.aws.ec2_vpc_igw_info: + region: "{{ aws_region }}" + filters: + attachment.vpc-id: "{{ vpc_id }}" + register: igw_info failed_when: false changed_when: false - name: Process internet gateways - when: igw_ids.stdout | trim != "" + when: igw_info.internet_gateways | length > 0 block: - name: Detach internet gateways - command: > - aws ec2 detach-internet-gateway - --internet-gateway-id {{ item }} - --vpc-id {{ vpc_id }} - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - with_items: "{{ igw_ids.stdout.split() }}" - failed_when: false - ignore_errors: true + amazon.aws.ec2_vpc_igw: + region: "{{ aws_region }}" + vpc_id: "{{ vpc_id }}" + state: absent + register: igw_detached + ignore_errors: yes - name: Delete internet gateways - command: > - aws ec2 delete-internet-gateway - --internet-gateway-id {{ item }} - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - with_items: "{{ igw_ids.stdout.split() }}" + amazon.aws.ec2_vpc_igw: + region: "{{ aws_region }}" + igw_id: "{{ item.id }}" + state: absent + loop: "{{ igw_info.internet_gateways }}" register: deleted_igws - failed_when: false - ignore_errors: true + ignore_errors: yes - name: Update cleaned internet gateways set_fact: - cleaned_resources: "{{ cleaned_resources | combine({'internet_gateways': cleaned_resources.internet_gateways + igw_ids.stdout.split()}, recursive=True) }}" - when: igw_ids.stdout | trim != "" + cleaned_resources: "{{ cleaned_resources | combine({'internet_gateways': cleaned_resources.internet_gateways + [item.id]}, recursive=True) }}" + with_items: "{{ igw_info.internet_gateways }}" -# Step 3: Subnets +# Step 4: Subnets - name: Find subnets for VPC {{ vpc_id }} - command: > - aws ec2 describe-subnets - --filters "Name=vpc-id,Values={{ vpc_id }}" - --query "Subnets[].SubnetId" - --output text - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - register: subnet_ids + amazon.aws.ec2_vpc_subnet_info: + region: "{{ aws_region }}" + filters: + vpc-id: "{{ vpc_id }}" + register: subnet_info failed_when: false changed_when: false - name: Delete subnets - command: > - aws ec2 delete-subnet - --subnet-id {{ item }} - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - with_items: "{{ subnet_ids.stdout.split() }}" + amazon.aws.ec2_vpc_subnet: + region: "{{ aws_region }}" + vpc_id: "{{ vpc_id }}" + cidr: "{{ item.cidr_block }}" + state: absent + loop: "{{ subnet_info.subnets }}" register: deleted_subnets - failed_when: false ignore_errors: true - when: subnet_ids.stdout | trim != "" + when: subnet_info.subnets | length > 0 - name: Update cleaned subnets set_fact: - cleaned_resources: "{{ cleaned_resources | combine({'subnets': cleaned_resources.subnets + subnet_ids.stdout.split()}, recursive=True) }}" - when: subnet_ids.stdout | trim != "" + cleaned_resources: "{{ cleaned_resources | combine({'subnets': cleaned_resources.subnets + [item.id]}, recursive=True) }}" + with_items: "{{ subnet_info.subnets }}" + when: subnet_info.subnets | length > 0 -# Step 4: Security Groups (except default) +# Step 5: Security Groups (except default) - name: Find non-default security groups for VPC {{ vpc_id }} - command: > - aws ec2 describe-security-groups - --filters "Name=vpc-id,Values={{ vpc_id }}" - --query "SecurityGroups[?GroupName != 'default'].GroupId" - --output text - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - register: sg_ids + amazon.aws.ec2_security_group_info: + region: "{{ aws_region }}" + filters: + vpc-id: "{{ vpc_id }}" + register: sg_info failed_when: false changed_when: false -- name: Delete security groups - command: > - aws ec2 delete-security-group - --group-id {{ item }} - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - with_items: "{{ sg_ids.stdout.split() }}" +- name: Delete non-default security groups + amazon.aws.ec2_security_group: + region: "{{ aws_region }}" + group_id: "{{ item.group_id }}" + state: absent + loop: "{{ sg_info.security_groups }}" + when: item.group_name != 'default' register: deleted_sgs - failed_when: false ignore_errors: true - when: sg_ids.stdout | trim != "" - name: Update cleaned security groups set_fact: - cleaned_resources: "{{ cleaned_resources | combine({'security_groups': cleaned_resources.security_groups + sg_ids.stdout.split()}, recursive=True) }}" - when: sg_ids.stdout | trim != "" + cleaned_resources: "{{ cleaned_resources | combine({'security_groups': cleaned_resources.security_groups + [item.group_id]}, recursive=True) }}" + with_items: "{{ sg_info.security_groups }}" + when: item.group_name != 'default' -# Step 5: Wait a bit and delete VPC +# Step 6: Wait a bit and delete VPC - name: Wait before trying to delete VPC pause: seconds: 10 - name: Delete VPC {{ vpc_id }} - command: > - aws ec2 delete-vpc - --vpc-id {{ vpc_id }} - --region {{ aws_region }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + amazon.aws.ec2_vpc_net: + region: "{{ aws_region }}" + vpc_id: "{{ vpc_id }}" + state: absent register: deleted_vpc - failed_when: false ignore_errors: true - name: Update cleaned VPCs set_fact: cleaned_resources: "{{ cleaned_resources | combine({'vpcs': cleaned_resources.vpcs + [vpc_id]}, recursive=True) }}" - when: deleted_vpc.rc == 0 \ No newline at end of file + when: deleted_vpc is success \ No newline at end of file diff --git a/AWS/redirector.yml b/AWS/redirector.yml index 20cb5cf..0ba8347 100644 --- a/AWS/redirector.yml +++ b/AWS/redirector.yml @@ -16,7 +16,8 @@ redirector_name: "{{ redirector_name | default('r-' + deployment_id) }}" shell_handler_port: "{{ shell_handler_port | default(4000 + 60000 | random) }}" # Check for shared infrastructure - use_shared_infra: "{{ not (c2_region is defined and redirector_region is defined and c2_region != redirector_region) }}" + # Only use shared when C2 and redirector are in the same region + use_shared_infra: "{{ not (c2_region is defined and redirector_region is defined and c2_region != redirector_region) and not c2_only | default(false) | bool and not redirector_only | default(false) | bool }}" # Ubuntu AMI IDs for different regions (Ubuntu 22.04 LTS) ubuntu_ami_map: us-east-1: "ami-0aa2b7722dc1b5612" @@ -137,12 +138,14 @@ set_fact: vpc_id: "{{ shared_infra.vpc_id }}" subnet_id: "{{ shared_infra.subnet_id }}" + redirector_vpc_id: "{{ shared_infra.vpc_id }}" # Store for cleanup reference when: use_shared_infra | bool and infra_state_file.stat.exists | default(false) - name: Set VPC ID from created infrastructure set_fact: vpc_id: "{{ vpc_result.vpc.id }}" subnet_id: "{{ subnet_result.subnet.id }}" + redirector_vpc_id: "{{ vpc_result.vpc.id }}" # Store for cleanup reference when: not (use_shared_infra | bool and infra_state_file.stat.exists | default(false)) # Create security group diff --git a/tasks/security_hardening.yml b/tasks/security_hardening.yml index 70994fb..0887da2 100644 --- a/tasks/security_hardening.yml +++ b/tasks/security_hardening.yml @@ -58,7 +58,7 @@ maxretry = 5 bantime = 3600 mode: '0644' - notify: Restart fail2ban + register: fail2ban_config_updated - name: Enable automatic security updates copy: @@ -125,15 +125,20 @@ - { limit_type: soft, limit_item: nproc, value: 4096 } - { limit_type: hard, limit_item: nproc, value: 4096 } -# Replace handlers with direct service restart tasks -- name: Restart SSH service +# Service restart handlers +- name: Restart SSH service if configuration changed service: name: ssh state: restarted when: ssh_config_updated.changed -- name: Restart fail2ban service +- name: Check if fail2ban service exists + stat: + path: "/etc/init.d/fail2ban" + register: fail2ban_service_stat + +- name: Restart fail2ban service if installed and configuration changed service: name: fail2ban state: restarted - when: ansible_facts.services['fail2ban.service'] is defined + when: fail2ban_service_stat.stat.exists and fail2ban_config_updated.changed \ No newline at end of file