googleauth 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +2 -2
- data/.travis.yml +18 -2
- data/CHANGELOG.md +26 -1
- data/googleauth.gemspec +2 -1
- data/lib/googleauth.rb +29 -6
- data/lib/googleauth/credentials_loader.rb +53 -8
- data/lib/googleauth/iam.rb +75 -0
- data/lib/googleauth/service_account.rb +19 -6
- data/lib/googleauth/user_refresh.rb +9 -2
- data/lib/googleauth/version.rb +1 -1
- data/spec/googleauth/get_application_default_spec.rb +66 -21
- data/spec/googleauth/iam_spec.rb +80 -0
- data/spec/googleauth/service_account_spec.rb +77 -24
- data/spec/googleauth/user_refresh_spec.rb +76 -16
- metadata +45 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: adef96ddcbbab3bf0cdf0bcb5e2772bbf3de2f04
|
4
|
+
data.tar.gz: ab58fe380898294110ec76ac571a22ef411efe6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ad82896ca3cac5f605ece8cf51c512bc4625c782045452fee044064ae4d751e33e29101f6c9caef569f08816b1b1066626000a3b541c30dc02033a70cbebe7c
|
7
|
+
data.tar.gz: cd31e77291d39c9cf44c6ffa39a3e939274a5ca9834d6ee558f2e5ec4d5b575d6c8d29655cbaa4b25dc8e5ca89330a5f87d61dd1eea302398ac388c27f56aa46
|
data/.rubocop_todo.yml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# This configuration was generated by `rubocop --auto-gen-config`
|
2
|
-
# on 2015-
|
2
|
+
# on 2015-05-18 09:38:28 -0700 using RuboCop version 0.31.0.
|
3
3
|
# The point is for the user to remove these configuration records
|
4
4
|
# one by one as the offenses are removed from the code base.
|
5
5
|
# Note that changes in the inspected code, or installation of new
|
@@ -9,7 +9,7 @@
|
|
9
9
|
Metrics/AbcSize:
|
10
10
|
Max: 24
|
11
11
|
|
12
|
-
# Offense count:
|
12
|
+
# Offense count: 10
|
13
13
|
# Configuration parameters: CountComments.
|
14
14
|
Metrics/MethodLength:
|
15
15
|
Max: 13
|
data/.travis.yml
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
sudo: false
|
1
2
|
language: ruby
|
2
3
|
rvm:
|
3
4
|
- 2.2
|
@@ -7,9 +8,24 @@ rvm:
|
|
7
8
|
- rbx-2
|
8
9
|
- jruby
|
9
10
|
script: "bundle exec rake"
|
11
|
+
addons:
|
12
|
+
apt:
|
13
|
+
packages:
|
14
|
+
- idn
|
15
|
+
- build-essential # this and below attempt allow rubinius to be setup ok
|
16
|
+
- bison
|
17
|
+
- ruby-dev
|
18
|
+
- rake zlib1g-dev
|
19
|
+
- libyaml-dev
|
20
|
+
- libssl-dev
|
21
|
+
- libreadline-dev
|
22
|
+
- libncurses5-dev
|
23
|
+
- llvm
|
24
|
+
- llvm-dev
|
25
|
+
- libeditline-dev
|
26
|
+
- libedit-dev
|
10
27
|
before_install:
|
11
|
-
-
|
12
|
-
- sudo apt-get install idn
|
28
|
+
- gem update bundler
|
13
29
|
notifications:
|
14
30
|
email:
|
15
31
|
recipients:
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
## 0.4.2 (05/08/2015)
|
2
|
+
|
3
|
+
### Changes
|
4
|
+
|
5
|
+
* Updated UserRefreshCredentials hash to use string keys ([@haabator][])
|
6
|
+
[#36](https://github.com/google/google-auth-library-ruby/issues/36)
|
7
|
+
|
8
|
+
* Add support for a system default credentials file. ([@mr-salty][])
|
9
|
+
[#33](https://github.com/google/google-auth-library-ruby/issues/33)
|
10
|
+
|
11
|
+
* Fix bug when loading credentials from ENV ([@dwilkie][])
|
12
|
+
[#31](https://github.com/google/google-auth-library-ruby/issues/31)
|
13
|
+
|
14
|
+
* Relax the constraint of dependent version of multi_json ([@igrep][])
|
15
|
+
[#30](https://github.com/google/google-auth-library-ruby/issues/30)
|
16
|
+
|
17
|
+
### Changes
|
18
|
+
|
19
|
+
* Enables passing credentials via environment variables. ([@haabaato][])
|
20
|
+
[#27](https://github.com/google/google-auth-library-ruby/issues/27)
|
21
|
+
|
1
22
|
## 0.4.1 (25/04/2015)
|
2
23
|
|
3
24
|
### Changes
|
@@ -18,5 +39,9 @@
|
|
18
39
|
* makes the scope parameter's optional in all APIs. ([@tbetbetbe][])
|
19
40
|
* changes the scope parameter's position in various constructors. ([@tbetbetbe][])
|
20
41
|
|
21
|
-
[@
|
42
|
+
[@dwilkie]: https://github.com/dwilkie
|
43
|
+
[@haabaato]: https://github.com/haabaato
|
44
|
+
[@igrep]: https://github.com/igrep
|
22
45
|
[@joneslee85]: https://github.com/joneslee85
|
46
|
+
[@mr-salty]: https://github.com/mr-salty
|
47
|
+
[@tbetbetbe]: https://github.com/tbetbetbe
|
data/googleauth.gemspec
CHANGED
@@ -29,12 +29,13 @@ Gem::Specification.new do |s|
|
|
29
29
|
s.add_dependency 'logging', '~> 2.0'
|
30
30
|
s.add_dependency 'jwt', '~> 1.4'
|
31
31
|
s.add_dependency 'memoist', '~> 0.12'
|
32
|
-
s.add_dependency 'multi_json', '1.11'
|
32
|
+
s.add_dependency 'multi_json', '~> 1.11'
|
33
33
|
s.add_dependency 'signet', '~> 0.6'
|
34
34
|
|
35
35
|
s.add_development_dependency 'bundler', '~> 1.9'
|
36
36
|
s.add_development_dependency 'simplecov', '~> 0.9'
|
37
37
|
s.add_development_dependency 'coveralls', '~> 0.7'
|
38
|
+
s.add_development_dependency 'fakefs', '~> 0.6'
|
38
39
|
s.add_development_dependency 'rake', '~> 10.0'
|
39
40
|
s.add_development_dependency 'rubocop', '~> 0.30'
|
40
41
|
s.add_development_dependency 'rspec', '~> 3.0'
|
data/lib/googleauth.rb
CHANGED
@@ -52,16 +52,38 @@ END
|
|
52
52
|
|
53
53
|
# override CredentialsLoader#make_creds to use the class determined by
|
54
54
|
# loading the json.
|
55
|
-
def self.make_creds(
|
56
|
-
|
57
|
-
|
55
|
+
def self.make_creds(options = {})
|
56
|
+
json_key_io, scope = options.values_at(:json_key_io, :scope)
|
57
|
+
if json_key_io
|
58
|
+
json_key, clz = determine_creds_class(json_key_io)
|
59
|
+
clz.new(json_key_io: StringIO.new(MultiJson.dump(json_key)),
|
60
|
+
scope: scope)
|
61
|
+
else
|
62
|
+
clz = read_creds
|
63
|
+
clz.new(scope: scope)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.read_creds
|
68
|
+
env_var = CredentialsLoader::ACCOUNT_TYPE_VAR
|
69
|
+
type = ENV[env_var]
|
70
|
+
fail "#{ACCOUNT_TYPE_VAR} is undefined in env" unless type
|
71
|
+
case type
|
72
|
+
when 'service_account'
|
73
|
+
ServiceAccountCredentials
|
74
|
+
when 'authorized_user'
|
75
|
+
UserRefreshCredentials
|
76
|
+
else
|
77
|
+
fail "credentials type '#{type}' is not supported"
|
78
|
+
end
|
58
79
|
end
|
59
80
|
|
60
81
|
# Reads the input json and determines which creds class to use.
|
61
82
|
def self.determine_creds_class(json_key_io)
|
62
83
|
json_key = MultiJson.load(json_key_io.read)
|
63
|
-
|
64
|
-
|
84
|
+
key = 'type'
|
85
|
+
fail "the json is missing the '#{key}' field" unless json_key.key?(key)
|
86
|
+
type = json_key[key]
|
65
87
|
case type
|
66
88
|
when 'service_account'
|
67
89
|
[json_key, ServiceAccountCredentials]
|
@@ -88,7 +110,8 @@ END
|
|
88
110
|
# @param options [hash] allows override of the connection being used
|
89
111
|
def get_application_default(scope = nil, options = {})
|
90
112
|
creds = DefaultCredentials.from_env(scope) ||
|
91
|
-
DefaultCredentials.from_well_known_path(scope)
|
113
|
+
DefaultCredentials.from_well_known_path(scope) ||
|
114
|
+
DefaultCredentials.from_system_default_path(scope)
|
92
115
|
return creds unless creds.nil?
|
93
116
|
fail NOT_FOUND_ERROR unless GCECredentials.on_gce?(options)
|
94
117
|
GCECredentials.new
|
@@ -39,11 +39,22 @@ module Google
|
|
39
39
|
module CredentialsLoader
|
40
40
|
extend Memoist
|
41
41
|
ENV_VAR = 'GOOGLE_APPLICATION_CREDENTIALS'
|
42
|
+
|
43
|
+
PRIVATE_KEY_VAR = 'GOOGLE_PRIVATE_KEY'
|
44
|
+
CLIENT_EMAIL_VAR = 'GOOGLE_CLIENT_EMAIL'
|
45
|
+
CLIENT_ID_VAR = 'GOOGLE_CLIENT_ID'
|
46
|
+
CLIENT_SECRET_VAR = 'GOOGLE_CLIENT_SECRET'
|
47
|
+
REFRESH_TOKEN_VAR = 'GOOGLE_REFRESH_TOKEN'
|
48
|
+
ACCOUNT_TYPE_VAR = 'GOOGLE_ACCOUNT_TYPE'
|
49
|
+
|
50
|
+
CREDENTIALS_FILE_NAME = 'application_default_credentials.json'
|
42
51
|
NOT_FOUND_ERROR =
|
43
52
|
"Unable to read the credential file specified by #{ENV_VAR}"
|
44
|
-
WELL_KNOWN_PATH =
|
53
|
+
WELL_KNOWN_PATH = "gcloud/#{CREDENTIALS_FILE_NAME}"
|
45
54
|
WELL_KNOWN_ERROR = 'Unable to read the default credential file'
|
46
55
|
|
56
|
+
SYSTEM_DEFAULT_ERROR = 'Unable to read the system default credential file'
|
57
|
+
|
47
58
|
# determines if the current OS is windows
|
48
59
|
def windows?
|
49
60
|
RbConfig::CONFIG['host_os'] =~ /Windows|mswin/
|
@@ -63,11 +74,14 @@ module Google
|
|
63
74
|
#
|
64
75
|
# @param scope [string|array|nil] the scope(s) to access
|
65
76
|
def from_env(scope = nil)
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
77
|
+
if ENV.key?(ENV_VAR)
|
78
|
+
path = ENV[ENV_VAR]
|
79
|
+
fail "file #{path} does not exist" unless File.exist?(path)
|
80
|
+
File.open(path) do |f|
|
81
|
+
return make_creds(json_key_io: f, scope: scope)
|
82
|
+
end
|
83
|
+
elsif service_account_env_vars? || authorized_user_env_vars?
|
84
|
+
return make_creds(scope: scope)
|
71
85
|
end
|
72
86
|
rescue StandardError => e
|
73
87
|
raise "#{NOT_FOUND_ERROR}: #{e}"
|
@@ -77,17 +91,48 @@ module Google
|
|
77
91
|
#
|
78
92
|
# @param scope [string|array|nil] the scope(s) to access
|
79
93
|
def from_well_known_path(scope = nil)
|
80
|
-
home_var
|
94
|
+
home_var = windows? ? 'APPDATA' : 'HOME'
|
95
|
+
base = WELL_KNOWN_PATH
|
81
96
|
root = ENV[home_var].nil? ? '' : ENV[home_var]
|
82
97
|
base = File.join('.config', base) unless windows?
|
83
98
|
path = File.join(root, base)
|
84
99
|
return nil unless File.exist?(path)
|
85
100
|
File.open(path) do |f|
|
86
|
-
return make_creds(f, scope)
|
101
|
+
return make_creds(json_key_io: f, scope: scope)
|
87
102
|
end
|
88
103
|
rescue StandardError => e
|
89
104
|
raise "#{WELL_KNOWN_ERROR}: #{e}"
|
90
105
|
end
|
106
|
+
|
107
|
+
# Creates an instance from the system default path
|
108
|
+
#
|
109
|
+
# @param scope [string|array|nil] the scope(s) to access
|
110
|
+
def from_system_default_path(scope = nil)
|
111
|
+
if windows?
|
112
|
+
return nil unless ENV['ProgramData']
|
113
|
+
prefix = File.join(ENV['ProgramData'], 'Google/Auth')
|
114
|
+
else
|
115
|
+
prefix = '/etc/google/auth/'
|
116
|
+
end
|
117
|
+
path = File.join(prefix, CREDENTIALS_FILE_NAME)
|
118
|
+
return nil unless File.exist?(path)
|
119
|
+
File.open(path) do |f|
|
120
|
+
return make_creds(json_key_io: f, scope: scope)
|
121
|
+
end
|
122
|
+
rescue StandardError => e
|
123
|
+
raise "#{SYSTEM_DEFAULT_ERROR}: #{e}"
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def service_account_env_vars?
|
129
|
+
([PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR] - ENV.keys).empty?
|
130
|
+
end
|
131
|
+
|
132
|
+
def authorized_user_env_vars?
|
133
|
+
([CLIENT_ID_VAR, CLIENT_SECRET_VAR, REFRESH_TOKEN_VAR] -
|
134
|
+
ENV.keys).empty?
|
135
|
+
end
|
91
136
|
end
|
92
137
|
end
|
93
138
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Copyright 2015, Google Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are
|
6
|
+
# met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright
|
9
|
+
# notice, this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above
|
11
|
+
# copyright notice, this list of conditions and the following disclaimer
|
12
|
+
# in the documentation and/or other materials provided with the
|
13
|
+
# distribution.
|
14
|
+
# * Neither the name of Google Inc. nor the names of its
|
15
|
+
# contributors may be used to endorse or promote products derived from
|
16
|
+
# this software without specific prior written permission.
|
17
|
+
#
|
18
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
19
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
20
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
21
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
22
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
23
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
24
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
26
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
27
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
|
30
|
+
require 'googleauth/signet'
|
31
|
+
require 'googleauth/credentials_loader'
|
32
|
+
require 'multi_json'
|
33
|
+
|
34
|
+
module Google
|
35
|
+
# Module Auth provides classes that provide Google-specific authorization
|
36
|
+
# used to access Google APIs.
|
37
|
+
module Auth
|
38
|
+
# Authenticates requests using IAM credentials.
|
39
|
+
class IAMCredentials
|
40
|
+
SELECTOR_KEY = 'x-goog-iam-authority-selector'
|
41
|
+
TOKEN_KEY = 'x-goog-iam-authorization-token'
|
42
|
+
|
43
|
+
# Initializes an IAMCredentials.
|
44
|
+
#
|
45
|
+
# @param selector the IAM selector.
|
46
|
+
# @param token the IAM token.
|
47
|
+
def initialize(selector, token)
|
48
|
+
fail TypeError unless selector.is_a? String
|
49
|
+
fail TypeError unless token.is_a? String
|
50
|
+
@selector = selector
|
51
|
+
@token = token
|
52
|
+
end
|
53
|
+
|
54
|
+
# Adds the credential fields to the hash.
|
55
|
+
def apply!(a_hash)
|
56
|
+
a_hash[SELECTOR_KEY] = @selector
|
57
|
+
a_hash[TOKEN_KEY] = @token
|
58
|
+
a_hash
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns a clone of a_hash updated with the authoriation header
|
62
|
+
def apply(a_hash)
|
63
|
+
a_copy = a_hash.clone
|
64
|
+
apply!(a_copy)
|
65
|
+
a_copy
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns a reference to the #apply method, suitable for passing as
|
69
|
+
# a closure
|
70
|
+
def updater_proc
|
71
|
+
lambda(&method(:apply))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -62,8 +62,15 @@ module Google
|
|
62
62
|
#
|
63
63
|
# @param json_key_io [IO] an IO from which the JSON key can be read
|
64
64
|
# @param scope [string|array|nil] the scope(s) to access
|
65
|
-
def initialize(
|
66
|
-
|
65
|
+
def initialize(options = {})
|
66
|
+
json_key_io, scope = options.values_at(:json_key_io, :scope)
|
67
|
+
if json_key_io
|
68
|
+
private_key, client_email = self.class.read_json_key(json_key_io)
|
69
|
+
else
|
70
|
+
private_key = ENV[CredentialsLoader::PRIVATE_KEY_VAR]
|
71
|
+
client_email = ENV[CredentialsLoader::CLIENT_EMAIL_VAR]
|
72
|
+
end
|
73
|
+
|
67
74
|
super(token_credential_uri: TOKEN_CRED_URI,
|
68
75
|
audience: TOKEN_CRED_URI,
|
69
76
|
scope: scope,
|
@@ -90,7 +97,7 @@ module Google
|
|
90
97
|
client_email: @issuer
|
91
98
|
}
|
92
99
|
alt_clz = ServiceAccountJwtHeaderCredentials
|
93
|
-
alt = alt_clz.new(StringIO.new(MultiJson.dump(cred_json)))
|
100
|
+
alt = alt_clz.new(json_key_io: StringIO.new(MultiJson.dump(cred_json)))
|
94
101
|
alt.apply!(a_hash)
|
95
102
|
end
|
96
103
|
end
|
@@ -120,7 +127,7 @@ module Google
|
|
120
127
|
# optional scope. Here's the constructor only has one param, so
|
121
128
|
# we modify make_creds to reflect this.
|
122
129
|
def self.make_creds(*args)
|
123
|
-
new(args[0])
|
130
|
+
new(json_key_io: args[0][:json_key_io])
|
124
131
|
end
|
125
132
|
|
126
133
|
# Reads the private key and client email fields from the service account
|
@@ -135,8 +142,14 @@ module Google
|
|
135
142
|
# Initializes a ServiceAccountJwtHeaderCredentials.
|
136
143
|
#
|
137
144
|
# @param json_key_io [IO] an IO from which the JSON key can be read
|
138
|
-
def initialize(
|
139
|
-
|
145
|
+
def initialize(options = {})
|
146
|
+
json_key_io = options[:json_key_io]
|
147
|
+
if json_key_io
|
148
|
+
private_key, client_email = self.class.read_json_key(json_key_io)
|
149
|
+
else
|
150
|
+
private_key = ENV[CredentialsLoader::PRIVATE_KEY_VAR]
|
151
|
+
client_email = ENV[CredentialsLoader::CLIENT_EMAIL_VAR]
|
152
|
+
end
|
140
153
|
@private_key = private_key
|
141
154
|
@issuer = client_email
|
142
155
|
@signing_key = OpenSSL::PKey::RSA.new(private_key)
|
@@ -63,8 +63,15 @@ module Google
|
|
63
63
|
#
|
64
64
|
# @param json_key_io [IO] an IO from which the JSON key can be read
|
65
65
|
# @param scope [string|array|nil] the scope(s) to access
|
66
|
-
def initialize(
|
67
|
-
|
66
|
+
def initialize(options = {})
|
67
|
+
json_key_io, scope = options.values_at(:json_key_io, :scope)
|
68
|
+
user_creds = self.class.read_json_key(json_key_io) if json_key_io
|
69
|
+
user_creds ||= {
|
70
|
+
'client_id' => ENV[CredentialsLoader::CLIENT_ID_VAR],
|
71
|
+
'client_secret' => ENV[CredentialsLoader::CLIENT_SECRET_VAR],
|
72
|
+
'refresh_token' => ENV[CredentialsLoader::REFRESH_TOKEN_VAR]
|
73
|
+
}
|
74
|
+
|
68
75
|
super(token_credential_uri: TOKEN_CRED_URI,
|
69
76
|
client_id: user_creds['client_id'],
|
70
77
|
client_secret: user_creds['client_secret'],
|
data/lib/googleauth/version.rb
CHANGED
@@ -32,20 +32,25 @@ $LOAD_PATH.unshift(spec_dir)
|
|
32
32
|
$LOAD_PATH.uniq!
|
33
33
|
|
34
34
|
require 'faraday'
|
35
|
+
require 'fakefs/safe'
|
35
36
|
require 'googleauth'
|
36
37
|
require 'spec_helper'
|
37
38
|
|
38
39
|
describe '#get_application_default' do
|
39
40
|
before(:example) do
|
40
41
|
@key = OpenSSL::PKey::RSA.new(2048)
|
41
|
-
@var_name =
|
42
|
-
@
|
42
|
+
@var_name = ENV_VAR
|
43
|
+
@credential_vars = [
|
44
|
+
ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, CLIENT_ID_VAR,
|
45
|
+
CLIENT_SECRET_VAR, REFRESH_TOKEN_VAR, ACCOUNT_TYPE_VAR]
|
46
|
+
@original_env_vals = {}
|
47
|
+
@credential_vars.each { |var| @original_env_vals[var] = ENV[var] }
|
43
48
|
@home = ENV['HOME']
|
44
49
|
@scope = 'https://www.googleapis.com/auth/userinfo.profile'
|
45
50
|
end
|
46
51
|
|
47
52
|
after(:example) do
|
48
|
-
ENV[
|
53
|
+
@credential_vars.each { |var| ENV[var] = @original_env_vals[var] }
|
49
54
|
ENV['HOME'] = @home unless @home == ENV['HOME']
|
50
55
|
end
|
51
56
|
|
@@ -54,7 +59,8 @@ describe '#get_application_default' do
|
|
54
59
|
Dir.mktmpdir do |dir|
|
55
60
|
key_path = File.join(dir, 'does-not-exist')
|
56
61
|
ENV[@var_name] = key_path
|
57
|
-
expect { Google::Auth.get_application_default(@scope) }
|
62
|
+
expect { Google::Auth.get_application_default(@scope) }
|
63
|
+
.to raise_error RuntimeError
|
58
64
|
end
|
59
65
|
end
|
60
66
|
|
@@ -65,17 +71,17 @@ describe '#get_application_default' do
|
|
65
71
|
{ 'Metadata-Flavor' => 'Google' },
|
66
72
|
'']
|
67
73
|
end
|
68
|
-
end
|
74
|
+
end # GCE not detected
|
69
75
|
Dir.mktmpdir do |dir|
|
70
76
|
ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var
|
71
|
-
ENV['HOME'] = dir
|
77
|
+
ENV['HOME'] = dir # no config present in this tmp dir
|
72
78
|
c = Faraday.new do |b|
|
73
79
|
b.adapter(:test, stubs)
|
74
80
|
end
|
75
81
|
blk = proc do
|
76
82
|
Google::Auth.get_application_default(@scope, connection: c)
|
77
83
|
end
|
78
|
-
expect(&blk).to raise_error
|
84
|
+
expect(&blk).to raise_error RuntimeError
|
79
85
|
end
|
80
86
|
stubs.verify_stubbed_calls
|
81
87
|
end
|
@@ -95,8 +101,7 @@ describe '#get_application_default' do
|
|
95
101
|
it 'succeeds with default file without GOOGLE_APPLICATION_CREDENTIALS' do
|
96
102
|
ENV.delete(@var_name) unless ENV[@var_name].nil?
|
97
103
|
Dir.mktmpdir do |dir|
|
98
|
-
key_path = File.join(dir, '.config',
|
99
|
-
CredentialsLoader::WELL_KNOWN_PATH)
|
104
|
+
key_path = File.join(dir, '.config', WELL_KNOWN_PATH)
|
100
105
|
FileUtils.mkdir_p(File.dirname(key_path))
|
101
106
|
File.write(key_path, cred_json_text)
|
102
107
|
ENV['HOME'] = dir
|
@@ -107,8 +112,7 @@ describe '#get_application_default' do
|
|
107
112
|
it 'succeeds with default file without a scope' do
|
108
113
|
ENV.delete(@var_name) unless ENV[@var_name].nil?
|
109
114
|
Dir.mktmpdir do |dir|
|
110
|
-
key_path = File.join(dir, '.config',
|
111
|
-
CredentialsLoader::WELL_KNOWN_PATH)
|
115
|
+
key_path = File.join(dir, '.config', WELL_KNOWN_PATH)
|
112
116
|
FileUtils.mkdir_p(File.dirname(key_path))
|
113
117
|
File.write(key_path, cred_json_text)
|
114
118
|
ENV['HOME'] = dir
|
@@ -123,10 +127,10 @@ describe '#get_application_default' do
|
|
123
127
|
{ 'Metadata-Flavor' => 'Google' },
|
124
128
|
'']
|
125
129
|
end
|
126
|
-
end
|
130
|
+
end # GCE detected
|
127
131
|
Dir.mktmpdir do |dir|
|
128
132
|
ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var
|
129
|
-
ENV['HOME'] = dir
|
133
|
+
ENV['HOME'] = dir # no config present in this tmp dir
|
130
134
|
c = Faraday.new do |b|
|
131
135
|
b.adapter(:test, stubs)
|
132
136
|
end
|
@@ -137,17 +141,42 @@ describe '#get_application_default' do
|
|
137
141
|
end
|
138
142
|
stubs.verify_stubbed_calls
|
139
143
|
end
|
144
|
+
|
145
|
+
it 'succeeds with system default file' do
|
146
|
+
ENV.delete(@var_name) unless ENV[@var_name].nil?
|
147
|
+
FakeFS do
|
148
|
+
key_path = File.join('/etc/google/auth/', CREDENTIALS_FILE_NAME)
|
149
|
+
FileUtils.mkdir_p(File.dirname(key_path))
|
150
|
+
File.write(key_path, cred_json_text)
|
151
|
+
expect(Google::Auth.get_application_default(@scope)).to_not be_nil
|
152
|
+
File.delete(key_path)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'succeeds if environment vars are valid' do
|
157
|
+
ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var
|
158
|
+
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
159
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
160
|
+
ENV[CLIENT_ID_VAR] = cred_json[:client_id]
|
161
|
+
ENV[CLIENT_SECRET_VAR] = cred_json[:client_secret]
|
162
|
+
ENV[REFRESH_TOKEN_VAR] = cred_json[:refresh_token]
|
163
|
+
ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
|
164
|
+
expect(Google::Auth.get_application_default(@scope)).to_not be_nil
|
165
|
+
end
|
140
166
|
end
|
141
167
|
|
142
168
|
describe 'when credential type is service account' do
|
143
|
-
|
144
|
-
|
169
|
+
let(:cred_json) do
|
170
|
+
{
|
145
171
|
private_key_id: 'a_private_key_id',
|
146
172
|
private_key: @key.to_pem,
|
147
173
|
client_email: 'app@developer.gserviceaccount.com',
|
148
174
|
client_id: 'app.apps.googleusercontent.com',
|
149
175
|
type: 'service_account'
|
150
176
|
}
|
177
|
+
end
|
178
|
+
|
179
|
+
def cred_json_text
|
151
180
|
MultiJson.dump(cred_json)
|
152
181
|
end
|
153
182
|
|
@@ -156,13 +185,16 @@ describe '#get_application_default' do
|
|
156
185
|
end
|
157
186
|
|
158
187
|
describe 'when credential type is authorized_user' do
|
159
|
-
|
160
|
-
|
188
|
+
let(:cred_json) do
|
189
|
+
{
|
161
190
|
client_secret: 'privatekey',
|
162
191
|
refresh_token: 'refreshtoken',
|
163
192
|
client_id: 'app.apps.googleusercontent.com',
|
164
193
|
type: 'authorized_user'
|
165
194
|
}
|
195
|
+
end
|
196
|
+
|
197
|
+
def cred_json_text
|
166
198
|
MultiJson.dump(cred_json)
|
167
199
|
end
|
168
200
|
|
@@ -171,13 +203,18 @@ describe '#get_application_default' do
|
|
171
203
|
end
|
172
204
|
|
173
205
|
describe 'when credential type is unknown' do
|
174
|
-
|
175
|
-
|
206
|
+
let(:cred_json) do
|
207
|
+
{
|
176
208
|
client_secret: 'privatekey',
|
177
209
|
refresh_token: 'refreshtoken',
|
178
210
|
client_id: 'app.apps.googleusercontent.com',
|
211
|
+
private_key: @key.to_pem,
|
212
|
+
client_email: 'app@developer.gserviceaccount.com',
|
179
213
|
type: 'not_known_type'
|
180
214
|
}
|
215
|
+
end
|
216
|
+
|
217
|
+
def cred_json_text
|
181
218
|
MultiJson.dump(cred_json)
|
182
219
|
end
|
183
220
|
|
@@ -197,8 +234,7 @@ describe '#get_application_default' do
|
|
197
234
|
it 'fails if the well known file contains the creds' do
|
198
235
|
ENV.delete(@var_name) unless ENV[@var_name].nil?
|
199
236
|
Dir.mktmpdir do |dir|
|
200
|
-
key_path = File.join(dir, '.config',
|
201
|
-
CredentialsLoader::WELL_KNOWN_PATH)
|
237
|
+
key_path = File.join(dir, '.config', WELL_KNOWN_PATH)
|
202
238
|
FileUtils.mkdir_p(File.dirname(key_path))
|
203
239
|
File.write(key_path, cred_json_text)
|
204
240
|
ENV['HOME'] = dir
|
@@ -208,5 +244,14 @@ describe '#get_application_default' do
|
|
208
244
|
expect(&blk).to raise_error RuntimeError
|
209
245
|
end
|
210
246
|
end
|
247
|
+
|
248
|
+
it 'fails if env vars are set' do
|
249
|
+
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
250
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
251
|
+
blk = proc do
|
252
|
+
Google::Auth.get_application_default(@scope)
|
253
|
+
end
|
254
|
+
expect(&blk).to raise_error RuntimeError
|
255
|
+
end
|
211
256
|
end
|
212
257
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# Copyright 2015, Google Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are
|
6
|
+
# met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright
|
9
|
+
# notice, this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above
|
11
|
+
# copyright notice, this list of conditions and the following disclaimer
|
12
|
+
# in the documentation and/or other materials provided with the
|
13
|
+
# distribution.
|
14
|
+
# * Neither the name of Google Inc. nor the names of its
|
15
|
+
# contributors may be used to endorse or promote products derived from
|
16
|
+
# this software without specific prior written permission.
|
17
|
+
#
|
18
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
19
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
20
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
21
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
22
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
23
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
24
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
26
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
27
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
|
30
|
+
spec_dir = File.expand_path(File.join(File.dirname(__FILE__)))
|
31
|
+
$LOAD_PATH.unshift(spec_dir)
|
32
|
+
$LOAD_PATH.uniq!
|
33
|
+
|
34
|
+
require 'googleauth/iam'
|
35
|
+
|
36
|
+
describe Google::Auth::IAMCredentials do
|
37
|
+
IAMCredentials = Google::Auth::IAMCredentials
|
38
|
+
let(:test_selector) { 'the-test-selector' }
|
39
|
+
let(:test_token) { 'the-test-token' }
|
40
|
+
let(:test_creds) { IAMCredentials.new(test_selector, test_token) }
|
41
|
+
|
42
|
+
describe '#apply!' do
|
43
|
+
it 'should update the target hash with the iam values' do
|
44
|
+
md = { foo: 'bar' }
|
45
|
+
test_creds.apply!(md)
|
46
|
+
expect(md[IAMCredentials::SELECTOR_KEY]).to eq test_selector
|
47
|
+
expect(md[IAMCredentials::TOKEN_KEY]).to eq test_token
|
48
|
+
expect(md[:foo]).to eq 'bar'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'updater_proc' do
|
53
|
+
it 'should provide a proc that updates a hash with the iam values' do
|
54
|
+
md = { foo: 'bar' }
|
55
|
+
the_proc = test_creds.updater_proc
|
56
|
+
got = the_proc.call(md)
|
57
|
+
expect(got[IAMCredentials::SELECTOR_KEY]).to eq test_selector
|
58
|
+
expect(got[IAMCredentials::TOKEN_KEY]).to eq test_token
|
59
|
+
expect(got[:foo]).to eq 'bar'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#apply' do
|
64
|
+
it 'should not update the original hash with the iam values' do
|
65
|
+
md = { foo: 'bar' }
|
66
|
+
test_creds.apply(md)
|
67
|
+
expect(md[IAMCredentials::SELECTOR_KEY]).to be_nil
|
68
|
+
expect(md[IAMCredentials::TOKEN_KEY]).to be_nil
|
69
|
+
expect(md[:foo]).to eq 'bar'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should return a with the iam values' do
|
73
|
+
md = { foo: 'bar' }
|
74
|
+
got = test_creds.apply(md)
|
75
|
+
expect(got[IAMCredentials::SELECTOR_KEY]).to eq test_selector
|
76
|
+
expect(got[IAMCredentials::TOKEN_KEY]).to eq test_token
|
77
|
+
expect(got[:foo]).to eq 'bar'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -32,6 +32,7 @@ $LOAD_PATH.unshift(spec_dir)
|
|
32
32
|
$LOAD_PATH.uniq!
|
33
33
|
|
34
34
|
require 'apply_auth_examples'
|
35
|
+
require 'fakefs/safe'
|
35
36
|
require 'fileutils'
|
36
37
|
require 'googleauth/service_account'
|
37
38
|
require 'jwt'
|
@@ -53,7 +54,7 @@ shared_examples 'jwt header auth' do
|
|
53
54
|
expect(hdr).to_not be_nil
|
54
55
|
expect(hdr.start_with?(auth_prefix)).to be true
|
55
56
|
authorization = hdr[auth_prefix.length..-1]
|
56
|
-
payload,
|
57
|
+
payload, = JWT.decode(authorization, @key.public_key)
|
57
58
|
expect(payload['aud']).to eq(test_uri)
|
58
59
|
expect(payload['iss']).to eq(client_email)
|
59
60
|
end
|
@@ -108,12 +109,22 @@ end
|
|
108
109
|
describe Google::Auth::ServiceAccountCredentials do
|
109
110
|
ServiceAccountCredentials = Google::Auth::ServiceAccountCredentials
|
110
111
|
let(:client_email) { 'app@developer.gserviceaccount.com' }
|
112
|
+
let(:cred_json) do
|
113
|
+
{
|
114
|
+
private_key_id: 'a_private_key_id',
|
115
|
+
private_key: @key.to_pem,
|
116
|
+
client_email: client_email,
|
117
|
+
client_id: 'app.apps.googleusercontent.com',
|
118
|
+
type: 'service_account'
|
119
|
+
}
|
120
|
+
end
|
111
121
|
|
112
122
|
before(:example) do
|
113
123
|
@key = OpenSSL::PKey::RSA.new(2048)
|
114
124
|
@client = ServiceAccountCredentials.new(
|
115
|
-
StringIO.new(cred_json_text),
|
116
|
-
'https://www.googleapis.com/auth/userinfo.profile'
|
125
|
+
json_key_io: StringIO.new(cred_json_text),
|
126
|
+
scope: 'https://www.googleapis.com/auth/userinfo.profile'
|
127
|
+
)
|
117
128
|
end
|
118
129
|
|
119
130
|
def make_auth_stubs(opts = {})
|
@@ -131,13 +142,6 @@ describe Google::Auth::ServiceAccountCredentials do
|
|
131
142
|
end
|
132
143
|
|
133
144
|
def cred_json_text
|
134
|
-
cred_json = {
|
135
|
-
private_key_id: 'a_private_key_id',
|
136
|
-
private_key: @key.to_pem,
|
137
|
-
client_email: client_email,
|
138
|
-
client_id: 'app.apps.googleusercontent.com',
|
139
|
-
type: 'service_account'
|
140
|
-
}
|
141
145
|
MultiJson.dump(cred_json)
|
142
146
|
end
|
143
147
|
|
@@ -154,13 +158,18 @@ describe Google::Auth::ServiceAccountCredentials do
|
|
154
158
|
describe '#from_env' do
|
155
159
|
before(:example) do
|
156
160
|
@var_name = ENV_VAR
|
157
|
-
@
|
161
|
+
@credential_vars = [
|
162
|
+
ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR]
|
163
|
+
@original_env_vals = {}
|
164
|
+
@credential_vars.each { |var| @original_env_vals[var] = ENV[var] }
|
165
|
+
ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
|
166
|
+
|
158
167
|
@scope = 'https://www.googleapis.com/auth/userinfo.profile'
|
159
168
|
@clz = ServiceAccountCredentials
|
160
169
|
end
|
161
170
|
|
162
171
|
after(:example) do
|
163
|
-
ENV[
|
172
|
+
@credential_vars.each { |var| ENV[var] = @original_env_vals[var] }
|
164
173
|
end
|
165
174
|
|
166
175
|
it 'returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset' do
|
@@ -174,7 +183,7 @@ describe Google::Auth::ServiceAccountCredentials do
|
|
174
183
|
Dir.mktmpdir do |dir|
|
175
184
|
key_path = File.join(dir, 'does-not-exist')
|
176
185
|
ENV[@var_name] = key_path
|
177
|
-
expect { @clz.from_env(@scope) }.to raise_error
|
186
|
+
expect { @clz.from_env(@scope) }.to raise_error RuntimeError
|
178
187
|
end
|
179
188
|
end
|
180
189
|
|
@@ -187,6 +196,13 @@ describe Google::Auth::ServiceAccountCredentials do
|
|
187
196
|
expect(@clz.from_env(@scope)).to_not be_nil
|
188
197
|
end
|
189
198
|
end
|
199
|
+
|
200
|
+
it 'succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are'\
|
201
|
+
' valid' do
|
202
|
+
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
203
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
204
|
+
expect(@clz.from_env(@scope)).to_not be_nil
|
205
|
+
end
|
190
206
|
end
|
191
207
|
|
192
208
|
describe '#from_well_known_path' do
|
@@ -216,6 +232,30 @@ describe Google::Auth::ServiceAccountCredentials do
|
|
216
232
|
end
|
217
233
|
end
|
218
234
|
end
|
235
|
+
|
236
|
+
describe '#from_system_default_path' do
|
237
|
+
before(:example) do
|
238
|
+
@scope = 'https://www.googleapis.com/auth/userinfo.profile'
|
239
|
+
@path = File.join('/etc/google/auth/', CREDENTIALS_FILE_NAME)
|
240
|
+
@clz = ServiceAccountCredentials
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'is nil if no file exists' do
|
244
|
+
FakeFS do
|
245
|
+
expect(ServiceAccountCredentials.from_system_default_path(@scope))
|
246
|
+
.to be_nil
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'successfully loads the file when it is present' do
|
251
|
+
FakeFS do
|
252
|
+
FileUtils.mkdir_p(File.dirname(@path))
|
253
|
+
File.write(@path, cred_json_text)
|
254
|
+
expect(@clz.from_system_default_path(@scope)).to_not be_nil
|
255
|
+
File.delete(@path)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
219
259
|
end
|
220
260
|
|
221
261
|
describe Google::Auth::ServiceAccountJwtHeaderCredentials do
|
@@ -224,20 +264,22 @@ describe Google::Auth::ServiceAccountJwtHeaderCredentials do
|
|
224
264
|
|
225
265
|
let(:client_email) { 'app@developer.gserviceaccount.com' }
|
226
266
|
let(:clz) { Google::Auth::ServiceAccountJwtHeaderCredentials }
|
227
|
-
|
228
|
-
|
229
|
-
@key = OpenSSL::PKey::RSA.new(2048)
|
230
|
-
@client = clz.new(StringIO.new(cred_json_text))
|
231
|
-
end
|
232
|
-
|
233
|
-
def cred_json_text
|
234
|
-
cred_json = {
|
267
|
+
let(:cred_json) do
|
268
|
+
{
|
235
269
|
private_key_id: 'a_private_key_id',
|
236
270
|
private_key: @key.to_pem,
|
237
271
|
client_email: client_email,
|
238
272
|
client_id: 'app.apps.googleusercontent.com',
|
239
273
|
type: 'service_account'
|
240
274
|
}
|
275
|
+
end
|
276
|
+
|
277
|
+
before(:example) do
|
278
|
+
@key = OpenSSL::PKey::RSA.new(2048)
|
279
|
+
@client = clz.new(json_key_io: StringIO.new(cred_json_text))
|
280
|
+
end
|
281
|
+
|
282
|
+
def cred_json_text
|
241
283
|
MultiJson.dump(cred_json)
|
242
284
|
end
|
243
285
|
|
@@ -246,11 +288,15 @@ describe Google::Auth::ServiceAccountJwtHeaderCredentials do
|
|
246
288
|
describe '#from_env' do
|
247
289
|
before(:example) do
|
248
290
|
@var_name = ENV_VAR
|
249
|
-
@
|
291
|
+
@credential_vars = [
|
292
|
+
ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR]
|
293
|
+
@original_env_vals = {}
|
294
|
+
@credential_vars.each { |var| @original_env_vals[var] = ENV[var] }
|
295
|
+
ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
|
250
296
|
end
|
251
297
|
|
252
298
|
after(:example) do
|
253
|
-
ENV[
|
299
|
+
@credential_vars.each { |var| ENV[var] = @original_env_vals[var] }
|
254
300
|
end
|
255
301
|
|
256
302
|
it 'returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset' do
|
@@ -264,7 +310,7 @@ describe Google::Auth::ServiceAccountJwtHeaderCredentials do
|
|
264
310
|
Dir.mktmpdir do |dir|
|
265
311
|
key_path = File.join(dir, 'does-not-exist')
|
266
312
|
ENV[@var_name] = key_path
|
267
|
-
expect { clz.from_env }.to raise_error
|
313
|
+
expect { clz.from_env }.to raise_error RuntimeError
|
268
314
|
end
|
269
315
|
end
|
270
316
|
|
@@ -277,6 +323,13 @@ describe Google::Auth::ServiceAccountJwtHeaderCredentials do
|
|
277
323
|
expect(clz.from_env).to_not be_nil
|
278
324
|
end
|
279
325
|
end
|
326
|
+
|
327
|
+
it 'succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are'\
|
328
|
+
' valid' do
|
329
|
+
ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
|
330
|
+
ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
|
331
|
+
expect(clz.from_env(@scope)).to_not be_nil
|
332
|
+
end
|
280
333
|
end
|
281
334
|
|
282
335
|
describe '#from_well_known_path' do
|
@@ -32,6 +32,7 @@ $LOAD_PATH.unshift(spec_dir)
|
|
32
32
|
$LOAD_PATH.uniq!
|
33
33
|
|
34
34
|
require 'apply_auth_examples'
|
35
|
+
require 'fakefs/safe'
|
35
36
|
require 'fileutils'
|
36
37
|
require 'googleauth/user_refresh'
|
37
38
|
require 'jwt'
|
@@ -40,15 +41,26 @@ require 'openssl'
|
|
40
41
|
require 'spec_helper'
|
41
42
|
require 'tmpdir'
|
42
43
|
|
44
|
+
include Google::Auth::CredentialsLoader
|
45
|
+
|
43
46
|
describe Google::Auth::UserRefreshCredentials do
|
44
47
|
UserRefreshCredentials = Google::Auth::UserRefreshCredentials
|
45
|
-
|
48
|
+
|
49
|
+
let(:cred_json) do
|
50
|
+
{
|
51
|
+
client_secret: 'privatekey',
|
52
|
+
client_id: 'client123',
|
53
|
+
refresh_token: 'refreshtoken',
|
54
|
+
type: 'authorized_user'
|
55
|
+
}
|
56
|
+
end
|
46
57
|
|
47
58
|
before(:example) do
|
48
59
|
@key = OpenSSL::PKey::RSA.new(2048)
|
49
60
|
@client = UserRefreshCredentials.new(
|
50
|
-
StringIO.new(cred_json_text),
|
51
|
-
'https://www.googleapis.com/auth/userinfo.profile'
|
61
|
+
json_key_io: StringIO.new(cred_json_text),
|
62
|
+
scope: 'https://www.googleapis.com/auth/userinfo.profile'
|
63
|
+
)
|
52
64
|
end
|
53
65
|
|
54
66
|
def make_auth_stubs(opts = {})
|
@@ -64,12 +76,6 @@ describe Google::Auth::UserRefreshCredentials do
|
|
64
76
|
end
|
65
77
|
|
66
78
|
def cred_json_text(missing = nil)
|
67
|
-
cred_json = {
|
68
|
-
client_secret: 'privatekey',
|
69
|
-
client_id: 'client123',
|
70
|
-
refresh_token: 'refreshtoken',
|
71
|
-
type: 'authorized_user'
|
72
|
-
}
|
73
79
|
cred_json.delete(missing.to_sym) unless missing.nil?
|
74
80
|
MultiJson.dump(cred_json)
|
75
81
|
end
|
@@ -78,14 +84,18 @@ describe Google::Auth::UserRefreshCredentials do
|
|
78
84
|
|
79
85
|
describe '#from_env' do
|
80
86
|
before(:example) do
|
81
|
-
@var_name =
|
82
|
-
@
|
87
|
+
@var_name = ENV_VAR
|
88
|
+
@credential_vars = [
|
89
|
+
ENV_VAR, CLIENT_ID_VAR, CLIENT_SECRET_VAR, REFRESH_TOKEN_VAR,
|
90
|
+
ACCOUNT_TYPE_VAR]
|
91
|
+
@original_env_vals = {}
|
92
|
+
@credential_vars.each { |var| @original_env_vals[var] = ENV[var] }
|
83
93
|
@scope = 'https://www.googleapis.com/auth/userinfo.profile'
|
84
94
|
@clz = UserRefreshCredentials
|
85
95
|
end
|
86
96
|
|
87
97
|
after(:example) do
|
88
|
-
ENV[
|
98
|
+
@credential_vars.each { |var| ENV[var] = @original_env_vals[var] }
|
89
99
|
end
|
90
100
|
|
91
101
|
it 'returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset' do
|
@@ -99,7 +109,7 @@ describe Google::Auth::UserRefreshCredentials do
|
|
99
109
|
Dir.mktmpdir do |dir|
|
100
110
|
key_path = File.join(dir, 'does-not-exist')
|
101
111
|
ENV[@var_name] = key_path
|
102
|
-
expect { @clz.from_env(@scope) }.to raise_error
|
112
|
+
expect { @clz.from_env(@scope) }.to raise_error RuntimeError
|
103
113
|
end
|
104
114
|
end
|
105
115
|
|
@@ -111,7 +121,7 @@ describe Google::Auth::UserRefreshCredentials do
|
|
111
121
|
FileUtils.mkdir_p(File.dirname(key_path))
|
112
122
|
File.write(key_path, cred_json_text(missing))
|
113
123
|
ENV[@var_name] = key_path
|
114
|
-
expect { @clz.from_env(@scope) }.to raise_error
|
124
|
+
expect { @clz.from_env(@scope) }.to raise_error RuntimeError
|
115
125
|
end
|
116
126
|
end
|
117
127
|
end
|
@@ -125,13 +135,25 @@ describe Google::Auth::UserRefreshCredentials do
|
|
125
135
|
expect(@clz.from_env(@scope)).to_not be_nil
|
126
136
|
end
|
127
137
|
end
|
138
|
+
|
139
|
+
it 'succeeds when GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and '\
|
140
|
+
'GOOGLE_REFRESH_TOKEN env vars are valid' do
|
141
|
+
ENV[CLIENT_ID_VAR] = cred_json[:client_id]
|
142
|
+
ENV[CLIENT_SECRET_VAR] = cred_json[:client_secret]
|
143
|
+
ENV[REFRESH_TOKEN_VAR] = cred_json[:refresh_token]
|
144
|
+
ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
|
145
|
+
expect(@clz.from_env(@scope)).to_not be_nil
|
146
|
+
expect(subject.client_id).to eq(cred_json[:client_id])
|
147
|
+
expect(subject.client_secret).to eq(cred_json[:client_secret])
|
148
|
+
expect(subject.refresh_token).to eq(cred_json[:refresh_token])
|
149
|
+
end
|
128
150
|
end
|
129
151
|
|
130
152
|
describe '#from_well_known_path' do
|
131
153
|
before(:example) do
|
132
154
|
@home = ENV['HOME']
|
133
155
|
@scope = 'https://www.googleapis.com/auth/userinfo.profile'
|
134
|
-
@known_path =
|
156
|
+
@known_path = WELL_KNOWN_PATH
|
135
157
|
@clz = UserRefreshCredentials
|
136
158
|
end
|
137
159
|
|
@@ -152,7 +174,8 @@ describe Google::Auth::UserRefreshCredentials do
|
|
152
174
|
FileUtils.mkdir_p(File.dirname(key_path))
|
153
175
|
File.write(key_path, cred_json_text(missing))
|
154
176
|
ENV['HOME'] = dir
|
155
|
-
expect { @clz.
|
177
|
+
expect { @clz.from_well_known_path(@scope) }
|
178
|
+
.to raise_error RuntimeError
|
156
179
|
end
|
157
180
|
end
|
158
181
|
end
|
@@ -167,4 +190,41 @@ describe Google::Auth::UserRefreshCredentials do
|
|
167
190
|
end
|
168
191
|
end
|
169
192
|
end
|
193
|
+
|
194
|
+
describe '#from_system_default_path' do
|
195
|
+
before(:example) do
|
196
|
+
@scope = 'https://www.googleapis.com/auth/userinfo.profile'
|
197
|
+
@path = File.join('/etc/google/auth/', CREDENTIALS_FILE_NAME)
|
198
|
+
@clz = UserRefreshCredentials
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'is nil if no file exists' do
|
202
|
+
FakeFS do
|
203
|
+
expect(UserRefreshCredentials.from_system_default_path(@scope))
|
204
|
+
.to be_nil
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'fails if the file is invalid' do
|
209
|
+
needed = %w(client_id client_secret refresh_token)
|
210
|
+
needed.each do |missing|
|
211
|
+
FakeFS do
|
212
|
+
FileUtils.mkdir_p(File.dirname(@path))
|
213
|
+
File.write(@path, cred_json_text(missing))
|
214
|
+
expect { @clz.from_system_default_path(@scope) }
|
215
|
+
.to raise_error RuntimeError
|
216
|
+
File.delete(@path)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'successfully loads the file when it is present' do
|
222
|
+
FakeFS do
|
223
|
+
FileUtils.mkdir_p(File.dirname(@path))
|
224
|
+
File.write(@path, cred_json_text)
|
225
|
+
expect(@clz.from_system_default_path(@scope)).to_not be_nil
|
226
|
+
File.delete(@path)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
170
230
|
end
|
metadata
CHANGED
@@ -1,178 +1,192 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: googleauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Emiola
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
+
type: :runtime
|
14
15
|
name: faraday
|
16
|
+
prerelease: false
|
15
17
|
requirement: !ruby/object:Gem::Requirement
|
16
18
|
requirements:
|
17
19
|
- - "~>"
|
18
20
|
- !ruby/object:Gem::Version
|
19
21
|
version: '0.9'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.9'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
+
type: :runtime
|
28
29
|
name: logging
|
30
|
+
prerelease: false
|
29
31
|
requirement: !ruby/object:Gem::Requirement
|
30
32
|
requirements:
|
31
33
|
- - "~>"
|
32
34
|
- !ruby/object:Gem::Version
|
33
35
|
version: '2.0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
+
type: :runtime
|
42
43
|
name: jwt
|
44
|
+
prerelease: false
|
43
45
|
requirement: !ruby/object:Gem::Requirement
|
44
46
|
requirements:
|
45
47
|
- - "~>"
|
46
48
|
- !ruby/object:Gem::Version
|
47
49
|
version: '1.4'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.4'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
+
type: :runtime
|
56
57
|
name: memoist
|
58
|
+
prerelease: false
|
57
59
|
requirement: !ruby/object:Gem::Requirement
|
58
60
|
requirements:
|
59
61
|
- - "~>"
|
60
62
|
- !ruby/object:Gem::Version
|
61
63
|
version: '0.12'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0.12'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
+
type: :runtime
|
70
71
|
name: multi_json
|
72
|
+
prerelease: false
|
71
73
|
requirement: !ruby/object:Gem::Requirement
|
72
74
|
requirements:
|
73
|
-
- -
|
75
|
+
- - "~>"
|
74
76
|
- !ruby/object:Gem::Version
|
75
77
|
version: '1.11'
|
76
|
-
type: :runtime
|
77
|
-
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.11'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
+
type: :runtime
|
84
85
|
name: signet
|
86
|
+
prerelease: false
|
85
87
|
requirement: !ruby/object:Gem::Requirement
|
86
88
|
requirements:
|
87
89
|
- - "~>"
|
88
90
|
- !ruby/object:Gem::Version
|
89
91
|
version: '0.6'
|
90
|
-
type: :runtime
|
91
|
-
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.6'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
+
type: :development
|
98
99
|
name: bundler
|
100
|
+
prerelease: false
|
99
101
|
requirement: !ruby/object:Gem::Requirement
|
100
102
|
requirements:
|
101
103
|
- - "~>"
|
102
104
|
- !ruby/object:Gem::Version
|
103
105
|
version: '1.9'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '1.9'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
+
type: :development
|
112
113
|
name: simplecov
|
114
|
+
prerelease: false
|
113
115
|
requirement: !ruby/object:Gem::Requirement
|
114
116
|
requirements:
|
115
117
|
- - "~>"
|
116
118
|
- !ruby/object:Gem::Version
|
117
119
|
version: '0.9'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0.9'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
+
type: :development
|
126
127
|
name: coveralls
|
128
|
+
prerelease: false
|
127
129
|
requirement: !ruby/object:Gem::Requirement
|
128
130
|
requirements:
|
129
131
|
- - "~>"
|
130
132
|
- !ruby/object:Gem::Version
|
131
133
|
version: '0.7'
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.7'
|
139
|
+
- !ruby/object:Gem::Dependency
|
132
140
|
type: :development
|
141
|
+
name: fakefs
|
133
142
|
prerelease: false
|
143
|
+
requirement: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - "~>"
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0.6'
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
150
|
- - "~>"
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version: '0.
|
152
|
+
version: '0.6'
|
139
153
|
- !ruby/object:Gem::Dependency
|
154
|
+
type: :development
|
140
155
|
name: rake
|
156
|
+
prerelease: false
|
141
157
|
requirement: !ruby/object:Gem::Requirement
|
142
158
|
requirements:
|
143
159
|
- - "~>"
|
144
160
|
- !ruby/object:Gem::Version
|
145
161
|
version: '10.0'
|
146
|
-
type: :development
|
147
|
-
prerelease: false
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
149
163
|
requirements:
|
150
164
|
- - "~>"
|
151
165
|
- !ruby/object:Gem::Version
|
152
166
|
version: '10.0'
|
153
167
|
- !ruby/object:Gem::Dependency
|
168
|
+
type: :development
|
154
169
|
name: rubocop
|
170
|
+
prerelease: false
|
155
171
|
requirement: !ruby/object:Gem::Requirement
|
156
172
|
requirements:
|
157
173
|
- - "~>"
|
158
174
|
- !ruby/object:Gem::Version
|
159
175
|
version: '0.30'
|
160
|
-
type: :development
|
161
|
-
prerelease: false
|
162
176
|
version_requirements: !ruby/object:Gem::Requirement
|
163
177
|
requirements:
|
164
178
|
- - "~>"
|
165
179
|
- !ruby/object:Gem::Version
|
166
180
|
version: '0.30'
|
167
181
|
- !ruby/object:Gem::Dependency
|
182
|
+
type: :development
|
168
183
|
name: rspec
|
184
|
+
prerelease: false
|
169
185
|
requirement: !ruby/object:Gem::Requirement
|
170
186
|
requirements:
|
171
187
|
- - "~>"
|
172
188
|
- !ruby/object:Gem::Version
|
173
189
|
version: '3.0'
|
174
|
-
type: :development
|
175
|
-
prerelease: false
|
176
190
|
version_requirements: !ruby/object:Gem::Requirement
|
177
191
|
requirements:
|
178
192
|
- - "~>"
|
@@ -202,6 +216,7 @@ files:
|
|
202
216
|
- lib/googleauth.rb
|
203
217
|
- lib/googleauth/compute_engine.rb
|
204
218
|
- lib/googleauth/credentials_loader.rb
|
219
|
+
- lib/googleauth/iam.rb
|
205
220
|
- lib/googleauth/service_account.rb
|
206
221
|
- lib/googleauth/signet.rb
|
207
222
|
- lib/googleauth/user_refresh.rb
|
@@ -209,6 +224,7 @@ files:
|
|
209
224
|
- spec/googleauth/apply_auth_examples.rb
|
210
225
|
- spec/googleauth/compute_engine_spec.rb
|
211
226
|
- spec/googleauth/get_application_default_spec.rb
|
227
|
+
- spec/googleauth/iam_spec.rb
|
212
228
|
- spec/googleauth/service_account_spec.rb
|
213
229
|
- spec/googleauth/signet_spec.rb
|
214
230
|
- spec/googleauth/user_refresh_spec.rb
|
@@ -233,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
233
249
|
version: '0'
|
234
250
|
requirements: []
|
235
251
|
rubyforge_project:
|
236
|
-
rubygems_version: 2.4.
|
252
|
+
rubygems_version: 2.4.8
|
237
253
|
signing_key:
|
238
254
|
specification_version: 4
|
239
255
|
summary: Google Auth Library for Ruby
|
@@ -241,6 +257,7 @@ test_files:
|
|
241
257
|
- spec/googleauth/apply_auth_examples.rb
|
242
258
|
- spec/googleauth/compute_engine_spec.rb
|
243
259
|
- spec/googleauth/get_application_default_spec.rb
|
260
|
+
- spec/googleauth/iam_spec.rb
|
244
261
|
- spec/googleauth/service_account_spec.rb
|
245
262
|
- spec/googleauth/signet_spec.rb
|
246
263
|
- spec/googleauth/user_refresh_spec.rb
|