googleauth 0.9.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.kokoro/continuous/linux.cfg +12 -2
- data/.kokoro/continuous/osx.cfg +5 -0
- data/.kokoro/continuous/post.cfg +30 -0
- data/.kokoro/continuous/windows.cfg +10 -0
- data/.kokoro/presubmit/linux.cfg +11 -1
- data/.kokoro/presubmit/osx.cfg +5 -0
- data/.kokoro/presubmit/windows.cfg +10 -0
- data/.kokoro/release.cfg +42 -1
- data/.repo-metadata.json +5 -0
- data/.rubocop.yml +12 -35
- data/CHANGELOG.md +32 -0
- data/Gemfile +8 -3
- data/README.md +7 -11
- data/Rakefile +48 -5
- data/googleauth.gemspec +7 -4
- data/integration/helper.rb +31 -0
- data/integration/id_tokens/key_source_test.rb +74 -0
- data/lib/googleauth.rb +1 -0
- data/lib/googleauth/application_default.rb +9 -9
- data/lib/googleauth/compute_engine.rb +30 -27
- data/lib/googleauth/credentials.rb +92 -22
- data/lib/googleauth/credentials_loader.rb +14 -15
- data/lib/googleauth/id_tokens.rb +233 -0
- data/lib/googleauth/id_tokens/errors.rb +71 -0
- data/lib/googleauth/id_tokens/key_sources.rb +394 -0
- data/lib/googleauth/id_tokens/verifier.rb +144 -0
- data/lib/googleauth/json_key_reader.rb +6 -2
- data/lib/googleauth/service_account.rb +16 -7
- data/lib/googleauth/signet.rb +8 -6
- data/lib/googleauth/user_authorizer.rb +8 -3
- data/lib/googleauth/user_refresh.rb +1 -1
- data/lib/googleauth/version.rb +1 -1
- data/lib/googleauth/web_user_authorizer.rb +1 -1
- data/rakelib/devsite_builder.rb +45 -0
- data/rakelib/link_checker.rb +64 -0
- data/rakelib/repo_metadata.rb +59 -0
- data/spec/googleauth/apply_auth_examples.rb +28 -5
- data/spec/googleauth/compute_engine_spec.rb +37 -13
- data/spec/googleauth/credentials_spec.rb +25 -6
- data/spec/googleauth/service_account_spec.rb +23 -16
- data/spec/googleauth/signet_spec.rb +15 -7
- data/spec/googleauth/user_authorizer_spec.rb +21 -1
- data/spec/googleauth/user_refresh_spec.rb +1 -1
- data/test/helper.rb +33 -0
- data/test/id_tokens/key_sources_test.rb +240 -0
- data/test/id_tokens/verifier_test.rb +269 -0
- metadata +45 -12
data/googleauth.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
# encoding: utf-8
|
3
3
|
|
4
|
-
$LOAD_PATH.push File.expand_path("
|
4
|
+
$LOAD_PATH.push File.expand_path("lib", __dir__)
|
5
5
|
require "googleauth/version"
|
6
6
|
|
7
7
|
Gem::Specification.new do |gem|
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.version = Google::Auth::VERSION
|
10
10
|
gem.authors = ["Tim Emiola"]
|
11
11
|
gem.email = "temiola@google.com"
|
12
|
-
gem.homepage = "https://github.com/
|
12
|
+
gem.homepage = "https://github.com/googleapis/google-auth-library-ruby"
|
13
13
|
gem.summary = "Google Auth Library for Ruby"
|
14
14
|
gem.license = "Apache-2.0"
|
15
15
|
gem.description = <<-DESCRIPTION
|
@@ -25,11 +25,14 @@ Gem::Specification.new do |gem|
|
|
25
25
|
end
|
26
26
|
gem.require_paths = ["lib"]
|
27
27
|
gem.platform = Gem::Platform::RUBY
|
28
|
+
gem.required_ruby_version = ">= 2.4.0"
|
28
29
|
|
29
|
-
gem.add_dependency "faraday", "
|
30
|
+
gem.add_dependency "faraday", ">= 0.17.3", "< 2.0"
|
30
31
|
gem.add_dependency "jwt", ">= 1.4", "< 3.0"
|
31
32
|
gem.add_dependency "memoist", "~> 0.16"
|
32
33
|
gem.add_dependency "multi_json", "~> 1.11"
|
33
34
|
gem.add_dependency "os", ">= 0.9", "< 2.0"
|
34
|
-
gem.add_dependency "signet", "~> 0.
|
35
|
+
gem.add_dependency "signet", "~> 0.14"
|
36
|
+
|
37
|
+
gem.add_development_dependency "yard", "~> 0.9"
|
35
38
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Copyright 2020 Google LLC
|
2
|
+
#
|
3
|
+
# Redistribution and use in source and binary forms, with or without
|
4
|
+
# modification, are permitted provided that the following conditions are
|
5
|
+
# met:
|
6
|
+
#
|
7
|
+
# * Redistributions of source code must retain the above copyright
|
8
|
+
# notice, this list of conditions and the following disclaimer.
|
9
|
+
# * Redistributions in binary form must reproduce the above
|
10
|
+
# copyright notice, this list of conditions and the following disclaimer
|
11
|
+
# in the documentation and/or other materials provided with the
|
12
|
+
# distribution.
|
13
|
+
# * Neither the name of Google Inc. nor the names of its
|
14
|
+
# contributors may be used to endorse or promote products derived from
|
15
|
+
# this software without specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
18
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
19
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
20
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
21
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
22
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
23
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
24
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
25
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
26
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
|
29
|
+
require "minitest/autorun"
|
30
|
+
require "minitest/focus"
|
31
|
+
require "googleauth"
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Copyright 2020 Google LLC
|
2
|
+
#
|
3
|
+
# Redistribution and use in source and binary forms, with or without
|
4
|
+
# modification, are permitted provided that the following conditions are
|
5
|
+
# met:
|
6
|
+
#
|
7
|
+
# * Redistributions of source code must retain the above copyright
|
8
|
+
# notice, this list of conditions and the following disclaimer.
|
9
|
+
# * Redistributions in binary form must reproduce the above
|
10
|
+
# copyright notice, this list of conditions and the following disclaimer
|
11
|
+
# in the documentation and/or other materials provided with the
|
12
|
+
# distribution.
|
13
|
+
# * Neither the name of Google Inc. nor the names of its
|
14
|
+
# contributors may be used to endorse or promote products derived from
|
15
|
+
# this software without specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
18
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
19
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
20
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
21
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
22
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
23
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
24
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
25
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
26
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
|
29
|
+
require "helper"
|
30
|
+
|
31
|
+
describe Google::Auth::IDTokens do
|
32
|
+
describe "key source" do
|
33
|
+
let(:legacy_oidc_key_source) {
|
34
|
+
Google::Auth::IDTokens::X509CertHttpKeySource.new "https://www.googleapis.com/oauth2/v1/certs"
|
35
|
+
}
|
36
|
+
let(:oidc_key_source) { Google::Auth::IDTokens.oidc_key_source }
|
37
|
+
let(:iap_key_source) { Google::Auth::IDTokens.iap_key_source }
|
38
|
+
|
39
|
+
it "Gets real keys from the OAuth2 V1 cert URL" do
|
40
|
+
keys = legacy_oidc_key_source.refresh_keys
|
41
|
+
refute_empty keys
|
42
|
+
keys.each do |key|
|
43
|
+
assert_kind_of OpenSSL::PKey::RSA, key.key
|
44
|
+
refute key.key.private?
|
45
|
+
assert_equal "RS256", key.algorithm
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it "Gets real keys from the OAuth2 V3 cert URL" do
|
50
|
+
keys = oidc_key_source.refresh_keys
|
51
|
+
refute_empty keys
|
52
|
+
keys.each do |key|
|
53
|
+
assert_kind_of OpenSSL::PKey::RSA, key.key
|
54
|
+
refute key.key.private?
|
55
|
+
assert_equal "RS256", key.algorithm
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "Gets the same keys from the OAuth2 V1 and V3 cert URLs" do
|
60
|
+
keys_v1 = legacy_oidc_key_source.refresh_keys.map(&:key).map(&:export).sort
|
61
|
+
keys_v3 = oidc_key_source.refresh_keys.map(&:key).map(&:export).sort
|
62
|
+
assert_equal keys_v1, keys_v3
|
63
|
+
end
|
64
|
+
|
65
|
+
it "Gets real keys from the IAP public key URL" do
|
66
|
+
keys = iap_key_source.refresh_keys
|
67
|
+
refute_empty keys
|
68
|
+
keys.each do |key|
|
69
|
+
assert_kind_of OpenSSL::PKey::EC, key.key
|
70
|
+
assert_equal "ES256", key.algorithm
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/googleauth.rb
CHANGED
@@ -31,5 +31,6 @@ require "googleauth/application_default"
|
|
31
31
|
require "googleauth/client_id"
|
32
32
|
require "googleauth/credentials"
|
33
33
|
require "googleauth/default_credentials"
|
34
|
+
require "googleauth/id_tokens"
|
34
35
|
require "googleauth/user_authorizer"
|
35
36
|
require "googleauth/web_user_authorizer"
|
@@ -34,18 +34,20 @@ module Google
|
|
34
34
|
# Module Auth provides classes that provide Google-specific authorization
|
35
35
|
# used to access Google APIs.
|
36
36
|
module Auth
|
37
|
-
NOT_FOUND_ERROR =
|
38
|
-
Could not load the default credentials. Browse to
|
39
|
-
https://developers.google.com/accounts/docs/application-default-credentials
|
40
|
-
for more information
|
41
|
-
ERROR_MESSAGE
|
37
|
+
NOT_FOUND_ERROR = <<~ERROR_MESSAGE.freeze
|
38
|
+
Could not load the default credentials. Browse to
|
39
|
+
https://developers.google.com/accounts/docs/application-default-credentials
|
40
|
+
for more information
|
41
|
+
ERROR_MESSAGE
|
42
|
+
|
43
|
+
module_function
|
42
44
|
|
43
45
|
# Obtains the default credentials implementation to use in this
|
44
46
|
# environment.
|
45
47
|
#
|
46
48
|
# Use this to obtain the Application Default Credentials for accessing
|
47
49
|
# Google APIs. Application Default Credentials are described in detail
|
48
|
-
# at
|
50
|
+
# at https://cloud.google.com/docs/authentication/production.
|
49
51
|
#
|
50
52
|
# If supplied, scope is used to create the credentials instance, when it can
|
51
53
|
# be applied. E.g, on google compute engine and for user credentials the
|
@@ -73,9 +75,7 @@ ERROR_MESSAGE
|
|
73
75
|
GCECredentials.unmemoize_all
|
74
76
|
raise NOT_FOUND_ERROR
|
75
77
|
end
|
76
|
-
GCECredentials.new
|
78
|
+
GCECredentials.new scope: scope
|
77
79
|
end
|
78
|
-
|
79
|
-
module_function :get_application_default
|
80
80
|
end
|
81
81
|
end
|
@@ -35,46 +35,42 @@ module Google
|
|
35
35
|
# Module Auth provides classes that provide Google-specific authorization
|
36
36
|
# used to access Google APIs.
|
37
37
|
module Auth
|
38
|
-
NO_METADATA_SERVER_ERROR =
|
39
|
-
Error code 404 trying to get security access token
|
40
|
-
from Compute Engine metadata for the default service account. This
|
41
|
-
may be because the virtual machine instance does not have permission
|
42
|
-
scopes specified.
|
43
|
-
ERROR
|
44
|
-
UNEXPECTED_ERROR_SUFFIX =
|
45
|
-
trying to get security access token from Compute Engine metadata for
|
46
|
-
the default service account
|
47
|
-
ERROR
|
38
|
+
NO_METADATA_SERVER_ERROR = <<~ERROR.freeze
|
39
|
+
Error code 404 trying to get security access token
|
40
|
+
from Compute Engine metadata for the default service account. This
|
41
|
+
may be because the virtual machine instance does not have permission
|
42
|
+
scopes specified.
|
43
|
+
ERROR
|
44
|
+
UNEXPECTED_ERROR_SUFFIX = <<~ERROR.freeze
|
45
|
+
trying to get security access token from Compute Engine metadata for
|
46
|
+
the default service account
|
47
|
+
ERROR
|
48
48
|
|
49
49
|
# Extends Signet::OAuth2::Client so that the auth token is obtained from
|
50
50
|
# the GCE metadata server.
|
51
51
|
class GCECredentials < Signet::OAuth2::Client
|
52
52
|
# The IP Address is used in the URIs to speed up failures on non-GCE
|
53
53
|
# systems.
|
54
|
-
COMPUTE_AUTH_TOKEN_URI =
|
55
|
-
|
54
|
+
COMPUTE_AUTH_TOKEN_URI =
|
55
|
+
"http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token".freeze
|
56
|
+
COMPUTE_ID_TOKEN_URI =
|
57
|
+
"http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/identity".freeze
|
56
58
|
COMPUTE_CHECK_URI = "http://169.254.169.254".freeze
|
57
59
|
|
58
60
|
class << self
|
59
61
|
extend Memoist
|
60
62
|
|
61
63
|
# Detect if this appear to be a GCE instance, by checking if metadata
|
62
|
-
# is available
|
64
|
+
# is available.
|
63
65
|
def on_gce? options = {}
|
66
|
+
# TODO: This should use google-cloud-env instead.
|
64
67
|
c = options[:connection] || Faraday.default_connection
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
# issue is that resolving an unknown host on some networks will take
|
70
|
-
# 20-30 seconds; making this timeout short fixes the issue, but
|
71
|
-
# could lead to false negatives in the event that we are on GCE, but
|
72
|
-
# the metadata resolution was particularly slow. The latter case is
|
73
|
-
# "unlikely".
|
74
|
-
req.options.timeout = 0.1
|
68
|
+
headers = { "Metadata-Flavor" => "Google" }
|
69
|
+
resp = c.get COMPUTE_CHECK_URI, nil, headers do |req|
|
70
|
+
req.options.timeout = 1.0
|
71
|
+
req.options.open_timeout = 0.1
|
75
72
|
end
|
76
73
|
return false unless resp.status == 200
|
77
|
-
return false unless resp.headers.key? "Metadata-Flavor"
|
78
74
|
resp.headers["Metadata-Flavor"] == "Google"
|
79
75
|
rescue Faraday::TimeoutError, Faraday::ConnectionFailed
|
80
76
|
false
|
@@ -88,12 +84,19 @@ ERROR
|
|
88
84
|
def fetch_access_token options = {}
|
89
85
|
c = options[:connection] || Faraday.default_connection
|
90
86
|
retry_with_error do
|
87
|
+
uri = target_audience ? COMPUTE_ID_TOKEN_URI : COMPUTE_AUTH_TOKEN_URI
|
88
|
+
query = target_audience ? { "audience" => target_audience, "format" => "full" } : {}
|
89
|
+
query[:scopes] = Array(scope).join " " if scope
|
91
90
|
headers = { "Metadata-Flavor" => "Google" }
|
92
|
-
resp = c.get
|
91
|
+
resp = c.get uri, query, headers
|
93
92
|
case resp.status
|
94
93
|
when 200
|
95
|
-
|
96
|
-
|
94
|
+
content_type = resp.headers["content-type"]
|
95
|
+
if content_type == "text/html"
|
96
|
+
{ (target_audience ? "id_token" : "access_token") => resp.body }
|
97
|
+
else
|
98
|
+
Signet::OAuth2.parse_credentials resp.body, content_type
|
99
|
+
end
|
97
100
|
when 404
|
98
101
|
raise Signet::AuthorizationError, NO_METADATA_SERVER_ERROR
|
99
102
|
else
|
@@ -47,6 +47,8 @@ module Google
|
|
47
47
|
# The default target audience ID to be used when none is provided during initialization.
|
48
48
|
AUDIENCE = "https://oauth2.googleapis.com/token".freeze
|
49
49
|
|
50
|
+
@audience = @scope = @target_audience = @env_vars = @paths = nil
|
51
|
+
|
50
52
|
##
|
51
53
|
# The default token credential URI to be used when none is provided during initialization.
|
52
54
|
# The URI is the authorization server's HTTP endpoint capable of issuing tokens and
|
@@ -97,20 +99,25 @@ module Google
|
|
97
99
|
# A scope is an access range defined by the authorization server.
|
98
100
|
# The scope can be a single value or a list of values.
|
99
101
|
#
|
102
|
+
# Either {#scope} or {#target_audience}, but not both, should be non-nil.
|
103
|
+
# If {#scope} is set, this credential will produce access tokens.
|
104
|
+
# If {#target_audience} is set, this credential will produce ID tokens.
|
105
|
+
#
|
100
106
|
# @return [String, Array<String>]
|
101
107
|
#
|
102
108
|
def self.scope
|
103
109
|
return @scope unless @scope.nil?
|
104
110
|
|
105
|
-
|
106
|
-
# Pull in values is the SCOPE constant exists.
|
107
|
-
tmp_scope << const_get(:SCOPE) if const_defined? :SCOPE
|
108
|
-
tmp_scope.flatten.uniq
|
111
|
+
Array(const_get(:SCOPE)).flatten.uniq if const_defined? :SCOPE
|
109
112
|
end
|
110
113
|
|
111
114
|
##
|
112
115
|
# Sets the default scope to be used when none is provided during initialization.
|
113
116
|
#
|
117
|
+
# Either {#scope} or {#target_audience}, but not both, should be non-nil.
|
118
|
+
# If {#scope} is set, this credential will produce access tokens.
|
119
|
+
# If {#target_audience} is set, this credential will produce ID tokens.
|
120
|
+
#
|
114
121
|
# @param [String, Array<String>] new_scope
|
115
122
|
# @return [String, Array<String>]
|
116
123
|
#
|
@@ -119,6 +126,34 @@ module Google
|
|
119
126
|
@scope = new_scope
|
120
127
|
end
|
121
128
|
|
129
|
+
##
|
130
|
+
# The default final target audience for ID tokens, to be used when none
|
131
|
+
# is provided during initialization.
|
132
|
+
#
|
133
|
+
# Either {#scope} or {#target_audience}, but not both, should be non-nil.
|
134
|
+
# If {#scope} is set, this credential will produce access tokens.
|
135
|
+
# If {#target_audience} is set, this credential will produce ID tokens.
|
136
|
+
#
|
137
|
+
# @return [String]
|
138
|
+
#
|
139
|
+
def self.target_audience
|
140
|
+
@target_audience
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Sets the default final target audience for ID tokens, to be used when none
|
145
|
+
# is provided during initialization.
|
146
|
+
#
|
147
|
+
# Either {#scope} or {#target_audience}, but not both, should be non-nil.
|
148
|
+
# If {#scope} is set, this credential will produce access tokens.
|
149
|
+
# If {#target_audience} is set, this credential will produce ID tokens.
|
150
|
+
#
|
151
|
+
# @param [String] new_target_audience
|
152
|
+
#
|
153
|
+
def self.target_audience= new_target_audience
|
154
|
+
@target_audience = new_target_audience
|
155
|
+
end
|
156
|
+
|
122
157
|
##
|
123
158
|
# The environment variables to search for credentials. Values can either be a file path to the
|
124
159
|
# credentials file, or the JSON contents of the credentials file.
|
@@ -185,6 +220,13 @@ module Google
|
|
185
220
|
#
|
186
221
|
attr_reader :project_id
|
187
222
|
|
223
|
+
##
|
224
|
+
# Identifier for a separate project used for billing/quota, if any.
|
225
|
+
#
|
226
|
+
# @return [String,nil]
|
227
|
+
#
|
228
|
+
attr_reader :quota_project_id
|
229
|
+
|
188
230
|
# @private Delegate client methods to the client object.
|
189
231
|
extend Forwardable
|
190
232
|
|
@@ -201,6 +243,9 @@ module Google
|
|
201
243
|
# @return [String, Array<String>] The scope for this client. A scope is an access range
|
202
244
|
# defined by the authorization server. The scope can be a single value or a list of values.
|
203
245
|
#
|
246
|
+
# @!attribute [r] target_audience
|
247
|
+
# @return [String] The final target audience for ID tokens returned by this credential.
|
248
|
+
#
|
204
249
|
# @!attribute [r] issuer
|
205
250
|
# @return [String] The issuer ID associated with this client.
|
206
251
|
#
|
@@ -213,9 +258,7 @@ module Google
|
|
213
258
|
#
|
214
259
|
def_delegators :@client,
|
215
260
|
:token_credential_uri, :audience,
|
216
|
-
:scope, :issuer, :signing_key, :updater_proc
|
217
|
-
|
218
|
-
# rubocop:disable Metrics/AbcSize
|
261
|
+
:scope, :issuer, :signing_key, :updater_proc, :target_audience
|
219
262
|
|
220
263
|
##
|
221
264
|
# Creates a new Credentials instance with the provided auth credentials, and with the default
|
@@ -236,29 +279,23 @@ module Google
|
|
236
279
|
# * +:default_connection+ - the default connection to use for the client
|
237
280
|
#
|
238
281
|
def initialize keyfile, options = {}
|
239
|
-
scope = options[:scope]
|
240
282
|
verify_keyfile_provided! keyfile
|
241
283
|
@project_id = options["project_id"] || options["project"]
|
284
|
+
@quota_project_id = options["quota_project_id"]
|
242
285
|
if keyfile.is_a? Signet::OAuth2::Client
|
243
|
-
|
244
|
-
@project_id ||= keyfile.project_id if keyfile.respond_to? :project_id
|
286
|
+
update_from_signet keyfile
|
245
287
|
elsif keyfile.is_a? Hash
|
246
|
-
|
247
|
-
hash["scope"] ||= scope
|
248
|
-
@client = init_client hash, options
|
249
|
-
@project_id ||= (hash["project_id"] || hash["project"])
|
288
|
+
update_from_hash keyfile, options
|
250
289
|
else
|
251
|
-
|
252
|
-
json = JSON.parse ::File.read(keyfile)
|
253
|
-
json["scope"] ||= scope
|
254
|
-
@project_id ||= (json["project_id"] || json["project"])
|
255
|
-
@client = init_client json, options
|
290
|
+
update_from_filepath keyfile, options
|
256
291
|
end
|
257
292
|
CredentialsLoader.warn_if_cloud_sdk_credentials @client.client_id
|
258
293
|
@project_id ||= CredentialsLoader.load_gcloud_project_id
|
259
294
|
@client.fetch_access_token!
|
295
|
+
@env_vars = nil
|
296
|
+
@paths = nil
|
297
|
+
@scope = nil
|
260
298
|
end
|
261
|
-
# rubocop:enable Metrics/AbcSize
|
262
299
|
|
263
300
|
##
|
264
301
|
# Creates a new Credentials instance with auth credentials acquired by searching the
|
@@ -320,7 +357,8 @@ module Google
|
|
320
357
|
# @private Lookup Credentials using Google::Auth.get_application_default.
|
321
358
|
def self.from_application_default options
|
322
359
|
scope = options[:scope] || self.scope
|
323
|
-
|
360
|
+
auth_opts = { target_audience: options[:target_audience] || target_audience }
|
361
|
+
client = Google::Auth.get_application_default scope, auth_opts
|
324
362
|
new client, options
|
325
363
|
end
|
326
364
|
|
@@ -359,14 +397,46 @@ module Google
|
|
359
397
|
options["token_credential_uri"] ||= self.class.token_credential_uri
|
360
398
|
options["audience"] ||= self.class.audience
|
361
399
|
options["scope"] ||= self.class.scope
|
400
|
+
options["target_audience"] ||= self.class.target_audience
|
362
401
|
|
402
|
+
if !Array(options["scope"]).empty? && options["target_audience"]
|
403
|
+
raise ArgumentError, "Cannot specify both scope and target_audience"
|
404
|
+
end
|
405
|
+
|
406
|
+
needs_scope = options["target_audience"].nil?
|
363
407
|
# client options for initializing signet client
|
364
408
|
{ token_credential_uri: options["token_credential_uri"],
|
365
409
|
audience: options["audience"],
|
366
|
-
scope: Array(options["scope"]),
|
410
|
+
scope: (needs_scope ? Array(options["scope"]) : nil),
|
411
|
+
target_audience: options["target_audience"],
|
367
412
|
issuer: options["client_email"],
|
368
413
|
signing_key: OpenSSL::PKey::RSA.new(options["private_key"]) }
|
369
414
|
end
|
415
|
+
|
416
|
+
def update_from_signet client
|
417
|
+
@project_id ||= client.project_id if client.respond_to? :project_id
|
418
|
+
@quota_project_id ||= client.quota_project_id if client.respond_to? :quota_project_id
|
419
|
+
@client = client
|
420
|
+
end
|
421
|
+
|
422
|
+
def update_from_hash hash, options
|
423
|
+
hash = stringify_hash_keys hash
|
424
|
+
hash["scope"] ||= options[:scope]
|
425
|
+
hash["target_audience"] ||= options[:target_audience]
|
426
|
+
@project_id ||= (hash["project_id"] || hash["project"])
|
427
|
+
@quota_project_id ||= hash["quota_project_id"]
|
428
|
+
@client = init_client hash, options
|
429
|
+
end
|
430
|
+
|
431
|
+
def update_from_filepath path, options
|
432
|
+
verify_keyfile_exists! path
|
433
|
+
json = JSON.parse ::File.read(path)
|
434
|
+
json["scope"] ||= options[:scope]
|
435
|
+
json["target_audience"] ||= options[:target_audience]
|
436
|
+
@project_id ||= (json["project_id"] || json["project"])
|
437
|
+
@quota_project_id ||= json["quota_project_id"]
|
438
|
+
@client = init_client json, options
|
439
|
+
end
|
370
440
|
end
|
371
441
|
end
|
372
442
|
end
|