working on it
This commit is contained in:
+23
-3
@@ -14,9 +14,12 @@
|
|||||||
instance_type: "{{ aws_instance_type | default('t2.medium') }}"
|
instance_type: "{{ aws_instance_type | default('t2.medium') }}"
|
||||||
deployment_id: "{{ deployment_id | default('') }}"
|
deployment_id: "{{ deployment_id | default('') }}"
|
||||||
c2_name: "{{ c2_name | default('s-' + deployment_id) }}"
|
c2_name: "{{ c2_name | default('s-' + deployment_id) }}"
|
||||||
# Check for shared infrastructure
|
# Define split_regions - only true when regions are explicitly different
|
||||||
# Only use shared when C2 and redirector are in the same region
|
split_regions: "{{ c2_region is defined and redirector_region is defined and c2_region != redirector_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 }}"
|
# Only use shared infra when NOT doing split-region deployment
|
||||||
|
use_shared_infra: "{{ not split_regions and not c2_only | default(false) | bool and not redirector_only | default(false) | bool }}"
|
||||||
|
# Set correct region variable
|
||||||
|
aws_c2_region: "{{ c2_region | default(aws_region) }}"
|
||||||
# AMI map comes from vars.yaml - add fallback for safety
|
# AMI map comes from vars.yaml - add fallback for safety
|
||||||
kali_ami_map_fallback:
|
kali_ami_map_fallback:
|
||||||
us-east-1: "ami-061b17d332829ab1c"
|
us-east-1: "ami-061b17d332829ab1c"
|
||||||
@@ -249,6 +252,22 @@
|
|||||||
timeout: 300
|
timeout: 300
|
||||||
state: started
|
state: started
|
||||||
|
|
||||||
|
- name: Test SSH and prepare remote environment
|
||||||
|
block:
|
||||||
|
- name: Ensure .ansible directory exists with proper permissions
|
||||||
|
shell: |
|
||||||
|
ssh -i ~/.ssh/c2deploy_{{ deployment_id }}.pem -o StrictHostKeyChecking=no {{ ami_ssh_user }}@{{ c2_ip }} "sudo mkdir -p /root/.ansible/tmp && sudo chmod 0700 /root/.ansible/tmp && sudo chown {{ ami_ssh_user }}:{{ ami_ssh_user }} /root/.ansible/tmp"
|
||||||
|
register: ssh_prep
|
||||||
|
until: ssh_prep is success
|
||||||
|
retries: 5
|
||||||
|
delay: 15
|
||||||
|
ignore_errors: yes
|
||||||
|
delegate_to: localhost
|
||||||
|
|
||||||
|
- name: Display SSH preparation results
|
||||||
|
debug:
|
||||||
|
msg: "SSH preparation completed: {{ ssh_prep.stdout | default('No output') }}"
|
||||||
|
|
||||||
# Test SSH connection directly to verify key is working
|
# Test SSH connection directly to verify key is working
|
||||||
- name: Test SSH connection to verify key
|
- name: Test SSH connection to verify key
|
||||||
shell: "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -i ~/.ssh/c2deploy_{{ deployment_id }}.pem {{ ami_ssh_user }}@{{ c2_ip }} 'echo SSH CONNECTION SUCCESSFUL'"
|
shell: "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -i ~/.ssh/c2deploy_{{ deployment_id }}.pem {{ ami_ssh_user }}@{{ c2_ip }} 'echo SSH CONNECTION SUCCESSFUL'"
|
||||||
@@ -288,6 +307,7 @@
|
|||||||
- name: Configure C2 server
|
- name: Configure C2 server
|
||||||
hosts: c2servers
|
hosts: c2servers
|
||||||
become: yes
|
become: yes
|
||||||
|
become_user: root
|
||||||
gather_facts: true
|
gather_facts: true
|
||||||
vars_files:
|
vars_files:
|
||||||
- vars.yaml # Add this line to load the variables
|
- vars.yaml # Add this line to load the variables
|
||||||
|
|||||||
+31
-19
@@ -9,7 +9,7 @@
|
|||||||
- vars.yaml
|
- vars.yaml
|
||||||
vars:
|
vars:
|
||||||
# Default values
|
# Default values
|
||||||
ssh_user: "{{ ssh_user | default('ubuntu') }}" # Changed from 'root' to 'ubuntu'
|
ssh_user: "{{ ssh_user | default('ubuntu') }}"
|
||||||
aws_region: "{{ aws_region | default(aws_region_choices | random) }}"
|
aws_region: "{{ aws_region | default(aws_region_choices | random) }}"
|
||||||
instance_type: "{{ aws_instance_type | default('t2.micro') }}"
|
instance_type: "{{ aws_instance_type | default('t2.micro') }}"
|
||||||
deployment_id: "{{ deployment_id | default('') }}"
|
deployment_id: "{{ deployment_id | default('') }}"
|
||||||
@@ -41,18 +41,25 @@
|
|||||||
- aws_secret_key is defined and aws_secret_key != ""
|
- aws_secret_key is defined and aws_secret_key != ""
|
||||||
fail_msg: "AWS credentials are required"
|
fail_msg: "AWS credentials are required"
|
||||||
|
|
||||||
# Load shared infrastructure state if available
|
# Set region for redirector - fix for noop task error
|
||||||
|
- name: Set region for redirector
|
||||||
|
set_fact:
|
||||||
|
aws_redirector_region: "{{ redirector_region | default(aws_region) }}"
|
||||||
|
|
||||||
|
# Load shared infrastructure state if available - fixed implementation
|
||||||
- name: Check for shared infrastructure state
|
- name: Check for shared infrastructure state
|
||||||
stat:
|
block:
|
||||||
path: "infrastructure_state_{{ deployment_id }}.json"
|
- name: Check if state file exists
|
||||||
register: infra_state_file
|
stat:
|
||||||
|
path: "infrastructure_state_{{ deployment_id }}.json"
|
||||||
|
register: infra_state_file
|
||||||
|
|
||||||
|
- name: Include vars if file exists
|
||||||
|
include_vars:
|
||||||
|
file: "infrastructure_state_{{ deployment_id }}.json"
|
||||||
|
name: shared_infra
|
||||||
|
when: infra_state_file.stat.exists | default(false)
|
||||||
when: use_shared_infra | bool
|
when: use_shared_infra | bool
|
||||||
|
|
||||||
- name: Load shared infrastructure state
|
|
||||||
include_vars:
|
|
||||||
file: "infrastructure_state_{{ deployment_id }}.json"
|
|
||||||
name: shared_infra
|
|
||||||
when: use_shared_infra | bool and infra_state_file.stat.exists | default(false)
|
|
||||||
|
|
||||||
# After loading shared infrastructure state
|
# After loading shared infrastructure state
|
||||||
- name: Validate shared VPC exists
|
- name: Validate shared VPC exists
|
||||||
@@ -75,16 +82,11 @@
|
|||||||
use_shared_infra: false
|
use_shared_infra: false
|
||||||
when: use_shared_infra | bool and vpc_check.vpcs is defined and vpc_check.vpcs | length == 0
|
when: use_shared_infra | bool and vpc_check.vpcs is defined and vpc_check.vpcs | length == 0
|
||||||
|
|
||||||
- name: Set region for redirector from shared infra
|
- name: Set region variables from shared infra
|
||||||
set_fact:
|
set_fact:
|
||||||
aws_redirector_region: "{{ shared_infra.region | default(aws_region) }}"
|
aws_redirector_region: "{{ shared_infra.region | default(aws_region) }}"
|
||||||
when: use_shared_infra | bool and infra_state_file.stat.exists | default(false)
|
when: use_shared_infra | bool and infra_state_file.stat.exists | default(false)
|
||||||
|
|
||||||
- name: Set default region for redirector
|
|
||||||
set_fact:
|
|
||||||
aws_redirector_region: "{{ redirector_region | default(aws_region) }}"
|
|
||||||
when: not (use_shared_infra | bool and infra_state_file.stat.exists | default(false))
|
|
||||||
|
|
||||||
- name: Set AMI ID for selected region
|
- name: Set AMI ID for selected region
|
||||||
set_fact:
|
set_fact:
|
||||||
ami_id: "{{ ubuntu_ami_map[aws_redirector_region] | default(ubuntu_ami_map['us-east-1']) }}"
|
ami_id: "{{ ubuntu_ami_map[aws_redirector_region] | default(ubuntu_ami_map['us-east-1']) }}"
|
||||||
@@ -194,7 +196,7 @@
|
|||||||
state: present
|
state: present
|
||||||
register: security_group
|
register: security_group
|
||||||
|
|
||||||
# Save infrastructure state for reuse
|
# Save infrastructure state for reuse
|
||||||
- name: Save infrastructure state for reuse
|
- name: Save infrastructure state for reuse
|
||||||
copy:
|
copy:
|
||||||
content: |
|
content: |
|
||||||
@@ -231,6 +233,16 @@
|
|||||||
redirector_ip: "{{ redirector_instance.instances[0].public_ip_address }}"
|
redirector_ip: "{{ redirector_instance.instances[0].public_ip_address }}"
|
||||||
redirector_instance_id: "{{ redirector_instance.instances[0].instance_id }}"
|
redirector_instance_id: "{{ redirector_instance.instances[0].instance_id }}"
|
||||||
|
|
||||||
|
- name: Wait for instance initialization
|
||||||
|
pause:
|
||||||
|
seconds: 120
|
||||||
|
when: redirector_instance.changed
|
||||||
|
|
||||||
|
- name: Set correct permissions on SSH key
|
||||||
|
file:
|
||||||
|
path: "~/.ssh/{{ redirector_name }}.pem"
|
||||||
|
mode: "0600"
|
||||||
|
|
||||||
- name: Wait for redirector SSH to be available
|
- name: Wait for redirector SSH to be available
|
||||||
wait_for:
|
wait_for:
|
||||||
host: "{{ redirector_ip }}"
|
host: "{{ redirector_ip }}"
|
||||||
@@ -244,7 +256,7 @@
|
|||||||
name: "redirector"
|
name: "redirector"
|
||||||
groups: "redirectors"
|
groups: "redirectors"
|
||||||
ansible_host: "{{ redirector_ip }}"
|
ansible_host: "{{ redirector_ip }}"
|
||||||
ansible_user: "ubuntu" # Change this from 'root' to 'ubuntu'
|
ansible_user: "ubuntu"
|
||||||
ansible_ssh_private_key_file: "~/.ssh/{{ redirector_name }}.pem"
|
ansible_ssh_private_key_file: "~/.ssh/{{ redirector_name }}.pem"
|
||||||
ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes"
|
ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes"
|
||||||
ansible_python_interpreter: "/usr/bin/python3"
|
ansible_python_interpreter: "/usr/bin/python3"
|
||||||
|
|||||||
@@ -1786,46 +1786,99 @@ def cleanup_resources(config, interactive=True):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Failed to remove SSH public key {pub_key_path}.pub: {e}")
|
logging.error(f"Failed to remove SSH public key {pub_key_path}.pub: {e}")
|
||||||
|
|
||||||
# Use Ansible for cleanup with confirmation set to false
|
# Check for split-region deployment
|
||||||
extra_vars = {
|
is_split_region = provider == "aws" and 'redirector_region' in config and 'c2_region' in config and config['redirector_region'] != config['c2_region']
|
||||||
"confirm_cleanup": False, # Skip confirmation prompt
|
|
||||||
"redirector_name": config.get('redirector_name'),
|
|
||||||
"c2_name": config.get('c2_name'),
|
|
||||||
"tracker_name": config.get('tracker_name'),
|
|
||||||
"cleanup_redirector": True,
|
|
||||||
"cleanup_c2": True,
|
|
||||||
"cleanup_tracker": config.get('deploy_tracker', False) and not config.get('integrated_tracker', False)
|
|
||||||
}
|
|
||||||
|
|
||||||
playbook = f"{provider_dir}/cleanup.yml"
|
if is_split_region:
|
||||||
if os.path.exists(playbook):
|
logging.info("Detected split-region deployment, cleaning up both regions...")
|
||||||
logging.info(f"Running cleanup playbook: {playbook}")
|
|
||||||
inventory_path = create_inventory_file(config, "local")
|
|
||||||
|
|
||||||
# Add extra vars to config for cleanup
|
# Clean up each region separately
|
||||||
cleanup_config = config.copy()
|
regions_to_clean = [config['redirector_region'], config['c2_region']]
|
||||||
cleanup_config.update(extra_vars)
|
for region in regions_to_clean:
|
||||||
|
region_config = config.copy()
|
||||||
try:
|
region_config['aws_region'] = region
|
||||||
success, stdout, stderr = run_ansible_playbook(
|
region_config['selected_region'] = region
|
||||||
playbook, inventory_path, cleanup_config,
|
region_config['region'] = region
|
||||||
cleanup_config.get('debug', False)
|
|
||||||
)
|
|
||||||
|
|
||||||
if not success:
|
logging.info(f"Cleaning up resources in region: {region}")
|
||||||
logging.error(f"Cleanup playbook failed: {stderr}")
|
|
||||||
|
# Create inventory for this region
|
||||||
# Log what we attempted to clean up
|
inventory_path = create_inventory_file(region_config, "local")
|
||||||
logging.error(f"Failed to clean up resources: redirector={config.get('redirector_name')}, c2={config.get('c2_name')}, tracker={config.get('tracker_name')}")
|
|
||||||
else:
|
# Set confirmation to false for second run
|
||||||
logging.info("Cleanup completed successfully")
|
extra_vars = {
|
||||||
except Exception as e:
|
"confirm_cleanup": False,
|
||||||
logging.error(f"Cleanup playbook failed: {e}")
|
"redirector_name": config.get('redirector_name'),
|
||||||
finally:
|
"c2_name": config.get('c2_name'),
|
||||||
if os.path.exists(inventory_path):
|
"tracker_name": config.get('tracker_name'),
|
||||||
os.unlink(inventory_path)
|
"cleanup_redirector": True,
|
||||||
|
"cleanup_c2": True,
|
||||||
|
"cleanup_tracker": config.get('deploy_tracker', False) and not config.get('integrated_tracker', False),
|
||||||
|
"aws_region": region
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add extra vars to config for cleanup
|
||||||
|
cleanup_config = region_config.copy()
|
||||||
|
cleanup_config.update(extra_vars)
|
||||||
|
|
||||||
|
playbook = f"{provider_dir}/cleanup.yml"
|
||||||
|
if os.path.exists(playbook):
|
||||||
|
try:
|
||||||
|
success, stdout, stderr = run_ansible_playbook(
|
||||||
|
playbook, inventory_path, cleanup_config,
|
||||||
|
cleanup_config.get('debug', False)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
logging.error(f"Cleanup playbook failed in region {region}: {stderr}")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Cleanup playbook failed in region {region}: {e}")
|
||||||
|
finally:
|
||||||
|
if os.path.exists(inventory_path):
|
||||||
|
os.unlink(inventory_path)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logging.warning(f"No cleanup playbook found at {playbook}")
|
# Standard single-region cleanup
|
||||||
|
# Use Ansible for cleanup with confirmation set to false
|
||||||
|
extra_vars = {
|
||||||
|
"confirm_cleanup": False, # Skip confirmation prompt
|
||||||
|
"redirector_name": config.get('redirector_name'),
|
||||||
|
"c2_name": config.get('c2_name'),
|
||||||
|
"tracker_name": config.get('tracker_name'),
|
||||||
|
"cleanup_redirector": True,
|
||||||
|
"cleanup_c2": True,
|
||||||
|
"cleanup_tracker": config.get('deploy_tracker', False) and not config.get('integrated_tracker', False)
|
||||||
|
}
|
||||||
|
|
||||||
|
playbook = f"{provider_dir}/cleanup.yml"
|
||||||
|
if os.path.exists(playbook):
|
||||||
|
logging.info(f"Running cleanup playbook: {playbook}")
|
||||||
|
inventory_path = create_inventory_file(config, "local")
|
||||||
|
|
||||||
|
# Add extra vars to config for cleanup
|
||||||
|
cleanup_config = config.copy()
|
||||||
|
cleanup_config.update(extra_vars)
|
||||||
|
|
||||||
|
try:
|
||||||
|
success, stdout, stderr = run_ansible_playbook(
|
||||||
|
playbook, inventory_path, cleanup_config,
|
||||||
|
cleanup_config.get('debug', False)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
logging.error(f"Cleanup playbook failed: {stderr}")
|
||||||
|
|
||||||
|
# Log what we attempted to clean up
|
||||||
|
logging.error(f"Failed to clean up resources: redirector={config.get('redirector_name')}, c2={config.get('c2_name')}, tracker={config.get('tracker_name')}")
|
||||||
|
else:
|
||||||
|
logging.info("Cleanup completed successfully")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Cleanup playbook failed: {e}")
|
||||||
|
finally:
|
||||||
|
if os.path.exists(inventory_path):
|
||||||
|
os.unlink(inventory_path)
|
||||||
|
else:
|
||||||
|
logging.warning(f"No cleanup playbook found at {playbook}")
|
||||||
|
|
||||||
# Clean up SSH key if we generated one
|
# Clean up SSH key if we generated one
|
||||||
ssh_key = config.get('ssh_key')
|
ssh_key = config.get('ssh_key')
|
||||||
@@ -2332,8 +2385,8 @@ def generate_deployment_info(config, success=True):
|
|||||||
return log_file
|
return log_file
|
||||||
|
|
||||||
def deploy_cross_provider(config, redirector_provider, c2_provider):
|
def deploy_cross_provider(config, redirector_provider, c2_provider):
|
||||||
"""Deploy infrastructure across multiple providers"""
|
"""Deploy infrastructure across multiple providers or regions"""
|
||||||
# Create copies of config for each provider
|
# Create copies of config for each provider/region
|
||||||
redirector_config = config.copy()
|
redirector_config = config.copy()
|
||||||
redirector_config['provider'] = redirector_provider
|
redirector_config['provider'] = redirector_provider
|
||||||
redirector_config['c2_only'] = False
|
redirector_config['c2_only'] = False
|
||||||
@@ -2347,8 +2400,15 @@ def deploy_cross_provider(config, redirector_provider, c2_provider):
|
|||||||
# Set specific regions if provided
|
# Set specific regions if provided
|
||||||
if config.get('redirector_region'):
|
if config.get('redirector_region'):
|
||||||
redirector_config['region'] = config['redirector_region']
|
redirector_config['region'] = config['redirector_region']
|
||||||
|
# For AWS, set both region variables
|
||||||
|
if redirector_provider == 'aws':
|
||||||
|
redirector_config['aws_region'] = config['redirector_region']
|
||||||
|
|
||||||
if config.get('c2_region'):
|
if config.get('c2_region'):
|
||||||
c2_config['region'] = config['c2_region']
|
c2_config['region'] = config['c2_region']
|
||||||
|
# For AWS, set both region variables
|
||||||
|
if c2_provider == 'aws':
|
||||||
|
c2_config['aws_region'] = config['c2_region']
|
||||||
|
|
||||||
logging.info(f"Cross-provider deployment: Redirector using {redirector_provider} in {redirector_config.get('region', 'default region')}")
|
logging.info(f"Cross-provider deployment: Redirector using {redirector_provider} in {redirector_config.get('region', 'default region')}")
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
# Common task for installing offensive security tools
|
# Common task for installing offensive security tools
|
||||||
# Shared across all providers
|
# Shared across all providers
|
||||||
|
|
||||||
|
- name: Force tools directory to root regardless of user
|
||||||
|
set_fact:
|
||||||
|
home_dir: "/root"
|
||||||
|
tools_dir: "/root/Tools"
|
||||||
|
when: provider == "aws"
|
||||||
|
|
||||||
- name: Determine home directory path
|
- name: Determine home directory path
|
||||||
set_fact:
|
set_fact:
|
||||||
home_dir: "{{ (ansible_user == 'root') | ternary('/root', '/home/' + ansible_user) }}"
|
home_dir: "{{ (ansible_user == 'root') | ternary('/root', '/home/' + ansible_user) }}"
|
||||||
|
|||||||
Reference in New Issue
Block a user