googleauth 1.11.2 → 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/googleauth/base_client.rb +11 -1
- data/lib/googleauth/compute_engine.rb +47 -11
- data/lib/googleauth/credentials.rb +32 -10
- data/lib/googleauth/external_account/base_credentials.rb +33 -2
- data/lib/googleauth/id_tokens.rb +0 -2
- data/lib/googleauth/service_account.rb +12 -1
- data/lib/googleauth/signet.rb +68 -2
- data/lib/googleauth/version.rb +1 -1
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f0abc7ed9fc9deefc0b45abbd3b66d6b4a5aa859774f652e2b8c8c8ff12ff77
|
4
|
+
data.tar.gz: c8a2ab192e92bf610f96044c04d5e02ad138dd99f2a1311d14d4e029639b210e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17bde72c9466591719a1f069875242a6abbfa9533fef63d5c9d696c16227d68ac2fd053d63f9d46588cb23c38841eb04a27953a38bbd63c2bc8f8f02709f684c
|
7
|
+
data.tar.gz: 4e4c81aad747f3beb7fd610e836ef871e5fa03a2ab7e9b6c2b223cd48e5e891976e736ad90539a493de8ce2805c692667bf3f11162ecb8646ba7a59be82eface
|
data/CHANGELOG.md
CHANGED
@@ -12,6 +12,8 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
require "google/logging/message"
|
16
|
+
|
15
17
|
module Google
|
16
18
|
# Module Auth provides classes that provide Google-specific authorization
|
17
19
|
# used to access Google APIs.
|
@@ -29,7 +31,12 @@ module Google
|
|
29
31
|
# fetch the access token there is currently not one, or if the client
|
30
32
|
# has expired
|
31
33
|
fetch_access_token! opts if needs_access_token?
|
32
|
-
|
34
|
+
token = send token_type
|
35
|
+
a_hash[AUTH_METADATA_KEY] = "Bearer #{token}"
|
36
|
+
logger&.debug do
|
37
|
+
hash = Digest::SHA256.hexdigest token
|
38
|
+
Google::Logging::Message.from message: "Sending auth token. (sha256:#{hash})"
|
39
|
+
end
|
33
40
|
end
|
34
41
|
|
35
42
|
# Returns a clone of a_hash updated with the authentication token
|
@@ -66,6 +73,9 @@ module Google
|
|
66
73
|
raise NoMethodError, "expires_within? not implemented"
|
67
74
|
end
|
68
75
|
|
76
|
+
# The logger used to log operations on this client, such as token refresh.
|
77
|
+
attr_accessor :logger
|
78
|
+
|
69
79
|
private
|
70
80
|
|
71
81
|
def token_type
|
@@ -96,35 +96,71 @@ module Google
|
|
96
96
|
# Overrides the super class method to change how access tokens are
|
97
97
|
# fetched.
|
98
98
|
def fetch_access_token _options = {}
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
99
|
+
query, entry =
|
100
|
+
if token_type == :id_token
|
101
|
+
[{ "audience" => target_audience, "format" => "full" }, "service-accounts/default/identity"]
|
102
|
+
else
|
103
|
+
[{}, "service-accounts/default/token"]
|
104
|
+
end
|
106
105
|
query[:scopes] = Array(scope).join "," if scope
|
107
106
|
begin
|
107
|
+
log_fetch_query
|
108
108
|
resp = Google::Cloud.env.lookup_metadata_response "instance", entry, query: query
|
109
|
+
log_fetch_resp resp
|
109
110
|
case resp.status
|
110
111
|
when 200
|
111
112
|
build_token_hash resp.body, resp.headers["content-type"], resp.retrieval_monotonic_time
|
112
113
|
when 403, 500
|
113
|
-
|
114
|
-
raise Signet::UnexpectedStatusError, msg
|
114
|
+
raise Signet::UnexpectedStatusError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
|
115
115
|
when 404
|
116
116
|
raise Signet::AuthorizationError, NO_METADATA_SERVER_ERROR
|
117
117
|
else
|
118
|
-
|
119
|
-
raise Signet::AuthorizationError, msg
|
118
|
+
raise Signet::AuthorizationError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
|
120
119
|
end
|
121
120
|
rescue Google::Cloud::Env::MetadataServerNotResponding => e
|
121
|
+
log_fetch_err e
|
122
122
|
raise Signet::AuthorizationError, e.message
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
126
|
private
|
127
127
|
|
128
|
+
def log_fetch_query
|
129
|
+
if token_type == :id_token
|
130
|
+
logger&.info do
|
131
|
+
Google::Logging::Message.from(
|
132
|
+
message: "Requesting id token from MDS with aud=#{target_audience}",
|
133
|
+
"credentialsId" => object_id
|
134
|
+
)
|
135
|
+
end
|
136
|
+
else
|
137
|
+
logger&.info do
|
138
|
+
Google::Logging::Message.from(
|
139
|
+
message: "Requesting access token from MDS",
|
140
|
+
"credentialsId" => object_id
|
141
|
+
)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def log_fetch_resp resp
|
147
|
+
logger&.info do
|
148
|
+
Google::Logging::Message.from(
|
149
|
+
message: "Received #{resp.status} from MDS",
|
150
|
+
"credentialsId" => object_id
|
151
|
+
)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def log_fetch_err _err
|
156
|
+
logger&.info do
|
157
|
+
Google::Logging::Message.from(
|
158
|
+
message: "MDS did not respond to token request",
|
159
|
+
"credentialsId" => object_id
|
160
|
+
)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
128
164
|
def build_token_hash body, content_type, retrieval_time
|
129
165
|
hash =
|
130
166
|
if ["text/html", "application/text"].include? content_type
|
@@ -337,10 +337,13 @@ module Google
|
|
337
337
|
# @!attribute [rw] universe_domain
|
338
338
|
# @return [String] The universe domain issuing these credentials.
|
339
339
|
#
|
340
|
+
# @!attribute [rw] logger
|
341
|
+
# @return [Logger] The logger used to log credential operations such as token refresh.
|
342
|
+
#
|
340
343
|
def_delegators :@client,
|
341
344
|
:token_credential_uri, :audience,
|
342
345
|
:scope, :issuer, :signing_key, :updater_proc, :target_audience,
|
343
|
-
:universe_domain, :universe_domain=
|
346
|
+
:universe_domain, :universe_domain=, :logger, :logger=
|
344
347
|
|
345
348
|
##
|
346
349
|
# Creates a new Credentials instance with the provided auth credentials, and with the default
|
@@ -349,16 +352,17 @@ module Google
|
|
349
352
|
# @param [String, Hash, Signet::OAuth2::Client] keyfile
|
350
353
|
# The keyfile can be provided as one of the following:
|
351
354
|
#
|
352
|
-
# * The path to a JSON keyfile (as a
|
353
|
-
# * The contents of a JSON keyfile (as a
|
354
|
-
# * A
|
355
|
+
# * The path to a JSON keyfile (as a `String`)
|
356
|
+
# * The contents of a JSON keyfile (as a `Hash`)
|
357
|
+
# * A `Signet::OAuth2::Client` object
|
355
358
|
# @param [Hash] options
|
356
359
|
# The options for configuring the credentials instance. The following is supported:
|
357
360
|
#
|
358
|
-
# *
|
359
|
-
# *
|
360
|
-
# *
|
361
|
-
# *
|
361
|
+
# * `:scope` - the scope for the client
|
362
|
+
# * `project_id` (and optionally `project`) - the project identifier for the client
|
363
|
+
# * `:connection_builder` - the connection builder to use for the client
|
364
|
+
# * `:default_connection` - the default connection to use for the client
|
365
|
+
# * `:logger` - the logger used to log credential operations such as token refresh.
|
362
366
|
#
|
363
367
|
def initialize keyfile, options = {}
|
364
368
|
verify_keyfile_provided! keyfile
|
@@ -373,8 +377,8 @@ module Google
|
|
373
377
|
else
|
374
378
|
update_from_filepath keyfile, options
|
375
379
|
end
|
380
|
+
setup_logging logger: options.fetch(:logger, :default)
|
376
381
|
@project_id ||= CredentialsLoader.load_gcloud_project_id
|
377
|
-
@client.fetch_access_token! if @client.needs_access_token?
|
378
382
|
@env_vars = nil
|
379
383
|
@paths = nil
|
380
384
|
@scope = nil
|
@@ -468,7 +472,8 @@ module Google
|
|
468
472
|
audience: options[:audience] || audience
|
469
473
|
}
|
470
474
|
client = Google::Auth::DefaultCredentials.make_creds creds_input
|
471
|
-
|
475
|
+
options = options.select { |k, _v| k == :logger }
|
476
|
+
new client, options
|
472
477
|
end
|
473
478
|
|
474
479
|
private_class_method :from_env_vars,
|
@@ -549,6 +554,23 @@ module Google
|
|
549
554
|
@quota_project_id ||= json["quota_project_id"]
|
550
555
|
@client = init_client json, options
|
551
556
|
end
|
557
|
+
|
558
|
+
def setup_logging logger: :default
|
559
|
+
return unless @client.respond_to? :logger=
|
560
|
+
logging_env = ENV["GOOGLE_SDK_RUBY_LOGGING_GEMS"].to_s.downcase
|
561
|
+
if ["false", "none"].include? logging_env
|
562
|
+
logger = nil
|
563
|
+
elsif @client.logger
|
564
|
+
logger = @client.logger
|
565
|
+
elsif logger == :default
|
566
|
+
logger = nil
|
567
|
+
if ["true", "all"].include?(logging_env) || logging_env.split(",").include?("googleauth")
|
568
|
+
formatter = Google::Logging::StructuredFormatter.new if Google::Cloud::Env.get.logging_agent_expected?
|
569
|
+
logger = Logger.new $stderr, progname: "googleauth", formatter: formatter
|
570
|
+
end
|
571
|
+
end
|
572
|
+
@client.logger = logger
|
573
|
+
end
|
552
574
|
end
|
553
575
|
end
|
554
576
|
end
|
@@ -129,7 +129,7 @@ module Google
|
|
129
129
|
if @client_id.nil? && @workforce_pool_user_project
|
130
130
|
additional_options = { userProject: @workforce_pool_user_project }
|
131
131
|
end
|
132
|
-
|
132
|
+
token_request = {
|
133
133
|
audience: @audience,
|
134
134
|
grant_type: STS_GRANT_TYPE,
|
135
135
|
subject_token: retrieve_subject_token!,
|
@@ -137,10 +137,31 @@ module Google
|
|
137
137
|
scopes: @service_account_impersonation_url ? IAM_SCOPE : @scope,
|
138
138
|
requested_token_type: STS_REQUESTED_TOKEN_TYPE,
|
139
139
|
additional_options: additional_options
|
140
|
-
|
140
|
+
}
|
141
|
+
log_token_request token_request
|
142
|
+
@sts_client.exchange_token token_request
|
143
|
+
end
|
144
|
+
|
145
|
+
def log_token_request token_request
|
146
|
+
logger&.info do
|
147
|
+
Google::Logging::Message.from(
|
148
|
+
message: "Requesting access token from #{token_request[:grant_type]}",
|
149
|
+
"credentialsId" => object_id
|
150
|
+
)
|
151
|
+
end
|
152
|
+
logger&.debug do
|
153
|
+
digest = Digest::SHA256.hexdigest token_request[:subject_token].to_s
|
154
|
+
loggable_request = token_request.merge subject_token: "(sha256:#{digest})"
|
155
|
+
Google::Logging::Message.from(
|
156
|
+
message: "Request data",
|
157
|
+
"request" => loggable_request,
|
158
|
+
"credentialsId" => object_id
|
159
|
+
)
|
160
|
+
end
|
141
161
|
end
|
142
162
|
|
143
163
|
def get_impersonated_access_token token, _options = {}
|
164
|
+
log_impersonated_token_request token
|
144
165
|
response = connection.post @service_account_impersonation_url do |req|
|
145
166
|
req.headers["Authorization"] = "Bearer #{token}"
|
146
167
|
req.headers["Content-Type"] = "application/json"
|
@@ -153,6 +174,16 @@ module Google
|
|
153
174
|
|
154
175
|
MultiJson.load response.body
|
155
176
|
end
|
177
|
+
|
178
|
+
def log_impersonated_token_request original_token
|
179
|
+
logger&.info do
|
180
|
+
digest = Digest::SHA256.hexdigest original_token
|
181
|
+
Google::Logging::Message.from(
|
182
|
+
message: "Requesting impersonated access token with original token (sha256:#{digest})",
|
183
|
+
"credentialsId" => object_id
|
184
|
+
)
|
185
|
+
end
|
186
|
+
end
|
156
187
|
end
|
157
188
|
end
|
158
189
|
end
|
data/lib/googleauth/id_tokens.rb
CHANGED
@@ -168,7 +168,6 @@ module Google
|
|
168
168
|
aud: nil,
|
169
169
|
azp: nil,
|
170
170
|
iss: OIDC_ISSUERS
|
171
|
-
|
172
171
|
verifier = Verifier.new key_source: oidc_key_source,
|
173
172
|
aud: aud,
|
174
173
|
azp: azp,
|
@@ -206,7 +205,6 @@ module Google
|
|
206
205
|
aud: nil,
|
207
206
|
azp: nil,
|
208
207
|
iss: IAP_ISSUERS
|
209
|
-
|
210
208
|
verifier = Verifier.new key_source: iap_key_source,
|
211
209
|
aud: aud,
|
212
210
|
azp: azp,
|
@@ -12,6 +12,7 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
require "google/logging/message"
|
15
16
|
require "googleauth/signet"
|
16
17
|
require "googleauth/credentials_loader"
|
17
18
|
require "googleauth/json_key_reader"
|
@@ -123,6 +124,7 @@ module Google
|
|
123
124
|
}
|
124
125
|
key_io = StringIO.new MultiJson.dump(cred_json)
|
125
126
|
alt = ServiceAccountJwtHeaderCredentials.make_creds json_key_io: key_io, scope: scope
|
127
|
+
alt.logger = logger
|
126
128
|
alt.apply! a_hash
|
127
129
|
end
|
128
130
|
end
|
@@ -147,6 +149,7 @@ module Google
|
|
147
149
|
attr_reader :project_id
|
148
150
|
attr_reader :quota_project_id
|
149
151
|
attr_accessor :universe_domain
|
152
|
+
attr_accessor :logger
|
150
153
|
|
151
154
|
# Create a ServiceAccountJwtHeaderCredentials.
|
152
155
|
#
|
@@ -187,10 +190,14 @@ module Google
|
|
187
190
|
return a_hash if jwt_aud_uri.nil? && @scope.nil?
|
188
191
|
jwt_token = new_jwt_token jwt_aud_uri, opts
|
189
192
|
a_hash[AUTH_METADATA_KEY] = "Bearer #{jwt_token}"
|
193
|
+
logger&.debug do
|
194
|
+
hash = Digest::SHA256.hexdigest jwt_token
|
195
|
+
Google::Logging::Message.from message: "Sending JWT auth token. (sha256:#{hash})"
|
196
|
+
end
|
190
197
|
a_hash
|
191
198
|
end
|
192
199
|
|
193
|
-
# Returns a clone of a_hash updated with the
|
200
|
+
# Returns a clone of a_hash updated with the authorization header
|
194
201
|
def apply a_hash, opts = {}
|
195
202
|
a_copy = a_hash.clone
|
196
203
|
apply! a_copy, opts
|
@@ -219,6 +226,10 @@ module Google
|
|
219
226
|
assertion["scope"] = Array(@scope).join " " if @scope
|
220
227
|
assertion["aud"] = jwt_aud_uri if jwt_aud_uri
|
221
228
|
|
229
|
+
logger&.debug do
|
230
|
+
Google::Logging::Message.from message: "JWT assertion: #{assertion}"
|
231
|
+
end
|
232
|
+
|
222
233
|
JWT.encode assertion, @signing_key, SIGNING_ALGORITHM
|
223
234
|
end
|
224
235
|
|
data/lib/googleauth/signet.rb
CHANGED
@@ -65,6 +65,24 @@ module Signet
|
|
65
65
|
info
|
66
66
|
end
|
67
67
|
|
68
|
+
alias googleauth_orig_generate_access_token_request generate_access_token_request
|
69
|
+
def generate_access_token_request options = {}
|
70
|
+
parameters = googleauth_orig_generate_access_token_request options
|
71
|
+
logger&.info do
|
72
|
+
Google::Logging::Message.from(
|
73
|
+
message: "Requesting access token from #{parameters['grant_type']}",
|
74
|
+
"credentialsId" => object_id
|
75
|
+
)
|
76
|
+
end
|
77
|
+
logger&.debug do
|
78
|
+
Google::Logging::Message.from(
|
79
|
+
message: "Token fetch params: #{parameters}",
|
80
|
+
"credentialsId" => object_id
|
81
|
+
)
|
82
|
+
end
|
83
|
+
parameters
|
84
|
+
end
|
85
|
+
|
68
86
|
def build_default_connection
|
69
87
|
if !defined?(@connection_info)
|
70
88
|
nil
|
@@ -79,15 +97,20 @@ module Signet
|
|
79
97
|
retry_count = 0
|
80
98
|
|
81
99
|
begin
|
82
|
-
yield
|
100
|
+
yield.tap { |resp| log_response resp }
|
83
101
|
rescue StandardError => e
|
84
|
-
|
102
|
+
if e.is_a?(Signet::AuthorizationError) || e.is_a?(Signet::ParseError)
|
103
|
+
log_auth_error e
|
104
|
+
raise e
|
105
|
+
end
|
85
106
|
|
86
107
|
if retry_count < max_retry_count
|
108
|
+
log_transient_error e
|
87
109
|
retry_count += 1
|
88
110
|
sleep retry_count * 0.3
|
89
111
|
retry
|
90
112
|
else
|
113
|
+
log_retries_exhausted e
|
91
114
|
msg = "Unexpected error: #{e.inspect}"
|
92
115
|
raise Signet::AuthorizationError, msg
|
93
116
|
end
|
@@ -106,6 +129,49 @@ module Signet
|
|
106
129
|
# Shouldn't happen unless we get a garbled ID token
|
107
130
|
nil
|
108
131
|
end
|
132
|
+
|
133
|
+
def log_response token_response
|
134
|
+
response_hash = JSON.parse token_response rescue {}
|
135
|
+
if response_hash["access_token"]
|
136
|
+
digest = Digest::SHA256.hexdigest response_hash["access_token"]
|
137
|
+
response_hash["access_token"] = "(sha256:#{digest})"
|
138
|
+
end
|
139
|
+
if response_hash["id_token"]
|
140
|
+
digest = Digest::SHA256.hexdigest response_hash["id_token"]
|
141
|
+
response_hash["id_token"] = "(sha256:#{digest})"
|
142
|
+
end
|
143
|
+
Google::Logging::Message.from(
|
144
|
+
message: "Received auth token response: #{response_hash}",
|
145
|
+
"credentialsId" => object_id
|
146
|
+
)
|
147
|
+
end
|
148
|
+
|
149
|
+
def log_auth_error err
|
150
|
+
logger&.info do
|
151
|
+
Google::Logging::Message.from(
|
152
|
+
message: "Auth error when fetching auth token: #{err}",
|
153
|
+
"credentialsId" => object_id
|
154
|
+
)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def log_transient_error err
|
159
|
+
logger&.info do
|
160
|
+
Google::Logging::Message.from(
|
161
|
+
message: "Transient error when fetching auth token: #{err}",
|
162
|
+
"credentialsId" => object_id
|
163
|
+
)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def log_retries_exhausted err
|
168
|
+
logger&.info do
|
169
|
+
Google::Logging::Message.from(
|
170
|
+
message: "Exhausted retries when fetching auth token: #{err}",
|
171
|
+
"credentialsId" => object_id
|
172
|
+
)
|
173
|
+
end
|
174
|
+
end
|
109
175
|
end
|
110
176
|
end
|
111
177
|
end
|
data/lib/googleauth/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: googleauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Emiola
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -36,14 +36,28 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '2.
|
39
|
+
version: '2.2'
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '2.
|
46
|
+
version: '2.2'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: google-logging-utils
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0.1'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0.1'
|
47
61
|
- !ruby/object:Gem::Dependency
|
48
62
|
name: jwt
|
49
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -186,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
186
200
|
- !ruby/object:Gem::Version
|
187
201
|
version: '0'
|
188
202
|
requirements: []
|
189
|
-
rubygems_version: 3.5.
|
203
|
+
rubygems_version: 3.5.23
|
190
204
|
signing_key:
|
191
205
|
specification_version: 4
|
192
206
|
summary: Google Auth Library for Ruby
|