#!/usr/bin/env python3 """ Cloudflare Credential Setup Wizard Interactive script to guide users through configuring Cloudflare API credentials """ import os import sys import re from pathlib import Path def validate_api_token(token): """Validate Cloudflare API token format""" # Cloudflare API tokens are typically 40+ characters return len(token.strip()) >= 40 def validate_account_id(account_id): """Validate Cloudflare Account ID format""" # Account IDs are typically 32-character hex strings return re.match(r"^[a-f0-9]{32}$", account_id.strip(), re.IGNORECASE) is not None def validate_zone_id(zone_id): """Validate Cloudflare Zone ID format""" # Zone IDs are also 32-character hex strings return re.match(r"^[a-f0-9]{32}$", zone_id.strip(), re.IGNORECASE) is not None def get_input(prompt, validation_func=None, secret=False): """Get validated user input""" while True: try: if secret: import getpass value = getpass.getpass(prompt) else: value = input(prompt) if validation_func: if validation_func(value): return value else: print("โŒ Invalid format. Please try again.") else: return value except KeyboardInterrupt: print("\n\nSetup cancelled.") sys.exit(1) def create_env_file(env_vars): """Create or update .env file with credentials""" env_path = Path(".env") # Read existing .env if it exists existing_vars = {} if env_path.exists(): with open(env_path, "r") as f: for line in f: if line.strip() and not line.startswith("#") and "=" in line: key, value = line.strip().split("=", 1) existing_vars[key] = value # Update with new values existing_vars.update(env_vars) # Write back with open(env_path, "w") as f: f.write("# OpenCode Environment Variables\n") f.write("# Generated by setup_credentials.py\n") f.write("# IMPORTANT: Never commit this file to git\n\n") # Write Cloudflare section f.write( "# ============================================================================\n" ) f.write("# CLOUDFLARE API CONFIGURATION\n") f.write( "# ============================================================================\n" ) for key, value in env_vars.items(): f.write(f'{key}="{value}"\n') f.write("\n") # Preserve other sections if they exist sections = { "GITHUB": [k for k in existing_vars.keys() if k.startswith("GITHUB")], "GITLAB": [k for k in existing_vars.keys() if k.startswith("GITLAB")], "OTHER": [ k for k in existing_vars.keys() if k not in env_vars and not k.startswith(("GITHUB", "GITLAB")) ], } for section_name, keys in sections.items(): if keys: f.write( f"# ============================================================================\n" ) f.write(f"# {section_name} CONFIGURATION\n") f.write( f"# ============================================================================\n" ) for key in keys: f.write(f'{key}="{existing_vars[key]}"\n') f.write("\n") return env_path def main(): print("๐Ÿš€ Cloudflare Credential Setup Wizard") print("=" * 50) print() print("This wizard will help you configure your Cloudflare API credentials.") print("You'll need:") print("1. Cloudflare API Token (with appropriate permissions)") print("2. Cloudflare Account ID") print("3. Optional: Zone ID for specific domain management") print() # Check if we're in the right directory current_dir = Path.cwd() if "cloudflare" not in str(current_dir): print("โš ๏ธ Warning: This script should be run from the cloudflare directory") print(f" Current directory: {current_dir}") proceed = get_input("Continue anyway? (y/n): ") if proceed.lower() != "y": print( "Please navigate to the cloudflare directory and run this script again." ) return # Collect credentials print("\n๐Ÿ” Cloudflare API Configuration") print("-" * 30) # API Token print("\n๐Ÿ“‹ Step 1: Cloudflare API Token") print("Get your token from: https://dash.cloudflare.com/profile/api-tokens") print("Required permissions: Zone:DNS:Edit, Zone:Page Rules:Edit, Account:Read") api_token = get_input( "API Token: ", validation_func=validate_api_token, secret=True ) # Account ID print("\n๐Ÿข Step 2: Cloudflare Account ID") print("Find your Account ID in the Cloudflare dashboard sidebar") print("Format: 32-character hex string (e.g., 1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p)") account_id = get_input("Account ID: ", validation_func=validate_account_id) # Zone ID (optional) print("\n๐ŸŒ Step 3: Zone ID (Optional)") print("If you want to manage a specific domain, provide its Zone ID") print("Leave blank to skip") zone_id = get_input( "Zone ID (optional): ", validation_func=lambda x: x.strip() == "" or validate_zone_id(x), ) # Prepare environment variables env_vars = {"CLOUDFLARE_API_TOKEN": api_token, "CLOUDFLARE_ACCOUNT_ID": account_id} if zone_id.strip(): env_vars["CLOUDFLARE_ZONE_ID"] = zone_id # Create .env file print("\n๐Ÿ’พ Saving credentials...") env_path = create_env_file(env_vars) # Set file permissions env_path.chmod(0o600) # Only user read/write print(f"โœ… Credentials saved to: {env_path}") print("๐Ÿ”’ File permissions set to 600 (owner read/write only)") # Test configuration (basic validation only - no external dependencies) print("\n๐Ÿงช Validating credentials...") # Basic format validation if validate_api_token(api_token) and validate_account_id(account_id): print("โœ… Credential formats are valid") print("โš ๏ธ Note: Full API connectivity test requires 'requests' module") print(" Install with: pip install requests") else: print("โŒ Credential validation failed") print(" Please check your inputs and try again") # Final instructions print("\n๐ŸŽ‰ Setup Complete!") print("=" * 50) print("\nNext steps:") print("1. Source the environment file:") print(" source .env") print("\n2. Test Terraform configuration:") print(" cd terraform && terraform init && terraform plan") print("\n3. Deploy infrastructure:") print(" terraform apply") print("\n4. Start MCP servers:") print(" Check MCP_GUIDE.md for server startup instructions") print("\n๐Ÿ“š Documentation:") print("- USAGE_GUIDE.md - Complete usage instructions") print("- DEPLOYMENT_GUIDE.md - Deployment procedures") print("- MCP_GUIDE.md - MCP server management") # Security reminder print("\n๐Ÿ” Security Reminder:") print("- Never commit .env to version control") print("- Use .gitignore to exclude .env files") print("- Consider using environment-specific .env files (.env.production, etc.)") if __name__ == "__main__": main()