occi-api 4.3.14 → 4.3.15
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/lib/occi/api/client/http/authn_plugins/keystone.rb +72 -86
- data/lib/occi/api/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f64a3d6fe0539314a30e9706b45f56ab47401377
|
4
|
+
data.tar.gz: 629ca876122fbafb32c9471cb281ffb01aa2f9df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf983b6653c70a5af66b962911aff1433dd72c9d3cfe9ff9ff6a511ee816ac69fd689e5ae2493cb6bce14329655f3a6c95f3d91e44646d643a997e1cc6ba070e
|
7
|
+
data.tar.gz: a47d841cc9af98dcc0bac4bde8ff630148490276c42f31e6b58990289fab2471f11e1d5b2d0631862a2360e9d9af6397a72eba596dbca67944ef77e711ec0289
|
@@ -1,9 +1,7 @@
|
|
1
1
|
module Occi::Api::Client
|
2
2
|
module Http
|
3
3
|
module AuthnPlugins
|
4
|
-
|
5
4
|
class Keystone < Base
|
6
|
-
|
7
5
|
KEYSTONE_URI_REGEXP = /^(Keystone|snf-auth) uri=("|')(.+)("|')$/
|
8
6
|
KEYSTONE_VERSION_REGEXP = /^v([0-9]).*$/
|
9
7
|
|
@@ -13,33 +11,33 @@ module Occi::Api::Client
|
|
13
11
|
|
14
12
|
# discover Keystone API version
|
15
13
|
@env_ref.class.headers.delete 'X-Auth-Token'
|
16
|
-
|
17
|
-
|
18
|
-
end
|
14
|
+
|
15
|
+
keystone_version = '3' if @options[:type] == 'oauth2'
|
19
16
|
set_auth_token ENV['ROCCI_CLIENT_KEYSTONE_TENANT'], keystone_version
|
20
17
|
|
21
|
-
|
22
|
-
|
18
|
+
if @env_ref.class.headers['X-Auth-Token'].blank?
|
19
|
+
raise ::Occi::Api::Client::Errors::AuthnError, "Unable to get a tenant from Keystone, fallback failed!"
|
20
|
+
end
|
23
21
|
end
|
24
22
|
|
25
23
|
def authenticate(options = {})
|
26
24
|
# OCCI-OS doesn't support HEAD method!
|
27
|
-
response = @env_ref.class.get "#{@env_ref.endpoint
|
25
|
+
response = @env_ref.class.get "#{@env_ref.endpoint}/-/"
|
28
26
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
29
|
-
"Authentication failed with code #{response.code
|
27
|
+
"Authentication failed with code #{response.code}!" unless response.success?
|
30
28
|
end
|
31
29
|
|
32
30
|
private
|
33
31
|
|
34
32
|
def set_keystone_base_url
|
35
|
-
response = @env_ref.class.get "#{@env_ref.endpoint
|
33
|
+
response = @env_ref.class.get "#{@env_ref.endpoint}/-/"
|
36
34
|
Occi::Api::Log.debug response.inspect
|
37
35
|
|
38
36
|
return if response.success?
|
39
37
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
40
|
-
"Keystone AuthN failed with #{response.code
|
38
|
+
"Keystone AuthN failed with #{response.code}!" unless response.unauthorized?
|
41
39
|
|
42
|
-
process_headers
|
40
|
+
process_headers response
|
43
41
|
end
|
44
42
|
|
45
43
|
def process_headers(response)
|
@@ -58,48 +56,36 @@ module Occi::Api::Client
|
|
58
56
|
end
|
59
57
|
|
60
58
|
def set_auth_token(tenant = nil, keystone_version = nil)
|
61
|
-
response = @env_ref.class.get
|
59
|
+
response = @env_ref.class.get(@keystone_url, :headers => get_req_headers)
|
62
60
|
Occi::Api::Log.debug response.inspect
|
63
61
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
# multiple choices, sort them by version id (preferred is v2)
|
68
|
-
if response.code == 300
|
69
|
-
versions = response['versions']['values'].sort_by { |v| v['id']}
|
70
|
-
else
|
71
|
-
# assume a single version
|
72
|
-
versions = [response['version']]
|
62
|
+
unless response.success? || response.multiple_choices?
|
63
|
+
raise ::Occi::Api::Client::Errors::AuthnError,
|
64
|
+
'Unable to get Keystone API version from the response, fallback failed!'
|
73
65
|
end
|
74
66
|
|
67
|
+
versions = if response.multiple_choices?
|
68
|
+
response['versions']['values'].sort_by { |v| v['id'] } # multiple versions, sort by version id
|
69
|
+
else
|
70
|
+
[response['version']] # assume a single version
|
71
|
+
end
|
72
|
+
|
75
73
|
versions.each do |v|
|
76
74
|
match = KEYSTONE_VERSION_REGEXP.match(v['id'])
|
77
75
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
78
76
|
"Unable to get Keystone API version from the response, fallback failed!" unless match && match[1]
|
79
|
-
if match[1]
|
80
|
-
|
81
|
-
|
82
|
-
handler_class = KeystoneV2
|
83
|
-
else
|
84
|
-
next
|
85
|
-
end
|
86
|
-
elsif match[1] == '3'
|
87
|
-
if keystone_version == nil or keystone_version == 3
|
88
|
-
Occi::Api::Log.debug "Selecting Keystone V3 interface"
|
89
|
-
handler_class = KeystoneV3
|
90
|
-
else
|
91
|
-
next
|
92
|
-
end
|
93
|
-
end
|
77
|
+
next if keystone_version && keystone_version != match[1]
|
78
|
+
|
79
|
+
handler_class = match[1] == '3' ? KeystoneV3 : KeystoneV2
|
94
80
|
v['links'].each do |link|
|
95
81
|
begin
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
82
|
+
next unless link['rel'] == 'self'
|
83
|
+
|
84
|
+
keystone_url = link['href'].chomp('/')
|
85
|
+
keystone_handler = handler_class.new(keystone_url, @env_ref, @options)
|
86
|
+
keystone_handler.set_auth_token tenant
|
87
|
+
|
88
|
+
return # found a working keystone, stop looking
|
103
89
|
rescue ::Occi::Api::Client::Errors::AuthnError
|
104
90
|
# ignore and try with next link
|
105
91
|
end
|
@@ -107,6 +93,13 @@ module Occi::Api::Client
|
|
107
93
|
end
|
108
94
|
end
|
109
95
|
|
96
|
+
def get_req_headers
|
97
|
+
headers = @env_ref.class.headers.clone
|
98
|
+
headers['Content-Type'] = "application/json"
|
99
|
+
headers['Accept'] = headers['Content-Type']
|
100
|
+
|
101
|
+
headers
|
102
|
+
end
|
110
103
|
end
|
111
104
|
|
112
105
|
class KeystoneV2
|
@@ -117,14 +110,13 @@ module Occi::Api::Client
|
|
117
110
|
end
|
118
111
|
|
119
112
|
def set_auth_token(tenant = nil)
|
120
|
-
if
|
121
|
-
# get a scoped token for the specified tenant directly
|
122
|
-
authenticate ENV['ROCCI_CLIENT_KEYSTONE_TENANT']
|
123
|
-
else
|
113
|
+
if tenant.blank?
|
124
114
|
# get an unscoped token, use the unscoped token
|
125
115
|
# for tenant discovery and get a scoped token
|
126
116
|
authenticate
|
127
117
|
get_first_working_tenant
|
118
|
+
else
|
119
|
+
authenticate tenant
|
128
120
|
end
|
129
121
|
end
|
130
122
|
|
@@ -136,12 +128,12 @@ module Occi::Api::Client
|
|
136
128
|
)
|
137
129
|
Occi::Api::Log.debug response.inspect
|
138
130
|
|
139
|
-
if response.success?
|
140
|
-
@env_ref.class.headers['X-Auth-Token'] = response['access']['token']['id']
|
141
|
-
else
|
131
|
+
if !response.success? || response['access'].blank?
|
142
132
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
143
133
|
"Unable to get a token from Keystone, fallback failed!"
|
144
134
|
end
|
135
|
+
|
136
|
+
@env_ref.class.headers['X-Auth-Token'] = response['access']['token']['id']
|
145
137
|
end
|
146
138
|
|
147
139
|
def get_keystone_req(tenant = nil)
|
@@ -173,16 +165,16 @@ module Occi::Api::Client
|
|
173
165
|
)
|
174
166
|
Occi::Api::Log.debug response.inspect
|
175
167
|
|
176
|
-
|
177
|
-
|
168
|
+
if !response.success? || response['tenants'].blank?
|
169
|
+
raise ::Occi::Api::Client::Errors::AuthnError,
|
170
|
+
"Keystone didn't return any tenants, fallback failed!"
|
171
|
+
end
|
178
172
|
|
179
173
|
response['tenants'].each do |tenant|
|
180
174
|
begin
|
181
175
|
Occi::Api::Log.debug "Authenticating for tenant #{tenant['name'].inspect}"
|
182
|
-
authenticate
|
183
|
-
|
184
|
-
# found a working tenant, stop looking
|
185
|
-
break
|
176
|
+
authenticate tenant['name']
|
177
|
+
break # found a working tenant, stop looking
|
186
178
|
rescue ::Occi::Api::Client::Errors::AuthnError
|
187
179
|
# ignoring and trying the next tenant
|
188
180
|
end
|
@@ -214,15 +206,10 @@ module Occi::Api::Client
|
|
214
206
|
passwd_authenticate
|
215
207
|
else
|
216
208
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
217
|
-
"Unable to request a token from Keystone! Chosen "
|
218
|
-
"AuthN is not supported, fallback failed!"
|
209
|
+
"Unable to request a token from Keystone! Chosen AuthN is not supported, fallback failed!"
|
219
210
|
end
|
220
211
|
|
221
|
-
|
222
|
-
set_scoped_token(tenant)
|
223
|
-
else
|
224
|
-
get_first_working_project
|
225
|
-
end
|
212
|
+
tenant.blank? ? get_first_working_project : set_scoped_token(tenant)
|
226
213
|
end
|
227
214
|
|
228
215
|
def passwd_authenticate
|
@@ -231,36 +218,37 @@ module Occi::Api::Client
|
|
231
218
|
end
|
232
219
|
|
233
220
|
def set_voms_unscoped_token
|
234
|
-
response = @env_ref.class.
|
221
|
+
response = @env_ref.class.get(
|
235
222
|
# FIXME(enolfc) egi.eu and mapped below should be configurable
|
236
223
|
"#{@base_url}/OS-FEDERATION/identity_providers/egi.eu/protocols/mapped/auth",
|
224
|
+
:headers => get_req_headers
|
237
225
|
)
|
238
226
|
Occi::Api::Log.debug response.inspect
|
239
227
|
|
240
|
-
if response.success?
|
241
|
-
@env_ref.class.headers['X-Auth-Token'] = response.headers['x-subject-token']
|
242
|
-
else
|
228
|
+
if !response.success? || response.headers['x-subject-token'].blank?
|
243
229
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
244
230
|
"Unable to get a token from Keystone, fallback failed!"
|
245
231
|
end
|
232
|
+
|
233
|
+
@env_ref.class.headers['X-Auth-Token'] = response.headers['x-subject-token']
|
246
234
|
end
|
247
235
|
|
248
236
|
def set_oauth2_unscoped_token
|
249
237
|
headers = get_req_headers
|
250
238
|
headers['Authorization'] = "Bearer #{@options[:token]}"
|
251
|
-
response = @env_ref.class.
|
239
|
+
response = @env_ref.class.get(
|
252
240
|
# FIXME(enolfc) egi.eu and oidc below should be configurable
|
253
241
|
"#{@base_url}/OS-FEDERATION/identity_providers/egi.eu/protocols/oidc/auth",
|
254
242
|
:headers => headers
|
255
243
|
)
|
256
244
|
Occi::Api::Log.debug response.inspect
|
257
245
|
|
258
|
-
if response.success?
|
259
|
-
@env_ref.class.headers['X-Auth-Token'] = response.headers['x-subject-token']
|
260
|
-
else
|
246
|
+
if !response.success? || response.headers['x-subject-token'].blank?
|
261
247
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
262
248
|
"Unable to get a token from Keystone, fallback failed!"
|
263
249
|
end
|
250
|
+
|
251
|
+
@env_ref.class.headers['X-Auth-Token'] = response.headers['x-subject-token']
|
264
252
|
end
|
265
253
|
|
266
254
|
def get_first_working_project
|
@@ -270,16 +258,16 @@ module Occi::Api::Client
|
|
270
258
|
)
|
271
259
|
Occi::Api::Log.debug response.inspect
|
272
260
|
|
273
|
-
|
274
|
-
|
261
|
+
if !response.success? || response['projects'].blank?
|
262
|
+
raise ::Occi::Api::Client::Errors::AuthnError,
|
263
|
+
"Keystone didn't return any projects, fallback failed!"
|
264
|
+
end
|
275
265
|
|
276
266
|
response['projects'].each do |project|
|
277
267
|
begin
|
278
268
|
Occi::Api::Log.debug "Authenticating for project #{project['name'].inspect}"
|
279
|
-
set_scoped_token
|
280
|
-
|
281
|
-
# found a working project, stop looking
|
282
|
-
break
|
269
|
+
set_scoped_token project['id']
|
270
|
+
break # found a working project, stop looking
|
283
271
|
rescue ::Occi::Api::Client::Errors::AuthnError
|
284
272
|
# ignoring and trying the next tenant
|
285
273
|
end
|
@@ -291,27 +279,27 @@ module Occi::Api::Client
|
|
291
279
|
"auth" => {
|
292
280
|
"identity" => {
|
293
281
|
"methods" => ["token"],
|
294
|
-
"token" => {"id" => @env_ref.class.headers['X-Auth-Token'] }
|
282
|
+
"token" => { "id" => @env_ref.class.headers['X-Auth-Token'] }
|
295
283
|
},
|
296
284
|
"scope" => {
|
297
|
-
"project" => {"id" => project}
|
285
|
+
"project" => { "id" => project }
|
298
286
|
}
|
299
287
|
}
|
300
288
|
}
|
289
|
+
|
301
290
|
response = @env_ref.class.post(
|
302
291
|
"#{@base_url}/auth/tokens",
|
303
292
|
:body => body.to_json,
|
304
293
|
:headers => get_req_headers
|
305
294
|
)
|
306
|
-
|
307
295
|
Occi::Api::Log.debug response.inspect
|
308
296
|
|
309
|
-
if response.success?
|
310
|
-
@env_ref.class.headers['X-Auth-Token'] = response.headers['x-subject-token']
|
311
|
-
else
|
297
|
+
if !response.success? || response.headers['x-subject-token'].blank?
|
312
298
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
313
299
|
"Unable to get a token from Keystone, fallback failed!"
|
314
300
|
end
|
301
|
+
|
302
|
+
@env_ref.class.headers['X-Auth-Token'] = response.headers['x-subject-token']
|
315
303
|
end
|
316
304
|
|
317
305
|
def get_req_headers
|
@@ -321,9 +309,7 @@ module Occi::Api::Client
|
|
321
309
|
|
322
310
|
headers
|
323
311
|
end
|
324
|
-
|
325
312
|
end
|
326
|
-
|
327
313
|
end
|
328
314
|
end
|
329
315
|
end
|
data/lib/occi/api/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: occi-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.3.
|
4
|
+
version: 4.3.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Feldhaus
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-
|
13
|
+
date: 2017-10-05 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: occi-core
|
@@ -463,7 +463,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
463
463
|
version: '0'
|
464
464
|
requirements: []
|
465
465
|
rubyforge_project:
|
466
|
-
rubygems_version: 2.6.
|
466
|
+
rubygems_version: 2.6.13
|
467
467
|
signing_key:
|
468
468
|
specification_version: 4
|
469
469
|
summary: OCCI development library providing a high-level client API
|