Thrift-1978: Ruby: Thrift should allow for the SSL verify mode to be set
Client: rb
Patch: Timur Alperovich
Ruby SSL verify mode cannot be specified, which means thrift cannot be used against servers with self-signed certificates over SSL. The suggested fix is to expose the SSL verification mode as a constructor argument in lib/rb/lib/thrift/transport/http_client_transport.rb.
diff --git a/lib/rb/lib/thrift/transport/http_client_transport.rb b/lib/rb/lib/thrift/transport/http_client_transport.rb
index 07f74bc..77ffe35 100644
--- a/lib/rb/lib/thrift/transport/http_client_transport.rb
+++ b/lib/rb/lib/thrift/transport/http_client_transport.rb
@@ -20,16 +20,18 @@
require 'net/http'
require 'net/https'
+require 'openssl'
require 'uri'
require 'stringio'
module Thrift
class HTTPClientTransport < BaseTransport
- def initialize(url)
+ def initialize(url, opts = {})
@url = URI url
@headers = {'Content-Type' => 'application/x-thrift'}
@outbuf = Bytes.empty_byte_buffer
+ @ssl_verify_mode = opts.fetch(:ssl_verify_mode, OpenSSL::SSL::VERIFY_PEER)
end
def open?; true end
@@ -43,6 +45,7 @@
def flush
http = Net::HTTP.new @url.host, @url.port
http.use_ssl = @url.scheme == 'https'
+ http.verify_mode = @ssl_verify_mode if @url.scheme == 'https'
resp = http.post(@url.request_uri, @outbuf, @headers)
data = resp.body
data = Bytes.force_binary_encoding(data)
diff --git a/lib/rb/spec/http_client_spec.rb b/lib/rb/spec/http_client_spec.rb
index 0890a8b..793fc73 100644
--- a/lib/rb/spec/http_client_spec.rb
+++ b/lib/rb/spec/http_client_spec.rb
@@ -68,4 +68,53 @@
@client.flush
end
end
+
+ describe 'ssl enabled' do
+ before(:each) do
+ @service_path = "/path/to/service?param=value"
+ @server_uri = "https://my.domain.com"
+ end
+
+ it "should use SSL for https" do
+ client = Thrift::HTTPClientTransport.new("#{@server_uri}#{@service_path}")
+
+ client.write "test"
+
+ Net::HTTP.should_receive(:new).with("my.domain.com", 443).and_return do
+ mock("Net::HTTP").tap do |http|
+ http.should_receive(:use_ssl=).with(true)
+ http.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
+ http.should_receive(:post).with(@service_path, "test",
+ "Content-Type" => "application/x-thrift").and_return do
+ mock("Net::HTTPOK").tap do |response|
+ response.should_receive(:body).and_return "data"
+ end
+ end
+ end
+ end
+ client.flush
+ client.read(4).should == "data"
+ end
+
+ it "should set SSL verify mode when specified" do
+ client = Thrift::HTTPClientTransport.new("#{@server_uri}#{@service_path}",
+ :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE)
+
+ client.write "test"
+ Net::HTTP.should_receive(:new).with("my.domain.com", 443).and_return do
+ mock("Net::HTTP").tap do |http|
+ http.should_receive(:use_ssl=).with(true)
+ http.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
+ http.should_receive(:post).with(@service_path, "test",
+ "Content-Type" => "application/x-thrift").and_return do
+ mock("Net::HTTPOK").tap do |response|
+ response.should_receive(:body).and_return "data"
+ end
+ end
+ end
+ end
+ client.flush
+ client.read(4).should == "data"
+ end
+ end
end