diff options
author | jfarrell <jfarrell@apache.org> | 2016-09-20 15:27:54 -0400 |
---|---|---|
committer | jfarrell <jfarrell@apache.org> | 2016-09-20 15:27:54 -0400 |
commit | 04e6f62c8fc68a1e846544c45943aad76934ce56 (patch) | |
tree | de87e5c9682ac231b2b273b8c9e5855f1a403e40 | |
parent | 311c98455a9cb9070e9dad86a28f9c3ecbdf0a01 (diff) | |
download | thrift-04e6f62c8fc68a1e846544c45943aad76934ce56.tar.gz |
THRIFT-1108: SSL support for the Ruby library
Client: ruby
Patch: Mansi Nahar
Add ssl support to ruby lib.
-rw-r--r-- | lib/rb/lib/thrift.rb | 10 | ||||
-rw-r--r-- | lib/rb/lib/thrift/transport/ssl_server_socket.rb | 37 | ||||
-rw-r--r-- | lib/rb/lib/thrift/transport/ssl_socket.rb | 47 | ||||
-rw-r--r-- | lib/rb/spec/ssl_socket_spec.rb | 74 |
4 files changed, 164 insertions, 4 deletions
diff --git a/lib/rb/lib/thrift.rb b/lib/rb/lib/thrift.rb index fadebca94..0f581229c 100644 --- a/lib/rb/lib/thrift.rb +++ b/lib/rb/lib/thrift.rb @@ -1,4 +1,4 @@ -# +# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -6,16 +6,16 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -# +# # Contains some contributions under the Thrift Software License. # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. @@ -49,7 +49,9 @@ require 'thrift/protocol/multiplexed_protocol' require 'thrift/transport/base_transport' require 'thrift/transport/base_server_transport' require 'thrift/transport/socket' +require 'thrift/transport/ssl_socket' require 'thrift/transport/server_socket' +require 'thrift/transport/ssl_server_socket' require 'thrift/transport/unix_socket' require 'thrift/transport/unix_server_socket' require 'thrift/transport/buffered_transport' diff --git a/lib/rb/lib/thrift/transport/ssl_server_socket.rb b/lib/rb/lib/thrift/transport/ssl_server_socket.rb new file mode 100644 index 000000000..abc134390 --- /dev/null +++ b/lib/rb/lib/thrift/transport/ssl_server_socket.rb @@ -0,0 +1,37 @@ +# encoding: ascii-8bit +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +require 'socket' + +module Thrift + class SSLServerSocket < ServerSocket + def initialize(host_or_port, port = nil, ssl_context = nil) + super(host_or_port, port) + @ssl_context = ssl_context + end + + attr_accessor :ssl_context + + def listen + socket = TCPServer.new(@host, @port) + @handle = OpenSSL::SSL::SSLServer.new(socket, @ssl_context) + end + end +end diff --git a/lib/rb/lib/thrift/transport/ssl_socket.rb b/lib/rb/lib/thrift/transport/ssl_socket.rb new file mode 100644 index 000000000..dbbcc94fa --- /dev/null +++ b/lib/rb/lib/thrift/transport/ssl_socket.rb @@ -0,0 +1,47 @@ +# encoding: ascii-8bit +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +module Thrift + class SSLSocket < Socket + def initialize(host='localhost', port=9090, timeout=nil, ssl_context=nil) + super(host, port, timeout) + @ssl_context = ssl_context + end + + attr_accessor :ssl_context + + def open + socket = super + @handle = OpenSSL::SSL::SSLSocket.new(socket, @ssl_context) + begin + @handle.connect_nonblock + @handle.post_connection_check(@host) + @handle + rescue IO::WaitReadable + IO.select([ @handle ], nil, nil, @timeout) + retry + rescue IO::WaitWritable + IO.select(nil, [ @handle ], nil, @timeout) + retry + rescue StandardError => e + raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}: #{e}") + end + end + end +end diff --git a/lib/rb/spec/ssl_socket_spec.rb b/lib/rb/spec/ssl_socket_spec.rb new file mode 100644 index 000000000..a8bc78540 --- /dev/null +++ b/lib/rb/spec/ssl_socket_spec.rb @@ -0,0 +1,74 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +require 'spec_helper' +require File.expand_path("#{File.dirname(__FILE__)}/socket_spec_shared") + +describe 'SSLSocket' do + + describe Thrift::SSLSocket do + before(:each) do + @context = OpenSSL::SSL::SSLContext.new + @socket = Thrift::SSLSocket.new + @simple_socket_handle = mock("Handle", :closed? => false) + @simple_socket_handle.stub!(:close) + @simple_socket_handle.stub!(:connect_nonblock) + @simple_socket_handle.stub!(:setsockopt) + + @handle = mock(mock("SSLHandle", :connect_nonblock => true, :post_connection_check => true), :closed? => false) + @handle.stub!(:connect_nonblock) + @handle.stub!(:close) + @handle.stub!(:post_connection_check) + + ::Socket.stub!(:new).and_return(@simple_socket_handle) + OpenSSL::SSL::SSLSocket.stub!(:new).and_return(@handle) + end + + it_should_behave_like "a socket" + + it "should raise a TransportException when it cannot open a ssl socket" do + ::Socket.should_receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]]) + lambda { @socket.open }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::NOT_OPEN } + end + + it "should open a ::Socket with default args" do + OpenSSL::SSL::SSLSocket.should_receive(:new).with(@simple_socket_handle, nil).and_return(@handle) + @handle.should_receive(:post_connection_check).with('localhost') + @socket.open + end + + it "should accept host/port options" do + handle = mock("Handle", :connect_nonblock => true, :setsockopt => nil) + ::Socket.stub!(:new).and_return(handle) + ::Socket.should_receive(:getaddrinfo).with("my.domain", 1234, nil, ::Socket::SOCK_STREAM).and_return([[]]) + ::Socket.should_receive(:sockaddr_in) + OpenSSL::SSL::SSLSocket.should_receive(:new).with(handle, nil).and_return(@handle) + @handle.should_receive(:post_connection_check).with('my.domain') + Thrift::SSLSocket.new('my.domain', 1234, 6000, nil).open + end + + it "should accept an optional timeout" do + Thrift::SSLSocket.new('localhost', 8080, 5).timeout.should == 5 + end + + it "should accept an optional context" do + Thrift::SSLSocket.new('localhost', 8080, 5, @context).ssl_context.should == @context + end + end +end |