172 lines
5.5 KiB
Python
Executable File
172 lines
5.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Smart Executor - Automatically choose between SSH and WinRM
|
|
Based on script size and complexity
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
from pathlib import Path
|
|
from winrm import Session
|
|
|
|
|
|
class SmartExecutor:
|
|
def __init__(self, host=None, username=None, password=None):
|
|
self.host = host or os.getenv('HOST', '192.168.88.108')
|
|
self.username = username or os.getenv('USER_NAME', 'Admin')
|
|
self.password = password or os.getenv('PASS', 'P@ssw0rd!')
|
|
|
|
def analyze_script(self, script_path):
|
|
"""Analyze script to determine best execution method"""
|
|
script_path = Path(script_path)
|
|
|
|
if not script_path.exists():
|
|
return None
|
|
|
|
# Get script size
|
|
size = script_path.stat().st_size
|
|
|
|
# Read content for analysis
|
|
with open(script_path, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
|
|
lines = len(content.split('\n'))
|
|
chars = len(content)
|
|
|
|
analysis = {
|
|
'size_bytes': size,
|
|
'lines': lines,
|
|
'characters': chars,
|
|
'has_file_operations': any(keyword in content.lower() for keyword in
|
|
['out-file', 'copy-item', 'move-item', 'new-item', 'remove-item']),
|
|
'has_long_commands': any(len(line) > 500 for line in content.split('\n')),
|
|
'complexity_score': lines + (chars / 100) + (size / 1000)
|
|
}
|
|
|
|
return analysis
|
|
|
|
def choose_method(self, script_path):
|
|
"""Choose optimal execution method"""
|
|
analysis = self.analyze_script(script_path)
|
|
|
|
if not analysis:
|
|
return "error"
|
|
|
|
# Decision logic
|
|
if analysis['size_bytes'] > 5000: # Large scripts
|
|
return "ssh"
|
|
elif analysis['lines'] > 100: # Many lines
|
|
return "ssh"
|
|
elif analysis['has_file_operations']: # File operations
|
|
return "ssh"
|
|
elif analysis['has_long_commands']: # Very long command lines
|
|
return "ssh"
|
|
elif analysis['complexity_score'] > 150: # Complex scripts
|
|
return "ssh"
|
|
else:
|
|
return "winrm" # Simple, fast execution
|
|
|
|
def execute_via_ssh(self, script_path):
|
|
"""Execute script using SSH method"""
|
|
script_name = Path(script_path).stem
|
|
ssh_script = f"{script_name}.sh"
|
|
|
|
if not Path(ssh_script).exists():
|
|
print(f"❌ SSH wrapper {ssh_script} not found")
|
|
return False
|
|
|
|
try:
|
|
result = subprocess.run([f'./{ssh_script}'], capture_output=False, timeout=300)
|
|
return result.returncode == 0
|
|
except Exception as e:
|
|
print(f"❌ SSH execution failed: {e}")
|
|
return False
|
|
|
|
def execute_via_winrm(self, script_path):
|
|
"""Execute script using WinRM method"""
|
|
try:
|
|
# Read and execute script content directly
|
|
with open(script_path, 'r', encoding='utf-8') as f:
|
|
script_content = f.read()
|
|
|
|
# Connect via WinRM
|
|
session = Session(
|
|
f'http://{self.host}:5985/wsman',
|
|
auth=(self.username, self.password),
|
|
transport='ntlm'
|
|
)
|
|
|
|
# Execute PowerShell
|
|
result = session.run_ps(script_content)
|
|
|
|
# Output results
|
|
if result.std_out:
|
|
output = result.std_out.decode('utf-8', errors='replace')
|
|
for line in output.split('\n'):
|
|
if line.strip():
|
|
print(line)
|
|
|
|
if result.std_err:
|
|
error = result.std_err.decode('utf-8', errors='replace')
|
|
if error.strip():
|
|
for line in error.split('\n'):
|
|
if line.strip():
|
|
print(f"ERROR: {line}")
|
|
|
|
return result.status_code == 0
|
|
|
|
except Exception as e:
|
|
print(f"❌ WinRM execution failed: {e}")
|
|
return False
|
|
|
|
def execute(self, script_path):
|
|
"""Smart execute with automatic method selection"""
|
|
script_path = Path(script_path)
|
|
|
|
print(f"🧠 Analyzing script: {script_path.name}")
|
|
|
|
analysis = self.analyze_script(script_path)
|
|
method = self.choose_method(script_path)
|
|
|
|
print(f"📊 Script analysis:")
|
|
print(f" Size: {analysis['size_bytes']} bytes")
|
|
print(f" Lines: {analysis['lines']}")
|
|
print(f" Complexity: {analysis['complexity_score']:.1f}")
|
|
print(f" File operations: {analysis['has_file_operations']}")
|
|
|
|
print(f"⚡ Selected method: {method.upper()}")
|
|
|
|
if method == "ssh":
|
|
print("🔗 Executing via SSH (for large/complex scripts)")
|
|
return self.execute_via_ssh(script_path)
|
|
elif method == "winrm":
|
|
print("⚡ Executing via WinRM (for speed)")
|
|
return self.execute_via_winrm(script_path)
|
|
else:
|
|
print("❌ Unable to determine execution method")
|
|
return False
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) != 2:
|
|
print("Usage: python3 smart_executor.py <script.ps1>")
|
|
sys.exit(1)
|
|
|
|
script_path = sys.argv[1]
|
|
executor = SmartExecutor()
|
|
|
|
print("🎯 Smart PowerShell Executor")
|
|
print("============================")
|
|
|
|
success = executor.execute(script_path)
|
|
|
|
if success:
|
|
print(f"\n✅ Script execution completed successfully")
|
|
else:
|
|
print(f"\n❌ Script execution failed")
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |