diff --git a/src/ruby/bin/apis/pubsub_demo.rb b/src/ruby/bin/apis/pubsub_demo.rb index 6656a561309..9bb324ff646 100755 --- a/src/ruby/bin/apis/pubsub_demo.rb +++ b/src/ruby/bin/apis/pubsub_demo.rb @@ -31,10 +31,9 @@ # pubsub_demo demos accesses the Google PubSub API via its gRPC interface # -# TODO: update the Usage once the usable auth gem is available -# $ SSL_CERT_FILE= \ +# $ GOOGLE_APPLICATION_CREDENTIALS= \ +# SSL_CERT_FILE= \ # path/to/pubsub_demo.rb \ -# --service_account_key_file= \ # [--action= ] # # There are options related to the chosen action, see #parse_args below. @@ -49,6 +48,7 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'optparse' require 'grpc' +require 'googleauth' require 'google/protobuf' require 'google/protobuf/empty' @@ -59,7 +59,9 @@ require 'tech/pubsub/proto/pubsub_services' def load_prod_cert fail 'could not find a production cert' if ENV['SSL_CERT_FILE'].nil? p "loading prod certs from #{ENV['SSL_CERT_FILE']}" - File.open(ENV['SSL_CERT_FILE']).read + File.open(ENV['SSL_CERT_FILE']) do |f| + return f.read + end end # creates a SSL Credentials from the production certificates. @@ -68,14 +70,9 @@ def ssl_creds end # Builds the metadata authentication update proc. -# -# TODO: replace this once the ruby usable auth repo is available. def auth_proc(opts) - if GRPC::Auth::GCECredentials.on_gce? - return GRPC::Auth::GCECredentials.new.updater_proc - end - fd = StringIO.new(File.read(opts.oauth_key_file)) - GRPC::Auth::ServiceAccountCredentials.new(opts.oauth_scope, fd).updater_proc + auth_creds = Google::Auth.get_application_default(opts.oauth_scope) + return auth_creds.updater_proc end # Creates a stub for accessing the publisher service. @@ -216,14 +213,14 @@ class NamedActions end # Args is used to hold the command line info. -Args = Struct.new(:host, :oauth_scope, :oauth_key_file, :port, :action, - :project_id, :topic_name, :sub_name) +Args = Struct.new(:host, :oauth_scope, :port, :action, :project_id, :topic_name, + :sub_name) # validates the the command line options, returning them as an Arg. def parse_args args = Args.new('pubsub-staging.googleapis.com', 'https://www.googleapis.com/auth/pubsub', - nil, 443, 'list_some_topics', 'stoked-keyword-656') + 443, 'list_some_topics', 'stoked-keyword-656') OptionParser.new do |opts| opts.on('--oauth_scope scope', 'Scope for OAuth tokens') { |v| args['oauth_scope'] = v } @@ -233,10 +230,6 @@ def parse_args opts.on('--server_port SERVER_PORT', 'server port') do |v| args.port = v end - opts.on('--service_account_key_file PATH', - 'Path to the service account json key file') do |v| - args.oauth_key_file = v - end # instance_methods(false) gives only the methods defined in that class. scenes = NamedActions.instance_methods(false).map { |t| t.to_s } @@ -257,15 +250,11 @@ def parse_args end def _check_args(args) - %w(host port action).each do |a| + %w(host port action oauth_scope).each do |a| if args[a].nil? raise OptionParser::MissingArgument.new("please specify --#{a}") end end - if args['oauth_key_file'].nil? || args['oauth_scope'].nil? - fail(OptionParser::MissingArgument, - 'please specify both of --service_account_key_file and --oauth_scope') - end args end diff --git a/src/ruby/bin/interop/interop_client.rb b/src/ruby/bin/interop/interop_client.rb index 380ceb11df0..b0b24b949f2 100755 --- a/src/ruby/bin/interop/interop_client.rb +++ b/src/ruby/bin/interop/interop_client.rb @@ -48,6 +48,7 @@ require 'minitest' require 'minitest/assertions' require 'grpc' +require 'googleauth' require 'google/protobuf' require 'test/cpp/interop/test_services' @@ -56,7 +57,7 @@ require 'test/cpp/interop/empty' require 'signet/ssl_config' -include GRPC::Auth +AUTH_ENV = Google::Auth::ServiceAccountCredentials::ENV_VAR # loads the certificates used to access the test server securely. def load_test_certs @@ -101,22 +102,14 @@ def create_stub(opts) } # Add service account creds if specified - if %w(all service_account_creds).include?(opts.test_case) + wants_creds = %w(all compute_engine_creds service_account_creds) + if wants_creds.include?(opts.test_case) unless opts.oauth_scope.nil? - fd = StringIO.new(File.read(opts.oauth_key_file)) - logger.info("loading oauth certs from #{opts.oauth_key_file}") - auth_creds = ServiceAccountCredentials.new(opts.oauth_scope, fd) + auth_creds = Google::Auth.get_application_default(opts.oauth_scope) stub_opts[:update_metadata] = auth_creds.updater_proc end end - # Add compute engine creds if specified - if %w(all compute_engine_creds).include?(opts.test_case) - unless opts.oauth_scope.nil? - stub_opts[:update_metadata] = GCECredentials.new.update_proc - end - end - logger.info("... connecting securely to #{address}") Grpc::Testing::TestService::Stub.new(address, **stub_opts) else @@ -193,11 +186,11 @@ class NamedTests def service_account_creds # ignore this test if the oauth options are not set - if @args.oauth_scope.nil? || @args.oauth_key_file.nil? + if @args.oauth_scope.nil? p 'NOT RUN: service_account_creds; no service_account settings' return end - json_key = File.read(@args.oauth_key_file) + json_key = File.read(ENV[AUTH_ENV]) wanted_email = MultiJson.load(json_key)['client_email'] resp = perform_large_unary(fill_username: true, fill_oauth_scope: true) @@ -285,7 +278,7 @@ end # Args is used to hold the command line info. Args = Struct.new(:default_service_account, :host, :host_override, - :oauth_scope, :oauth_key_file, :port, :secure, :test_case, + :oauth_scope, :port, :secure, :test_case, :use_test_ca) # validates the the command line options, returning them as a Hash. @@ -302,10 +295,6 @@ def parse_args 'email address of the default service account') do |v| args['default_service_account'] = v end - opts.on('--service_account_key_file PATH', - 'Path to the service account json key file') do |v| - args['oauth_key_file'] = v - end opts.on('--server_host_override HOST_OVERRIDE', 'override host via a HTTP header') do |v| args['host_override'] = v @@ -333,10 +322,6 @@ def _check_args(args) fail(OptionParser::MissingArgument, "please specify --#{arg}") end end - if args['oauth_key_file'].nil? ^ args['oauth_scope'].nil? - fail(OptionParser::MissingArgument, - 'please specify both of --service_account_key_file and --oauth_scope') - end args end diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec index bc59c234e5a..25a3ff5ce27 100755 --- a/src/ruby/grpc.gemspec +++ b/src/ruby/grpc.gemspec @@ -22,6 +22,7 @@ Gem::Specification.new do |s| s.add_dependency 'faraday', '~> 0.9' s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1' + s.add_dependency 'googleauth', '~> 0.1' s.add_dependency 'logging', '~> 1.8' s.add_dependency 'jwt', '~> 1.2.1' s.add_dependency 'minitest', '~> 5.4' # reqd for interop tests diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb index a2a609f59ee..dd02ef7666a 100644 --- a/src/ruby/lib/grpc.rb +++ b/src/ruby/lib/grpc.rb @@ -27,8 +27,6 @@ # (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/auth/compute_engine.rb' -require 'grpc/auth/service_account.rb' require 'grpc/errors' require 'grpc/grpc' require 'grpc/logconfig' diff --git a/src/ruby/lib/grpc/auth/compute_engine.rb b/src/ruby/lib/grpc/auth/compute_engine.rb deleted file mode 100644 index 5cb1e1a4dcf..00000000000 --- a/src/ruby/lib/grpc/auth/compute_engine.rb +++ /dev/null @@ -1,67 +0,0 @@ -# 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 'faraday' -require 'grpc/auth/signet' - -module GRPC - # Module Auth provides classes that provide Google-specific authentication - # used to access Google gRPC services. - module Auth - # Extends Signet::OAuth2::Client so that the auth token is obtained from - # the GCE metadata server. - class GCECredentials < Signet::OAuth2::Client - COMPUTE_AUTH_TOKEN_URI = 'http://metadata/computeMetadata/v1/'\ - 'instance/service-accounts/default/token' - COMPUTE_CHECK_URI = 'http://metadata.google.internal' - - # Detect if this appear to be a GCE instance, by checking if metadata - # is available - def self.on_gce?(options = {}) - c = options[:connection] || Faraday.default_connection - resp = c.get(COMPUTE_CHECK_URI) - return false unless resp.status == 200 - return false unless resp.headers.key?('Metadata-Flavor') - return resp.headers['Metadata-Flavor'] == 'Google' - rescue Faraday::ConnectionFailed - return false - end - - # Overrides the super class method to change how access tokens are - # fetched. - def fetch_access_token(options = {}) - c = options[:connection] || Faraday.default_connection - c.headers = { 'Metadata-Flavor' => 'Google' } - resp = c.get(COMPUTE_AUTH_TOKEN_URI) - Signet::OAuth2.parse_credentials(resp.body, - resp.headers['content-type']) - end - end - end -end diff --git a/src/ruby/lib/grpc/auth/service_account.rb b/src/ruby/lib/grpc/auth/service_account.rb deleted file mode 100644 index 14b81a9e034..00000000000 --- a/src/ruby/lib/grpc/auth/service_account.rb +++ /dev/null @@ -1,66 +0,0 @@ -# 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/auth/signet' -require 'multi_json' -require 'openssl' - -# Reads the private key and client email fields from service account JSON key. -def read_json_key(json_key_io) - json_key = MultiJson.load(json_key_io.read) - fail 'missing client_email' unless json_key.key?('client_email') - fail 'missing private_key' unless json_key.key?('private_key') - [json_key['private_key'], json_key['client_email']] -end - -module GRPC - # Module Auth provides classes that provide Google-specific authentication - # used to access Google gRPC services. - module Auth - # Authenticates requests using Google's Service Account credentials. - # (cf https://developers.google.com/accounts/docs/OAuth2ServiceAccount) - class ServiceAccountCredentials < Signet::OAuth2::Client - TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v3/token' - AUDIENCE = TOKEN_CRED_URI - - # Initializes a ServiceAccountCredentials. - # - # @param scope [string|array] the scope(s) to access - # @param json_key_io [IO] an IO from which the JSON key can be read - def initialize(scope, json_key_io) - private_key, client_email = read_json_key(json_key_io) - super(token_credential_uri: TOKEN_CRED_URI, - audience: AUDIENCE, - scope: scope, - issuer: client_email, - signing_key: OpenSSL::PKey::RSA.new(private_key)) - end - end - end -end diff --git a/src/ruby/lib/grpc/auth/signet.rb b/src/ruby/lib/grpc/auth/signet.rb deleted file mode 100644 index a8bce1255c2..00000000000 --- a/src/ruby/lib/grpc/auth/signet.rb +++ /dev/null @@ -1,67 +0,0 @@ -# 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 'signet/oauth_2/client' - -module Signet - # Signet::OAuth2 supports OAuth2 authentication. - module OAuth2 - AUTH_METADATA_KEY = :Authorization - # Signet::OAuth2::Client creates an OAuth2 client - # - # Here client is re-opened to add the #apply and #apply! methods which - # update a hash map with the fetched authentication token - # - # Eventually, this change may be merged into signet itself, or some other - # package that provides Google-specific auth via signet, and this extension - # will be unnecessary. - class Client - # Updates a_hash updated with the authentication token - def apply!(a_hash, opts = {}) - # fetch the access token there is currently not one, or if the client - # has expired - fetch_access_token!(opts) if access_token.nil? || expired? - a_hash[AUTH_METADATA_KEY] = "Bearer #{access_token}" - end - - # Returns a clone of a_hash updated with the authentication token - def apply(a_hash, opts = {}) - a_copy = a_hash.clone - apply!(a_copy, opts) - a_copy - end - - # Returns a reference to the #apply method, suitable for passing as - # a closure - def updater_proc - lambda(&method(:apply)) - end - end - end -end diff --git a/src/ruby/spec/auth/apply_auth_examples.rb b/src/ruby/spec/auth/apply_auth_examples.rb deleted file mode 100644 index 09b393026f0..00000000000 --- a/src/ruby/spec/auth/apply_auth_examples.rb +++ /dev/null @@ -1,163 +0,0 @@ -# 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. - -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) -$LOAD_PATH.uniq! - -require 'faraday' -require 'spec_helper' - -def build_json_response(payload) - [200, - { 'Content-Type' => 'application/json; charset=utf-8' }, - MultiJson.dump(payload)] -end - -WANTED_AUTH_KEY = :Authorization - -shared_examples 'apply/apply! are OK' do - # tests that use these examples need to define - # - # @client which should be an auth client - # - # @make_auth_stubs, which should stub out the expected http behaviour of the - # auth client - describe '#fetch_access_token' do - it 'should set access_token to the fetched value' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - @client.fetch_access_token!(connection: c) - expect(@client.access_token).to eq(token) - stubs.verify_stubbed_calls - end - end - - describe '#apply!' do - it 'should update the target hash with fetched access token' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - md = { foo: 'bar' } - @client.apply!(md, connection: c) - want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" } - expect(md).to eq(want) - stubs.verify_stubbed_calls - end - end - - describe 'updater_proc' do - it 'should provide a proc that updates a hash with the access token' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - md = { foo: 'bar' } - the_proc = @client.updater_proc - got = the_proc.call(md, connection: c) - want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" } - expect(got).to eq(want) - stubs.verify_stubbed_calls - end - end - - describe '#apply' do - it 'should not update the original hash with the access token' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - md = { foo: 'bar' } - @client.apply(md, connection: c) - want = { foo: 'bar' } - expect(md).to eq(want) - stubs.verify_stubbed_calls - end - - it 'should add the token to the returned hash' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - md = { foo: 'bar' } - got = @client.apply(md, connection: c) - want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" } - expect(got).to eq(want) - stubs.verify_stubbed_calls - end - - it 'should not fetch a new token if the current is not expired' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - n = 5 # arbitrary - n.times do |_t| - md = { foo: 'bar' } - got = @client.apply(md, connection: c) - want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" } - expect(got).to eq(want) - end - stubs.verify_stubbed_calls - end - - it 'should fetch a new token if the current one is expired' do - token_1 = '1/abcdef1234567890' - token_2 = '2/abcdef1234567890' - - [token_1, token_2].each do |t| - stubs = make_auth_stubs with_access_token: t - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - md = { foo: 'bar' } - got = @client.apply(md, connection: c) - want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{t}" } - expect(got).to eq(want) - stubs.verify_stubbed_calls - @client.expires_at -= 3601 # default is to expire in 1hr - end - end - end -end diff --git a/src/ruby/spec/auth/compute_engine_spec.rb b/src/ruby/spec/auth/compute_engine_spec.rb deleted file mode 100644 index c43214d0861..00000000000 --- a/src/ruby/spec/auth/compute_engine_spec.rb +++ /dev/null @@ -1,108 +0,0 @@ -# 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. - -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) -$LOAD_PATH.uniq! - -require 'apply_auth_examples' -require 'faraday' -require 'grpc/auth/compute_engine' -require 'spec_helper' - -describe GRPC::Auth::GCECredentials do - MD_URI = '/computeMetadata/v1/instance/service-accounts/default/token' - GCECredentials = GRPC::Auth::GCECredentials - - before(:example) do - @client = GCECredentials.new - end - - def make_auth_stubs(with_access_token: '') - Faraday::Adapter::Test::Stubs.new do |stub| - stub.get(MD_URI) do |env| - headers = env[:request_headers] - expect(headers['Metadata-Flavor']).to eq('Google') - build_json_response( - 'access_token' => with_access_token, - 'token_type' => 'Bearer', - 'expires_in' => 3600) - end - end - end - - it_behaves_like 'apply/apply! are OK' - - describe '#on_gce?' do - it 'should be true when Metadata-Flavor is Google' do - stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/') do |_env| - [200, - { 'Metadata-Flavor' => 'Google' }, - ''] - end - end - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - expect(GCECredentials.on_gce?(connection: c)).to eq(true) - stubs.verify_stubbed_calls - end - - it 'should be false when Metadata-Flavor is not Google' do - stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/') do |_env| - [200, - { 'Metadata-Flavor' => 'NotGoogle' }, - ''] - end - end - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - expect(GCECredentials.on_gce?(connection: c)).to eq(false) - stubs.verify_stubbed_calls - end - - it 'should be false if the response is not 200' do - stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/') do |_env| - [404, - { 'Metadata-Flavor' => 'Google' }, - ''] - end - end - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - expect(GCECredentials.on_gce?(connection: c)).to eq(false) - stubs.verify_stubbed_calls - end - end -end diff --git a/src/ruby/spec/auth/service_account_spec.rb b/src/ruby/spec/auth/service_account_spec.rb deleted file mode 100644 index 2f14a1ae053..00000000000 --- a/src/ruby/spec/auth/service_account_spec.rb +++ /dev/null @@ -1,75 +0,0 @@ -# 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. - -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) -$LOAD_PATH.uniq! - -require 'apply_auth_examples' -require 'grpc/auth/service_account' -require 'jwt' -require 'multi_json' -require 'openssl' -require 'spec_helper' - -describe GRPC::Auth::ServiceAccountCredentials do - before(:example) do - @key = OpenSSL::PKey::RSA.new(2048) - cred_json = { - private_key_id: 'a_private_key_id', - private_key: @key.to_pem, - client_email: 'app@developer.gserviceaccount.com', - client_id: 'app.apps.googleusercontent.com', - type: 'service_account' - } - cred_json_text = MultiJson.dump(cred_json) - @client = GRPC::Auth::ServiceAccountCredentials.new( - 'https://www.googleapis.com/auth/userinfo.profile', - StringIO.new(cred_json_text)) - end - - def make_auth_stubs(with_access_token: '') - Faraday::Adapter::Test::Stubs.new do |stub| - stub.post('/oauth2/v3/token') do |env| - params = Addressable::URI.form_unencode(env[:body]) - _claim, _header = JWT.decode(params.assoc('assertion').last, - @key.public_key) - want = ['grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer'] - expect(params.assoc('grant_type')).to eq(want) - build_json_response( - 'access_token' => with_access_token, - 'token_type' => 'Bearer', - 'expires_in' => 3600 - ) - end - end - end - - it_behaves_like 'apply/apply! are OK' -end diff --git a/src/ruby/spec/auth/signet_spec.rb b/src/ruby/spec/auth/signet_spec.rb deleted file mode 100644 index 1712edf2961..00000000000 --- a/src/ruby/spec/auth/signet_spec.rb +++ /dev/null @@ -1,70 +0,0 @@ -# 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. - -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) -$LOAD_PATH.uniq! - -require 'apply_auth_examples' -require 'grpc/auth/signet' -require 'jwt' -require 'openssl' -require 'spec_helper' - -describe Signet::OAuth2::Client do - before(:example) do - @key = OpenSSL::PKey::RSA.new(2048) - @client = Signet::OAuth2::Client.new( - token_credential_uri: 'https://accounts.google.com/o/oauth2/token', - scope: 'https://www.googleapis.com/auth/userinfo.profile', - issuer: 'app@example.com', - audience: 'https://accounts.google.com/o/oauth2/token', - signing_key: @key - ) - end - - def make_auth_stubs(with_access_token: '') - Faraday::Adapter::Test::Stubs.new do |stub| - stub.post('/o/oauth2/token') do |env| - params = Addressable::URI.form_unencode(env[:body]) - _claim, _header = JWT.decode(params.assoc('assertion').last, - @key.public_key) - want = ['grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer'] - expect(params.assoc('grant_type')).to eq(want) - build_json_response( - 'access_token' => with_access_token, - 'token_type' => 'Bearer', - 'expires_in' => 3600 - ) - end - end - end - - it_behaves_like 'apply/apply! are OK' -end diff --git a/tools/gce_setup/grpc_docker.sh b/tools/gce_setup/grpc_docker.sh index 231625efb3a..f6b8d8c2f5c 100755 --- a/tools/gce_setup/grpc_docker.sh +++ b/tools/gce_setup/grpc_docker.sh @@ -957,9 +957,10 @@ grpc_cloud_prod_auth_service_account_creds_gen_ruby_cmd() { local test_script="/var/local/git/grpc/src/ruby/bin/interop/interop_client.rb" local test_script+=" --use_tls" local gfe_flags=$(_grpc_prod_gfe_flags) - local added_gfe_flags=$(_grpc_svc_acc_test_flags) + local added_gfe_flags=$(_grpc_default_creds_test_flags) local env_prefix="SSL_CERT_FILE=/cacerts/roots.pem" - local the_cmd="$cmd_prefix '$env_prefix ruby $test_script $gfe_flags $added_gfe_flag $@'" + env_prefix+=" GOOGLE_APPLICATION_CREDENTIALS=/service_account/stubbyCloudTestingTest-7dd63462c60c.json" + local the_cmd="$cmd_prefix '$env_prefix ruby $test_script $gfe_flags $added_gfe_flags $@'" echo $the_cmd } @@ -975,7 +976,7 @@ grpc_cloud_prod_auth_compute_engine_creds_gen_ruby_cmd() { local gfe_flags=$(_grpc_prod_gfe_flags) local added_gfe_flags=$(_grpc_gce_test_flags) local env_prefix="SSL_CERT_FILE=/cacerts/roots.pem" - local the_cmd="$cmd_prefix '$env_prefix ruby $test_script $gfe_flags $added_gfe_flag $@'" + local the_cmd="$cmd_prefix '$env_prefix ruby $test_script $gfe_flags $added_gfe_flags $@'" echo $the_cmd } @@ -1153,6 +1154,11 @@ _grpc_svc_acc_test_flags() { echo " --service_account_key_file=/service_account/stubbyCloudTestingTest-7dd63462c60c.json --oauth_scope=https://www.googleapis.com/auth/xapi.zoo" } +# default credentials test flag +_grpc_default_creds_test_flags() { + echo " --oauth_scope=https://www.googleapis.com/auth/xapi.zoo" +} + # outputs the flags passed to the gcloud auth tests _grpc_gce_test_flags() { echo " --default_service_account=155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel@developer.gserviceaccount.com --oauth_scope=https://www.googleapis.com/auth/xapi.zoo"