googleauth 0.5.1 → 0.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 +5 -5
- data/.github/CODEOWNERS +7 -0
- data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +5 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +36 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
- data/.github/ISSUE_TEMPLATE/support_request.md +7 -0
- data/.kokoro/build.bat +16 -0
- data/.kokoro/build.sh +4 -0
- data/.kokoro/continuous/common.cfg +24 -0
- data/.kokoro/continuous/linux.cfg +25 -0
- data/.kokoro/continuous/osx.cfg +8 -0
- data/.kokoro/continuous/post.cfg +30 -0
- data/.kokoro/continuous/windows.cfg +29 -0
- data/.kokoro/osx.sh +4 -0
- data/.kokoro/presubmit/common.cfg +24 -0
- data/.kokoro/presubmit/linux.cfg +24 -0
- data/.kokoro/presubmit/osx.cfg +8 -0
- data/.kokoro/presubmit/windows.cfg +29 -0
- data/.kokoro/release.cfg +94 -0
- data/.kokoro/trampoline.bat +10 -0
- data/.kokoro/trampoline.sh +4 -0
- data/.repo-metadata.json +5 -0
- data/.rubocop.yml +19 -1
- data/CHANGELOG.md +112 -19
- data/CODE_OF_CONDUCT.md +43 -0
- data/Gemfile +19 -13
- data/{COPYING → LICENSE} +0 -0
- data/README.md +58 -18
- data/Rakefile +126 -9
- data/googleauth.gemspec +28 -25
- data/integration/helper.rb +31 -0
- data/integration/id_tokens/key_source_test.rb +74 -0
- data/lib/googleauth.rb +7 -96
- data/lib/googleauth/application_default.rb +81 -0
- data/lib/googleauth/client_id.rb +21 -19
- data/lib/googleauth/compute_engine.rb +70 -43
- data/lib/googleauth/credentials.rb +442 -0
- data/lib/googleauth/credentials_loader.rb +117 -43
- data/lib/googleauth/default_credentials.rb +93 -0
- data/lib/googleauth/iam.rb +11 -11
- 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 +50 -0
- data/lib/googleauth/scope_util.rb +12 -12
- data/lib/googleauth/service_account.rb +74 -63
- data/lib/googleauth/signet.rb +55 -13
- data/lib/googleauth/stores/file_token_store.rb +8 -8
- data/lib/googleauth/stores/redis_token_store.rb +22 -22
- data/lib/googleauth/token_store.rb +6 -6
- data/lib/googleauth/user_authorizer.rb +80 -68
- data/lib/googleauth/user_refresh.rb +44 -35
- data/lib/googleauth/version.rb +1 -1
- data/lib/googleauth/web_user_authorizer.rb +77 -68
- 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 +74 -50
- data/spec/googleauth/client_id_spec.rb +75 -55
- data/spec/googleauth/compute_engine_spec.rb +98 -46
- data/spec/googleauth/credentials_spec.rb +478 -0
- data/spec/googleauth/get_application_default_spec.rb +149 -111
- data/spec/googleauth/iam_spec.rb +25 -25
- data/spec/googleauth/scope_util_spec.rb +26 -24
- data/spec/googleauth/service_account_spec.rb +269 -144
- data/spec/googleauth/signet_spec.rb +101 -30
- data/spec/googleauth/stores/file_token_store_spec.rb +12 -13
- data/spec/googleauth/stores/redis_token_store_spec.rb +11 -11
- data/spec/googleauth/stores/store_examples.rb +16 -16
- data/spec/googleauth/user_authorizer_spec.rb +153 -124
- data/spec/googleauth/user_refresh_spec.rb +186 -121
- data/spec/googleauth/web_user_authorizer_spec.rb +82 -69
- data/spec/spec_helper.rb +21 -19
- 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 +87 -34
- data/.rubocop_todo.yml +0 -32
- data/.travis.yml +0 -37
@@ -27,80 +27,81 @@
|
|
27
27
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
28
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
29
|
|
30
|
-
spec_dir = File.expand_path
|
31
|
-
$LOAD_PATH.unshift
|
30
|
+
spec_dir = File.expand_path File.join(File.dirname(__FILE__))
|
31
|
+
$LOAD_PATH.unshift spec_dir
|
32
32
|
$LOAD_PATH.uniq!
|
33
33
|
|
34
|
-
require
|
35
|
-
require
|
36
|
-
require
|
37
|
-
require
|
38
|
-
require
|
39
|
-
require
|
40
|
-
require
|
41
|
-
require
|
42
|
-
require
|
34
|
+
require "apply_auth_examples"
|
35
|
+
require "fakefs/safe"
|
36
|
+
require "fileutils"
|
37
|
+
require "googleauth/service_account"
|
38
|
+
require "jwt"
|
39
|
+
require "multi_json"
|
40
|
+
require "openssl"
|
41
|
+
require "spec_helper"
|
42
|
+
require "tmpdir"
|
43
|
+
require "os"
|
43
44
|
|
44
45
|
include Google::Auth::CredentialsLoader
|
45
46
|
|
46
|
-
shared_examples
|
47
|
-
context
|
48
|
-
let(:test_uri) {
|
49
|
-
let(:auth_prefix) {
|
47
|
+
shared_examples "jwt header auth" do
|
48
|
+
context "when jwt_aud_uri is present" do
|
49
|
+
let(:test_uri) { "https://www.googleapis.com/myservice" }
|
50
|
+
let(:auth_prefix) { "Bearer " }
|
50
51
|
let(:auth_key) { ServiceAccountJwtHeaderCredentials::AUTH_METADATA_KEY }
|
51
52
|
let(:jwt_uri_key) { ServiceAccountJwtHeaderCredentials::JWT_AUD_URI_KEY }
|
52
53
|
|
53
|
-
def expect_is_encoded_jwt
|
54
|
+
def expect_is_encoded_jwt hdr
|
54
55
|
expect(hdr).to_not be_nil
|
55
56
|
expect(hdr.start_with?(auth_prefix)).to be true
|
56
57
|
authorization = hdr[auth_prefix.length..-1]
|
57
|
-
payload, = JWT.decode
|
58
|
-
expect(payload[
|
59
|
-
expect(payload[
|
58
|
+
payload, = JWT.decode authorization, @key.public_key, true, algorithm: "RS256"
|
59
|
+
expect(payload["aud"]).to eq(test_uri)
|
60
|
+
expect(payload["iss"]).to eq(client_email)
|
60
61
|
end
|
61
62
|
|
62
|
-
describe
|
63
|
-
it
|
64
|
-
md = { foo:
|
63
|
+
describe "#apply!" do
|
64
|
+
it "should update the target hash with a jwt token" do
|
65
|
+
md = { foo: "bar" }
|
65
66
|
md[jwt_uri_key] = test_uri
|
66
|
-
@client.apply!
|
67
|
+
@client.apply! md
|
67
68
|
auth_header = md[auth_key]
|
68
|
-
expect_is_encoded_jwt
|
69
|
+
expect_is_encoded_jwt auth_header
|
69
70
|
expect(md[jwt_uri_key]).to be_nil
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
73
|
-
describe
|
74
|
-
it
|
75
|
-
md = { foo:
|
74
|
+
describe "updater_proc" do
|
75
|
+
it "should provide a proc that updates a hash with a jwt token" do
|
76
|
+
md = { foo: "bar" }
|
76
77
|
md[jwt_uri_key] = test_uri
|
77
78
|
the_proc = @client.updater_proc
|
78
|
-
got = the_proc.call
|
79
|
+
got = the_proc.call md
|
79
80
|
auth_header = got[auth_key]
|
80
|
-
expect_is_encoded_jwt
|
81
|
+
expect_is_encoded_jwt auth_header
|
81
82
|
expect(got[jwt_uri_key]).to be_nil
|
82
83
|
expect(md[jwt_uri_key]).to_not be_nil
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
86
|
-
describe
|
87
|
-
it
|
88
|
-
md = { foo:
|
87
|
+
describe "#apply" do
|
88
|
+
it "should not update the original hash with a jwt token" do
|
89
|
+
md = { foo: "bar" }
|
89
90
|
md[jwt_uri_key] = test_uri
|
90
91
|
the_proc = @client.updater_proc
|
91
|
-
got = the_proc.call
|
92
|
+
got = the_proc.call md
|
92
93
|
auth_header = md[auth_key]
|
93
94
|
expect(auth_header).to be_nil
|
94
95
|
expect(got[jwt_uri_key]).to be_nil
|
95
96
|
expect(md[jwt_uri_key]).to_not be_nil
|
96
97
|
end
|
97
98
|
|
98
|
-
it
|
99
|
-
md = { foo:
|
99
|
+
it "should add a jwt token to the returned hash" do
|
100
|
+
md = { foo: "bar" }
|
100
101
|
md[jwt_uri_key] = test_uri
|
101
|
-
got = @client.apply
|
102
|
+
got = @client.apply md
|
102
103
|
auth_header = got[auth_key]
|
103
|
-
expect_is_encoded_jwt
|
104
|
+
expect_is_encoded_jwt auth_header
|
104
105
|
end
|
105
106
|
end
|
106
107
|
end
|
@@ -108,156 +109,245 @@ end
|
|
108
109
|
|
109
110
|
describe Google::Auth::ServiceAccountCredentials do
|
110
111
|
ServiceAccountCredentials = Google::Auth::ServiceAccountCredentials
|
111
|
-
let(:client_email) {
|
112
|
-
let
|
112
|
+
let(:client_email) { "app@developer.gserviceaccount.com" }
|
113
|
+
let :cred_json do
|
113
114
|
{
|
114
|
-
private_key_id:
|
115
|
-
private_key:
|
116
|
-
client_email:
|
117
|
-
client_id:
|
118
|
-
type:
|
115
|
+
private_key_id: "a_private_key_id",
|
116
|
+
private_key: @key.to_pem,
|
117
|
+
client_email: client_email,
|
118
|
+
client_id: "app.apps.googleusercontent.com",
|
119
|
+
type: "service_account",
|
120
|
+
project_id: "a_project_id",
|
121
|
+
quota_project_id: "b_project_id"
|
119
122
|
}
|
120
123
|
end
|
121
124
|
|
122
|
-
before
|
123
|
-
@key = OpenSSL::PKey::RSA.new
|
125
|
+
before :example do
|
126
|
+
@key = OpenSSL::PKey::RSA.new 2048
|
124
127
|
@client = ServiceAccountCredentials.make_creds(
|
125
128
|
json_key_io: StringIO.new(cred_json_text),
|
126
|
-
scope:
|
129
|
+
scope: "https://www.googleapis.com/auth/userinfo.profile"
|
130
|
+
)
|
131
|
+
@id_client = ServiceAccountCredentials.make_creds(
|
132
|
+
json_key_io: StringIO.new(cred_json_text),
|
133
|
+
target_audience: "https://pubsub.googleapis.com/"
|
127
134
|
)
|
128
135
|
end
|
129
136
|
|
130
|
-
def make_auth_stubs
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
137
|
+
def make_auth_stubs opts
|
138
|
+
body_fields = { "token_type" => "Bearer", "expires_in" => 3600 }
|
139
|
+
body_fields["access_token"] = opts[:access_token] if opts[:access_token]
|
140
|
+
body_fields["id_token"] = opts[:id_token] if opts[:id_token]
|
141
|
+
body = MultiJson.dump body_fields
|
135
142
|
blk = proc do |request|
|
136
|
-
params = Addressable::URI.form_unencode
|
137
|
-
|
138
|
-
|
143
|
+
params = Addressable::URI.form_unencode request.body
|
144
|
+
claim, _header = JWT.decode(params.assoc("assertion").last,
|
145
|
+
@key.public_key, true,
|
146
|
+
algorithm: "RS256")
|
147
|
+
!opts[:id_token] || claim["target_audience"] == "https://pubsub.googleapis.com/"
|
139
148
|
end
|
140
|
-
stub_request(:post,
|
149
|
+
stub_request(:post, "https://www.googleapis.com/oauth2/v4/token")
|
141
150
|
.with(body: hash_including(
|
142
|
-
|
143
|
-
|
144
|
-
.to_return(body:
|
145
|
-
status:
|
146
|
-
headers: {
|
151
|
+
"grant_type" => "urn:ietf:params:oauth:grant-type:jwt-bearer"
|
152
|
+
), &blk)
|
153
|
+
.to_return(body: body,
|
154
|
+
status: 200,
|
155
|
+
headers: { "Content-Type" => "application/json" })
|
147
156
|
end
|
148
157
|
|
149
158
|
def cred_json_text
|
150
|
-
MultiJson.dump
|
159
|
+
MultiJson.dump cred_json
|
151
160
|
end
|
152
161
|
|
153
|
-
it_behaves_like
|
162
|
+
it_behaves_like "apply/apply! are OK"
|
154
163
|
|
155
|
-
context
|
156
|
-
before
|
164
|
+
context "when scope is nil" do
|
165
|
+
before :example do
|
157
166
|
@client.scope = nil
|
158
167
|
end
|
159
168
|
|
160
|
-
it_behaves_like
|
169
|
+
it_behaves_like "jwt header auth"
|
161
170
|
end
|
162
171
|
|
163
|
-
describe
|
164
|
-
before
|
172
|
+
describe "#from_env" do
|
173
|
+
before :example do
|
165
174
|
@var_name = ENV_VAR
|
166
175
|
@credential_vars = [
|
167
|
-
ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR
|
176
|
+
ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR
|
177
|
+
]
|
168
178
|
@original_env_vals = {}
|
169
179
|
@credential_vars.each { |var| @original_env_vals[var] = ENV[var] }
|
170
180
|
ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
|
171
181
|
|
172
|
-
@scope =
|
182
|
+
@scope = "https://www.googleapis.com/auth/userinfo.profile"
|
173
183
|
@clz = ServiceAccountCredentials
|
174
184
|
end
|
175
185
|
|
176
|
-
after
|
186
|
+
after :example do
|
177
187
|
@credential_vars.each { |var| ENV[var] = @original_env_vals[var] }
|
178
188
|
end
|
179
189
|
|
180
|
-
it
|
181
|
-
ENV.delete
|
190
|
+
it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset" do
|
191
|
+
ENV.delete @var_name unless ENV[@var_name].nil?
|
192
|
+
expect(ServiceAccountCredentials.from_env(@scope)).to be_nil
|
193
|
+
end
|
194
|
+
|
195
|
+
it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is empty" do
|
196
|
+
ENV[@var_name] = ""
|
182
197
|
expect(ServiceAccountCredentials.from_env(@scope)).to be_nil
|
183
198
|
end
|
184
199
|
|
185
|
-
it
|
186
|
-
ENV.delete
|
200
|
+
it "fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist" do
|
201
|
+
ENV.delete @var_name unless ENV[@var_name].nil?
|
187
202
|
expect(ServiceAccountCredentials.from_env(@scope)).to be_nil
|
188
203
|
Dir.mktmpdir do |dir|
|
189
|
-
key_path = File.join
|
204
|
+
key_path = File.join dir, "does-not-exist"
|
190
205
|
ENV[@var_name] = key_path
|
191
|
-
expect { @clz.from_env
|
206
|
+
expect { @clz.from_env @scope }.to raise_error RuntimeError
|
192
207
|
end
|
193
208
|
end
|
194
209
|
|
195
|
-
it
|
210
|
+
it "succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid" do
|
196
211
|
Dir.mktmpdir do |dir|
|
197
|
-
key_path = File.join
|
198
|
-
FileUtils.mkdir_p
|
199
|
-
File.write
|
212
|
+
key_path = File.join dir, "my_cert_file"
|
213
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
214
|
+
File.write key_path, cred_json_text
|
200
215
|
ENV[@var_name] = key_path
|
201
216
|
expect(@clz.from_env(@scope)).to_not be_nil
|
202
217
|
end
|
203
218
|
end
|
204
219
|
|
205
|
-
it
|
206
|
-
|
220
|
+
it "succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are"\
|
221
|
+
" valid" do
|
207
222
|
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
208
223
|
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
209
224
|
expect(@clz.from_env(@scope)).to_not be_nil
|
210
225
|
end
|
226
|
+
|
227
|
+
it "sets project_id when the PROJECT_ID_VAR env var is set" do
|
228
|
+
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
229
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
230
|
+
ENV[PROJECT_ID_VAR] = cred_json[:project_id]
|
231
|
+
ENV[ENV_VAR] = nil
|
232
|
+
credentials = @clz.from_env @scope
|
233
|
+
expect(credentials.project_id).to eq(cred_json[:project_id])
|
234
|
+
end
|
235
|
+
|
236
|
+
it "succeeds when GOOGLE_PRIVATE_KEY is escaped" do
|
237
|
+
escaped_key = cred_json[:private_key].gsub "\n", '\n'
|
238
|
+
ENV[PRIVATE_KEY_VAR] = "\"#{escaped_key}\""
|
239
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
240
|
+
expect(@clz.from_env(@scope)).to_not be_nil
|
241
|
+
end
|
242
|
+
|
243
|
+
it "propagates default_connection option" do
|
244
|
+
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
245
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
246
|
+
connection = Faraday.new headers: { "User-Agent" => "hello" }
|
247
|
+
creds = @clz.from_env @scope, default_connection: connection
|
248
|
+
expect(creds.build_default_connection).to be connection
|
249
|
+
end
|
211
250
|
end
|
212
251
|
|
213
|
-
describe
|
214
|
-
before
|
215
|
-
@home = ENV[
|
216
|
-
@
|
252
|
+
describe "#from_well_known_path" do
|
253
|
+
before :example do
|
254
|
+
@home = ENV["HOME"]
|
255
|
+
@app_data = ENV["APPDATA"]
|
256
|
+
@scope = "https://www.googleapis.com/auth/userinfo.profile"
|
217
257
|
@known_path = WELL_KNOWN_PATH
|
218
258
|
@clz = ServiceAccountCredentials
|
219
259
|
end
|
220
260
|
|
221
|
-
after
|
222
|
-
ENV[
|
261
|
+
after :example do
|
262
|
+
ENV["HOME"] = @home unless @home == ENV["HOME"]
|
263
|
+
ENV["APPDATA"] = @app_data unless @app_data == ENV["APPDATA"]
|
223
264
|
end
|
224
265
|
|
225
|
-
it
|
226
|
-
ENV[
|
266
|
+
it "is nil if no file exists" do
|
267
|
+
ENV["HOME"] = File.dirname __FILE__
|
227
268
|
expect(ServiceAccountCredentials.from_well_known_path(@scope)).to be_nil
|
228
269
|
end
|
229
270
|
|
230
|
-
it
|
271
|
+
it "successfully loads the file when it is present" do
|
231
272
|
Dir.mktmpdir do |dir|
|
232
|
-
key_path = File.join
|
233
|
-
|
234
|
-
File.
|
235
|
-
|
273
|
+
key_path = File.join dir, ".config", @known_path
|
274
|
+
key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
|
275
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
276
|
+
File.write key_path, cred_json_text
|
277
|
+
ENV["HOME"] = dir
|
278
|
+
ENV["APPDATA"] = dir
|
236
279
|
expect(@clz.from_well_known_path(@scope)).to_not be_nil
|
237
280
|
end
|
238
281
|
end
|
282
|
+
|
283
|
+
it "successfully sets project_id when file is present" do
|
284
|
+
Dir.mktmpdir do |dir|
|
285
|
+
key_path = File.join dir, ".config", @known_path
|
286
|
+
key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
|
287
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
288
|
+
File.write key_path, cred_json_text
|
289
|
+
ENV["HOME"] = dir
|
290
|
+
ENV["APPDATA"] = dir
|
291
|
+
credentials = @clz.from_well_known_path @scope
|
292
|
+
expect(credentials.project_id).to eq(cred_json[:project_id])
|
293
|
+
expect(credentials.quota_project_id).to eq(cred_json[:quota_project_id])
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
it "propagates default_connection option" do
|
298
|
+
Dir.mktmpdir do |dir|
|
299
|
+
key_path = File.join dir, ".config", @known_path
|
300
|
+
key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
|
301
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
302
|
+
File.write key_path, cred_json_text
|
303
|
+
ENV["HOME"] = dir
|
304
|
+
ENV["APPDATA"] = dir
|
305
|
+
connection = Faraday.new headers: { "User-Agent" => "hello" }
|
306
|
+
creds = @clz.from_well_known_path @scope, default_connection: connection
|
307
|
+
expect(creds.build_default_connection).to be connection
|
308
|
+
end
|
309
|
+
end
|
239
310
|
end
|
240
311
|
|
241
|
-
describe
|
242
|
-
before
|
243
|
-
@scope =
|
244
|
-
@
|
312
|
+
describe "#from_system_default_path" do
|
313
|
+
before :example do
|
314
|
+
@scope = "https://www.googleapis.com/auth/userinfo.profile"
|
315
|
+
@program_data = ENV["ProgramData"]
|
316
|
+
@prefix = OS.windows? ? "/etc/Google/Auth/" : "/etc/google/auth/"
|
317
|
+
@path = File.join @prefix, CREDENTIALS_FILE_NAME
|
245
318
|
@clz = ServiceAccountCredentials
|
246
319
|
end
|
247
320
|
|
248
|
-
|
321
|
+
after :example do
|
322
|
+
ENV["ProgramData"] = @program_data
|
323
|
+
end
|
324
|
+
|
325
|
+
it "is nil if no file exists" do
|
249
326
|
FakeFS do
|
250
327
|
expect(ServiceAccountCredentials.from_system_default_path(@scope))
|
251
328
|
.to be_nil
|
252
329
|
end
|
253
330
|
end
|
254
331
|
|
255
|
-
it
|
332
|
+
it "successfully loads the file when it is present" do
|
256
333
|
FakeFS do
|
257
|
-
|
258
|
-
File.
|
334
|
+
ENV["ProgramData"] = "/etc"
|
335
|
+
FileUtils.mkdir_p File.dirname(@path)
|
336
|
+
File.write @path, cred_json_text
|
259
337
|
expect(@clz.from_system_default_path(@scope)).to_not be_nil
|
260
|
-
File.delete
|
338
|
+
File.delete @path
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
it "propagates default_connection option" do
|
343
|
+
FakeFS do
|
344
|
+
ENV["ProgramData"] = "/etc"
|
345
|
+
FileUtils.mkdir_p File.dirname(@path)
|
346
|
+
File.write @path, cred_json_text
|
347
|
+
connection = Faraday.new headers: { "User-Agent" => "hello" }
|
348
|
+
creds = @clz.from_system_default_path @scope, default_connection: connection
|
349
|
+
expect(creds.build_default_connection).to be connection
|
350
|
+
File.delete @path
|
261
351
|
end
|
262
352
|
end
|
263
353
|
end
|
@@ -267,98 +357,133 @@ describe Google::Auth::ServiceAccountJwtHeaderCredentials do
|
|
267
357
|
ServiceAccountJwtHeaderCredentials =
|
268
358
|
Google::Auth::ServiceAccountJwtHeaderCredentials
|
269
359
|
|
270
|
-
let(:client_email) {
|
360
|
+
let(:client_email) { "app@developer.gserviceaccount.com" }
|
271
361
|
let(:clz) { Google::Auth::ServiceAccountJwtHeaderCredentials }
|
272
|
-
let
|
362
|
+
let :cred_json do
|
273
363
|
{
|
274
|
-
private_key_id:
|
275
|
-
private_key:
|
276
|
-
client_email:
|
277
|
-
client_id:
|
278
|
-
type:
|
364
|
+
private_key_id: "a_private_key_id",
|
365
|
+
private_key: @key.to_pem,
|
366
|
+
client_email: client_email,
|
367
|
+
client_id: "app.apps.googleusercontent.com",
|
368
|
+
type: "service_account",
|
369
|
+
project_id: "a_project_id"
|
279
370
|
}
|
280
371
|
end
|
281
372
|
|
282
|
-
before
|
283
|
-
@key = OpenSSL::PKey::RSA.new
|
284
|
-
@client = clz.make_creds
|
373
|
+
before :example do
|
374
|
+
@key = OpenSSL::PKey::RSA.new 2048
|
375
|
+
@client = clz.make_creds json_key_io: StringIO.new(cred_json_text)
|
285
376
|
end
|
286
377
|
|
287
378
|
def cred_json_text
|
288
|
-
MultiJson.dump
|
379
|
+
MultiJson.dump cred_json
|
289
380
|
end
|
290
381
|
|
291
|
-
it_behaves_like
|
382
|
+
it_behaves_like "jwt header auth"
|
292
383
|
|
293
|
-
describe
|
294
|
-
before
|
384
|
+
describe "#from_env" do
|
385
|
+
before :example do
|
295
386
|
@var_name = ENV_VAR
|
296
387
|
@credential_vars = [
|
297
|
-
ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR
|
388
|
+
ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR
|
389
|
+
]
|
298
390
|
@original_env_vals = {}
|
299
391
|
@credential_vars.each { |var| @original_env_vals[var] = ENV[var] }
|
300
392
|
ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
|
301
393
|
end
|
302
394
|
|
303
|
-
after
|
395
|
+
after :example do
|
304
396
|
@credential_vars.each { |var| ENV[var] = @original_env_vals[var] }
|
305
397
|
end
|
306
398
|
|
307
|
-
it
|
308
|
-
ENV.delete
|
399
|
+
it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset" do
|
400
|
+
ENV.delete @var_name unless ENV[@var_name].nil?
|
401
|
+
expect(clz.from_env).to be_nil
|
402
|
+
end
|
403
|
+
|
404
|
+
it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is empty" do
|
405
|
+
ENV[@var_name] = ""
|
309
406
|
expect(clz.from_env).to be_nil
|
310
407
|
end
|
311
408
|
|
312
|
-
it
|
313
|
-
ENV.delete
|
409
|
+
it "fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist" do
|
410
|
+
ENV.delete @var_name unless ENV[@var_name].nil?
|
314
411
|
expect(clz.from_env).to be_nil
|
315
412
|
Dir.mktmpdir do |dir|
|
316
|
-
key_path = File.join
|
413
|
+
key_path = File.join dir, "does-not-exist"
|
317
414
|
ENV[@var_name] = key_path
|
318
415
|
expect { clz.from_env }.to raise_error RuntimeError
|
319
416
|
end
|
320
417
|
end
|
321
418
|
|
322
|
-
it
|
419
|
+
it "succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid" do
|
323
420
|
Dir.mktmpdir do |dir|
|
324
|
-
key_path = File.join
|
325
|
-
FileUtils.mkdir_p
|
326
|
-
File.write
|
421
|
+
key_path = File.join dir, "my_cert_file"
|
422
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
423
|
+
File.write key_path, cred_json_text
|
327
424
|
ENV[@var_name] = key_path
|
328
425
|
expect(clz.from_env).to_not be_nil
|
329
426
|
end
|
330
427
|
end
|
331
428
|
|
332
|
-
it
|
333
|
-
|
429
|
+
it "succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are"\
|
430
|
+
" valid" do
|
334
431
|
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
335
432
|
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
336
433
|
expect(clz.from_env(@scope)).to_not be_nil
|
337
434
|
end
|
435
|
+
|
436
|
+
it "sets project_id when the PROJECT_ID_VAR env var is set" do
|
437
|
+
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
438
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
439
|
+
ENV[PROJECT_ID_VAR] = cred_json[:project_id]
|
440
|
+
ENV[ENV_VAR] = nil
|
441
|
+
credentials = clz.from_env @scope
|
442
|
+
expect(credentials).to_not be_nil
|
443
|
+
expect(credentials.project_id).to eq(cred_json[:project_id])
|
444
|
+
end
|
338
445
|
end
|
339
446
|
|
340
|
-
describe
|
341
|
-
before
|
342
|
-
@home = ENV[
|
447
|
+
describe "#from_well_known_path" do
|
448
|
+
before :example do
|
449
|
+
@home = ENV["HOME"]
|
450
|
+
@app_data = ENV["APPDATA"]
|
343
451
|
end
|
344
452
|
|
345
|
-
after
|
346
|
-
ENV[
|
453
|
+
after :example do
|
454
|
+
ENV["HOME"] = @home unless @home == ENV["HOME"]
|
455
|
+
ENV["APPDATA"] = @app_data unless @app_data == ENV["APPDATA"]
|
347
456
|
end
|
348
457
|
|
349
|
-
it
|
350
|
-
ENV[
|
458
|
+
it "is nil if no file exists" do
|
459
|
+
ENV["HOME"] = File.dirname __FILE__
|
351
460
|
expect(clz.from_well_known_path).to be_nil
|
352
461
|
end
|
353
462
|
|
354
|
-
it
|
463
|
+
it "successfully loads the file when it is present" do
|
355
464
|
Dir.mktmpdir do |dir|
|
356
|
-
key_path = File.join
|
357
|
-
|
358
|
-
File.
|
359
|
-
|
465
|
+
key_path = File.join dir, ".config", WELL_KNOWN_PATH
|
466
|
+
key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
|
467
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
468
|
+
File.write key_path, cred_json_text
|
469
|
+
ENV["HOME"] = dir
|
470
|
+
ENV["APPDATA"] = dir
|
360
471
|
expect(clz.from_well_known_path).to_not be_nil
|
361
472
|
end
|
362
473
|
end
|
474
|
+
|
475
|
+
it "successfully sets project_id when file is present" do
|
476
|
+
Dir.mktmpdir do |dir|
|
477
|
+
key_path = File.join dir, ".config", WELL_KNOWN_PATH
|
478
|
+
key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
|
479
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
480
|
+
File.write key_path, cred_json_text
|
481
|
+
ENV["HOME"] = dir
|
482
|
+
ENV["APPDATA"] = dir
|
483
|
+
credentials = clz.from_well_known_path @scope
|
484
|
+
expect(credentials.project_id).to eq(cred_json[:project_id])
|
485
|
+
expect(credentials.quota_project_id).to be_nil
|
486
|
+
end
|
487
|
+
end
|
363
488
|
end
|
364
489
|
end
|