googleauth 1.12.2 → 1.14.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 +29 -0
- data/README.md +10 -1
- data/lib/googleauth/api_key.rb +155 -0
- data/lib/googleauth/bearer_token.rb +148 -0
- data/lib/googleauth/compute_engine.rb +40 -1
- data/lib/googleauth/credentials.rb +107 -25
- data/lib/googleauth/credentials_loader.rb +2 -2
- data/lib/googleauth/default_credentials.rb +13 -2
- data/lib/googleauth/helpers/connection.rb +7 -1
- data/lib/googleauth/impersonated_service_account.rb +282 -0
- data/lib/googleauth/service_account.rb +55 -113
- data/lib/googleauth/service_account_jwt_header.rb +180 -0
- data/lib/googleauth/signet.rb +52 -0
- data/lib/googleauth/user_refresh.rb +43 -0
- data/lib/googleauth/version.rb +1 -1
- data/lib/googleauth.rb +7 -0
- metadata +10 -9
@@ -0,0 +1,180 @@
|
|
1
|
+
# Copyright 2025 Google, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require "google/logging/message"
|
16
|
+
require "googleauth/credentials_loader"
|
17
|
+
require "googleauth/json_key_reader"
|
18
|
+
require "jwt"
|
19
|
+
|
20
|
+
module Google
|
21
|
+
# Module Auth provides classes that provide Google-specific authorization
|
22
|
+
# used to access Google APIs.
|
23
|
+
module Auth
|
24
|
+
# Authenticates requests using Google's Service Account credentials via
|
25
|
+
# JWT Header.
|
26
|
+
#
|
27
|
+
# This class allows authorizing requests for service accounts directly
|
28
|
+
# from credentials from a json key file downloaded from the developer
|
29
|
+
# console (via 'Generate new Json Key'). It is not part of any OAuth2
|
30
|
+
# flow, rather it creates a JWT and sends that as a credential.
|
31
|
+
#
|
32
|
+
# cf [Application Default Credentials](https://cloud.google.com/docs/authentication/production)
|
33
|
+
class ServiceAccountJwtHeaderCredentials
|
34
|
+
JWT_AUD_URI_KEY = :jwt_aud_uri
|
35
|
+
AUTH_METADATA_KEY = Google::Auth::BaseClient::AUTH_METADATA_KEY
|
36
|
+
TOKEN_CRED_URI = "https://www.googleapis.com/oauth2/v4/token".freeze
|
37
|
+
SIGNING_ALGORITHM = "RS256".freeze
|
38
|
+
EXPIRY = 60
|
39
|
+
|
40
|
+
extend CredentialsLoader
|
41
|
+
extend JsonKeyReader
|
42
|
+
|
43
|
+
attr_reader :project_id
|
44
|
+
attr_reader :quota_project_id
|
45
|
+
attr_accessor :universe_domain
|
46
|
+
attr_accessor :logger
|
47
|
+
|
48
|
+
# Create a ServiceAccountJwtHeaderCredentials.
|
49
|
+
#
|
50
|
+
# @param json_key_io [IO] an IO from which the JSON key can be read
|
51
|
+
# @param scope [string|array|nil] the scope(s) to access
|
52
|
+
def self.make_creds options = {}
|
53
|
+
json_key_io, scope = options.values_at :json_key_io, :scope
|
54
|
+
new json_key_io: json_key_io, scope: scope
|
55
|
+
end
|
56
|
+
|
57
|
+
# Initializes a ServiceAccountJwtHeaderCredentials.
|
58
|
+
#
|
59
|
+
# @param json_key_io [IO] an IO from which the JSON key can be read
|
60
|
+
def initialize options = {}
|
61
|
+
json_key_io = options[:json_key_io]
|
62
|
+
if json_key_io
|
63
|
+
@private_key, @issuer, @project_id, @quota_project_id, @universe_domain =
|
64
|
+
self.class.read_json_key json_key_io
|
65
|
+
else
|
66
|
+
@private_key = options.key?(:private_key) ? options[:private_key] : ENV[CredentialsLoader::PRIVATE_KEY_VAR]
|
67
|
+
@issuer = options.key?(:issuer) ? options[:issuer] : ENV[CredentialsLoader::CLIENT_EMAIL_VAR]
|
68
|
+
@project_id = options.key?(:project_id) ? options[:project_id] : ENV[CredentialsLoader::PROJECT_ID_VAR]
|
69
|
+
@quota_project_id = options[:quota_project_id] if options.key? :quota_project_id
|
70
|
+
@universe_domain = options[:universe_domain] if options.key? :universe_domain
|
71
|
+
end
|
72
|
+
@universe_domain ||= "googleapis.com"
|
73
|
+
@project_id ||= CredentialsLoader.load_gcloud_project_id
|
74
|
+
@signing_key = OpenSSL::PKey::RSA.new @private_key
|
75
|
+
@scope = options[:scope] if options.key? :scope
|
76
|
+
@logger = options[:logger] if options.key? :logger
|
77
|
+
end
|
78
|
+
|
79
|
+
# Creates a duplicate of these credentials
|
80
|
+
#
|
81
|
+
# @param options [Hash] Overrides for the credentials parameters.
|
82
|
+
# The following keys are recognized
|
83
|
+
# * `private key` the private key in string form
|
84
|
+
# * `issuer` the SA issuer
|
85
|
+
# * `scope` the scope(s) to access
|
86
|
+
# * `project_id` the project id to use during the authentication
|
87
|
+
# * `quota_project_id` the quota project id to use
|
88
|
+
# * `universe_domain` the universe domain of the credentials
|
89
|
+
def duplicate options = {}
|
90
|
+
options = deep_hash_normalize options
|
91
|
+
|
92
|
+
options = {
|
93
|
+
private_key: @private_key,
|
94
|
+
issuer: @issuer,
|
95
|
+
scope: @scope,
|
96
|
+
project_id: project_id,
|
97
|
+
quota_project_id: quota_project_id,
|
98
|
+
universe_domain: universe_domain,
|
99
|
+
logger: logger
|
100
|
+
}.merge(options)
|
101
|
+
|
102
|
+
self.class.new options
|
103
|
+
end
|
104
|
+
|
105
|
+
# Construct a jwt token if the JWT_AUD_URI key is present in the input
|
106
|
+
# hash.
|
107
|
+
#
|
108
|
+
# The jwt token is used as the value of a 'Bearer '.
|
109
|
+
def apply! a_hash, opts = {}
|
110
|
+
jwt_aud_uri = a_hash.delete JWT_AUD_URI_KEY
|
111
|
+
return a_hash if jwt_aud_uri.nil? && @scope.nil?
|
112
|
+
jwt_token = new_jwt_token jwt_aud_uri, opts
|
113
|
+
a_hash[AUTH_METADATA_KEY] = "Bearer #{jwt_token}"
|
114
|
+
logger&.debug do
|
115
|
+
hash = Digest::SHA256.hexdigest jwt_token
|
116
|
+
Google::Logging::Message.from message: "Sending JWT auth token. (sha256:#{hash})"
|
117
|
+
end
|
118
|
+
a_hash
|
119
|
+
end
|
120
|
+
|
121
|
+
# Returns a clone of a_hash updated with the authorization header
|
122
|
+
def apply a_hash, opts = {}
|
123
|
+
a_copy = a_hash.clone
|
124
|
+
apply! a_copy, opts
|
125
|
+
a_copy
|
126
|
+
end
|
127
|
+
|
128
|
+
# Returns a reference to the #apply method, suitable for passing as
|
129
|
+
# a closure
|
130
|
+
def updater_proc
|
131
|
+
proc { |a_hash, opts = {}| apply a_hash, opts }
|
132
|
+
end
|
133
|
+
|
134
|
+
# Creates a jwt uri token.
|
135
|
+
def new_jwt_token jwt_aud_uri = nil, options = {}
|
136
|
+
now = Time.new
|
137
|
+
skew = options[:skew] || 60
|
138
|
+
assertion = {
|
139
|
+
"iss" => @issuer,
|
140
|
+
"sub" => @issuer,
|
141
|
+
"exp" => (now + EXPIRY).to_i,
|
142
|
+
"iat" => (now - skew).to_i
|
143
|
+
}
|
144
|
+
|
145
|
+
jwt_aud_uri = nil if @scope
|
146
|
+
|
147
|
+
assertion["scope"] = Array(@scope).join " " if @scope
|
148
|
+
assertion["aud"] = jwt_aud_uri if jwt_aud_uri
|
149
|
+
|
150
|
+
logger&.debug do
|
151
|
+
Google::Logging::Message.from message: "JWT assertion: #{assertion}"
|
152
|
+
end
|
153
|
+
|
154
|
+
JWT.encode assertion, @signing_key, SIGNING_ALGORITHM
|
155
|
+
end
|
156
|
+
|
157
|
+
# Duck-types the corresponding method from BaseClient
|
158
|
+
def needs_access_token?
|
159
|
+
false
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
def deep_hash_normalize old_hash
|
165
|
+
sym_hash = {}
|
166
|
+
old_hash&.each { |k, v| sym_hash[k.to_sym] = recursive_hash_normalize_keys v }
|
167
|
+
sym_hash
|
168
|
+
end
|
169
|
+
|
170
|
+
# Convert all keys in this hash (nested) to symbols for uniform retrieval
|
171
|
+
def recursive_hash_normalize_keys val
|
172
|
+
if val.is_a? Hash
|
173
|
+
deep_hash_normalize val
|
174
|
+
else
|
175
|
+
val
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
data/lib/googleauth/signet.rb
CHANGED
@@ -38,6 +38,22 @@ module Signet
|
|
38
38
|
self
|
39
39
|
end
|
40
40
|
|
41
|
+
alias update_signet_base update!
|
42
|
+
def update! options = {}
|
43
|
+
# Normalize all keys to symbols to allow indifferent access.
|
44
|
+
options = deep_hash_normalize options
|
45
|
+
|
46
|
+
# This `update!` method "overide" adds the `@logger`` update and
|
47
|
+
# the `universe_domain` update.
|
48
|
+
#
|
49
|
+
# The `universe_domain` is also updated in `update_token!` but is
|
50
|
+
# included here for completeness
|
51
|
+
self.universe_domain = options[:universe_domain] if options.key? :universe_domain
|
52
|
+
@logger = options[:logger] if options.key? :logger
|
53
|
+
|
54
|
+
update_signet_base options
|
55
|
+
end
|
56
|
+
|
41
57
|
def configure_connection options
|
42
58
|
@connection_info =
|
43
59
|
options[:connection_builder] || options[:default_connection]
|
@@ -117,6 +133,42 @@ module Signet
|
|
117
133
|
end
|
118
134
|
end
|
119
135
|
|
136
|
+
# Creates a duplicate of these credentials
|
137
|
+
# without the Signet::OAuth2::Client-specific
|
138
|
+
# transient state (e.g. cached tokens)
|
139
|
+
#
|
140
|
+
# @param options [Hash] Overrides for the credentials parameters.
|
141
|
+
# @see Signet::OAuth2::Client#update!
|
142
|
+
def duplicate options = {}
|
143
|
+
options = deep_hash_normalize options
|
144
|
+
|
145
|
+
opts = {
|
146
|
+
authorization_uri: @authorization_uri,
|
147
|
+
token_credential_uri: @token_credential_uri,
|
148
|
+
client_id: @client_id,
|
149
|
+
client_secret: @client_secret,
|
150
|
+
scope: @scope,
|
151
|
+
target_audience: @target_audience,
|
152
|
+
redirect_uri: @redirect_uri,
|
153
|
+
username: @username,
|
154
|
+
password: @password,
|
155
|
+
issuer: @issuer,
|
156
|
+
person: @person,
|
157
|
+
sub: @sub,
|
158
|
+
audience: @audience,
|
159
|
+
signing_key: @signing_key,
|
160
|
+
extension_parameters: @extension_parameters,
|
161
|
+
additional_parameters: @additional_parameters,
|
162
|
+
access_type: @access_type,
|
163
|
+
universe_domain: @universe_domain,
|
164
|
+
logger: @logger
|
165
|
+
}.merge(options)
|
166
|
+
|
167
|
+
new_client = self.class.new opts
|
168
|
+
|
169
|
+
new_client.configure_connection options
|
170
|
+
end
|
171
|
+
|
120
172
|
private
|
121
173
|
|
122
174
|
def expires_at_from_id_token id_token
|
@@ -85,6 +85,26 @@ module Google
|
|
85
85
|
super options
|
86
86
|
end
|
87
87
|
|
88
|
+
# Creates a duplicate of these credentials
|
89
|
+
# without the Signet::OAuth2::Client-specific
|
90
|
+
# transient state (e.g. cached tokens)
|
91
|
+
#
|
92
|
+
# @param options [Hash] Overrides for the credentials parameters.
|
93
|
+
# The following keys are recognized in addition to keys in the
|
94
|
+
# Signet::OAuth2::Client
|
95
|
+
# * `project_id` the project id to use during the authentication
|
96
|
+
# * `quota_project_id` the quota project id to use
|
97
|
+
# during the authentication
|
98
|
+
def duplicate options = {}
|
99
|
+
options = deep_hash_normalize options
|
100
|
+
super(
|
101
|
+
{
|
102
|
+
project_id: @project_id,
|
103
|
+
quota_project_id: @quota_project_id
|
104
|
+
}.merge(options)
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
88
108
|
# Revokes the credential
|
89
109
|
def revoke! options = {}
|
90
110
|
c = options[:connection] || Faraday.default_connection
|
@@ -114,6 +134,29 @@ module Google
|
|
114
134
|
Google::Auth::ScopeUtil.normalize(scope)
|
115
135
|
missing_scope.empty?
|
116
136
|
end
|
137
|
+
|
138
|
+
# Destructively updates these credentials
|
139
|
+
#
|
140
|
+
# This method is called by `Signet::OAuth2::Client`'s constructor
|
141
|
+
#
|
142
|
+
# @param options [Hash] Overrides for the credentials parameters.
|
143
|
+
# The following keys are recognized in addition to keys in the
|
144
|
+
# Signet::OAuth2::Client
|
145
|
+
# * `project_id` the project id to use during the authentication
|
146
|
+
# * `quota_project_id` the quota project id to use
|
147
|
+
# during the authentication
|
148
|
+
# @return [Google::Auth::UserRefreshCredentials]
|
149
|
+
def update! options = {}
|
150
|
+
# Normalize all keys to symbols to allow indifferent access.
|
151
|
+
options = deep_hash_normalize options
|
152
|
+
|
153
|
+
@project_id = options[:project_id] if options.key? :project_id
|
154
|
+
@quota_project_id = options[:quota_project_id] if options.key? :quota_project_id
|
155
|
+
|
156
|
+
super(options)
|
157
|
+
|
158
|
+
self
|
159
|
+
end
|
117
160
|
end
|
118
161
|
end
|
119
162
|
end
|
data/lib/googleauth/version.rb
CHANGED
data/lib/googleauth.rb
CHANGED
@@ -13,9 +13,16 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
require "googleauth/application_default"
|
16
|
+
require "googleauth/api_key"
|
17
|
+
require "googleauth/bearer_token"
|
16
18
|
require "googleauth/client_id"
|
17
19
|
require "googleauth/credentials"
|
18
20
|
require "googleauth/default_credentials"
|
21
|
+
require "googleauth/external_account"
|
19
22
|
require "googleauth/id_tokens"
|
23
|
+
require "googleauth/impersonated_service_account"
|
24
|
+
require "googleauth/service_account"
|
25
|
+
require "googleauth/service_account_jwt_header"
|
20
26
|
require "googleauth/user_authorizer"
|
27
|
+
require "googleauth/user_refresh"
|
21
28
|
require "googleauth/web_user_authorizer"
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: googleauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
autorequire:
|
7
|
+
- Google LLC
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-03-14 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: faraday
|
@@ -135,7 +134,7 @@ dependencies:
|
|
135
134
|
description: Implements simple authorization for accessing Google APIs, and provides
|
136
135
|
support for Application Default Credentials.
|
137
136
|
email:
|
138
|
-
-
|
137
|
+
- googleapis-packages@google.com
|
139
138
|
executables: []
|
140
139
|
extensions: []
|
141
140
|
extra_rdoc_files: []
|
@@ -147,8 +146,10 @@ files:
|
|
147
146
|
- README.md
|
148
147
|
- SECURITY.md
|
149
148
|
- lib/googleauth.rb
|
149
|
+
- lib/googleauth/api_key.rb
|
150
150
|
- lib/googleauth/application_default.rb
|
151
151
|
- lib/googleauth/base_client.rb
|
152
|
+
- lib/googleauth/bearer_token.rb
|
152
153
|
- lib/googleauth/client_id.rb
|
153
154
|
- lib/googleauth/compute_engine.rb
|
154
155
|
- lib/googleauth/credentials.rb
|
@@ -166,10 +167,12 @@ files:
|
|
166
167
|
- lib/googleauth/id_tokens/errors.rb
|
167
168
|
- lib/googleauth/id_tokens/key_sources.rb
|
168
169
|
- lib/googleauth/id_tokens/verifier.rb
|
170
|
+
- lib/googleauth/impersonated_service_account.rb
|
169
171
|
- lib/googleauth/json_key_reader.rb
|
170
172
|
- lib/googleauth/oauth2/sts_client.rb
|
171
173
|
- lib/googleauth/scope_util.rb
|
172
174
|
- lib/googleauth/service_account.rb
|
175
|
+
- lib/googleauth/service_account_jwt_header.rb
|
173
176
|
- lib/googleauth/signet.rb
|
174
177
|
- lib/googleauth/stores/file_token_store.rb
|
175
178
|
- lib/googleauth/stores/redis_token_store.rb
|
@@ -185,7 +188,6 @@ metadata:
|
|
185
188
|
changelog_uri: https://github.com/googleapis/google-auth-library-ruby/blob/main/CHANGELOG.md
|
186
189
|
source_code_uri: https://github.com/googleapis/google-auth-library-ruby
|
187
190
|
bug_tracker_uri: https://github.com/googleapis/google-auth-library-ruby/issues
|
188
|
-
post_install_message:
|
189
191
|
rdoc_options: []
|
190
192
|
require_paths:
|
191
193
|
- lib
|
@@ -193,15 +195,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
193
195
|
requirements:
|
194
196
|
- - ">="
|
195
197
|
- !ruby/object:Gem::Version
|
196
|
-
version: '
|
198
|
+
version: '3.0'
|
197
199
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
198
200
|
requirements:
|
199
201
|
- - ">="
|
200
202
|
- !ruby/object:Gem::Version
|
201
203
|
version: '0'
|
202
204
|
requirements: []
|
203
|
-
rubygems_version: 3.5
|
204
|
-
signing_key:
|
205
|
+
rubygems_version: 3.6.5
|
205
206
|
specification_version: 4
|
206
207
|
summary: Google Auth Library for Ruby
|
207
208
|
test_files: []
|