googleauth 0.5.1 → 0.11.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/{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 +17 -1
- data/CHANGELOG.md +90 -19
- data/CODE_OF_CONDUCT.md +43 -0
- data/Gemfile +16 -13
- data/README.md +58 -18
- data/Rakefile +106 -10
- data/googleauth.gemspec +27 -25
- data/lib/googleauth/application_default.rb +81 -0
- data/lib/googleauth/client_id.rb +21 -19
- data/lib/googleauth/compute_engine.rb +40 -43
- data/lib/googleauth/credentials.rb +375 -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/json_key_reader.rb +46 -0
- data/lib/googleauth/scope_util.rb +12 -12
- data/lib/googleauth/service_account.rb +64 -62
- data/lib/googleauth/signet.rb +53 -12
- 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/lib/googleauth.rb +6 -96
- 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 +47 -46
- data/spec/googleauth/client_id_spec.rb +75 -55
- data/spec/googleauth/compute_engine_spec.rb +60 -43
- data/spec/googleauth/credentials_spec.rb +467 -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 +261 -143
- data/spec/googleauth/signet_spec.rb +93 -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
- metadata +75 -32
- 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,239 @@ 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"
|
119
121
|
}
|
120
122
|
end
|
121
123
|
|
122
|
-
before
|
123
|
-
@key = OpenSSL::PKey::RSA.new
|
124
|
+
before :example do
|
125
|
+
@key = OpenSSL::PKey::RSA.new 2048
|
124
126
|
@client = ServiceAccountCredentials.make_creds(
|
125
127
|
json_key_io: StringIO.new(cred_json_text),
|
126
|
-
scope:
|
128
|
+
scope: "https://www.googleapis.com/auth/userinfo.profile"
|
127
129
|
)
|
128
130
|
end
|
129
131
|
|
130
|
-
def make_auth_stubs
|
131
|
-
access_token = opts[:access_token] ||
|
132
|
-
body = MultiJson.dump(
|
133
|
-
|
134
|
-
|
132
|
+
def make_auth_stubs opts = {}
|
133
|
+
access_token = opts[:access_token] || ""
|
134
|
+
body = MultiJson.dump("access_token" => access_token,
|
135
|
+
"token_type" => "Bearer",
|
136
|
+
"expires_in" => 3600)
|
135
137
|
blk = proc do |request|
|
136
|
-
params = Addressable::URI.form_unencode
|
137
|
-
_claim, _header = JWT.decode(params.assoc(
|
138
|
-
@key.public_key
|
138
|
+
params = Addressable::URI.form_unencode request.body
|
139
|
+
_claim, _header = JWT.decode(params.assoc("assertion").last,
|
140
|
+
@key.public_key, true,
|
141
|
+
algorithm: "RS256")
|
139
142
|
end
|
140
|
-
stub_request(:post,
|
143
|
+
stub_request(:post, "https://www.googleapis.com/oauth2/v4/token")
|
141
144
|
.with(body: hash_including(
|
142
|
-
|
145
|
+
"grant_type" => "urn:ietf:params:oauth:grant-type:jwt-bearer"
|
146
|
+
),
|
143
147
|
&blk)
|
144
|
-
.to_return(body:
|
145
|
-
status:
|
146
|
-
headers: {
|
148
|
+
.to_return(body: body,
|
149
|
+
status: 200,
|
150
|
+
headers: { "Content-Type" => "application/json" })
|
147
151
|
end
|
148
152
|
|
149
153
|
def cred_json_text
|
150
|
-
MultiJson.dump
|
154
|
+
MultiJson.dump cred_json
|
151
155
|
end
|
152
156
|
|
153
|
-
it_behaves_like
|
157
|
+
it_behaves_like "apply/apply! are OK"
|
154
158
|
|
155
|
-
context
|
156
|
-
before
|
159
|
+
context "when scope is nil" do
|
160
|
+
before :example do
|
157
161
|
@client.scope = nil
|
158
162
|
end
|
159
163
|
|
160
|
-
it_behaves_like
|
164
|
+
it_behaves_like "jwt header auth"
|
161
165
|
end
|
162
166
|
|
163
|
-
describe
|
164
|
-
before
|
167
|
+
describe "#from_env" do
|
168
|
+
before :example do
|
165
169
|
@var_name = ENV_VAR
|
166
170
|
@credential_vars = [
|
167
|
-
ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR
|
171
|
+
ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR
|
172
|
+
]
|
168
173
|
@original_env_vals = {}
|
169
174
|
@credential_vars.each { |var| @original_env_vals[var] = ENV[var] }
|
170
175
|
ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
|
171
176
|
|
172
|
-
@scope =
|
177
|
+
@scope = "https://www.googleapis.com/auth/userinfo.profile"
|
173
178
|
@clz = ServiceAccountCredentials
|
174
179
|
end
|
175
180
|
|
176
|
-
after
|
181
|
+
after :example do
|
177
182
|
@credential_vars.each { |var| ENV[var] = @original_env_vals[var] }
|
178
183
|
end
|
179
184
|
|
180
|
-
it
|
181
|
-
ENV.delete
|
185
|
+
it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset" do
|
186
|
+
ENV.delete @var_name unless ENV[@var_name].nil?
|
182
187
|
expect(ServiceAccountCredentials.from_env(@scope)).to be_nil
|
183
188
|
end
|
184
189
|
|
185
|
-
it
|
186
|
-
ENV
|
190
|
+
it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is empty" do
|
191
|
+
ENV[@var_name] = ""
|
192
|
+
expect(ServiceAccountCredentials.from_env(@scope)).to be_nil
|
193
|
+
end
|
194
|
+
|
195
|
+
it "fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist" do
|
196
|
+
ENV.delete @var_name unless ENV[@var_name].nil?
|
187
197
|
expect(ServiceAccountCredentials.from_env(@scope)).to be_nil
|
188
198
|
Dir.mktmpdir do |dir|
|
189
|
-
key_path = File.join
|
199
|
+
key_path = File.join dir, "does-not-exist"
|
190
200
|
ENV[@var_name] = key_path
|
191
|
-
expect { @clz.from_env
|
201
|
+
expect { @clz.from_env @scope }.to raise_error RuntimeError
|
192
202
|
end
|
193
203
|
end
|
194
204
|
|
195
|
-
it
|
205
|
+
it "succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid" do
|
196
206
|
Dir.mktmpdir do |dir|
|
197
|
-
key_path = File.join
|
198
|
-
FileUtils.mkdir_p
|
199
|
-
File.write
|
207
|
+
key_path = File.join dir, "my_cert_file"
|
208
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
209
|
+
File.write key_path, cred_json_text
|
200
210
|
ENV[@var_name] = key_path
|
201
211
|
expect(@clz.from_env(@scope)).to_not be_nil
|
202
212
|
end
|
203
213
|
end
|
204
214
|
|
205
|
-
it
|
206
|
-
|
215
|
+
it "succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are"\
|
216
|
+
" valid" do
|
217
|
+
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
218
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
219
|
+
expect(@clz.from_env(@scope)).to_not be_nil
|
220
|
+
end
|
221
|
+
|
222
|
+
it "sets project_id when the PROJECT_ID_VAR env var is set" do
|
207
223
|
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
208
224
|
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
225
|
+
ENV[PROJECT_ID_VAR] = cred_json[:project_id]
|
226
|
+
ENV[ENV_VAR] = nil
|
227
|
+
credentials = @clz.from_env @scope
|
228
|
+
expect(credentials.project_id).to eq(cred_json[:project_id])
|
229
|
+
end
|
230
|
+
|
231
|
+
it "succeeds when GOOGLE_PRIVATE_KEY is escaped" do
|
232
|
+
escaped_key = cred_json[:private_key].gsub "\n", '\n'
|
233
|
+
ENV[PRIVATE_KEY_VAR] = "\"#{escaped_key}\""
|
234
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
209
235
|
expect(@clz.from_env(@scope)).to_not be_nil
|
210
236
|
end
|
237
|
+
|
238
|
+
it "propagates default_connection option" do
|
239
|
+
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
240
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
241
|
+
connection = Faraday.new headers: { "User-Agent" => "hello" }
|
242
|
+
creds = @clz.from_env @scope, default_connection: connection
|
243
|
+
expect(creds.build_default_connection).to be connection
|
244
|
+
end
|
211
245
|
end
|
212
246
|
|
213
|
-
describe
|
214
|
-
before
|
215
|
-
@home = ENV[
|
216
|
-
@
|
247
|
+
describe "#from_well_known_path" do
|
248
|
+
before :example do
|
249
|
+
@home = ENV["HOME"]
|
250
|
+
@app_data = ENV["APPDATA"]
|
251
|
+
@scope = "https://www.googleapis.com/auth/userinfo.profile"
|
217
252
|
@known_path = WELL_KNOWN_PATH
|
218
253
|
@clz = ServiceAccountCredentials
|
219
254
|
end
|
220
255
|
|
221
|
-
after
|
222
|
-
ENV[
|
256
|
+
after :example do
|
257
|
+
ENV["HOME"] = @home unless @home == ENV["HOME"]
|
258
|
+
ENV["APPDATA"] = @app_data unless @app_data == ENV["APPDATA"]
|
223
259
|
end
|
224
260
|
|
225
|
-
it
|
226
|
-
ENV[
|
261
|
+
it "is nil if no file exists" do
|
262
|
+
ENV["HOME"] = File.dirname __FILE__
|
227
263
|
expect(ServiceAccountCredentials.from_well_known_path(@scope)).to be_nil
|
228
264
|
end
|
229
265
|
|
230
|
-
it
|
266
|
+
it "successfully loads the file when it is present" do
|
231
267
|
Dir.mktmpdir do |dir|
|
232
|
-
key_path = File.join
|
233
|
-
|
234
|
-
File.
|
235
|
-
|
268
|
+
key_path = File.join dir, ".config", @known_path
|
269
|
+
key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
|
270
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
271
|
+
File.write key_path, cred_json_text
|
272
|
+
ENV["HOME"] = dir
|
273
|
+
ENV["APPDATA"] = dir
|
236
274
|
expect(@clz.from_well_known_path(@scope)).to_not be_nil
|
237
275
|
end
|
238
276
|
end
|
277
|
+
|
278
|
+
it "successfully sets project_id when file is present" do
|
279
|
+
Dir.mktmpdir do |dir|
|
280
|
+
key_path = File.join dir, ".config", @known_path
|
281
|
+
key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
|
282
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
283
|
+
File.write key_path, cred_json_text
|
284
|
+
ENV["HOME"] = dir
|
285
|
+
ENV["APPDATA"] = dir
|
286
|
+
credentials = @clz.from_well_known_path @scope
|
287
|
+
expect(credentials.project_id).to eq(cred_json[:project_id])
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
it "propagates default_connection option" do
|
292
|
+
Dir.mktmpdir do |dir|
|
293
|
+
key_path = File.join dir, ".config", @known_path
|
294
|
+
key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
|
295
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
296
|
+
File.write key_path, cred_json_text
|
297
|
+
ENV["HOME"] = dir
|
298
|
+
ENV["APPDATA"] = dir
|
299
|
+
connection = Faraday.new headers: { "User-Agent" => "hello" }
|
300
|
+
creds = @clz.from_well_known_path @scope, default_connection: connection
|
301
|
+
expect(creds.build_default_connection).to be connection
|
302
|
+
end
|
303
|
+
end
|
239
304
|
end
|
240
305
|
|
241
|
-
describe
|
242
|
-
before
|
243
|
-
@scope =
|
244
|
-
@
|
306
|
+
describe "#from_system_default_path" do
|
307
|
+
before :example do
|
308
|
+
@scope = "https://www.googleapis.com/auth/userinfo.profile"
|
309
|
+
@program_data = ENV["ProgramData"]
|
310
|
+
@prefix = OS.windows? ? "/etc/Google/Auth/" : "/etc/google/auth/"
|
311
|
+
@path = File.join @prefix, CREDENTIALS_FILE_NAME
|
245
312
|
@clz = ServiceAccountCredentials
|
246
313
|
end
|
247
314
|
|
248
|
-
|
315
|
+
after :example do
|
316
|
+
ENV["ProgramData"] = @program_data
|
317
|
+
end
|
318
|
+
|
319
|
+
it "is nil if no file exists" do
|
249
320
|
FakeFS do
|
250
321
|
expect(ServiceAccountCredentials.from_system_default_path(@scope))
|
251
322
|
.to be_nil
|
252
323
|
end
|
253
324
|
end
|
254
325
|
|
255
|
-
it
|
326
|
+
it "successfully loads the file when it is present" do
|
256
327
|
FakeFS do
|
257
|
-
|
258
|
-
File.
|
328
|
+
ENV["ProgramData"] = "/etc"
|
329
|
+
FileUtils.mkdir_p File.dirname(@path)
|
330
|
+
File.write @path, cred_json_text
|
259
331
|
expect(@clz.from_system_default_path(@scope)).to_not be_nil
|
260
|
-
File.delete
|
332
|
+
File.delete @path
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
it "propagates default_connection option" do
|
337
|
+
FakeFS do
|
338
|
+
ENV["ProgramData"] = "/etc"
|
339
|
+
FileUtils.mkdir_p File.dirname(@path)
|
340
|
+
File.write @path, cred_json_text
|
341
|
+
connection = Faraday.new headers: { "User-Agent" => "hello" }
|
342
|
+
creds = @clz.from_system_default_path @scope, default_connection: connection
|
343
|
+
expect(creds.build_default_connection).to be connection
|
344
|
+
File.delete @path
|
261
345
|
end
|
262
346
|
end
|
263
347
|
end
|
@@ -267,98 +351,132 @@ describe Google::Auth::ServiceAccountJwtHeaderCredentials do
|
|
267
351
|
ServiceAccountJwtHeaderCredentials =
|
268
352
|
Google::Auth::ServiceAccountJwtHeaderCredentials
|
269
353
|
|
270
|
-
let(:client_email) {
|
354
|
+
let(:client_email) { "app@developer.gserviceaccount.com" }
|
271
355
|
let(:clz) { Google::Auth::ServiceAccountJwtHeaderCredentials }
|
272
|
-
let
|
356
|
+
let :cred_json do
|
273
357
|
{
|
274
|
-
private_key_id:
|
275
|
-
private_key:
|
276
|
-
client_email:
|
277
|
-
client_id:
|
278
|
-
type:
|
358
|
+
private_key_id: "a_private_key_id",
|
359
|
+
private_key: @key.to_pem,
|
360
|
+
client_email: client_email,
|
361
|
+
client_id: "app.apps.googleusercontent.com",
|
362
|
+
type: "service_account",
|
363
|
+
project_id: "a_project_id"
|
279
364
|
}
|
280
365
|
end
|
281
366
|
|
282
|
-
before
|
283
|
-
@key = OpenSSL::PKey::RSA.new
|
284
|
-
@client = clz.make_creds
|
367
|
+
before :example do
|
368
|
+
@key = OpenSSL::PKey::RSA.new 2048
|
369
|
+
@client = clz.make_creds json_key_io: StringIO.new(cred_json_text)
|
285
370
|
end
|
286
371
|
|
287
372
|
def cred_json_text
|
288
|
-
MultiJson.dump
|
373
|
+
MultiJson.dump cred_json
|
289
374
|
end
|
290
375
|
|
291
|
-
it_behaves_like
|
376
|
+
it_behaves_like "jwt header auth"
|
292
377
|
|
293
|
-
describe
|
294
|
-
before
|
378
|
+
describe "#from_env" do
|
379
|
+
before :example do
|
295
380
|
@var_name = ENV_VAR
|
296
381
|
@credential_vars = [
|
297
|
-
ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR
|
382
|
+
ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR
|
383
|
+
]
|
298
384
|
@original_env_vals = {}
|
299
385
|
@credential_vars.each { |var| @original_env_vals[var] = ENV[var] }
|
300
386
|
ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
|
301
387
|
end
|
302
388
|
|
303
|
-
after
|
389
|
+
after :example do
|
304
390
|
@credential_vars.each { |var| ENV[var] = @original_env_vals[var] }
|
305
391
|
end
|
306
392
|
|
307
|
-
it
|
308
|
-
ENV.delete
|
393
|
+
it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset" do
|
394
|
+
ENV.delete @var_name unless ENV[@var_name].nil?
|
395
|
+
expect(clz.from_env).to be_nil
|
396
|
+
end
|
397
|
+
|
398
|
+
it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is empty" do
|
399
|
+
ENV[@var_name] = ""
|
309
400
|
expect(clz.from_env).to be_nil
|
310
401
|
end
|
311
402
|
|
312
|
-
it
|
313
|
-
ENV.delete
|
403
|
+
it "fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist" do
|
404
|
+
ENV.delete @var_name unless ENV[@var_name].nil?
|
314
405
|
expect(clz.from_env).to be_nil
|
315
406
|
Dir.mktmpdir do |dir|
|
316
|
-
key_path = File.join
|
407
|
+
key_path = File.join dir, "does-not-exist"
|
317
408
|
ENV[@var_name] = key_path
|
318
409
|
expect { clz.from_env }.to raise_error RuntimeError
|
319
410
|
end
|
320
411
|
end
|
321
412
|
|
322
|
-
it
|
413
|
+
it "succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid" do
|
323
414
|
Dir.mktmpdir do |dir|
|
324
|
-
key_path = File.join
|
325
|
-
FileUtils.mkdir_p
|
326
|
-
File.write
|
415
|
+
key_path = File.join dir, "my_cert_file"
|
416
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
417
|
+
File.write key_path, cred_json_text
|
327
418
|
ENV[@var_name] = key_path
|
328
419
|
expect(clz.from_env).to_not be_nil
|
329
420
|
end
|
330
421
|
end
|
331
422
|
|
332
|
-
it
|
333
|
-
|
423
|
+
it "succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are"\
|
424
|
+
" valid" do
|
334
425
|
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
335
426
|
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
336
427
|
expect(clz.from_env(@scope)).to_not be_nil
|
337
428
|
end
|
429
|
+
|
430
|
+
it "sets project_id when the PROJECT_ID_VAR env var is set" do
|
431
|
+
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
432
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
433
|
+
ENV[PROJECT_ID_VAR] = cred_json[:project_id]
|
434
|
+
ENV[ENV_VAR] = nil
|
435
|
+
credentials = clz.from_env @scope
|
436
|
+
expect(credentials).to_not be_nil
|
437
|
+
expect(credentials.project_id).to eq(cred_json[:project_id])
|
438
|
+
end
|
338
439
|
end
|
339
440
|
|
340
|
-
describe
|
341
|
-
before
|
342
|
-
@home = ENV[
|
441
|
+
describe "#from_well_known_path" do
|
442
|
+
before :example do
|
443
|
+
@home = ENV["HOME"]
|
444
|
+
@app_data = ENV["APPDATA"]
|
343
445
|
end
|
344
446
|
|
345
|
-
after
|
346
|
-
ENV[
|
447
|
+
after :example do
|
448
|
+
ENV["HOME"] = @home unless @home == ENV["HOME"]
|
449
|
+
ENV["APPDATA"] = @app_data unless @app_data == ENV["APPDATA"]
|
347
450
|
end
|
348
451
|
|
349
|
-
it
|
350
|
-
ENV[
|
452
|
+
it "is nil if no file exists" do
|
453
|
+
ENV["HOME"] = File.dirname __FILE__
|
351
454
|
expect(clz.from_well_known_path).to be_nil
|
352
455
|
end
|
353
456
|
|
354
|
-
it
|
457
|
+
it "successfully loads the file when it is present" do
|
355
458
|
Dir.mktmpdir do |dir|
|
356
|
-
key_path = File.join
|
357
|
-
|
358
|
-
File.
|
359
|
-
|
459
|
+
key_path = File.join dir, ".config", WELL_KNOWN_PATH
|
460
|
+
key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
|
461
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
462
|
+
File.write key_path, cred_json_text
|
463
|
+
ENV["HOME"] = dir
|
464
|
+
ENV["APPDATA"] = dir
|
360
465
|
expect(clz.from_well_known_path).to_not be_nil
|
361
466
|
end
|
362
467
|
end
|
468
|
+
|
469
|
+
it "successfully sets project_id when file is present" do
|
470
|
+
Dir.mktmpdir do |dir|
|
471
|
+
key_path = File.join dir, ".config", WELL_KNOWN_PATH
|
472
|
+
key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
|
473
|
+
FileUtils.mkdir_p File.dirname(key_path)
|
474
|
+
File.write key_path, cred_json_text
|
475
|
+
ENV["HOME"] = dir
|
476
|
+
ENV["APPDATA"] = dir
|
477
|
+
credentials = clz.from_well_known_path @scope
|
478
|
+
expect(credentials.project_id).to eq(cred_json[:project_id])
|
479
|
+
end
|
480
|
+
end
|
363
481
|
end
|
364
482
|
end
|