googleauth 1.11.2 → 1.12.0
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/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
|