Module: TrainPlugins::Juniper::CommandExecutor
- Included in:
- Connection
- Defined in:
- lib/train-juniper/connection/command_executor.rb
Overview
Handles command execution, sanitization, and output formatting
Constant Summary collapse
- DANGEROUS_COMMAND_PATTERNS =
Command sanitization patterns Note: Pipe (|) is allowed as it's commonly used in JunOS commands
[ /[;&<>$`]/, # Shell metacharacters (excluding pipe) /\n|\r/, # Newlines that could inject commands /\\(?![nrt])/ # Escape sequences (except valid ones like \n, \r, \t) ].freeze
Instance Method Summary collapse
-
#clean_output(output, cmd) ⇒ Object
private
Clean command output.
-
#error_result(message) ⇒ Train::Extras::CommandResult
private
Factory method for error command results.
-
#format_junos_result(output, cmd) ⇒ Object
private
Format JunOS command results.
-
#mock_command_result(cmd) ⇒ Object
private
Mock command execution for testing.
-
#run_command_via_connection(cmd) ⇒ CommandResult
Execute commands on Juniper device via SSH.
-
#sanitize_command(cmd) ⇒ Object
private
Sanitize command to prevent injection attacks.
-
#success_result(output, cmd = nil) ⇒ Train::Extras::CommandResult
private
Factory method for successful command results.
Instance Method Details
#clean_output(output, cmd) ⇒ Object (private)
Clean command output
74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/train-juniper/connection/command_executor.rb', line 74 def clean_output(output, cmd) # Handle nil output gracefully return '' if output.nil? # Remove command echo and prompts lines = output.to_s.split("\n") lines.reject! { |line| line.strip == cmd.strip } # Remove JunOS prompt patterns from the end lines.pop while lines.last&.strip&.match?(/^[%>$#]+\s*$/) lines.join("\n") end |
#error_result(message) ⇒ Train::Extras::CommandResult (private)
Factory method for error command results
107 108 109 |
# File 'lib/train-juniper/connection/command_executor.rb', line 107 def error_result() Train::Extras::CommandResult.new('', , 1) end |
#format_junos_result(output, cmd) ⇒ Object (private)
Format JunOS command results
64 65 66 67 68 69 70 71 |
# File 'lib/train-juniper/connection/command_executor.rb', line 64 def format_junos_result(output, cmd) # Parse JunOS-specific error patterns if junos_error?(output) error_result(output) else success_result(output, cmd) end end |
#mock_command_result(cmd) ⇒ Object (private)
Mock command execution for testing
89 90 91 92 93 |
# File 'lib/train-juniper/connection/command_executor.rb', line 89 def mock_command_result(cmd) output, exit_status = MockResponses.response_for(cmd) # For mock mode, network devices return errors as stdout Train::Extras::CommandResult.new(output, '', exit_status) end |
#run_command_via_connection(cmd) ⇒ CommandResult
Execute commands on Juniper device via SSH
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/train-juniper/connection/command_executor.rb', line 22 def run_command_via_connection(cmd) # Sanitize command to prevent injection safe_cmd = sanitize_command(cmd) return mock_command_result(safe_cmd) if @options[:mock] begin # :nocov: Real SSH execution cannot be tested without actual devices # Ensure we're connected connect unless connected? log_command(safe_cmd) # Execute command via SSH session output = @ssh_session.exec!(safe_cmd) @logger.debug("Command output: #{output}") # Format JunOS result format_junos_result(output, safe_cmd) rescue StandardError => e log_error(e, "Command execution failed for: #{safe_cmd}") # Handle connection errors gracefully error_result("#{e.} (command: #{safe_cmd})") # :nocov: end end |
#sanitize_command(cmd) ⇒ Object (private)
Sanitize command to prevent injection attacks
53 54 55 56 57 58 59 60 61 |
# File 'lib/train-juniper/connection/command_executor.rb', line 53 def sanitize_command(cmd) cmd_str = cmd.to_s.strip if DANGEROUS_COMMAND_PATTERNS.any? { |pattern| cmd_str.match?(pattern) } raise Train::ClientError, "Invalid characters in command: #{cmd_str.inspect}" end cmd_str end |
#success_result(output, cmd = nil) ⇒ Train::Extras::CommandResult (private)
Factory method for successful command results
99 100 101 102 |
# File 'lib/train-juniper/connection/command_executor.rb', line 99 def success_result(output, cmd = nil) output = clean_output(output, cmd) if cmd Train::Extras::CommandResult.new(output, '', 0) end |