diff --git a/lib/httpi/adapter/curb.rb b/lib/httpi/adapter/curb.rb
index 99fc3b08..d83d704c 100644
--- a/lib/httpi/adapter/curb.rb
+++ b/lib/httpi/adapter/curb.rb
@@ -128,6 +128,9 @@ def setup_ssl_auth
when :SSLv23 then 2
when :SSLv3 then 3
end
+ if ssl.min_version || ssl.max_version
+ raise NotImplementedError, "Method Not Implemented"
+ end
end
def respond_with(client)
diff --git a/lib/httpi/adapter/excon.rb b/lib/httpi/adapter/excon.rb
index a03cd8f3..15705264 100644
--- a/lib/httpi/adapter/excon.rb
+++ b/lib/httpi/adapter/excon.rb
@@ -73,6 +73,8 @@ def client_opts
end
opts[:ssl_version] = ssl.ssl_version if ssl.ssl_version
+ opts[:ssl_min_version] = ssl.min_version if ssl.min_version
+ opts[:ssl_max_version] = ssl.max_version if ssl.max_version
opts
end
diff --git a/lib/httpi/adapter/http.rb b/lib/httpi/adapter/http.rb
index 8b702c02..61389c30 100644
--- a/lib/httpi/adapter/http.rb
+++ b/lib/httpi/adapter/http.rb
@@ -58,6 +58,8 @@ def create_client
context.cert = @request.auth.ssl.cert
context.key = @request.auth.ssl.cert_key
context.ssl_version = @request.auth.ssl.ssl_version if @request.auth.ssl.ssl_version != nil
+ context.min_version = @request.auth.ssl.min_version if @request.auth.ssl.min_version != nil
+ context.max_version = @request.auth.ssl.max_version if @request.auth.ssl.max_version != nil
context.verify_mode = @request.auth.ssl.openssl_verify_mode
client = ::HTTP::Client.new(:ssl_context => context)
diff --git a/lib/httpi/adapter/httpclient.rb b/lib/httpi/adapter/httpclient.rb
index 91658057..d2558ec4 100644
--- a/lib/httpi/adapter/httpclient.rb
+++ b/lib/httpi/adapter/httpclient.rb
@@ -78,6 +78,9 @@ def setup_ssl_auth
end
@client.ssl_config.ssl_version = ssl.ssl_version.to_s if ssl.ssl_version
+ if ssl.min_version || ssl.max_version
+ raise NotImplementedError, "Method Not Implemented"
+ end
end
def respond_with(response)
diff --git a/lib/httpi/adapter/net_http.rb b/lib/httpi/adapter/net_http.rb
index 8376cd14..9972d0c7 100644
--- a/lib/httpi/adapter/net_http.rb
+++ b/lib/httpi/adapter/net_http.rb
@@ -182,6 +182,8 @@ def setup_ssl_auth
end
@client.ssl_version = ssl.ssl_version if ssl.ssl_version
+ @client.min_version = ssl.min_version if ssl.min_version
+ @client.max_version = ssl.max_version if ssl.max_version
end
def ssl_cert_store(ssl)
diff --git a/lib/httpi/auth/ssl.rb b/lib/httpi/auth/ssl.rb
index f998a5a8..efa73556 100644
--- a/lib/httpi/auth/ssl.rb
+++ b/lib/httpi/auth/ssl.rb
@@ -20,6 +20,9 @@ class SSL
ssl_context::METHODS.reject { |method| method.match(/server|client/) }
end.sort.reverse
+ # Returns OpenSSL::SSL::*_VERSION values for min_version and max_version
+ MIN_MAX_VERSIONS = OpenSSL::SSL.constants.select{|constant| constant =~/_VERSION$/}.map{|version| version[0..-9].to_sym}.reverse
+
# Returns whether SSL configuration is present.
def present?
(verify_mode == :none) || (cert && cert_key) || ca_cert_file
@@ -90,6 +93,36 @@ def ssl_version=(version)
@ssl_version = version
end
+ # Returns the SSL min_version number. Defaults to nil (auto-negotiate).
+ def min_version
+ @min_version ||= nil
+ end
+
+ # Sets the SSL min_version number. Expects one of HTTPI::Auth::SSL::SSL_VERSIONS.
+ def min_version=(version)
+ unless MIN_MAX_VERSIONS.include? version
+ raise ArgumentError, "Invalid SSL min_version #{version.inspect}\n" +
+ "Please specify one of #{MIN_MAX_VERSIONS.inspect}"
+ end
+
+ @min_version = version
+ end
+
+ # Returns the SSL min_version number. Defaults to nil (auto-negotiate).
+ def max_version
+ @max_version ||= nil
+ end
+
+ # Sets the SSL min_version number. Expects one of HTTPI::Auth::SSL::SSL_VERSIONS.
+ def max_version=(version)
+ unless MIN_MAX_VERSIONS.include? version
+ raise ArgumentError, "Invalid SSL max_version #{version.inspect}\n" +
+ "Please specify one of #{MIN_MAX_VERSIONS.inspect}"
+ end
+
+ @max_version = version
+ end
+
# Returns an OpenSSL::X509::Certificate for the +cert_file+.
def cert
@cert ||= (OpenSSL::X509::Certificate.new File.read(cert_file) if cert_file)
diff --git a/spec/httpi/adapter/curb_spec.rb b/spec/httpi/adapter/curb_spec.rb
index ec931b75..8ce74ee6 100644
--- a/spec/httpi/adapter/curb_spec.rb
+++ b/spec/httpi/adapter/curb_spec.rb
@@ -278,6 +278,16 @@
adapter.request(:get)
end
end
+ it 'raises error when min_version not nil' do
+ request.auth.ssl.min_version = :TLS1_2
+ expect{ adapter.request(:get) }.
+ to raise_error(HTTPI::NotImplementedError, 'Method Not Implemented')
+ end
+ it 'raises error when max_version not nil' do
+ request.auth.ssl.max_version = :TLS1_2
+ expect{ adapter.request(:get) }.
+ to raise_error(HTTPI::NotImplementedError, 'Method Not Implemented')
+ end
end
context "(for SSL client auth)" do
diff --git a/spec/httpi/adapter/httpclient_spec.rb b/spec/httpi/adapter/httpclient_spec.rb
index e6371a3e..83dbef0f 100644
--- a/spec/httpi/adapter/httpclient_spec.rb
+++ b/spec/httpi/adapter/httpclient_spec.rb
@@ -178,6 +178,17 @@
adapter.request(:get)
end
+
+ it 'raises error when min_version not nil' do
+ request.auth.ssl.min_version = :TLS1_2
+ expect{ adapter.request(:get) }.
+ to raise_error(HTTPI::NotImplementedError, 'Method Not Implemented')
+ end
+ it 'raises error when max_version not nil' do
+ request.auth.ssl.max_version = :TLS1_2
+ expect{ adapter.request(:get) }.
+ to raise_error(HTTPI::NotImplementedError, 'Method Not Implemented')
+ end
end
context "(for SSL client auth with a verify mode of :none with no certs provided)" do
diff --git a/spec/httpi/auth/ssl_spec.rb b/spec/httpi/auth/ssl_spec.rb
index fe5e722c..10618241 100644
--- a/spec/httpi/auth/ssl_spec.rb
+++ b/spec/httpi/auth/ssl_spec.rb
@@ -4,6 +4,7 @@
describe HTTPI::Auth::SSL do
before(:all) do
@ssl_versions = HTTPI::Auth::SSL::SSL_VERSIONS
+ @min_max_versions = HTTPI::Auth::SSL::MIN_MAX_VERSIONS
end
describe "VERIFY_MODES" do
@@ -158,6 +159,36 @@
end
end
+ describe "#min_version" do
+ subject { HTTPI::Auth::SSL.new }
+
+ it "returns the min_version" do
+ subject.min_version = @min_max_versions.first
+ expect(subject.min_version).to eq(@min_max_versions.first)
+ end
+
+ it 'raises ArgumentError if the version is unsupported' do
+ expect { ssl.min_version = :ssl_fail }.
+ to raise_error(ArgumentError, "Invalid SSL min_version :ssl_fail\n" +
+ "Please specify one of #{@min_max_versions}")
+ end
+ end
+
+ describe "#max_version" do
+ subject { HTTPI::Auth::SSL.new }
+
+ it "returns the SSL version" do
+ subject.max_version = @min_max_versions.first
+ expect(subject.max_version).to eq(@min_max_versions.first)
+ end
+
+ it 'raises ArgumentError if the version is unsupported' do
+ expect { ssl.max_version = :ssl_fail }.
+ to raise_error(ArgumentError, "Invalid SSL max_version :ssl_fail\n" +
+ "Please specify one of #{@min_max_versions}")
+ end
+ end
+
def ssl
ssl = HTTPI::Auth::SSL.new
ssl.cert_key_file = "spec/fixtures/client_key.pem"
diff --git a/spec/integration/excon_spec.rb b/spec/integration/excon_spec.rb
index 5d3abc2f..81723eee 100644
--- a/spec/integration/excon_spec.rb
+++ b/spec/integration/excon_spec.rb
@@ -129,6 +129,16 @@
expect(response.body).to eq("get")
end
+ it "works with min_version/max_version" do
+ request = HTTPI::Request.new(@server.url)
+ request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
+ request.auth.ssl.min_version = :TLS1_2
+ request.auth.ssl.max_version = :TLS1_2
+
+ response = HTTPI.get(request, adapter)
+ expect(response.body).to eq("get")
+ end
+
it "works with client cert and key provided as file path" do
request = HTTPI::Request.new(@server.url)
request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
diff --git a/spec/integration/http_spec.rb b/spec/integration/http_spec.rb
index 7d1157bc..3593b260 100644
--- a/spec/integration/http_spec.rb
+++ b/spec/integration/http_spec.rb
@@ -131,6 +131,16 @@
response = HTTPI.get(request, adapter)
expect(response.body).to eq("get")
end
+
+ it "works with min_version/max_version" do
+ request = HTTPI::Request.new(@server.url)
+ request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
+ request.auth.ssl.min_version = :TLS1_2
+ request.auth.ssl.max_version = :TLS1_2
+
+ response = HTTPI.get(request, adapter)
+ expect(response.body).to eq("get")
+ end
end
end
diff --git a/spec/integration/net_http_spec.rb b/spec/integration/net_http_spec.rb
index 9b34fe85..34d60db4 100644
--- a/spec/integration/net_http_spec.rb
+++ b/spec/integration/net_http_spec.rb
@@ -217,6 +217,16 @@
response = HTTPI.get(request, adapter)
expect(response.body).to eq("get")
end
+
+ it "works with min_version/max_version" do
+ request = HTTPI::Request.new(@server.url)
+ request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
+ request.auth.ssl.min_version = :TLS1_2
+ request.auth.ssl.max_version = :TLS1_2
+
+ response = HTTPI.get(request, adapter)
+ expect(response.body).to eq("get")
+ end
end
end