Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 31 additions & 27 deletions lib/proxy/request.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'net/http'
require 'net/http/persistent'
require 'net/https'
require 'uri'
require 'cgi'
Expand Down Expand Up @@ -44,8 +45,36 @@ def create_post(path, body, headers = {}, query = {})
end

class ForemanRequest
class << self
def http
@http ||= begin
uri = URI.parse(Proxy::SETTINGS.foreman_url.to_s)
http = Net::HTTP::Persistent.new(name: 'smart_proxy_foreman')
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

if uri.scheme == 'https'
ca_file = Proxy::SETTINGS.foreman_ssl_ca || Proxy::SETTINGS.ssl_ca_file
certificate = Proxy::SETTINGS.foreman_ssl_cert || Proxy::SETTINGS.ssl_certificate
private_key = Proxy::SETTINGS.foreman_ssl_key || Proxy::SETTINGS.ssl_private_key

if ca_file && !ca_file.to_s.empty?
http.ca_file = ca_file
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
end

if certificate && !certificate.to_s.empty? && private_key && !private_key.to_s.empty?
http.certificate = OpenSSL::X509::Certificate.new(File.read(certificate))
http.private_key = OpenSSL::PKey.read(File.read(private_key), nil)
end
end

http
end
end
end

def send_request(request)
http.request(request)
http.request(uri, request)
end

def request_factory
Expand All @@ -57,32 +86,7 @@ def uri
end

def http
@http ||= http_init
end

private

def http_init
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == 'https'
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

if http.use_ssl?
ca_file = Proxy::SETTINGS.foreman_ssl_ca || Proxy::SETTINGS.ssl_ca_file
certificate = Proxy::SETTINGS.foreman_ssl_cert || Proxy::SETTINGS.ssl_certificate
private_key = Proxy::SETTINGS.foreman_ssl_key || Proxy::SETTINGS.ssl_private_key

if ca_file && !ca_file.to_s.empty?
http.ca_file = ca_file
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
end

if certificate && !certificate.to_s.empty? && private_key && !private_key.to_s.empty?
http.cert = OpenSSL::X509::Certificate.new(File.read(certificate))
http.key = OpenSSL::PKey.read(File.read(private_key), nil)
end
end
http
self.class.http
end
end
end
1 change: 1 addition & 0 deletions smart_proxy.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Gem::Specification.new do |s|
s.add_dependency 'base64'
s.add_dependency 'json'
s.add_dependency 'logging'
s.add_dependency 'net-http-persistent', '~> 4.0'
s.add_dependency 'ostruct'
s.add_dependency 'rack', '>= 1.3'
s.add_dependency 'rexml', '~> 3.2'
Expand Down
2 changes: 2 additions & 0 deletions test/registration/registration_api_test.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'test_helper'
require 'registration/registration_api'
require 'registration/registration_plugin'

class RegistrationRegisterApiTest < Test::Unit::TestCase
include Rack::Test::Methods
Expand All @@ -11,6 +12,7 @@ def app
def setup
@foreman_url = 'http://foreman.example.com'
Proxy::SETTINGS.stubs(:foreman_url).returns(@foreman_url)
Proxy::Registration::Plugin.load_test_settings
end

def test_global_register_template
Expand Down
38 changes: 38 additions & 0 deletions test/request_test.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require 'test_helper'
require 'uri'
require 'net/http'
require 'openssl'
require 'tempfile'
require 'mocha'
require 'templates/templates_plugin'
require "proxy/util"
Expand All @@ -11,6 +13,15 @@ class RequestTest < Test::Unit::TestCase
def setup
@foreman_url = 'https://foreman.example.com'
Proxy::SETTINGS.stubs(:foreman_url).returns(@foreman_url)
Proxy::SETTINGS.stubs(:foreman_ssl_ca).returns(nil)
Proxy::SETTINGS.stubs(:ssl_ca_file).returns(nil)
Proxy::SETTINGS.stubs(:foreman_ssl_cert).returns(nil)
Proxy::SETTINGS.stubs(:ssl_certificate).returns(nil)
Proxy::SETTINGS.stubs(:foreman_ssl_key).returns(nil)
Proxy::SETTINGS.stubs(:ssl_private_key).returns(nil)
cached_connection = Proxy::HttpRequest::ForemanRequest.instance_variable_get(:@http)
cached_connection&.shutdown
Proxy::HttpRequest::ForemanRequest.instance_variable_set(:@http, nil)
@template_url = 'http://proxy.lan:8443'
Proxy::Templates::Plugin.load_test_settings(:template_url => @template_url)
@request = Proxy::HttpRequest::ForemanRequest.new
Expand Down Expand Up @@ -54,6 +65,33 @@ def test_post
assert_equal("body", result.body)
end

def test_connection_is_shared_across_request_instances
request_a = Proxy::HttpRequest::ForemanRequest.new
request_b = Proxy::HttpRequest::ForemanRequest.new

assert_same request_a.http, request_b.http
assert_kind_of Net::HTTP::Persistent, request_a.http
end

def test_ssl_verify_peer_when_ca_configured
ca_file = Tempfile.new(['foreman-ca', '.pem'])
ca_file.write("ca-content")
ca_file.flush

Proxy::SETTINGS.stubs(:foreman_ssl_ca).returns(ca_file.path)
cached_connection = Proxy::HttpRequest::ForemanRequest.instance_variable_get(:@http)
cached_connection&.shutdown
Proxy::HttpRequest::ForemanRequest.instance_variable_set(:@http, nil)

connection = Proxy::HttpRequest::ForemanRequest.new.http

assert_equal OpenSSL::SSL::VERIFY_PEER, connection.verify_mode
assert_equal ca_file.path, connection.ca_file
ensure
ca_file&.close
ca_file&.unlink
end

def test_post_with_nested_params
stub_request(:post, @foreman_url + '/register?activation_keys%5B%5D=ac_AlmaLinux8&location_id=2&organization_id=1&repo_data%5B%5D%5Brepo%5D=repo1&repo_data%5B%5D%5Brepo_gpg_key_url%5D=key1&repo_data%5B%5D%5Brepo%5D=repo2&repo_data%5B%5D%5Brepo_gpg_key_url%5D=key2&update_packages=false')
.to_return(status: 200, body: "body", headers: {h1: "header"})
Expand Down
2 changes: 2 additions & 0 deletions test/templates/template_proxy_request_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ def test_template_requests_via_post
headers: {
'Accept' => ['*/*', 'application/json,version=2'],
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'Connection' => 'keep-alive',
'Content-Type' => 'application/json',
'Keep-Alive' => '30',
'User-Agent' => 'Ruby',
'X-Forwarded-For' => '1.2.3.4',
}).
Expand Down
Loading