googleauth 0.8.1 → 0.13.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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.kokoro/build.bat +9 -1
  3. data/.kokoro/continuous/linux.cfg +12 -2
  4. data/.kokoro/continuous/osx.cfg +5 -0
  5. data/.kokoro/continuous/post.cfg +30 -0
  6. data/.kokoro/continuous/windows.cfg +27 -1
  7. data/.kokoro/presubmit/linux.cfg +11 -1
  8. data/.kokoro/presubmit/osx.cfg +5 -0
  9. data/.kokoro/presubmit/windows.cfg +27 -1
  10. data/.kokoro/release.cfg +42 -1
  11. data/.kokoro/trampoline.bat +10 -0
  12. data/.repo-metadata.json +5 -0
  13. data/.rubocop.yml +10 -2
  14. data/CHANGELOG.md +34 -0
  15. data/Gemfile +8 -3
  16. data/README.md +7 -12
  17. data/Rakefile +48 -5
  18. data/googleauth.gemspec +6 -3
  19. data/integration/helper.rb +31 -0
  20. data/integration/id_tokens/key_source_test.rb +74 -0
  21. data/lib/googleauth.rb +1 -0
  22. data/lib/googleauth/application_default.rb +1 -1
  23. data/lib/googleauth/compute_engine.rb +19 -17
  24. data/lib/googleauth/credentials.rb +318 -63
  25. data/lib/googleauth/credentials_loader.rb +10 -8
  26. data/lib/googleauth/id_tokens.rb +233 -0
  27. data/lib/googleauth/id_tokens/errors.rb +71 -0
  28. data/lib/googleauth/id_tokens/key_sources.rb +394 -0
  29. data/lib/googleauth/id_tokens/verifier.rb +144 -0
  30. data/lib/googleauth/json_key_reader.rb +6 -2
  31. data/lib/googleauth/service_account.rb +16 -7
  32. data/lib/googleauth/signet.rb +8 -5
  33. data/lib/googleauth/user_authorizer.rb +6 -1
  34. data/lib/googleauth/user_refresh.rb +2 -2
  35. data/lib/googleauth/version.rb +1 -1
  36. data/lib/googleauth/web_user_authorizer.rb +13 -8
  37. data/rakelib/devsite_builder.rb +45 -0
  38. data/rakelib/link_checker.rb +64 -0
  39. data/rakelib/repo_metadata.rb +59 -0
  40. data/spec/googleauth/apply_auth_examples.rb +28 -5
  41. data/spec/googleauth/compute_engine_spec.rb +25 -13
  42. data/spec/googleauth/credentials_spec.rb +366 -161
  43. data/spec/googleauth/service_account_spec.rb +23 -16
  44. data/spec/googleauth/signet_spec.rb +46 -7
  45. data/spec/googleauth/user_authorizer_spec.rb +21 -1
  46. data/spec/googleauth/user_refresh_spec.rb +1 -1
  47. data/spec/googleauth/web_user_authorizer_spec.rb +6 -0
  48. data/test/helper.rb +33 -0
  49. data/test/id_tokens/key_sources_test.rb +240 -0
  50. data/test/id_tokens/verifier_test.rb +269 -0
  51. metadata +46 -12
  52. data/.kokoro/windows.sh +0 -4
@@ -0,0 +1,59 @@
1
+ require "json"
2
+
3
+ class RepoMetadata
4
+ attr_reader :data
5
+
6
+ def initialize data
7
+ @data = data
8
+ normalize_data!
9
+ end
10
+
11
+ def allowed_fields
12
+ [
13
+ "name", "version", "language", "distribution-name",
14
+ "product-page", "github-repository", "issue-tracker"
15
+ ]
16
+ end
17
+
18
+ def build output_directory
19
+ fields = @data.to_a.map { |kv| "--#{kv[0]} #{kv[1]}" }
20
+ Dir.chdir output_directory do
21
+ cmd "python3 -m docuploader create-metadata #{fields.join ' '}"
22
+ end
23
+ end
24
+
25
+ def normalize_data!
26
+ require_relative "../lib/googleauth/version.rb"
27
+
28
+ @data.delete_if { |k, _| !allowed_fields.include?(k) }
29
+ @data["version"] = "v#{Google::Auth::VERSION}"
30
+ end
31
+
32
+ def [] key
33
+ data[key]
34
+ end
35
+
36
+ def []= key, value
37
+ @data[key] = value
38
+ end
39
+
40
+ def cmd line
41
+ puts line
42
+ output = `#{line}`
43
+ puts output
44
+ output
45
+ end
46
+
47
+ def self.from_source source
48
+ if source.is_a? RepoMetadata
49
+ data = source.data
50
+ elsif source.is_a? Hash
51
+ data = source
52
+ elsif File.file? source
53
+ data = JSON.parse File.read(source)
54
+ else
55
+ raise "Source must be a path, hash, or RepoMetadata instance"
56
+ end
57
+ RepoMetadata.new data
58
+ end
59
+ end
@@ -45,26 +45,37 @@ shared_examples "apply/apply! are OK" do
45
45
  # auth client
46
46
  describe "#fetch_access_token" do
47
47
  let(:token) { "1/abcdef1234567890" }
48
- let :stub do
48
+ let :access_stub do
49
49
  make_auth_stubs access_token: token
50
50
  end
51
+ let :id_stub do
52
+ make_auth_stubs id_token: token
53
+ end
51
54
 
52
55
  it "should set access_token to the fetched value" do
53
- stub
56
+ access_stub
54
57
  @client.fetch_access_token!
55
58
  expect(@client.access_token).to eq(token)
56
- expect(stub).to have_been_requested
59
+ expect(access_stub).to have_been_requested
60
+ end
61
+
62
+ it "should set id_token to the fetched value" do
63
+ skip unless @id_client
64
+ id_stub
65
+ @id_client.fetch_access_token!
66
+ expect(@id_client.id_token).to eq(token)
67
+ expect(id_stub).to have_been_requested
57
68
  end
58
69
 
59
70
  it "should notify refresh listeners after updating" do
60
- stub
71
+ access_stub
61
72
  expect do |b|
62
73
  @client.on_refresh(&b)
63
74
  @client.fetch_access_token!
64
75
  end.to yield_with_args(have_attributes(
65
76
  access_token: "1/abcdef1234567890"
66
77
  ))
67
- expect(stub).to have_been_requested
78
+ expect(access_stub).to have_been_requested
68
79
  end
69
80
  end
70
81
 
@@ -79,6 +90,18 @@ shared_examples "apply/apply! are OK" do
79
90
  expect(md).to eq(want)
80
91
  expect(stub).to have_been_requested
81
92
  end
93
+
94
+ it "should update the target hash with fetched ID token" do
95
+ skip unless @id_client
96
+ token = "1/abcdef1234567890"
97
+ stub = make_auth_stubs id_token: token
98
+
99
+ md = { foo: "bar" }
100
+ @id_client.apply! md
101
+ want = { :foo => "bar", auth_key => "Bearer #{token}" }
102
+ expect(md).to eq(want)
103
+ expect(stub).to have_been_requested
104
+ end
82
105
  end
83
106
 
84
107
  describe "updater_proc" do
@@ -37,23 +37,32 @@ require "googleauth/compute_engine"
37
37
  require "spec_helper"
38
38
 
39
39
  describe Google::Auth::GCECredentials do
40
- MD_URI = "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token".freeze
40
+ MD_ACCESS_URI = "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token".freeze
41
+ MD_ID_URI = "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://pubsub.googleapis.com/&format=full".freeze
41
42
  GCECredentials = Google::Auth::GCECredentials
42
43
 
43
44
  before :example do
44
45
  @client = GCECredentials.new
46
+ @id_client = GCECredentials.new target_audience: "https://pubsub.googleapis.com/"
45
47
  end
46
48
 
47
- def make_auth_stubs opts = {}
48
- access_token = opts[:access_token] || ""
49
- body = MultiJson.dump("access_token" => access_token,
50
- "token_type" => "Bearer",
51
- "expires_in" => 3600)
52
- stub_request(:get, MD_URI)
53
- .with(headers: { "Metadata-Flavor" => "Google" })
54
- .to_return(body: body,
55
- status: 200,
56
- headers: { "Content-Type" => "application/json" })
49
+ def make_auth_stubs opts
50
+ if opts[:access_token]
51
+ body = MultiJson.dump("access_token" => opts[:access_token],
52
+ "token_type" => "Bearer",
53
+ "expires_in" => 3600)
54
+ stub_request(:get, MD_ACCESS_URI)
55
+ .with(headers: { "Metadata-Flavor" => "Google" })
56
+ .to_return(body: body,
57
+ status: 200,
58
+ headers: { "Content-Type" => "application/json" })
59
+ elsif opts[:id_token]
60
+ stub_request(:get, MD_ID_URI)
61
+ .with(headers: { "Metadata-Flavor" => "Google" })
62
+ .to_return(body: opts[:id_token],
63
+ status: 200,
64
+ headers: { "Content-Type" => "text/html" })
65
+ end
57
66
  end
58
67
 
59
68
  it_behaves_like "apply/apply! are OK"
@@ -61,7 +70,7 @@ describe Google::Auth::GCECredentials do
61
70
  context "metadata is unavailable" do
62
71
  describe "#fetch_access_token" do
63
72
  it "should fail if the metadata request returns a 404" do
64
- stub = stub_request(:get, MD_URI)
73
+ stub = stub_request(:get, MD_ACCESS_URI)
65
74
  .to_return(status: 404,
66
75
  headers: { "Metadata-Flavor" => "Google" })
67
76
  expect { @client.fetch_access_token! }
@@ -70,7 +79,7 @@ describe Google::Auth::GCECredentials do
70
79
  end
71
80
 
72
81
  it "should fail if the metadata request returns an unexpected code" do
73
- stub = stub_request(:get, MD_URI)
82
+ stub = stub_request(:get, MD_ACCESS_URI)
74
83
  .to_return(status: 503,
75
84
  headers: { "Metadata-Flavor" => "Google" })
76
85
  expect { @client.fetch_access_token! }
@@ -97,6 +106,7 @@ describe Google::Auth::GCECredentials do
97
106
  describe "#on_gce?" do
98
107
  it "should be true when Metadata-Flavor is Google" do
99
108
  stub = stub_request(:get, "http://169.254.169.254")
109
+ .with(headers: { "Metadata-Flavor" => "Google" })
100
110
  .to_return(status: 200,
101
111
  headers: { "Metadata-Flavor" => "Google" })
102
112
  expect(GCECredentials.on_gce?({}, true)).to eq(true)
@@ -105,6 +115,7 @@ describe Google::Auth::GCECredentials do
105
115
 
106
116
  it "should be false when Metadata-Flavor is not Google" do
107
117
  stub = stub_request(:get, "http://169.254.169.254")
118
+ .with(headers: { "Metadata-Flavor" => "Google" })
108
119
  .to_return(status: 200,
109
120
  headers: { "Metadata-Flavor" => "NotGoogle" })
110
121
  expect(GCECredentials.on_gce?({}, true)).to eq(false)
@@ -113,6 +124,7 @@ describe Google::Auth::GCECredentials do
113
124
 
114
125
  it "should be false if the response is not 200" do
115
126
  stub = stub_request(:get, "http://169.254.169.254")
127
+ .with(headers: { "Metadata-Flavor" => "Google" })
116
128
  .to_return(status: 404,
117
129
  headers: { "Metadata-Flavor" => "NotGoogle" })
118
130
  expect(GCECredentials.on_gce?({}, true)).to eq(false)
@@ -36,12 +36,13 @@ require "googleauth"
36
36
  describe Google::Auth::Credentials, :private do
37
37
  let :default_keyfile_hash do
38
38
  {
39
- "private_key_id" => "testabc1234567890xyz",
40
- "private_key" => "-----BEGIN RSA PRIVATE KEY-----\nMIIBOwIBAAJBAOyi0Hy1l4Ym2m2o71Q0TF4O9E81isZEsX0bb+Bqz1SXEaSxLiXM\nUZE8wu0eEXivXuZg6QVCW/5l+f2+9UPrdNUCAwEAAQJAJkqubA/Chj3RSL92guy3\nktzeodarLyw8gF8pOmpuRGSiEo/OLTeRUMKKD1/kX4f9sxf3qDhB4e7dulXR1co/\nIQIhAPx8kMW4XTTL6lJYd2K5GrH8uBMp8qL5ya3/XHrBgw3dAiEA7+3Iw3ULTn2I\n1J34WlJ2D5fbzMzB4FAHUNEV7Ys3f1kCIQDtUahCMChrl7+H5t9QS+xrn77lRGhs\nB50pjvy95WXpgQIhAI2joW6JzTfz8fAapb+kiJ/h9Vcs1ZN3iyoRlNFb61JZAiA8\nNy5NyNrMVwtB/lfJf1dAK/p/Bwd8LZLtgM6PapRfgw==\n-----END RSA PRIVATE KEY-----\n",
41
- "client_email" => "credz-testabc1234567890xyz@developer.gserviceaccount.com",
42
- "client_id" => "credz-testabc1234567890xyz.apps.googleusercontent.com",
43
- "type" => "service_account",
44
- "project_id" => "a_project_id"
39
+ "private_key_id" => "testabc1234567890xyz",
40
+ "private_key" => "-----BEGIN RSA PRIVATE KEY-----\nMIIBOwIBAAJBAOyi0Hy1l4Ym2m2o71Q0TF4O9E81isZEsX0bb+Bqz1SXEaSxLiXM\nUZE8wu0eEXivXuZg6QVCW/5l+f2+9UPrdNUCAwEAAQJAJkqubA/Chj3RSL92guy3\nktzeodarLyw8gF8pOmpuRGSiEo/OLTeRUMKKD1/kX4f9sxf3qDhB4e7dulXR1co/\nIQIhAPx8kMW4XTTL6lJYd2K5GrH8uBMp8qL5ya3/XHrBgw3dAiEA7+3Iw3ULTn2I\n1J34WlJ2D5fbzMzB4FAHUNEV7Ys3f1kCIQDtUahCMChrl7+H5t9QS+xrn77lRGhs\nB50pjvy95WXpgQIhAI2joW6JzTfz8fAapb+kiJ/h9Vcs1ZN3iyoRlNFb61JZAiA8\nNy5NyNrMVwtB/lfJf1dAK/p/Bwd8LZLtgM6PapRfgw==\n-----END RSA PRIVATE KEY-----\n",
41
+ "client_email" => "credz-testabc1234567890xyz@developer.gserviceaccount.com",
42
+ "client_id" => "credz-testabc1234567890xyz.apps.googleusercontent.com",
43
+ "type" => "service_account",
44
+ "project_id" => "a_project_id",
45
+ "quota_project_id" => "b_project_id"
45
46
  }
46
47
  end
47
48
 
@@ -81,181 +82,385 @@ describe Google::Auth::Credentials, :private do
81
82
  Google::Auth::Credentials.new default_keyfile_hash, scope: "http://example.com/scope"
82
83
  end
83
84
 
84
- it "can be subclassed to pass in other env paths" do
85
- TEST_PATH_ENV_VAR = "TEST_PATH".freeze
86
- TEST_PATH_ENV_VAL = "/unknown/path/to/file.txt".freeze
87
- TEST_JSON_ENV_VAR = "TEST_JSON_VARS".freeze
88
-
89
- ENV[TEST_PATH_ENV_VAR] = TEST_PATH_ENV_VAL
90
- ENV[TEST_JSON_ENV_VAR] = JSON.generate default_keyfile_hash
91
-
92
- class TestCredentials < Google::Auth::Credentials
93
- SCOPE = "http://example.com/scope".freeze
94
- PATH_ENV_VARS = [TEST_PATH_ENV_VAR].freeze
95
- JSON_ENV_VARS = [TEST_JSON_ENV_VAR].freeze
85
+ describe "using CONSTANTS" do
86
+ it "can be subclassed to pass in other env paths" do
87
+ test_path_env_val = "/unknown/path/to/file.txt".freeze
88
+ test_json_env_val = JSON.generate default_keyfile_hash
89
+
90
+ ENV["TEST_PATH"] = test_path_env_val
91
+ ENV["TEST_JSON_VARS"] = test_json_env_val
92
+
93
+ class TestCredentials1 < Google::Auth::Credentials
94
+ TOKEN_CREDENTIAL_URI = "https://example.com/token".freeze
95
+ AUDIENCE = "https://example.com/audience".freeze
96
+ SCOPE = "http://example.com/scope".freeze
97
+ PATH_ENV_VARS = ["TEST_PATH"].freeze
98
+ JSON_ENV_VARS = ["TEST_JSON_VARS"].freeze
99
+ end
100
+
101
+ allow(::File).to receive(:file?).with(test_path_env_val) { false }
102
+ allow(::File).to receive(:file?).with(test_json_env_val) { false }
103
+
104
+ mocked_signet = double "Signet::OAuth2::Client"
105
+ allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
106
+ allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
107
+ allow(mocked_signet).to receive(:client_id)
108
+ allow(Signet::OAuth2::Client).to receive(:new) do |options|
109
+ expect(options[:token_credential_uri]).to eq("https://example.com/token")
110
+ expect(options[:audience]).to eq("https://example.com/audience")
111
+ expect(options[:scope]).to eq(["http://example.com/scope"])
112
+ expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
113
+ expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
114
+
115
+ mocked_signet
116
+ end
117
+
118
+ creds = TestCredentials1.default
119
+ expect(creds).to be_a_kind_of(TestCredentials1)
120
+ expect(creds.client).to eq(mocked_signet)
121
+ expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
122
+ expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
96
123
  end
97
124
 
98
- allow(::File).to receive(:file?).with(TEST_PATH_ENV_VAL) { false }
99
-
100
- mocked_signet = double "Signet::OAuth2::Client"
101
- allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
102
- allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
103
- allow(mocked_signet).to receive(:client_id)
104
- allow(Signet::OAuth2::Client).to receive(:new) do |options|
105
- expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
106
- expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
107
- expect(options[:scope]).to eq(["http://example.com/scope"])
108
- expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
109
- expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
110
-
111
- mocked_signet
125
+ it "subclasses can use PATH_ENV_VARS to get keyfile path" do
126
+ class TestCredentials2 < Google::Auth::Credentials
127
+ SCOPE = "http://example.com/scope".freeze
128
+ PATH_ENV_VARS = %w[PATH_ENV_DUMMY PATH_ENV_TEST].freeze
129
+ JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze
130
+ DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
131
+ end
132
+
133
+ allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
134
+ allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
135
+ allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
136
+ allow(::ENV).to receive(:[]).with("PATH_ENV_TEST") { "/unknown/path/to/file.txt" }
137
+ allow(::File).to receive(:file?).with("/unknown/path/to/file.txt") { true }
138
+ allow(::File).to receive(:read).with("/unknown/path/to/file.txt") { JSON.generate default_keyfile_hash }
139
+
140
+ mocked_signet = double "Signet::OAuth2::Client"
141
+ allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
142
+ allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
143
+ allow(mocked_signet).to receive(:client_id)
144
+ allow(Signet::OAuth2::Client).to receive(:new) do |options|
145
+ expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
146
+ expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
147
+ expect(options[:scope]).to eq(["http://example.com/scope"])
148
+ expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
149
+ expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
150
+
151
+ mocked_signet
152
+ end
153
+
154
+ creds = TestCredentials2.default
155
+ expect(creds).to be_a_kind_of(TestCredentials2)
156
+ expect(creds.client).to eq(mocked_signet)
157
+ expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
158
+ expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
112
159
  end
113
160
 
114
- creds = TestCredentials.default
115
- expect(creds).to be_a_kind_of(TestCredentials)
116
- expect(creds.client).to eq(mocked_signet)
117
- expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
118
- end
119
-
120
- it "subclasses can use PATH_ENV_VARS to get keyfile path" do
121
- class TestCredentials < Google::Auth::Credentials
122
- SCOPE = "http://example.com/scope".freeze
123
- PATH_ENV_VARS = %w[PATH_ENV_DUMMY PATH_ENV_TEST].freeze
124
- JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze
125
- DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
161
+ it "subclasses can use JSON_ENV_VARS to get keyfile contents" do
162
+ test_json_env_val = JSON.generate default_keyfile_hash
163
+
164
+ class TestCredentials3 < Google::Auth::Credentials
165
+ SCOPE = "http://example.com/scope".freeze
166
+ PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze
167
+ JSON_ENV_VARS = %w[JSON_ENV_DUMMY JSON_ENV_TEST].freeze
168
+ DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
169
+ end
170
+
171
+ allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
172
+ allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
173
+ allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
174
+ allow(::File).to receive(:file?).with(test_json_env_val) { false }
175
+ allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
176
+ allow(::ENV).to receive(:[]).with("JSON_ENV_TEST") { test_json_env_val }
177
+
178
+ mocked_signet = double "Signet::OAuth2::Client"
179
+ allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
180
+ allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
181
+ allow(mocked_signet).to receive(:client_id)
182
+ allow(Signet::OAuth2::Client).to receive(:new) do |options|
183
+ expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
184
+ expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
185
+ expect(options[:scope]).to eq(["http://example.com/scope"])
186
+ expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
187
+ expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
188
+
189
+ mocked_signet
190
+ end
191
+
192
+ creds = TestCredentials3.default
193
+ expect(creds).to be_a_kind_of(TestCredentials3)
194
+ expect(creds.client).to eq(mocked_signet)
195
+ expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
196
+ expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
126
197
  end
127
198
 
128
- allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
129
- allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
130
- allow(::ENV).to receive(:[]).with("PATH_ENV_TEST") { "/unknown/path/to/file.txt" }
131
- allow(::File).to receive(:file?).with("/unknown/path/to/file.txt") { true }
132
- allow(::File).to receive(:read).with("/unknown/path/to/file.txt") { JSON.generate default_keyfile_hash }
133
-
134
- mocked_signet = double "Signet::OAuth2::Client"
135
- allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
136
- allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
137
- allow(mocked_signet).to receive(:client_id)
138
- allow(Signet::OAuth2::Client).to receive(:new) do |options|
139
- expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
140
- expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
141
- expect(options[:scope]).to eq(["http://example.com/scope"])
142
- expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
143
- expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
144
-
145
- mocked_signet
199
+ it "subclasses can use DEFAULT_PATHS to get keyfile path" do
200
+ class TestCredentials4 < Google::Auth::Credentials
201
+ SCOPE = "http://example.com/scope".freeze
202
+ PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze
203
+ JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze
204
+ DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
205
+ end
206
+
207
+ allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
208
+ allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
209
+ allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
210
+ allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
211
+ allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { true }
212
+ allow(::File).to receive(:read).with("~/default/path/to/file.txt") { JSON.generate default_keyfile_hash }
213
+
214
+ mocked_signet = double "Signet::OAuth2::Client"
215
+ allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
216
+ allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
217
+ allow(mocked_signet).to receive(:client_id)
218
+ allow(Signet::OAuth2::Client).to receive(:new) do |options|
219
+ expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
220
+ expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
221
+ expect(options[:scope]).to eq(["http://example.com/scope"])
222
+ expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
223
+ expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
224
+
225
+ mocked_signet
226
+ end
227
+
228
+ creds = TestCredentials4.default
229
+ expect(creds).to be_a_kind_of(TestCredentials4)
230
+ expect(creds.client).to eq(mocked_signet)
231
+ expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
232
+ expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
146
233
  end
147
234
 
148
- creds = TestCredentials.default
149
- expect(creds).to be_a_kind_of(TestCredentials)
150
- expect(creds.client).to eq(mocked_signet)
151
- expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
152
- end
153
-
154
- it "subclasses can use JSON_ENV_VARS to get keyfile contents" do
155
- class TestCredentials < Google::Auth::Credentials
156
- SCOPE = "http://example.com/scope".freeze
157
- PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze
158
- JSON_ENV_VARS = %w[JSON_ENV_DUMMY JSON_ENV_TEST].freeze
159
- DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
235
+ it "subclasses that find no matches default to Google::Auth.get_application_default" do
236
+ class TestCredentials5 < Google::Auth::Credentials
237
+ SCOPE = "http://example.com/scope".freeze
238
+ PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze
239
+ JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze
240
+ DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
241
+ end
242
+
243
+ allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
244
+ allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
245
+ allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
246
+ allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
247
+ allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { false }
248
+
249
+ mocked_signet = double "Signet::OAuth2::Client"
250
+ allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
251
+ allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
252
+ allow(mocked_signet).to receive(:client_id)
253
+ allow(Google::Auth).to receive(:get_application_default) do |scope|
254
+ expect(scope).to eq([TestCredentials5::SCOPE])
255
+
256
+ # This should really be a Signet::OAuth2::Client object,
257
+ # but mocking is making that difficult, so return a valid hash instead.
258
+ default_keyfile_hash
259
+ end
260
+ allow(Signet::OAuth2::Client).to receive(:new) do |options|
261
+ expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
262
+ expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
263
+ expect(options[:scope]).to eq(["http://example.com/scope"])
264
+ expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
265
+ expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
266
+
267
+ mocked_signet
268
+ end
269
+
270
+ creds = TestCredentials5.default
271
+ expect(creds).to be_a_kind_of(TestCredentials5)
272
+ expect(creds.client).to eq(mocked_signet)
273
+ expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
274
+ expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
160
275
  end
161
-
162
- allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
163
- allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
164
- allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
165
- allow(::ENV).to receive(:[]).with("JSON_ENV_TEST") { JSON.generate default_keyfile_hash }
166
-
167
- mocked_signet = double "Signet::OAuth2::Client"
168
- allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
169
- allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
170
- allow(mocked_signet).to receive(:client_id)
171
- allow(Signet::OAuth2::Client).to receive(:new) do |options|
172
- expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
173
- expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
174
- expect(options[:scope]).to eq(["http://example.com/scope"])
175
- expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
176
- expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
177
-
178
- mocked_signet
179
- end
180
-
181
- creds = TestCredentials.default
182
- expect(creds).to be_a_kind_of(TestCredentials)
183
- expect(creds.client).to eq(mocked_signet)
184
- expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
185
276
  end
186
277
 
187
- it "subclasses can use DEFAULT_PATHS to get keyfile path" do
188
- class TestCredentials < Google::Auth::Credentials
189
- SCOPE = "http://example.com/scope".freeze
190
- PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze
191
- JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze
192
- DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
278
+ describe "using class methods" do
279
+ it "can be subclassed to pass in other env paths" do
280
+ test_path_env_val = "/unknown/path/to/file.txt".freeze
281
+ test_json_env_val = JSON.generate default_keyfile_hash
282
+
283
+ ENV["TEST_PATH"] = test_path_env_val
284
+ ENV["TEST_JSON_VARS"] = test_json_env_val
285
+
286
+ class TestCredentials11 < Google::Auth::Credentials
287
+ self.token_credential_uri = "https://example.com/token"
288
+ self.audience = "https://example.com/audience"
289
+ self.scope = "http://example.com/scope"
290
+ self.env_vars = ["TEST_PATH", "TEST_JSON_VARS"]
291
+ end
292
+
293
+ allow(::File).to receive(:file?).with(test_path_env_val) { false }
294
+ allow(::File).to receive(:file?).with(test_json_env_val) { false }
295
+
296
+ mocked_signet = double "Signet::OAuth2::Client"
297
+ allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
298
+ allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
299
+ allow(mocked_signet).to receive(:client_id)
300
+ allow(Signet::OAuth2::Client).to receive(:new) do |options|
301
+ expect(options[:token_credential_uri]).to eq("https://example.com/token")
302
+ expect(options[:audience]).to eq("https://example.com/audience")
303
+ expect(options[:scope]).to eq(["http://example.com/scope"])
304
+ expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
305
+ expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
306
+
307
+ mocked_signet
308
+ end
309
+
310
+ creds = TestCredentials11.default
311
+ expect(creds).to be_a_kind_of(TestCredentials11)
312
+ expect(creds.client).to eq(mocked_signet)
313
+ expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
314
+ expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
193
315
  end
194
316
 
195
- allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
196
- allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
197
- allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
198
- allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { true }
199
- allow(::File).to receive(:read).with("~/default/path/to/file.txt") { JSON.generate default_keyfile_hash }
200
-
201
- mocked_signet = double "Signet::OAuth2::Client"
202
- allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
203
- allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
204
- allow(mocked_signet).to receive(:client_id)
205
- allow(Signet::OAuth2::Client).to receive(:new) do |options|
206
- expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
207
- expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
208
- expect(options[:scope]).to eq(["http://example.com/scope"])
209
- expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
210
- expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
211
-
212
- mocked_signet
317
+ it "subclasses can use PATH_ENV_VARS to get keyfile path" do
318
+ class TestCredentials12 < Google::Auth::Credentials
319
+ self.scope = "http://example.com/scope"
320
+ self.env_vars = %w[PATH_ENV_DUMMY PATH_ENV_TEST JSON_ENV_DUMMY]
321
+ self.paths = ["~/default/path/to/file.txt"]
322
+ end
323
+
324
+ allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
325
+ allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
326
+ allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
327
+ allow(::ENV).to receive(:[]).with("PATH_ENV_TEST") { "/unknown/path/to/file.txt" }
328
+ allow(::File).to receive(:file?).with("/unknown/path/to/file.txt") { true }
329
+ allow(::File).to receive(:read).with("/unknown/path/to/file.txt") { JSON.generate default_keyfile_hash }
330
+
331
+ mocked_signet = double "Signet::OAuth2::Client"
332
+ allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
333
+ allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
334
+ allow(mocked_signet).to receive(:client_id)
335
+ allow(Signet::OAuth2::Client).to receive(:new) do |options|
336
+ expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
337
+ expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
338
+ expect(options[:scope]).to eq(["http://example.com/scope"])
339
+ expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
340
+ expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
341
+
342
+ mocked_signet
343
+ end
344
+
345
+ creds = TestCredentials12.default
346
+ expect(creds).to be_a_kind_of(TestCredentials12)
347
+ expect(creds.client).to eq(mocked_signet)
348
+ expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
349
+ expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
213
350
  end
214
351
 
215
- creds = TestCredentials.default
216
- expect(creds).to be_a_kind_of(TestCredentials)
217
- expect(creds.client).to eq(mocked_signet)
218
- expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
219
- end
220
-
221
- it "subclasses that find no matches default to Google::Auth.get_application_default" do
222
- class TestCredentials < Google::Auth::Credentials
223
- SCOPE = "http://example.com/scope".freeze
224
- PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze
225
- JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze
226
- DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
352
+ it "subclasses can use JSON_ENV_VARS to get keyfile contents" do
353
+ test_json_env_val = JSON.generate default_keyfile_hash
354
+
355
+ class TestCredentials13 < Google::Auth::Credentials
356
+ self.scope = "http://example.com/scope"
357
+ self.env_vars = %w[PATH_ENV_DUMMY JSON_ENV_DUMMY JSON_ENV_TEST]
358
+ self.paths = ["~/default/path/to/file.txt"]
359
+ end
360
+
361
+ allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
362
+ allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
363
+ allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
364
+ allow(::File).to receive(:file?).with(test_json_env_val) { false }
365
+ allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
366
+ allow(::ENV).to receive(:[]).with("JSON_ENV_TEST") { test_json_env_val }
367
+
368
+ mocked_signet = double "Signet::OAuth2::Client"
369
+ allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
370
+ allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
371
+ allow(mocked_signet).to receive(:client_id)
372
+ allow(Signet::OAuth2::Client).to receive(:new) do |options|
373
+ expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
374
+ expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
375
+ expect(options[:scope]).to eq(["http://example.com/scope"])
376
+ expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
377
+ expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
378
+
379
+ mocked_signet
380
+ end
381
+
382
+ creds = TestCredentials13.default
383
+ expect(creds).to be_a_kind_of(TestCredentials13)
384
+ expect(creds.client).to eq(mocked_signet)
385
+ expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
386
+ expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
227
387
  end
228
388
 
229
- allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
230
- allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
231
- allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
232
- allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { false }
233
-
234
- mocked_signet = double "Signet::OAuth2::Client"
235
- allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
236
- allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
237
- allow(mocked_signet).to receive(:client_id)
238
- allow(Google::Auth).to receive(:get_application_default) do |scope|
239
- expect(scope).to eq(TestCredentials::SCOPE)
240
-
241
- # This should really be a Signet::OAuth2::Client object,
242
- # but mocking is making that difficult, so return a valid hash instead.
243
- default_keyfile_hash
389
+ it "subclasses can use DEFAULT_PATHS to get keyfile path" do
390
+ class TestCredentials14 < Google::Auth::Credentials
391
+ self.scope = "http://example.com/scope"
392
+ self.env_vars = %w[PATH_ENV_DUMMY JSON_ENV_DUMMY]
393
+ self.paths = ["~/default/path/to/file.txt"]
394
+ end
395
+
396
+ allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
397
+ allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
398
+ allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
399
+ allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
400
+ allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { true }
401
+ allow(::File).to receive(:read).with("~/default/path/to/file.txt") { JSON.generate default_keyfile_hash }
402
+
403
+ mocked_signet = double "Signet::OAuth2::Client"
404
+ allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
405
+ allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
406
+ allow(mocked_signet).to receive(:client_id)
407
+ allow(Signet::OAuth2::Client).to receive(:new) do |options|
408
+ expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
409
+ expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
410
+ expect(options[:scope]).to eq(["http://example.com/scope"])
411
+ expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
412
+ expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
413
+
414
+ mocked_signet
415
+ end
416
+
417
+ creds = TestCredentials14.default
418
+ expect(creds).to be_a_kind_of(TestCredentials14)
419
+ expect(creds.client).to eq(mocked_signet)
420
+ expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
421
+ expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
244
422
  end
245
- allow(Signet::OAuth2::Client).to receive(:new) do |options|
246
- expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
247
- expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
248
- expect(options[:scope]).to eq(["http://example.com/scope"])
249
- expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
250
- expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
251
423
 
252
- mocked_signet
424
+ it "subclasses that find no matches default to Google::Auth.get_application_default" do
425
+ class TestCredentials15 < Google::Auth::Credentials
426
+ self.scope = "http://example.com/scope"
427
+ self.env_vars = %w[PATH_ENV_DUMMY JSON_ENV_DUMMY]
428
+ self.paths = ["~/default/path/to/file.txt"]
429
+ end
430
+
431
+ allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
432
+ allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
433
+ allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
434
+ allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
435
+ allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { false }
436
+
437
+ mocked_signet = double "Signet::OAuth2::Client"
438
+ allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
439
+ allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
440
+ allow(mocked_signet).to receive(:client_id)
441
+ allow(Google::Auth).to receive(:get_application_default) do |scope|
442
+ expect(scope).to eq(TestCredentials15.scope)
443
+
444
+ # This should really be a Signet::OAuth2::Client object,
445
+ # but mocking is making that difficult, so return a valid hash instead.
446
+ default_keyfile_hash
447
+ end
448
+ allow(Signet::OAuth2::Client).to receive(:new) do |options|
449
+ expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
450
+ expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
451
+ expect(options[:scope]).to eq(["http://example.com/scope"])
452
+ expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
453
+ expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
454
+
455
+ mocked_signet
456
+ end
457
+
458
+ creds = TestCredentials15.default
459
+ expect(creds).to be_a_kind_of(TestCredentials15)
460
+ expect(creds.client).to eq(mocked_signet)
461
+ expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
462
+ expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
253
463
  end
254
-
255
- creds = TestCredentials.default
256
- expect(creds).to be_a_kind_of(TestCredentials)
257
- expect(creds.client).to eq(mocked_signet)
258
- expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
259
464
  end
260
465
 
261
466
  it "warns when cloud sdk credentials are used" do