aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar murgatroid99 <mlumish@google.com>2015-12-04 14:36:52 -0800
committerGravatar murgatroid99 <mlumish@google.com>2015-12-04 14:36:52 -0800
commitcfa26e1ce7f65f70801cada2f2573437915d5fb8 (patch)
treecdb0701294660a2fa14175c85253cb0bb4d99a52 /src
parent9946f2b80a9dcc01fece8b9ddae4c80a77647b9d (diff)
Plumb CallCredentials through Ruby code, replacing metadata_updater functionality
Diffstat (limited to 'src')
-rwxr-xr-xsrc/ruby/bin/apis/pubsub_demo.rb10
-rw-r--r--src/ruby/lib/grpc/generic/client_stub.rb82
-rwxr-xr-xsrc/ruby/pb/test/client.rb9
-rw-r--r--src/ruby/spec/call_credentials_spec.rb57
-rw-r--r--src/ruby/spec/call_spec.rb9
-rw-r--r--src/ruby/spec/channel_credentials_spec.rb29
-rw-r--r--src/ruby/spec/client_server_spec.rb29
-rw-r--r--src/ruby/spec/generic/client_stub_spec.rb57
-rw-r--r--src/ruby/spec/generic/rpc_server_spec.rb19
9 files changed, 168 insertions, 133 deletions
diff --git a/src/ruby/bin/apis/pubsub_demo.rb b/src/ruby/bin/apis/pubsub_demo.rb
index 003e91a6b3..eca43215b7 100755
--- a/src/ruby/bin/apis/pubsub_demo.rb
+++ b/src/ruby/bin/apis/pubsub_demo.rb
@@ -80,8 +80,9 @@ def publisher_stub(opts)
address = "#{opts.host}:#{opts.port}"
stub_clz = Tech::Pubsub::PublisherService::Stub # shorter
GRPC.logger.info("... access PublisherService at #{address}")
- stub_clz.new(address,
- creds: ssl_creds, update_metadata: auth_proc(opts),
+ call_creds = GRPC::Core::CallCredentials.new(auth_proc(opts))
+ combined_creds = ssl_creds.compose(call_creds)
+ stub_clz.new(address, creds: combined_creds,
GRPC::Core::Channel::SSL_TARGET => opts.host)
end
@@ -90,8 +91,9 @@ def subscriber_stub(opts)
address = "#{opts.host}:#{opts.port}"
stub_clz = Tech::Pubsub::SubscriberService::Stub # shorter
GRPC.logger.info("... access SubscriberService at #{address}")
- stub_clz.new(address,
- creds: ssl_creds, update_metadata: auth_proc(opts),
+ call_creds = GRPC::Core::CallCredentials.new(auth_proc(opts))
+ combined_creds = ssl_creds.compose(call_creds)
+ stub_clz.new(address, creds: combined_creds,
GRPC::Core::Channel::SSL_TARGET => opts.host)
end
diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb
index 90aaa026ec..13100a614c 100644
--- a/src/ruby/lib/grpc/generic/client_stub.rb
+++ b/src/ruby/lib/grpc/generic/client_stub.rb
@@ -57,21 +57,6 @@ module GRPC
Core::Channel.new(host, kw, creds)
end
- def self.update_with_jwt_aud_uri(a_hash, host, method)
- last_slash_idx, res = method.rindex('/'), a_hash.clone
- return res if last_slash_idx.nil?
- service_name = method[0..(last_slash_idx - 1)]
- res[:jwt_aud_uri] = "https://#{host}#{service_name}"
- res
- end
-
- # check_update_metadata is used by #initialize verify that it's a Proc.
- def self.check_update_metadata(update_metadata)
- return update_metadata if update_metadata.nil?
- fail(TypeError, '!is_a?Proc') unless update_metadata.is_a?(Proc)
- update_metadata
- end
-
# Allows users of the stub to modify the propagate mask.
#
# This is an advanced feature for use when making calls to another gRPC
@@ -99,29 +84,21 @@ module GRPC
# - :timeout
# when present, this is the default timeout used for calls
#
- # - :update_metadata
- # when present, this a func that takes a hash and returns a hash
- # it can be used to update metadata, i.e, remove, or amend
- # metadata values.
- #
# @param host [String] the host the stub connects to
# @param q [Core::CompletionQueue] used to wait for events
# @param channel_override [Core::Channel] a pre-created channel
# @param timeout [Number] the default timeout to use in requests
# @param creds [Core::ChannelCredentials] the channel credentials
- # @param update_metadata a func that updates metadata as described above
# @param kw [KeywordArgs]the channel arguments
def initialize(host, q,
channel_override: nil,
timeout: nil,
creds: nil,
propagate_mask: nil,
- update_metadata: nil,
**kw)
fail(TypeError, '!CompletionQueue') unless q.is_a?(Core::CompletionQueue)
@queue = q
@ch = ClientStub.setup_channel(channel_override, host, creds, **kw)
- @update_metadata = ClientStub.check_update_metadata(update_metadata)
alt_host = kw[Core::Channel::SSL_TARGET]
@host = alt_host.nil? ? host : alt_host
@propagate_mask = propagate_mask
@@ -166,6 +143,8 @@ module GRPC
# @param deadline [Time] (optional) the time the request should complete
# @param parent [Core::Call] a prior call whose reserved metadata
# will be propagated by this one.
+ # @param credentials [Core::CallCredentials] credentials to use when making
+ # the call
# @param return_op [true|false] return an Operation if true
# @return [Object] the response received from the server
def request_response(method, req, marshal, unmarshal,
@@ -173,19 +152,20 @@ module GRPC
timeout: nil,
return_op: false,
parent: nil,
+ credentials: nil,
**kw)
c = new_active_call(method, marshal, unmarshal,
deadline: deadline,
timeout: timeout,
- parent: parent)
- md = update_metadata(kw, method)
- return c.request_response(req, **md) unless return_op
+ parent: parent,
+ credentials: credentials)
+ return c.request_response(req, **kw) unless return_op
# return the operation view of the active_call; define #execute as a
# new method for this instance that invokes #request_response.
op = c.operation
op.define_singleton_method(:execute) do
- c.request_response(req, **md)
+ c.request_response(req, **kw)
end
op
end
@@ -234,25 +214,28 @@ module GRPC
# @param return_op [true|false] return an Operation if true
# @param parent [Core::Call] a prior call whose reserved metadata
# will be propagated by this one.
+ # @param credentials [Core::CallCredentials] credentials to use when making
+ # the call
# @return [Object|Operation] the response received from the server
def client_streamer(method, requests, marshal, unmarshal,
deadline: nil,
timeout: nil,
return_op: false,
parent: nil,
+ credentials: nil,
**kw)
c = new_active_call(method, marshal, unmarshal,
deadline: deadline,
timeout: timeout,
- parent: parent)
- md = update_metadata(kw, method)
- return c.client_streamer(requests, **md) unless return_op
+ parent: parent,
+ credentials: credentials)
+ return c.client_streamer(requests, **kw) unless return_op
# return the operation view of the active_call; define #execute as a
# new method for this instance that invokes #client_streamer.
op = c.operation
op.define_singleton_method(:execute) do
- c.client_streamer(requests, **md)
+ c.client_streamer(requests, **kw)
end
op
end
@@ -309,6 +292,8 @@ module GRPC
# @param return_op [true|false]return an Operation if true
# @param parent [Core::Call] a prior call whose reserved metadata
# will be propagated by this one.
+ # @param credentials [Core::CallCredentials] credentials to use when making
+ # the call
# @param blk [Block] when provided, is executed for each response
# @return [Enumerator|Operation|nil] as discussed above
def server_streamer(method, req, marshal, unmarshal,
@@ -316,20 +301,21 @@ module GRPC
timeout: nil,
return_op: false,
parent: nil,
+ credentials: nil,
**kw,
&blk)
c = new_active_call(method, marshal, unmarshal,
deadline: deadline,
timeout: timeout,
- parent: parent)
- md = update_metadata(kw, method)
- return c.server_streamer(req, **md, &blk) unless return_op
+ parent: parent,
+ credentials: credentials)
+ return c.server_streamer(req, **kw, &blk) unless return_op
# return the operation view of the active_call; define #execute
# as a new method for this instance that invokes #server_streamer
op = c.operation
op.define_singleton_method(:execute) do
- c.server_streamer(req, **md, &blk)
+ c.server_streamer(req, **kw, &blk)
end
op
end
@@ -424,6 +410,8 @@ module GRPC
# @param deadline [Time] (optional) the time the request should complete
# @param parent [Core::Call] a prior call whose reserved metadata
# will be propagated by this one.
+ # @param credentials [Core::CallCredentials] credentials to use when making
+ # the call
# @param return_op [true|false] return an Operation if true
# @param blk [Block] when provided, is executed for each response
# @return [Enumerator|nil|Operation] as discussed above
@@ -432,36 +420,28 @@ module GRPC
timeout: nil,
return_op: false,
parent: nil,
+ credentials: nil,
**kw,
&blk)
c = new_active_call(method, marshal, unmarshal,
deadline: deadline,
timeout: timeout,
- parent: parent)
- md = update_metadata(kw, method)
- return c.bidi_streamer(requests, **md, &blk) unless return_op
+ parent: parent,
+ credentials: credentials)
+
+ return c.bidi_streamer(requests, **kw, &blk) unless return_op
# return the operation view of the active_call; define #execute
# as a new method for this instance that invokes #bidi_streamer
op = c.operation
op.define_singleton_method(:execute) do
- c.bidi_streamer(requests, **md, &blk)
+ c.bidi_streamer(requests, **kw, &blk)
end
op
end
private
- def update_metadata(kw, method)
- return kw if @update_metadata.nil?
- just_jwt_uri = self.class.update_with_jwt_aud_uri({}, @host, method)
- updated = @update_metadata.call(just_jwt_uri)
-
- # keys should be lowercase
- updated = Hash[updated.each_pair.map { |k, v| [k.downcase, v] }]
- kw.merge(updated)
- end
-
# Creates a new active stub
#
# @param method [string] the method being called.
@@ -473,7 +453,8 @@ module GRPC
def new_active_call(method, marshal, unmarshal,
deadline: nil,
timeout: nil,
- parent: nil)
+ parent: nil,
+ credentials: nil)
if deadline.nil?
deadline = from_relative_time(timeout.nil? ? @timeout : timeout)
end
@@ -483,6 +464,7 @@ module GRPC
method,
nil, # host use nil,
deadline)
+ call.set_credentials credentials unless credentials.nil?
ActiveCall.new(call, @queue, marshal, unmarshal, deadline, started: false)
end
end
diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb
index 30550d6cc0..198b0395f8 100755
--- a/src/ruby/pb/test/client.rb
+++ b/src/ruby/pb/test/client.rb
@@ -132,7 +132,8 @@ def create_stub(opts)
if wants_creds.include?(opts.test_case)
unless opts.oauth_scope.nil?
auth_creds = Google::Auth.get_application_default(opts.oauth_scope)
- stub_opts[:update_metadata] = auth_creds.updater_proc
+ call_creds = GRPC::Core::CallCredentials.new(auth_creds.updater_proc)
+ stub_opts[:creds] = stub_opts[:creds].compose call_creds
end
end
@@ -141,12 +142,14 @@ def create_stub(opts)
kw = auth_creds.updater_proc.call({}) # gives as an auth token
# use a metadata update proc that just adds the auth token.
- stub_opts[:update_metadata] = proc { |md| md.merge(kw) }
+ call_creds = GRPC::Core::CallCredentials.new(proc { |md| md.merge(kw) })
+ stub_opts[:creds] = stub_opts[:creds].compose call_creds
end
if opts.test_case == 'jwt_token_creds' # don't use a scope
auth_creds = Google::Auth.get_application_default
- stub_opts[:update_metadata] = auth_creds.updater_proc
+ call_creds = GRPC::Core::CallCredentials.new(auth_creds.updater_proc)
+ stub_opts[:creds] = stub_opts[:creds].compose call_creds
end
GRPC.logger.info("... connecting securely to #{address}")
diff --git a/src/ruby/spec/call_credentials_spec.rb b/src/ruby/spec/call_credentials_spec.rb
new file mode 100644
index 0000000000..32a0ad44b7
--- /dev/null
+++ b/src/ruby/spec/call_credentials_spec.rb
@@ -0,0 +1,57 @@
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+require 'grpc'
+
+describe GRPC::Core::CallCredentials do
+ CallCredentials = GRPC::Core::CallCredentials
+
+ let(:auth_proc) { proc { { 'plugin_key' => 'plugin_value' } } }
+
+ describe '#new' do
+ it 'can successfully create a CallCredentials from a proc' do
+ expect { CallCredentials.new(auth_proc) }.not_to raise_error
+ end
+ end
+
+ describe '#compose' do
+ it 'can compose with another CallCredentials' do
+ creds1 = CallCredentials.new(auth_proc)
+ creds2 = CallCredentials.new(auth_proc)
+ expect { creds1.compose creds2 }.not_to raise_error
+ end
+
+ it 'can compose with multiple CallCredentials' do
+ creds1 = CallCredentials.new(auth_proc)
+ creds2 = CallCredentials.new(auth_proc)
+ creds3 = CallCredentials.new(auth_proc)
+ expect { creds1.compose(creds2, creds3) }.not_to raise_error
+ end
+ end
+end
diff --git a/src/ruby/spec/call_spec.rb b/src/ruby/spec/call_spec.rb
index dd3c45f754..6629570fba 100644
--- a/src/ruby/spec/call_spec.rb
+++ b/src/ruby/spec/call_spec.rb
@@ -144,6 +144,15 @@ describe GRPC::Core::Call do
end
end
+ describe '#set_credentials!' do
+ it 'can set a valid CallCredentials object' do
+ call = make_test_call
+ auth_proc = proc { { 'plugin_key' => 'plugin_value' } }
+ creds = GRPC::Core::CallCredentials.new auth_proc
+ expect { call.set_credentials! creds }.not_to raise_error
+ end
+ end
+
def make_test_call
@ch.create_call(client_queue, nil, nil, 'dummy_method', nil, deadline)
end
diff --git a/src/ruby/spec/channel_credentials_spec.rb b/src/ruby/spec/channel_credentials_spec.rb
index b2bdf7032e..ecab5dca12 100644
--- a/src/ruby/spec/channel_credentials_spec.rb
+++ b/src/ruby/spec/channel_credentials_spec.rb
@@ -31,6 +31,7 @@ require 'grpc'
describe GRPC::Core::ChannelCredentials do
ChannelCredentials = GRPC::Core::ChannelCredentials
+ CallCredentials = GRPC::Core::CallCredentials
def load_test_certs
test_root = File.join(File.dirname(__FILE__), 'testdata')
@@ -60,4 +61,32 @@ describe GRPC::Core::ChannelCredentials do
expect(&blk).to raise_error
end
end
+
+ describe '#compose' do
+ it 'can compose with a CallCredentials' do
+ certs = load_test_certs
+ channel_creds = ChannelCredentials.new(*certs)
+ auth_proc = proc { { 'plugin_key' => 'plugin_value' } }
+ call_creds = CallCredentials.new auth_proc
+ expect { channel_creds.compose call_creds }.not_to raise_error
+ end
+
+ it 'can compose with multiple CallCredentials' do
+ certs = load_test_certs
+ channel_creds = ChannelCredentials.new(*certs)
+ auth_proc = proc { { 'plugin_key' => 'plugin_value' } }
+ call_creds1 = CallCredentials.new auth_proc
+ call_creds2 = CallCredentials.new auth_proc
+ expect do
+ channel_creds.compose(call_creds1, call_creds2)
+ end.not_to raise_error
+ end
+
+ it 'cannot compose with ChannelCredentials' do
+ certs = load_test_certs
+ channel_creds1 = ChannelCredentials.new(*certs)
+ channel_creds2 = ChannelCredentials.new(*certs)
+ expect { channel_creds1.compose channel_creds2 }.to raise_error(TypeError)
+ end
+ end
end
diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb
index 734f176e94..7cce2076c9 100644
--- a/src/ruby/spec/client_server_spec.rb
+++ b/src/ruby/spec/client_server_spec.rb
@@ -413,6 +413,8 @@ describe 'the http client/server' do
end
describe 'the secure http client/server' do
+ include_context 'setup: tags'
+
def load_test_certs
test_root = File.join(File.dirname(__FILE__), 'testdata')
files = ['ca.pem', 'server1.key', 'server1.pem']
@@ -443,4 +445,31 @@ describe 'the secure http client/server' do
it_behaves_like 'GRPC metadata delivery works OK' do
end
+
+ it 'modifies metadata with CallCredentials' do
+ auth_proc = proc { { 'k1' => 'updated-v1' } }
+ call_creds = GRPC::Core::CallCredentials.new(auth_proc)
+ md = { 'k2' => 'v2' }
+ expected_md = { 'k1' => 'updated-v1', 'k2' => 'v2' }
+ recvd_rpc = nil
+ rcv_thread = Thread.new do
+ recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
+ end
+
+ call = new_client_call
+ call.set_credentials! call_creds
+ client_ops = {
+ CallOps::SEND_INITIAL_METADATA => md
+ }
+ batch_result = call.run_batch(@client_queue, @client_tag, deadline,
+ client_ops)
+ expect(batch_result.send_metadata).to be true
+
+ # confirm the server can receive the client metadata
+ rcv_thread.join
+ expect(recvd_rpc).to_not eq nil
+ recvd_md = recvd_rpc.metadata
+ replace_symbols = Hash[expected_md.each_pair.collect { |x, y| [x.to_s, y] }]
+ expect(recvd_md).to eq(recvd_md.merge(replace_symbols))
+ end
end
diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb
index da5bc6c9e5..40550230dd 100644
--- a/src/ruby/spec/generic/client_stub_spec.rb
+++ b/src/ruby/spec/generic/client_stub_spec.rb
@@ -145,34 +145,6 @@ describe 'ClientStub' do
th.join
end
- it 'should update the sent metadata with a provided metadata updater' do
- server_port = create_test_server
- host = "localhost:#{server_port}"
- th = run_request_response(@sent_msg, @resp, @pass,
- k1: 'updated-v1', k2: 'v2')
- update_md = proc do |md|
- md[:k1] = 'updated-v1'
- md
- end
- stub = GRPC::ClientStub.new(host, @cq, update_metadata: update_md)
- expect(get_response(stub)).to eq(@resp)
- th.join
- end
-
- it 'should downcase the keys provided by the metadata updater' do
- server_port = create_test_server
- host = "localhost:#{server_port}"
- th = run_request_response(@sent_msg, @resp, @pass,
- k1: 'downcased-key-v1', k2: 'v2')
- update_md = proc do |md|
- md[:K1] = 'downcased-key-v1'
- md
- end
- stub = GRPC::ClientStub.new(host, @cq, update_metadata: update_md)
- expect(get_response(stub)).to eq(@resp)
- th.join
- end
-
it 'should send a request when configured using an override channel' do
server_port = create_test_server
alt_host = "localhost:#{server_port}"
@@ -241,20 +213,6 @@ describe 'ClientStub' do
th.join
end
- it 'should update the sent metadata with a provided metadata updater' do
- server_port = create_test_server
- host = "localhost:#{server_port}"
- th = run_client_streamer(@sent_msgs, @resp, @pass,
- k1: 'updated-v1', k2: 'v2')
- update_md = proc do |md|
- md[:k1] = 'updated-v1'
- md
- end
- stub = GRPC::ClientStub.new(host, @cq, update_metadata: update_md)
- expect(get_response(stub)).to eq(@resp)
- th.join
- end
-
it 'should raise an error if the status is not ok' do
server_port = create_test_server
host = "localhost:#{server_port}"
@@ -323,21 +281,6 @@ describe 'ClientStub' do
expect { e.collect { |r| r } }.to raise_error(GRPC::BadStatus)
th.join
end
-
- it 'should update the sent metadata with a provided metadata updater' do
- server_port = create_test_server
- host = "localhost:#{server_port}"
- th = run_server_streamer(@sent_msg, @replys, @pass,
- k1: 'updated-v1', k2: 'v2')
- update_md = proc do |md|
- md[:k1] = 'updated-v1'
- md
- end
- stub = GRPC::ClientStub.new(host, @cq, update_metadata: update_md)
- e = get_responses(stub)
- expect(e.collect { |r| r }).to eq(@replys)
- th.join
- end
end
describe 'without a call operation' do
diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb
index efe07f734e..d95a021311 100644
--- a/src/ruby/spec/generic/rpc_server_spec.rb
+++ b/src/ruby/spec/generic/rpc_server_spec.rb
@@ -422,25 +422,6 @@ describe GRPC::RpcServer do
t.join
end
- it 'should receive updated metadata', server: true do
- service = EchoService.new
- @srv.handle(service)
- t = Thread.new { @srv.run }
- @srv.wait_till_running
- req = EchoMsg.new
- client_opts[:update_metadata] = proc do |md|
- md[:k1] = 'updated-v1'
- md
- end
- stub = EchoStub.new(@host, **client_opts)
- expect(stub.an_rpc(req, k1: 'v1', k2: 'v2')).to be_a(EchoMsg)
- wanted_md = [{ 'k1' => 'updated-v1', 'k2' => 'v2',
- 'jwt_aud_uri' => "https://#{@host}/EchoService" }]
- check_md(wanted_md, service.received_md)
- @srv.stop
- t.join
- end
-
it 'should handle multiple parallel requests', server: true do
@srv.handle(EchoService)
t = Thread.new { @srv.run }