Path: blob/master/spec/integration/msfmcpd/rpc_availability_spec.rb
70330 views
# frozen_string_literal: true12require 'msf/core/mcp'3require 'stringio'4require 'tempfile'56RSpec.describe 'RPC Availability Integration' do7let(:output) { StringIO.new }8let(:file_fixtures_path) { File.join(Msf::Config.install_root, 'spec', 'file_fixtures') }9let(:valid_messagepack_path) { File.join(file_fixtures_path, 'config_files', 'msfmcpd', 'valid_messagepack.yaml') }1011describe 'Application run with RPC already available but no credentials' do12it 'exits with RPC startup error when MessagePack credentials are missing' do13# Config with no credentials — validator allows this because auto-start14# could generate them, but RPC is already running so generation won't happen15config = {16msf_api: {17type: 'messagepack',18host: 'localhost',19port: 55553,20auto_start_rpc: true21}22}2324config_file = Tempfile.new(['no_creds', '.yaml'])25config_file.write(YAML.dump(JSON.parse(config.to_json)))26config_file.flush2728app = Msf::MCP::Application.new(['--config', config_file.path], output: output)2930# Stub RPC as already available31allow_any_instance_of(Msf::MCP::RpcManager).to receive(:rpc_available?).and_return(true)32allow(Signal).to receive(:trap)3334expect { app.run }.to raise_error(SystemExit) do |e|35expect(e.status).to eq(1)36end3738expect(output.string).to include('RPC startup error')39expect(output.string).to include('no credentials')4041config_file.close42config_file.unlink43end4445it 'exits with RPC startup error when JSON-RPC token is missing' do46config = {47msf_api: {48type: 'json-rpc',49host: 'localhost',50port: 808151}52}5354config_file = Tempfile.new(['no_token', '.yaml'])55config_file.write(YAML.dump(JSON.parse(config.to_json)))56config_file.flush5758app = Msf::MCP::Application.new(['--config', config_file.path], output: output)5960# Stub RPC as already available61allow_any_instance_of(Msf::MCP::RpcManager).to receive(:rpc_available?).and_return(true)62allow(Signal).to receive(:trap)6364expect { app.run }.to raise_error(SystemExit) do |e|65expect(e.status).to eq(1)66end6768# The validator catches missing token before RpcManager runs69expect(output.string).to match(/token|Configuration validation failed/i)7071config_file.close72config_file.unlink73end7475it 'proceeds when RPC is available and credentials are provided' do76app = Msf::MCP::Application.new(['--config', valid_messagepack_path], output: output)7778# Stub RPC as already available79allow_any_instance_of(Msf::MCP::RpcManager).to receive(:rpc_available?).and_return(true)8081# Stub the rest of the startup sequence82mock_client = instance_double(Msf::MCP::Metasploit::Client)83allow(Msf::MCP::Metasploit::Client).to receive(:new).and_return(mock_client)84allow(mock_client).to receive(:authenticate)85mock_server = instance_double(Msf::MCP::Server)86allow(Msf::MCP::Server).to receive(:new).and_return(mock_server)87allow(mock_server).to receive(:start)88allow(Signal).to receive(:trap)8990expect { app.run }.not_to raise_error9192expect(output.string).to include('already running')93expect(output.string).to include('Authentication successful')94end95end9697describe 'Application run with RPC not available' do98it 'exits with RPC startup error when auto-start is disabled' do99config = {100msf_api: {101type: 'messagepack',102host: 'localhost',103port: 55553,104user: 'msf',105password: 'pass',106auto_start_rpc: false107}108}109110config_file = Tempfile.new(['no_autostart', '.yaml'])111config_file.write(YAML.dump(JSON.parse(config.to_json)))112config_file.flush113114app = Msf::MCP::Application.new(['--config', config_file.path], output: output)115116# Stub RPC as not available117allow_any_instance_of(Msf::MCP::RpcManager).to receive(:rpc_available?).and_return(false)118allow(Signal).to receive(:trap)119120expect { app.run }.to raise_error(SystemExit) do |e|121expect(e.status).to eq(1)122end123124expect(output.string).to include('RPC startup error')125expect(output.string).to include('auto-start is disabled')126127config_file.close128config_file.unlink129end130131it 'exits with RPC startup error on remote host' do132config = {133msf_api: {134type: 'messagepack',135host: '192.0.2.1',136port: 55553,137user: 'msf',138password: 'pass',139auto_start_rpc: true140}141}142143config_file = Tempfile.new(['remote_host', '.yaml'])144config_file.write(YAML.dump(JSON.parse(config.to_json)))145config_file.flush146147app = Msf::MCP::Application.new(['--config', config_file.path], output: output)148149# Stub RPC as not available150allow_any_instance_of(Msf::MCP::RpcManager).to receive(:rpc_available?).and_return(false)151allow(Signal).to receive(:trap)152153expect { app.run }.to raise_error(SystemExit) do |e|154expect(e.status).to eq(1)155end156157expect(output.string).to include('RPC startup error')158expect(output.string).to include('192.0.2.1')159160config_file.close161config_file.unlink162end163end164end165166167