working on bugs

This commit is contained in:
n0mad1k
2025-05-08 16:50:04 -04:00
parent c61b810bbc
commit f4e24edf9b
+169 -125
View File
@@ -18,6 +18,42 @@ from datetime import datetime
debug_mode = True
deployment_id = None
# Constants for providers
PROVIDERS = ["aws", "linode", "flokinet"]
DEFAULT_SSH_USER = {
"aws": "root",
"linode": "root",
"flokinet": "root"
}
# Directory names - maintain correct case for each provider
PROVIDER_DIRS = {
"aws": "AWS",
"linode": "Linode",
"flokinet": "FlokiNET"
}
# Then fix the select_provider function
def select_provider():
"""Let the user select a cloud provider"""
print("\nAvailable cloud providers:")
for i, provider in enumerate(PROVIDERS, 1):
print(f" {i}. {provider.capitalize()}")
while True:
try:
provider_choice = input("\nSelect a provider (1-3 or 99 to cancel): ")
if provider_choice == "99":
return None
provider_choice = int(provider_choice)
if 1 <= provider_choice <= len(PROVIDERS):
return PROVIDERS[provider_choice - 1]
else:
print(f"{COLORS['RED']}Please enter a number between 1 and {len(PROVIDERS)}{COLORS['RESET']}")
except ValueError:
print(f"{COLORS['RED']}Please enter a valid number{COLORS['RESET']}")
# Color codes for terminal output
COLORS = {
"RESET": "\033[0m",
@@ -53,8 +89,12 @@ def print_banner():
def main_menu():
"""Display the main menu and handle user selection"""
global debug_mode
global debug_mode, deployment_id
while True:
# Reset deployment ID for each new operation from the menu
deployment_id = generate_deployment_id()
clear_screen()
print_banner()
print(f"{COLORS['WHITE']}MAIN MENU{COLORS['RESET']}")
@@ -72,7 +112,7 @@ def main_menu():
print(f"11) Custom Deployment")
print(f"12) Tools")
print(f"13) Debug Mode: {COLORS['GREEN'] if debug_mode else COLORS['RED']}{debug_mode}{COLORS['RESET']}")
print(f"")
print(f"\n")
print(f"99) Exit")
choice = input("\nSelect an option: ")
@@ -229,21 +269,24 @@ def deploy_tracker():
def custom_deployment():
"""Run the full interactive deployment wizard"""
deployment_id = generate_deployment_id()
config = interactive_setup(deployment_id)
current_deployment_id = generate_deployment_id()
config = interactive_setup(current_deployment_id)
if config:
execute_deployment(config)
def initialize_deployment():
"""Initialize global deployment ID"""
global deployment_id
deployment_id = generate_deployment_id()
return deployment_id
"""Initialize and return a fresh deployment ID"""
new_deployment_id = generate_deployment_id()
logging.info(f"Initialized new deployment ID: {new_deployment_id}")
return new_deployment_id
def gather_common_parameters():
"""Collect common parameters needed for deployments"""
global debug_mode, deployment_id
config = {'deployment_id': deployment_id}
global debug_mode
# Generate a fresh deployment ID for this specific deployment
current_deployment_id = generate_deployment_id()
config = {'deployment_id': current_deployment_id}
config['debug'] = debug_mode
# Get provider
@@ -317,13 +360,13 @@ def gather_common_parameters():
config['letsencrypt_email'] = email
# Set SSH key
config['ssh_key'] = generate_ssh_key(deployment_id)
config['ssh_key'] = generate_ssh_key(current_deployment_id)
config['ssh_key_path'] = f"{config['ssh_key']}.pub"
# Set consistent resource names based on deployment ID
config['redirector_name'] = f"r-{deployment_id}"
config['c2_name'] = f"s-{deployment_id}"
config['tracker_name'] = f"t-{deployment_id}"
config['redirector_name'] = f"r-{current_deployment_id}"
config['c2_name'] = f"s-{current_deployment_id}"
config['tracker_name'] = f"t-{current_deployment_id}"
# Security options
print("\nSecurity options:")
@@ -331,28 +374,11 @@ def gather_common_parameters():
config['secure_memory'] = input("Enable secure memory settings? (y/n) [default: y]: ").lower() != 'n'
config['zero_logs'] = input("Enable zero-logs configuration? (y/n) [default: y]: ").lower() != 'n'
# Add SSH option that was missing
config['ssh_after_deploy'] = input("\nSSH into instance after deployment? (y/n) [default: n]: ").lower() == 'y'
return config
def select_provider():
"""Let the user select a cloud provider"""
print("\nAvailable cloud providers:")
for i, provider in enumerate(PROVIDERS, 1):
print(f" {i}. {provider.capitalize()}")
while True:
try:
provider_choice = input("\nSelect a provider (1-3 or 99 to cancel): ")
if provider_choice == "99":
return None
provider_choice = int(provider_choice)
if 1 <= provider_choice <= len(PROVIDERS):
return PROVIDERS[provider_choice - 1]
else:
print(f"{COLORS['RED']}Please enter a number between 1 and {len(PROVIDERS)}{COLORS['RESET']}")
except ValueError:
print(f"{COLORS['RED']}Please enter a valid number{COLORS['RESET']}")
def get_aws_credentials(provider_vars):
"""Get AWS credentials from user or vars file"""
default_aws_key = provider_vars.get('aws_access_key', '')
@@ -484,29 +510,16 @@ def execute_deployment(config):
if success:
print(f"\n{COLORS['GREEN']}Deployment completed successfully!{COLORS['RESET']}")
# Explicitly handle SSH after deployment if requested
if config.get('ssh_after_deploy', False):
print(f"\n{COLORS['BLUE']}Connecting to instance via SSH...{COLORS['RESET']}")
ssh_to_instance(config)
else:
print(f"\n{COLORS['RED']}Deployment failed.{COLORS['RESET']}")
input("\nPress Enter to return to menu...")
# Disable Ansible host key checking
os.environ["ANSIBLE_HOST_KEY_CHECKING"] = "False"
# Constants for providers
PROVIDERS = ["aws", "linode", "flokinet"]
DEFAULT_SSH_USER = {
"aws": "root",
"linode": "root",
"flokinet": "root"
}
# Directory names - maintain correct case for each provider
PROVIDER_DIRS = {
"aws": "AWS",
"linode": "Linode",
"flokinet": "FlokiNET"
}
def generate_random_string(length=8):
"""Generate a random string of letters and digits."""
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
@@ -1253,99 +1266,109 @@ def deploy_infrastructure(config):
provider = config['provider']
logging.info(f"Deploying {provider} infrastructure...")
# Set provider-specific environment variables
if provider == "aws":
if config.get('aws_access_key'):
os.environ['AWS_ACCESS_KEY_ID'] = config['aws_access_key']
if config.get('aws_secret_key'):
os.environ['AWS_SECRET_ACCESS_KEY'] = config['aws_secret_key']
elif provider == "linode":
if config.get('linode_token'):
os.environ['LINODE_TOKEN'] = config['linode_token']
try:
# Set provider-specific environment variables
if provider == "aws":
if config.get('aws_access_key'):
os.environ['AWS_ACCESS_KEY_ID'] = config['aws_access_key']
if config.get('aws_secret_key'):
os.environ['AWS_SECRET_ACCESS_KEY'] = config['aws_secret_key']
elif provider == "linode":
if config.get('linode_token'):
os.environ['LINODE_TOKEN'] = config['linode_token']
# Set correct ssh_user based on provider
if not config.get('ssh_user'):
config['ssh_user'] = DEFAULT_SSH_USER.get(provider, 'root')
# Set correct ssh_user based on provider
if not config.get('ssh_user'):
config['ssh_user'] = DEFAULT_SSH_USER.get(provider, 'root')
# Handle cross-provider deployment
redirector_provider = config.get('redirector_provider', provider)
c2_provider = config.get('c2_provider', provider)
# Handle cross-provider deployment
redirector_provider = config.get('redirector_provider', provider)
c2_provider = config.get('c2_provider', provider)
is_cross_provider = (redirector_provider != c2_provider) or \
(config.get('redirector_region') and config.get('c2_region') and \
config.get('redirector_region') != config.get('c2_region'))
is_cross_provider = (redirector_provider != c2_provider) or \
(config.get('redirector_region') and config.get('c2_region') and \
config.get('redirector_region') != config.get('c2_region'))
if is_cross_provider and not (config.get('redirector_only') or config.get('c2_only')):
return deploy_cross_provider(config, redirector_provider, c2_provider)
if is_cross_provider and not (config.get('redirector_only') or config.get('c2_only')):
return deploy_cross_provider(config, redirector_provider, c2_provider)
# For FlokiNET, validate required IPs
if provider == "flokinet":
if not config.get('c2_only') and not config.get('flokinet_redirector_ip') and not config.get('redirector_ip'):
logging.error("FlokiNET redirector IP is required")
return False
# For FlokiNET, validate required IPs
if provider == "flokinet":
if not config.get('c2_only') and not config.get('flokinet_redirector_ip') and not config.get('redirector_ip'):
logging.error("FlokiNET redirector IP is required")
return False
if not config.get('redirector_only') and not config.get('flokinet_c2_ip') and not config.get('c2_ip'):
logging.error("FlokiNET C2 IP is required")
return False
if not config.get('redirector_only') and not config.get('flokinet_c2_ip') and not config.get('c2_ip'):
logging.error("FlokiNET C2 IP is required")
return False
# Get correct provider directory
provider_dir = PROVIDER_DIRS.get(provider, provider.capitalize())
# Get correct provider directory
provider_dir = PROVIDER_DIRS.get(provider, provider.capitalize())
# Deploy redirector if needed
if not config.get('c2_only'):
redirector_config = config.copy()
if config.get('redirector_region'):
redirector_config['region'] = config['redirector_region']
# Deploy redirector if needed
if not config.get('c2_only'):
redirector_config = config.copy()
if config.get('redirector_region'):
redirector_config['region'] = config['redirector_region']
playbook = f"{provider_dir}/redirector.yml"
inventory_path = create_inventory_file(redirector_config, "local")
playbook = f"{provider_dir}/redirector.yml"
inventory_path = create_inventory_file(redirector_config, "local")
logging.info(f"Deploying {provider} redirector using {playbook} in region {redirector_config.get('region', 'default')}")
redirector_success, stdout, stderr = run_ansible_playbook(
playbook, inventory_path, redirector_config, redirector_config.get('debug', False)
)
logging.info(f"Deploying {provider} redirector using {playbook} in region {redirector_config.get('region', 'default')}")
redirector_success, stdout, stderr = run_ansible_playbook(
playbook, inventory_path, redirector_config, redirector_config.get('debug', False)
)
if os.path.exists(inventory_path):
os.unlink(inventory_path)
if os.path.exists(inventory_path):
os.unlink(inventory_path)
if not redirector_success:
logging.error(f"{provider} redirector deployment failed")
if redirector_config.get('debug'):
logging.error(f"Ansible stderr: {stderr}")
return False
if not redirector_success:
logging.error(f"{provider} redirector deployment failed")
if redirector_config.get('debug'):
logging.error(f"Ansible stderr: {stderr}")
return False
# Extract and save redirector IP for C2 configuration
if 'redirector_ip' in redirector_config:
config['redirector_ip'] = redirector_config['redirector_ip']
# Extract and save redirector IP for C2 configuration
if 'redirector_ip' in redirector_config:
config['redirector_ip'] = redirector_config['redirector_ip']
# Deploy C2 if needed
if not config.get('redirector_only'):
c2_config = config.copy()
if config.get('c2_region'):
c2_config['region'] = config['c2_region']
# Deploy C2 if needed
if not config.get('redirector_only'):
c2_config = config.copy()
if config.get('c2_region'):
c2_config['region'] = config['c2_region']
playbook = f"{provider_dir}/c2.yml"
inventory_path = create_inventory_file(c2_config, "local")
playbook = f"{provider_dir}/c2.yml"
inventory_path = create_inventory_file(c2_config, "local")
logging.info(f"Deploying {provider} C2 server using {playbook} in region {c2_config.get('region', 'default')}")
c2_success, stdout, stderr = run_ansible_playbook(
playbook, inventory_path, c2_config, c2_config.get('debug', False)
)
logging.info(f"Deploying {provider} C2 server using {playbook} in region {c2_config.get('region', 'default')}")
c2_success, stdout, stderr = run_ansible_playbook(
playbook, inventory_path, c2_config, c2_config.get('debug', False)
)
if os.path.exists(inventory_path):
os.unlink(inventory_path)
if os.path.exists(inventory_path):
os.unlink(inventory_path)
if not c2_success:
logging.error(f"{provider} C2 server deployment failed")
if c2_config.get('debug'):
logging.error(f"Ansible stderr: {stderr}")
return False
if not c2_success:
logging.error(f"{provider} C2 server deployment failed")
if c2_config.get('debug'):
logging.error(f"Ansible stderr: {stderr}")
return False
# Extract and save C2 IP for reference
if 'c2_ip' in c2_config:
config['c2_ip'] = c2_config['c2_ip']
# Extract and save C2 IP for reference
if 'c2_ip' in c2_config:
config['c2_ip'] = c2_config['c2_ip']
return True
return True
except Exception as e:
logging.error(f"Deployment failed with error: {str(e)}")
if config.get('debug'):
import traceback
logging.error(traceback.format_exc())
# Clean up any partial resources that were created
cleanup_resources(config, interactive=True)
return False
def deploy_flokinet_redirector(config):
"""Deploy FlokiNET redirector separately"""
@@ -1601,6 +1624,26 @@ def cleanup_resources(config, interactive=True):
print("You can clean them up later by running with --teardown")
return False
# Clean up SSH keys
if 'deployment_id' in config:
ssh_key_path = f"~/.ssh/c2deploy_{config['deployment_id']}.pem"
expanded_path = os.path.expanduser(ssh_key_path)
if os.path.exists(expanded_path):
try:
os.remove(expanded_path)
logging.info(f"Removed SSH key: {ssh_key_path}")
except Exception as e:
logging.error(f"Failed to remove SSH key {ssh_key_path}: {e}")
# Also check for public key
pub_key_path = f"{expanded_path}.pub"
if os.path.exists(pub_key_path):
try:
os.remove(pub_key_path)
logging.info(f"Removed SSH public key: {pub_key_path}.pub")
except Exception as e:
logging.error(f"Failed to remove SSH public key {pub_key_path}.pub: {e}")
# Use Ansible for cleanup with confirmation set to false
extra_vars = {
"confirm_cleanup": False, # Skip confirmation prompt
@@ -1655,6 +1698,7 @@ def cleanup_resources(config, interactive=True):
return True
def check_dependencies():
"""Check if required dependencies are installed"""
dependencies = {