googleauth 0.8.1 → 0.16.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/.github/CODEOWNERS +7 -0
- data/.github/workflows/release.yml +39 -0
- data/.kokoro/build.bat +9 -1
- data/.kokoro/continuous/linux.cfg +12 -2
- data/.kokoro/continuous/osx.cfg +5 -0
- data/.kokoro/continuous/post.cfg +30 -0
- data/.kokoro/continuous/windows.cfg +27 -1
- data/.kokoro/presubmit/linux.cfg +11 -1
- data/.kokoro/presubmit/osx.cfg +5 -0
- data/.kokoro/presubmit/windows.cfg +27 -1
- data/.kokoro/release.cfg +42 -1
- data/.kokoro/trampoline.bat +10 -0
- data/.repo-metadata.json +5 -0
- data/.rubocop.yml +8 -2
- data/CHANGELOG.md +94 -20
- data/Gemfile +7 -7
- data/{COPYING → LICENSE} +0 -0
- data/README.md +12 -15
- data/Rakefile +48 -5
- data/googleauth.gemspec +7 -3
- data/integration/helper.rb +31 -0
- data/integration/id_tokens/key_source_test.rb +74 -0
- data/lib/googleauth.rb +1 -0
- data/lib/googleauth/application_default.rb +2 -2
- data/lib/googleauth/compute_engine.rb +45 -20
- data/lib/googleauth/credentials.rb +445 -71
- data/lib/googleauth/credentials_loader.rb +11 -9
- data/lib/googleauth/iam.rb +1 -1
- 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 +396 -0
- data/lib/googleauth/id_tokens/verifier.rb +142 -0
- data/lib/googleauth/json_key_reader.rb +6 -2
- data/lib/googleauth/scope_util.rb +1 -1
- data/lib/googleauth/service_account.rb +42 -23
- data/lib/googleauth/signet.rb +9 -6
- data/lib/googleauth/stores/file_token_store.rb +1 -0
- data/lib/googleauth/stores/redis_token_store.rb +1 -0
- data/lib/googleauth/user_authorizer.rb +6 -1
- data/lib/googleauth/user_refresh.rb +2 -2
- data/lib/googleauth/version.rb +1 -1
- data/lib/googleauth/web_user_authorizer.rb +16 -14
- 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 +28 -5
- data/spec/googleauth/compute_engine_spec.rb +69 -13
- data/spec/googleauth/credentials_spec.rb +492 -165
- data/spec/googleauth/service_account_spec.rb +31 -16
- data/spec/googleauth/signet_spec.rb +46 -7
- data/spec/googleauth/user_authorizer_spec.rb +21 -1
- data/spec/googleauth/user_refresh_spec.rb +1 -1
- data/spec/googleauth/web_user_authorizer_spec.rb +6 -0
- 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 +49 -13
- data/.kokoro/windows.sh +0 -4
@@ -0,0 +1,45 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
require_relative "repo_metadata.rb"
|
4
|
+
|
5
|
+
class DevsiteBuilder
|
6
|
+
def initialize master_dir = "."
|
7
|
+
@master_dir = Pathname.new master_dir
|
8
|
+
@output_dir = "doc"
|
9
|
+
@metadata = RepoMetadata.from_source "#{master_dir}/.repo-metadata.json"
|
10
|
+
end
|
11
|
+
|
12
|
+
def build
|
13
|
+
FileUtils.remove_dir @output_dir if Dir.exist? @output_dir
|
14
|
+
markup = "--markup markdown"
|
15
|
+
|
16
|
+
Dir.chdir @master_dir do
|
17
|
+
cmds = ["-o #{@output_dir}", markup]
|
18
|
+
cmd "yard --verbose #{cmds.join ' '}"
|
19
|
+
end
|
20
|
+
@metadata.build @master_dir + @output_dir
|
21
|
+
end
|
22
|
+
|
23
|
+
def upload
|
24
|
+
Dir.chdir @output_dir do
|
25
|
+
opts = [
|
26
|
+
"--credentials=#{ENV['KOKORO_KEYSTORE_DIR']}/73713_docuploader_service_account",
|
27
|
+
"--staging-bucket=#{ENV.fetch 'STAGING_BUCKET', 'docs-staging'}",
|
28
|
+
"--metadata-file=./docs.metadata"
|
29
|
+
]
|
30
|
+
cmd "python3 -m docuploader upload . #{opts.join ' '}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def publish
|
35
|
+
build
|
36
|
+
upload
|
37
|
+
end
|
38
|
+
|
39
|
+
def cmd line
|
40
|
+
puts line
|
41
|
+
output = `#{line}`
|
42
|
+
puts output
|
43
|
+
output
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "open3"
|
2
|
+
|
3
|
+
class LinkChecker
|
4
|
+
def initialize
|
5
|
+
@failed = false
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
job_info
|
10
|
+
git_commit = ENV.fetch "KOKORO_GITHUB_COMMIT", "master"
|
11
|
+
|
12
|
+
markdown_files = Dir.glob "**/*.md"
|
13
|
+
broken_markdown_links = check_links markdown_files,
|
14
|
+
"https://github.com/googleapis/google-auth-library-ruby/tree/#{git_commit}",
|
15
|
+
" --skip '^(?!(\\Wruby.*google|.*google.*\\Wruby|.*cloud\\.google\\.com))'"
|
16
|
+
|
17
|
+
broken_devsite_links = check_links ["googleauth"],
|
18
|
+
"https://googleapis.dev/ruby",
|
19
|
+
"/latest/ --recurse --skip https:.*github.*"
|
20
|
+
|
21
|
+
puts_broken_links broken_markdown_links
|
22
|
+
puts_broken_links broken_devsite_links
|
23
|
+
end
|
24
|
+
|
25
|
+
def check_links location_list, base, tail
|
26
|
+
broken_links = Hash.new { |h, k| h[k] = [] }
|
27
|
+
location_list.each do |location|
|
28
|
+
out, err, st = Open3.capture3 "npx linkinator #{base}/#{location}#{tail}"
|
29
|
+
puts out
|
30
|
+
unless st.to_i.zero?
|
31
|
+
@failed = true
|
32
|
+
puts err
|
33
|
+
end
|
34
|
+
checked_links = out.split "\n"
|
35
|
+
checked_links.select! { |link| link =~ /\[\d+\]/ && !link.include?("[200]") }
|
36
|
+
unless checked_links.empty?
|
37
|
+
@failed = true
|
38
|
+
broken_links[location] += checked_links
|
39
|
+
end
|
40
|
+
end
|
41
|
+
broken_links
|
42
|
+
end
|
43
|
+
|
44
|
+
def puts_broken_links link_hash
|
45
|
+
link_hash.each do |location, links|
|
46
|
+
puts "#{location} contains the following broken links:"
|
47
|
+
links.each { |link| puts " #{link}" }
|
48
|
+
puts ""
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def job_info
|
53
|
+
line_length = "Using Ruby - #{RUBY_VERSION}".length + 8
|
54
|
+
puts ""
|
55
|
+
puts "#" * line_length
|
56
|
+
puts "### Using Ruby - #{RUBY_VERSION} ###"
|
57
|
+
puts "#" * line_length
|
58
|
+
puts ""
|
59
|
+
end
|
60
|
+
|
61
|
+
def exit_status
|
62
|
+
@failed ? 1 : 0
|
63
|
+
end
|
64
|
+
end
|
@@ -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 :
|
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
|
-
|
56
|
+
access_stub
|
54
57
|
@client.fetch_access_token!
|
55
58
|
expect(@client.access_token).to eq(token)
|
56
|
-
expect(
|
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
|
-
|
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(
|
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,31 +37,52 @@ require "googleauth/compute_engine"
|
|
37
37
|
require "spec_helper"
|
38
38
|
|
39
39
|
describe Google::Auth::GCECredentials do
|
40
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
+
|
55
|
+
uri = MD_ACCESS_URI
|
56
|
+
uri += "?scopes=#{Array(opts[:scope]).join ','}" if opts[:scope]
|
57
|
+
|
58
|
+
stub_request(:get, uri)
|
59
|
+
.with(headers: { "Metadata-Flavor" => "Google" })
|
60
|
+
.to_return(body: body,
|
61
|
+
status: 200,
|
62
|
+
headers: { "Content-Type" => "application/json" })
|
63
|
+
elsif opts[:id_token]
|
64
|
+
stub_request(:get, MD_ID_URI)
|
65
|
+
.with(headers: { "Metadata-Flavor" => "Google" })
|
66
|
+
.to_return(body: opts[:id_token],
|
67
|
+
status: 200,
|
68
|
+
headers: { "Content-Type" => "text/html" })
|
69
|
+
end
|
57
70
|
end
|
58
71
|
|
59
72
|
it_behaves_like "apply/apply! are OK"
|
60
73
|
|
61
74
|
context "metadata is unavailable" do
|
62
75
|
describe "#fetch_access_token" do
|
76
|
+
it "should pass scopes when requesting an access token" do
|
77
|
+
scopes = ["https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/bigtable.data"]
|
78
|
+
stub = make_auth_stubs access_token: "1/abcdef1234567890", scope: scopes
|
79
|
+
@client = GCECredentials.new(scope: scopes)
|
80
|
+
@client.fetch_access_token!
|
81
|
+
expect(stub).to have_been_requested
|
82
|
+
end
|
83
|
+
|
63
84
|
it "should fail if the metadata request returns a 404" do
|
64
|
-
stub = stub_request(:get,
|
85
|
+
stub = stub_request(:get, MD_ACCESS_URI)
|
65
86
|
.to_return(status: 404,
|
66
87
|
headers: { "Metadata-Flavor" => "Google" })
|
67
88
|
expect { @client.fetch_access_token! }
|
@@ -69,8 +90,26 @@ describe Google::Auth::GCECredentials do
|
|
69
90
|
expect(stub).to have_been_requested
|
70
91
|
end
|
71
92
|
|
93
|
+
it "should fail if the metadata request returns a 403" do
|
94
|
+
stub = stub_request(:get, MD_ACCESS_URI)
|
95
|
+
.to_return(status: 403,
|
96
|
+
headers: { "Metadata-Flavor" => "Google" })
|
97
|
+
expect { @client.fetch_access_token! }
|
98
|
+
.to raise_error Signet::AuthorizationError
|
99
|
+
expect(stub).to have_been_requested.times(6)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should fail if the metadata request returns a 500" do
|
103
|
+
stub = stub_request(:get, MD_ACCESS_URI)
|
104
|
+
.to_return(status: 500,
|
105
|
+
headers: { "Metadata-Flavor" => "Google" })
|
106
|
+
expect { @client.fetch_access_token! }
|
107
|
+
.to raise_error Signet::AuthorizationError
|
108
|
+
expect(stub).to have_been_requested.times(6)
|
109
|
+
end
|
110
|
+
|
72
111
|
it "should fail if the metadata request returns an unexpected code" do
|
73
|
-
stub = stub_request(:get,
|
112
|
+
stub = stub_request(:get, MD_ACCESS_URI)
|
74
113
|
.to_return(status: 503,
|
75
114
|
headers: { "Metadata-Flavor" => "Google" })
|
76
115
|
expect { @client.fetch_access_token! }
|
@@ -97,6 +136,7 @@ describe Google::Auth::GCECredentials do
|
|
97
136
|
describe "#on_gce?" do
|
98
137
|
it "should be true when Metadata-Flavor is Google" do
|
99
138
|
stub = stub_request(:get, "http://169.254.169.254")
|
139
|
+
.with(headers: { "Metadata-Flavor" => "Google" })
|
100
140
|
.to_return(status: 200,
|
101
141
|
headers: { "Metadata-Flavor" => "Google" })
|
102
142
|
expect(GCECredentials.on_gce?({}, true)).to eq(true)
|
@@ -105,6 +145,7 @@ describe Google::Auth::GCECredentials do
|
|
105
145
|
|
106
146
|
it "should be false when Metadata-Flavor is not Google" do
|
107
147
|
stub = stub_request(:get, "http://169.254.169.254")
|
148
|
+
.with(headers: { "Metadata-Flavor" => "Google" })
|
108
149
|
.to_return(status: 200,
|
109
150
|
headers: { "Metadata-Flavor" => "NotGoogle" })
|
110
151
|
expect(GCECredentials.on_gce?({}, true)).to eq(false)
|
@@ -113,10 +154,25 @@ describe Google::Auth::GCECredentials do
|
|
113
154
|
|
114
155
|
it "should be false if the response is not 200" do
|
115
156
|
stub = stub_request(:get, "http://169.254.169.254")
|
157
|
+
.with(headers: { "Metadata-Flavor" => "Google" })
|
116
158
|
.to_return(status: 404,
|
117
159
|
headers: { "Metadata-Flavor" => "NotGoogle" })
|
118
160
|
expect(GCECredentials.on_gce?({}, true)).to eq(false)
|
119
161
|
expect(stub).to have_been_requested
|
120
162
|
end
|
163
|
+
|
164
|
+
it "should honor GCE_METADATA_HOST environment variable" do
|
165
|
+
ENV["GCE_METADATA_HOST"] = "mymetadata.example.com"
|
166
|
+
begin
|
167
|
+
stub = stub_request(:get, "http://mymetadata.example.com")
|
168
|
+
.with(headers: { "Metadata-Flavor" => "Google" })
|
169
|
+
.to_return(status: 200,
|
170
|
+
headers: { "Metadata-Flavor" => "Google" })
|
171
|
+
expect(GCECredentials.on_gce?({}, true)).to eq(true)
|
172
|
+
expect(stub).to have_been_requested
|
173
|
+
ensure
|
174
|
+
ENV.delete "GCE_METADATA_HOST"
|
175
|
+
end
|
176
|
+
end
|
121
177
|
end
|
122
178
|
end
|
@@ -36,226 +36,553 @@ require "googleauth"
|
|
36
36
|
describe Google::Auth::Credentials, :private do
|
37
37
|
let :default_keyfile_hash do
|
38
38
|
{
|
39
|
-
"private_key_id"
|
40
|
-
"private_key"
|
41
|
-
"client_email"
|
42
|
-
"client_id"
|
43
|
-
"type"
|
44
|
-
"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
|
|
48
|
-
|
49
|
+
def mock_signet
|
49
50
|
mocked_signet = double "Signet::OAuth2::Client"
|
50
51
|
allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
|
51
52
|
allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
|
52
53
|
allow(mocked_signet).to receive(:client_id)
|
53
54
|
allow(Signet::OAuth2::Client).to receive(:new) do |options|
|
55
|
+
yield options if block_given?
|
56
|
+
mocked_signet
|
57
|
+
end
|
58
|
+
mocked_signet
|
59
|
+
end
|
60
|
+
|
61
|
+
it "uses a default scope" do
|
62
|
+
mock_signet do |options|
|
54
63
|
expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
|
55
64
|
expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
|
56
65
|
expect(options[:scope]).to eq([])
|
57
66
|
expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
|
58
67
|
expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
|
59
|
-
|
60
|
-
mocked_signet
|
61
68
|
end
|
62
69
|
|
63
70
|
Google::Auth::Credentials.new default_keyfile_hash
|
64
71
|
end
|
65
72
|
|
66
73
|
it "uses a custom scope" do
|
67
|
-
|
68
|
-
allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet)
|
69
|
-
allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
|
70
|
-
allow(mocked_signet).to receive(:client_id)
|
71
|
-
allow(Signet::OAuth2::Client).to receive(:new) do |options|
|
74
|
+
mock_signet do |options|
|
72
75
|
expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
|
73
76
|
expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
|
74
77
|
expect(options[:scope]).to eq(["http://example.com/scope"])
|
75
78
|
expect(options[:issuer]).to eq(default_keyfile_hash["client_email"])
|
76
79
|
expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
|
77
|
-
|
78
|
-
mocked_signet
|
79
80
|
end
|
80
81
|
|
81
82
|
Google::Auth::Credentials.new default_keyfile_hash, scope: "http://example.com/scope"
|
82
83
|
end
|
83
84
|
|
84
|
-
it "
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
ENV[TEST_PATH_ENV_VAR] = TEST_PATH_ENV_VAL
|
90
|
-
ENV[TEST_JSON_ENV_VAR] = JSON.generate default_keyfile_hash
|
85
|
+
it "uses empty paths and env_vars by default" do
|
86
|
+
expect(Google::Auth::Credentials.paths).to eq([])
|
87
|
+
expect(Google::Auth::Credentials.env_vars).to eq([])
|
88
|
+
end
|
91
89
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
90
|
+
describe "using CONSTANTS" do
|
91
|
+
it "can be subclassed to pass in other env paths" do
|
92
|
+
test_path_env_val = "/unknown/path/to/file.txt".freeze
|
93
|
+
test_json_env_val = JSON.generate default_keyfile_hash
|
94
|
+
|
95
|
+
ENV["TEST_PATH"] = test_path_env_val
|
96
|
+
ENV["TEST_JSON_VARS"] = test_json_env_val
|
97
|
+
|
98
|
+
class TestCredentials1 < Google::Auth::Credentials
|
99
|
+
TOKEN_CREDENTIAL_URI = "https://example.com/token".freeze
|
100
|
+
AUDIENCE = "https://example.com/audience".freeze
|
101
|
+
SCOPE = "http://example.com/scope".freeze
|
102
|
+
PATH_ENV_VARS = ["TEST_PATH"].freeze
|
103
|
+
JSON_ENV_VARS = ["TEST_JSON_VARS"].freeze
|
104
|
+
end
|
105
|
+
|
106
|
+
allow(::File).to receive(:file?).with(test_path_env_val) { false }
|
107
|
+
allow(::File).to receive(:file?).with(test_json_env_val) { false }
|
108
|
+
|
109
|
+
mocked_signet = mock_signet
|
110
|
+
|
111
|
+
allow(Google::Auth::ServiceAccountCredentials).to receive(:make_creds) do |options|
|
112
|
+
expect(options[:token_credential_uri]).to eq("https://example.com/token")
|
113
|
+
expect(options[:audience]).to eq("https://example.com/audience")
|
114
|
+
expect(options[:scope]).to eq(["http://example.com/scope"])
|
115
|
+
expect(options[:enable_self_signed_jwt]).to eq(true)
|
116
|
+
expect(options[:target_audience]).to be_nil
|
117
|
+
expect(options[:json_key_io].read).to eq(test_json_env_val)
|
118
|
+
|
119
|
+
# This should really be a Signet::OAuth2::Client object,
|
120
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
121
|
+
default_keyfile_hash
|
122
|
+
end
|
123
|
+
|
124
|
+
creds = TestCredentials1.default enable_self_signed_jwt: true
|
125
|
+
expect(creds).to be_a_kind_of(TestCredentials1)
|
126
|
+
expect(creds.client).to eq(mocked_signet)
|
127
|
+
expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
|
128
|
+
expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
|
96
129
|
end
|
97
130
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
131
|
+
it "subclasses can use PATH_ENV_VARS to get keyfile path" do
|
132
|
+
class TestCredentials2 < Google::Auth::Credentials
|
133
|
+
SCOPE = "http://example.com/scope".freeze
|
134
|
+
PATH_ENV_VARS = %w[PATH_ENV_DUMMY PATH_ENV_TEST].freeze
|
135
|
+
JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze
|
136
|
+
DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
|
137
|
+
end
|
138
|
+
|
139
|
+
json_content = JSON.generate default_keyfile_hash
|
140
|
+
|
141
|
+
allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
|
142
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
|
143
|
+
allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
|
144
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_TEST") { "/unknown/path/to/file.txt" }
|
145
|
+
allow(::File).to receive(:file?).with("/unknown/path/to/file.txt") { true }
|
146
|
+
allow(::File).to receive(:read).with("/unknown/path/to/file.txt") { json_content }
|
147
|
+
|
148
|
+
mocked_signet = mock_signet
|
149
|
+
|
150
|
+
allow(Google::Auth::ServiceAccountCredentials).to receive(:make_creds) do |options|
|
151
|
+
expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
|
152
|
+
expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
|
153
|
+
expect(options[:scope]).to eq(["http://example.com/scope"])
|
154
|
+
expect(options[:enable_self_signed_jwt]).to be_nil
|
155
|
+
expect(options[:target_audience]).to be_nil
|
156
|
+
expect(options[:json_key_io].read).to eq(json_content)
|
157
|
+
|
158
|
+
# This should really be a Signet::OAuth2::Client object,
|
159
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
160
|
+
default_keyfile_hash
|
161
|
+
end
|
162
|
+
|
163
|
+
creds = TestCredentials2.default
|
164
|
+
expect(creds).to be_a_kind_of(TestCredentials2)
|
165
|
+
expect(creds.client).to eq(mocked_signet)
|
166
|
+
expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
|
167
|
+
expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
|
112
168
|
end
|
113
169
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
170
|
+
it "subclasses can use JSON_ENV_VARS to get keyfile contents" do
|
171
|
+
test_json_env_val = JSON.generate default_keyfile_hash
|
172
|
+
|
173
|
+
class TestCredentials3 < Google::Auth::Credentials
|
174
|
+
SCOPE = "http://example.com/scope".freeze
|
175
|
+
PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze
|
176
|
+
JSON_ENV_VARS = %w[JSON_ENV_DUMMY JSON_ENV_TEST].freeze
|
177
|
+
DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
|
178
|
+
end
|
179
|
+
|
180
|
+
allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
|
181
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
|
182
|
+
allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
|
183
|
+
allow(::File).to receive(:file?).with(test_json_env_val) { false }
|
184
|
+
allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
|
185
|
+
allow(::ENV).to receive(:[]).with("JSON_ENV_TEST") { test_json_env_val }
|
186
|
+
|
187
|
+
mocked_signet = mock_signet
|
188
|
+
|
189
|
+
allow(Google::Auth::ServiceAccountCredentials).to receive(:make_creds) do |options|
|
190
|
+
expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
|
191
|
+
expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
|
192
|
+
expect(options[:scope]).to eq(["http://example.com/scope"])
|
193
|
+
expect(options[:enable_self_signed_jwt]).to be_nil
|
194
|
+
expect(options[:target_audience]).to be_nil
|
195
|
+
expect(options[:json_key_io].read).to eq(test_json_env_val)
|
196
|
+
|
197
|
+
# This should really be a Signet::OAuth2::Client object,
|
198
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
199
|
+
default_keyfile_hash
|
200
|
+
end
|
201
|
+
|
202
|
+
creds = TestCredentials3.default
|
203
|
+
expect(creds).to be_a_kind_of(TestCredentials3)
|
204
|
+
expect(creds.client).to eq(mocked_signet)
|
205
|
+
expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
|
206
|
+
expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
|
126
207
|
end
|
127
208
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
mocked_signet
|
209
|
+
it "subclasses can use DEFAULT_PATHS to get keyfile path" do
|
210
|
+
class TestCredentials4 < Google::Auth::Credentials
|
211
|
+
SCOPE = "http://example.com/scope".freeze
|
212
|
+
PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze
|
213
|
+
JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze
|
214
|
+
DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
|
215
|
+
end
|
216
|
+
|
217
|
+
json_content = JSON.generate default_keyfile_hash
|
218
|
+
|
219
|
+
allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
|
220
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
|
221
|
+
allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
|
222
|
+
allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
|
223
|
+
allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { true }
|
224
|
+
allow(::File).to receive(:read).with("~/default/path/to/file.txt") { json_content }
|
225
|
+
|
226
|
+
mocked_signet = mock_signet
|
227
|
+
|
228
|
+
allow(Google::Auth::ServiceAccountCredentials).to receive(:make_creds) do |options|
|
229
|
+
expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
|
230
|
+
expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
|
231
|
+
expect(options[:scope]).to eq(["http://example.com/scope"])
|
232
|
+
expect(options[:enable_self_signed_jwt]).to be_nil
|
233
|
+
expect(options[:target_audience]).to be_nil
|
234
|
+
expect(options[:json_key_io].read).to eq(json_content)
|
235
|
+
|
236
|
+
# This should really be a Signet::OAuth2::Client object,
|
237
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
238
|
+
default_keyfile_hash
|
239
|
+
end
|
240
|
+
|
241
|
+
creds = TestCredentials4.default
|
242
|
+
expect(creds).to be_a_kind_of(TestCredentials4)
|
243
|
+
expect(creds.client).to eq(mocked_signet)
|
244
|
+
expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
|
245
|
+
expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
|
146
246
|
end
|
147
247
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
248
|
+
it "subclasses that find no matches default to Google::Auth.get_application_default" do
|
249
|
+
class TestCredentials5 < Google::Auth::Credentials
|
250
|
+
SCOPE = "http://example.com/scope".freeze
|
251
|
+
PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze
|
252
|
+
JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze
|
253
|
+
DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze
|
254
|
+
end
|
255
|
+
|
256
|
+
allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
|
257
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
|
258
|
+
allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
|
259
|
+
allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
|
260
|
+
allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { false }
|
261
|
+
|
262
|
+
mocked_signet = mock_signet
|
263
|
+
|
264
|
+
allow(Google::Auth).to receive(:get_application_default) do |scope, options|
|
265
|
+
expect(scope).to eq([TestCredentials5::SCOPE])
|
266
|
+
expect(options[:enable_self_signed_jwt]).to be_nil
|
267
|
+
expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
|
268
|
+
expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
|
269
|
+
|
270
|
+
# This should really be a Signet::OAuth2::Client object,
|
271
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
272
|
+
default_keyfile_hash
|
273
|
+
end
|
274
|
+
|
275
|
+
creds = TestCredentials5.default
|
276
|
+
expect(creds).to be_a_kind_of(TestCredentials5)
|
277
|
+
expect(creds.client).to eq(mocked_signet)
|
278
|
+
expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
|
279
|
+
expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
|
160
280
|
end
|
161
281
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
expect(
|
176
|
-
expect(
|
177
|
-
|
178
|
-
|
282
|
+
it "can be subclassed to pass in other env paths" do
|
283
|
+
class TestCredentials6 < Google::Auth::Credentials
|
284
|
+
TOKEN_CREDENTIAL_URI = "https://example.com/token".freeze
|
285
|
+
AUDIENCE = "https://example.com/audience".freeze
|
286
|
+
SCOPE = "http://example.com/scope".freeze
|
287
|
+
PATH_ENV_VARS = ["TEST_PATH"].freeze
|
288
|
+
JSON_ENV_VARS = ["TEST_JSON_VARS"].freeze
|
289
|
+
DEFAULT_PATHS = ["~/default/path/to/file.txt"]
|
290
|
+
end
|
291
|
+
|
292
|
+
class TestCredentials7 < TestCredentials6
|
293
|
+
end
|
294
|
+
|
295
|
+
expect(TestCredentials7.token_credential_uri).to eq("https://example.com/token")
|
296
|
+
expect(TestCredentials7.audience).to eq("https://example.com/audience")
|
297
|
+
expect(TestCredentials7.scope).to eq(["http://example.com/scope"])
|
298
|
+
expect(TestCredentials7.env_vars).to eq(["TEST_PATH", "TEST_JSON_VARS"])
|
299
|
+
expect(TestCredentials7.paths).to eq(["~/default/path/to/file.txt"])
|
300
|
+
|
301
|
+
TestCredentials7::TOKEN_CREDENTIAL_URI = "https://example.com/token2"
|
302
|
+
expect(TestCredentials7.token_credential_uri).to eq("https://example.com/token2")
|
303
|
+
TestCredentials7::AUDIENCE = nil
|
304
|
+
expect(TestCredentials7.audience).to eq("https://example.com/audience")
|
179
305
|
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
306
|
end
|
186
307
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
308
|
+
describe "using class methods" do
|
309
|
+
it "can be subclassed to pass in other env paths" do
|
310
|
+
test_path_env_val = "/unknown/path/to/file.txt".freeze
|
311
|
+
test_json_env_val = JSON.generate default_keyfile_hash
|
312
|
+
|
313
|
+
ENV["TEST_PATH"] = test_path_env_val
|
314
|
+
ENV["TEST_JSON_VARS"] = test_json_env_val
|
315
|
+
|
316
|
+
class TestCredentials11 < Google::Auth::Credentials
|
317
|
+
self.token_credential_uri = "https://example.com/token"
|
318
|
+
self.audience = "https://example.com/audience"
|
319
|
+
self.scope = "http://example.com/scope"
|
320
|
+
self.env_vars = ["TEST_PATH", "TEST_JSON_VARS"]
|
321
|
+
end
|
322
|
+
|
323
|
+
allow(::File).to receive(:file?).with(test_path_env_val) { false }
|
324
|
+
allow(::File).to receive(:file?).with(test_json_env_val) { false }
|
325
|
+
|
326
|
+
mocked_signet = mock_signet
|
327
|
+
|
328
|
+
allow(Google::Auth::ServiceAccountCredentials).to receive(:make_creds) do |options|
|
329
|
+
expect(options[:token_credential_uri]).to eq("https://example.com/token")
|
330
|
+
expect(options[:audience]).to eq("https://example.com/audience")
|
331
|
+
expect(options[:scope]).to eq(["http://example.com/scope"])
|
332
|
+
expect(options[:enable_self_signed_jwt]).to be_nil
|
333
|
+
expect(options[:target_audience]).to be_nil
|
334
|
+
expect(options[:json_key_io].read).to eq(test_json_env_val)
|
335
|
+
|
336
|
+
# This should really be a Signet::OAuth2::Client object,
|
337
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
338
|
+
default_keyfile_hash
|
339
|
+
end
|
340
|
+
|
341
|
+
creds = TestCredentials11.default
|
342
|
+
expect(creds).to be_a_kind_of(TestCredentials11)
|
343
|
+
expect(creds.client).to eq(mocked_signet)
|
344
|
+
expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
|
345
|
+
expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
|
193
346
|
end
|
194
347
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
348
|
+
it "subclasses can use PATH_ENV_VARS to get keyfile path" do
|
349
|
+
class TestCredentials12 < Google::Auth::Credentials
|
350
|
+
self.scope = "http://example.com/scope"
|
351
|
+
self.env_vars = %w[PATH_ENV_DUMMY PATH_ENV_TEST JSON_ENV_DUMMY]
|
352
|
+
self.paths = ["~/default/path/to/file.txt"]
|
353
|
+
end
|
354
|
+
|
355
|
+
json_content = JSON.generate default_keyfile_hash
|
356
|
+
|
357
|
+
allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
|
358
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
|
359
|
+
allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
|
360
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_TEST") { "/unknown/path/to/file.txt" }
|
361
|
+
allow(::File).to receive(:file?).with("/unknown/path/to/file.txt") { true }
|
362
|
+
allow(::File).to receive(:read).with("/unknown/path/to/file.txt") { json_content }
|
363
|
+
|
364
|
+
mocked_signet = mock_signet
|
365
|
+
|
366
|
+
allow(Google::Auth::ServiceAccountCredentials).to receive(:make_creds) do |options|
|
367
|
+
expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
|
368
|
+
expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
|
369
|
+
expect(options[:scope]).to eq(["http://example.com/scope"])
|
370
|
+
expect(options[:enable_self_signed_jwt]).to be_nil
|
371
|
+
expect(options[:target_audience]).to be_nil
|
372
|
+
expect(options[:json_key_io].read).to eq(json_content)
|
373
|
+
|
374
|
+
# This should really be a Signet::OAuth2::Client object,
|
375
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
376
|
+
default_keyfile_hash
|
377
|
+
end
|
378
|
+
|
379
|
+
creds = TestCredentials12.default
|
380
|
+
expect(creds).to be_a_kind_of(TestCredentials12)
|
381
|
+
expect(creds.client).to eq(mocked_signet)
|
382
|
+
expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
|
383
|
+
expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
|
213
384
|
end
|
214
385
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
386
|
+
it "subclasses can use JSON_ENV_VARS to get keyfile contents" do
|
387
|
+
test_json_env_val = JSON.generate default_keyfile_hash
|
388
|
+
|
389
|
+
class TestCredentials13 < Google::Auth::Credentials
|
390
|
+
self.scope = "http://example.com/scope"
|
391
|
+
self.env_vars = %w[PATH_ENV_DUMMY JSON_ENV_DUMMY JSON_ENV_TEST]
|
392
|
+
self.paths = ["~/default/path/to/file.txt"]
|
393
|
+
end
|
394
|
+
|
395
|
+
allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
|
396
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
|
397
|
+
allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
|
398
|
+
allow(::File).to receive(:file?).with(test_json_env_val) { false }
|
399
|
+
allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
|
400
|
+
allow(::ENV).to receive(:[]).with("JSON_ENV_TEST") { test_json_env_val }
|
401
|
+
|
402
|
+
mocked_signet = mock_signet
|
403
|
+
|
404
|
+
allow(Google::Auth::ServiceAccountCredentials).to receive(:make_creds) do |options|
|
405
|
+
expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
|
406
|
+
expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
|
407
|
+
expect(options[:scope]).to eq(["http://example.com/scope"])
|
408
|
+
expect(options[:enable_self_signed_jwt]).to be_nil
|
409
|
+
expect(options[:target_audience]).to be_nil
|
410
|
+
expect(options[:json_key_io].read).to eq(test_json_env_val)
|
411
|
+
|
412
|
+
# This should really be a Signet::OAuth2::Client object,
|
413
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
414
|
+
default_keyfile_hash
|
415
|
+
end
|
416
|
+
|
417
|
+
creds = TestCredentials13.default
|
418
|
+
expect(creds).to be_a_kind_of(TestCredentials13)
|
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"])
|
227
422
|
end
|
228
423
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
424
|
+
it "subclasses can use DEFAULT_PATHS to get keyfile path" do
|
425
|
+
class TestCredentials14 < 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
|
+
json_content = JSON.generate default_keyfile_hash
|
432
|
+
|
433
|
+
allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
|
434
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
|
435
|
+
allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
|
436
|
+
allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
|
437
|
+
allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { true }
|
438
|
+
allow(::File).to receive(:read).with("~/default/path/to/file.txt") { json_content }
|
439
|
+
|
440
|
+
mocked_signet = mock_signet
|
441
|
+
|
442
|
+
allow(Google::Auth::ServiceAccountCredentials).to receive(:make_creds) do |options|
|
443
|
+
expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
|
444
|
+
expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
|
445
|
+
expect(options[:scope]).to eq(["http://example.com/scope"])
|
446
|
+
expect(options[:enable_self_signed_jwt]).to be_nil
|
447
|
+
expect(options[:target_audience]).to be_nil
|
448
|
+
expect(options[:json_key_io].read).to eq(json_content)
|
449
|
+
|
450
|
+
# This should really be a Signet::OAuth2::Client object,
|
451
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
452
|
+
default_keyfile_hash
|
453
|
+
end
|
454
|
+
|
455
|
+
creds = TestCredentials14.default
|
456
|
+
expect(creds).to be_a_kind_of(TestCredentials14)
|
457
|
+
expect(creds.client).to eq(mocked_signet)
|
458
|
+
expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
|
459
|
+
expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
|
460
|
+
end
|
233
461
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
462
|
+
it "subclasses that find no matches default to Google::Auth.get_application_default with self-signed jwt enabled" do
|
463
|
+
class TestCredentials15 < Google::Auth::Credentials
|
464
|
+
self.scope = "http://example.com/scope"
|
465
|
+
self.env_vars = %w[PATH_ENV_DUMMY JSON_ENV_DUMMY]
|
466
|
+
self.paths = ["~/default/path/to/file.txt"]
|
467
|
+
end
|
468
|
+
|
469
|
+
allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
|
470
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
|
471
|
+
allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
|
472
|
+
allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
|
473
|
+
allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { false }
|
474
|
+
|
475
|
+
mocked_signet = mock_signet
|
476
|
+
|
477
|
+
allow(Google::Auth).to receive(:get_application_default) do |scope, options|
|
478
|
+
expect(scope).to eq(TestCredentials15.scope)
|
479
|
+
expect(options[:enable_self_signed_jwt]).to eq(true)
|
480
|
+
expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
|
481
|
+
expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
|
482
|
+
|
483
|
+
# This should really be a Signet::OAuth2::Client object,
|
484
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
485
|
+
default_keyfile_hash
|
486
|
+
end
|
487
|
+
|
488
|
+
creds = TestCredentials15.default enable_self_signed_jwt: true
|
489
|
+
expect(creds).to be_a_kind_of(TestCredentials15)
|
490
|
+
expect(creds.client).to eq(mocked_signet)
|
491
|
+
expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
|
492
|
+
expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
|
493
|
+
end
|
240
494
|
|
241
|
-
|
242
|
-
|
243
|
-
|
495
|
+
it "subclasses that find no matches default to Google::Auth.get_application_default with self-signed jwt disabled" do
|
496
|
+
class TestCredentials16 < Google::Auth::Credentials
|
497
|
+
self.scope = "http://example.com/scope"
|
498
|
+
self.env_vars = %w[PATH_ENV_DUMMY JSON_ENV_DUMMY]
|
499
|
+
self.paths = ["~/default/path/to/file.txt"]
|
500
|
+
end
|
501
|
+
|
502
|
+
allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
|
503
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
|
504
|
+
allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
|
505
|
+
allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
|
506
|
+
allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { false }
|
507
|
+
|
508
|
+
mocked_signet = mock_signet
|
509
|
+
|
510
|
+
allow(Google::Auth).to receive(:get_application_default) do |scope, options|
|
511
|
+
expect(scope).to eq(TestCredentials16.scope)
|
512
|
+
expect(options[:enable_self_signed_jwt]).to be_nil
|
513
|
+
expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token")
|
514
|
+
expect(options[:audience]).to eq("https://oauth2.googleapis.com/token")
|
515
|
+
|
516
|
+
# This should really be a Signet::OAuth2::Client object,
|
517
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
518
|
+
default_keyfile_hash
|
519
|
+
end
|
520
|
+
|
521
|
+
creds = TestCredentials16.default
|
522
|
+
expect(creds).to be_a_kind_of(TestCredentials16)
|
523
|
+
expect(creds.client).to eq(mocked_signet)
|
524
|
+
expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
|
525
|
+
expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
|
244
526
|
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
527
|
|
252
|
-
|
528
|
+
it "subclasses that find no matches default to Google::Auth.get_application_default with custom values" do
|
529
|
+
scope2 = "http://example.com/scope2"
|
530
|
+
|
531
|
+
class TestCredentials17 < Google::Auth::Credentials
|
532
|
+
self.scope = "http://example.com/scope"
|
533
|
+
self.env_vars = %w[PATH_ENV_DUMMY JSON_ENV_DUMMY]
|
534
|
+
self.paths = ["~/default/path/to/file.txt"]
|
535
|
+
self.token_credential_uri = "https://example.com/token2"
|
536
|
+
self.audience = "https://example.com/token3"
|
537
|
+
end
|
538
|
+
|
539
|
+
allow(::ENV).to receive(:[]).with("GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS") { "true" }
|
540
|
+
allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" }
|
541
|
+
allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false }
|
542
|
+
allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil }
|
543
|
+
allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { false }
|
544
|
+
|
545
|
+
mocked_signet = mock_signet
|
546
|
+
|
547
|
+
allow(Google::Auth).to receive(:get_application_default) do |scope, options|
|
548
|
+
expect(scope).to eq(scope2)
|
549
|
+
expect(options[:enable_self_signed_jwt]).to eq(false)
|
550
|
+
expect(options[:token_credential_uri]).to eq("https://example.com/token2")
|
551
|
+
expect(options[:audience]).to eq("https://example.com/token3")
|
552
|
+
|
553
|
+
# This should really be a Signet::OAuth2::Client object,
|
554
|
+
# but mocking is making that difficult, so return a valid hash instead.
|
555
|
+
default_keyfile_hash
|
556
|
+
end
|
557
|
+
|
558
|
+
creds = TestCredentials17.default scope: scope2, enable_self_signed_jwt: true
|
559
|
+
expect(creds).to be_a_kind_of(TestCredentials17)
|
560
|
+
expect(creds.client).to eq(mocked_signet)
|
561
|
+
expect(creds.project_id).to eq(default_keyfile_hash["project_id"])
|
562
|
+
expect(creds.quota_project_id).to eq(default_keyfile_hash["quota_project_id"])
|
253
563
|
end
|
254
564
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
565
|
+
it "subclasses delegate up the class hierarchy" do
|
566
|
+
class TestCredentials18 < Google::Auth::Credentials
|
567
|
+
self.scope = "http://example.com/scope"
|
568
|
+
self.target_audience = "https://example.com/target_audience"
|
569
|
+
self.env_vars = ["TEST_PATH", "TEST_JSON_VARS"]
|
570
|
+
self.paths = ["~/default/path/to/file.txt"]
|
571
|
+
end
|
572
|
+
|
573
|
+
class TestCredentials19 < TestCredentials18
|
574
|
+
end
|
575
|
+
|
576
|
+
expect(TestCredentials19.scope).to eq(["http://example.com/scope"])
|
577
|
+
expect(TestCredentials19.target_audience).to eq("https://example.com/target_audience")
|
578
|
+
expect(TestCredentials19.env_vars).to eq(["TEST_PATH", "TEST_JSON_VARS"])
|
579
|
+
expect(TestCredentials19.paths).to eq(["~/default/path/to/file.txt"])
|
580
|
+
|
581
|
+
TestCredentials19.token_credential_uri = "https://example.com/token2"
|
582
|
+
expect(TestCredentials19.token_credential_uri).to eq("https://example.com/token2")
|
583
|
+
TestCredentials19.token_credential_uri = nil
|
584
|
+
expect(TestCredentials19.token_credential_uri).to eq("https://oauth2.googleapis.com/token")
|
585
|
+
end
|
259
586
|
end
|
260
587
|
|
261
588
|
it "warns when cloud sdk credentials are used" do
|