occi-api 4.3.5 → 4.3.6
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/.travis.yml +10 -25
- data/lib/occi/api/client/client_http.rb +2 -2
- data/lib/occi/api/client/http/authn_plugins/keystone.rb +177 -13
- data/lib/occi/api/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5e457c71d021773fd57e1632882d438166cf935
|
4
|
+
data.tar.gz: 9afa187517fd7ef0facc4295085a10a7b9bf1f97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d531511b8d1fa3d5d2c3658ad9fbb1d29c3c08430779d36ae3b471179443f8afe8b5fc2fd11df0e52df52707a6d09c08dfe9e4919ac86b94759798c855c5bb8
|
7
|
+
data.tar.gz: 2ab2461149750834ea980da58f36892366d5872cd55c35809cf873231d86fb24ce81e9ccb0be9bf778b049d09cc440960709a635ec88d19f5b36a60efcfd97e1
|
data/.travis.yml
CHANGED
@@ -4,36 +4,14 @@ rvm:
|
|
4
4
|
- 1.9.3
|
5
5
|
- 2.0.0
|
6
6
|
- 2.1
|
7
|
+
- 2.2
|
8
|
+
- 2.3
|
7
9
|
- ruby-head
|
8
|
-
- jruby-19mode
|
9
|
-
- jruby-head
|
10
|
-
|
11
|
-
jdk:
|
12
|
-
- openjdk7
|
13
|
-
- oraclejdk7
|
14
|
-
- openjdk6
|
15
10
|
|
16
11
|
matrix:
|
17
12
|
allow_failures:
|
13
|
+
- rvm: 2.3
|
18
14
|
- rvm: ruby-head
|
19
|
-
- rvm: jruby-head
|
20
|
-
exclude:
|
21
|
-
- rvm: 1.9.3
|
22
|
-
jdk: openjdk7
|
23
|
-
- rvm: 1.9.3
|
24
|
-
jdk: oraclejdk7
|
25
|
-
- rvm: 2.0.0
|
26
|
-
jdk: openjdk7
|
27
|
-
- rvm: 2.0.0
|
28
|
-
jdk: oraclejdk7
|
29
|
-
- rvm: 2.1
|
30
|
-
jdk: openjdk7
|
31
|
-
- rvm: 2.1
|
32
|
-
jdk: oraclejdk7
|
33
|
-
- rvm: ruby-head
|
34
|
-
jdk: openjdk7
|
35
|
-
- rvm: ruby-head
|
36
|
-
jdk: oraclejdk7
|
37
15
|
fast_finish: true
|
38
16
|
|
39
17
|
branches:
|
@@ -43,3 +21,10 @@ branches:
|
|
43
21
|
- 4.1.x
|
44
22
|
- 4.2.x
|
45
23
|
- 4.3.x
|
24
|
+
|
25
|
+
install: 'gem install bundler -v ">= 1.7.12" && bundle install --retry=10'
|
26
|
+
|
27
|
+
env:
|
28
|
+
- ON_TRAVIS_CI=yes
|
29
|
+
|
30
|
+
sudo: false
|
@@ -78,10 +78,10 @@ module Occi::Api::Client
|
|
78
78
|
)
|
79
79
|
|
80
80
|
response_msg = response_message(response)
|
81
|
-
raise "HTTP GET failed! #{response_msg}" unless response.code
|
81
|
+
raise "HTTP GET failed! #{response_msg}" unless [200, 204].include?(response.code)
|
82
82
|
|
83
83
|
# TODO: remove the gsub OCCI-OS hack as soon as they stop using 'uri:'
|
84
|
-
response.body.gsub(/\# uri:\/(compute|storage|network)\/[\n]?/, '').split("\n").compact
|
84
|
+
(response.body || '').gsub(/\# uri:\/(compute|storage|network)\/[\n]?/, '').split("\n").compact
|
85
85
|
end
|
86
86
|
|
87
87
|
# @see Occi::Api::Client::ClientBase
|
@@ -5,20 +5,14 @@ module Occi::Api::Client
|
|
5
5
|
class Keystone < Base
|
6
6
|
|
7
7
|
KEYSTONE_URI_REGEXP = /^(Keystone|snf-auth) uri='(.+)'$/
|
8
|
+
KEYSTONE_VERSION_REGEXP = /^v([0-9]).*$/
|
8
9
|
|
9
10
|
def setup(options = {})
|
10
11
|
# get Keystone URL if possible
|
11
12
|
set_keystone_base_url
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
set_auth_token ENV['ROCCI_CLIENT_KEYSTONE_TENANT']
|
16
|
-
else
|
17
|
-
# get an unscoped token, use the unscoped token
|
18
|
-
# for tenant discovery and get a scoped token
|
19
|
-
set_auth_token
|
20
|
-
get_first_working_tenant
|
21
|
-
end
|
14
|
+
# discover Keystone API version
|
15
|
+
set_auth_token ENV['ROCCI_CLIENT_KEYSTONE_TENANT']
|
22
16
|
|
23
17
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
24
18
|
"Unable to get a tenant from Keystone, fallback failed!" if @env_ref.class.headers['X-Auth-Token'].blank?
|
@@ -56,12 +50,73 @@ module Occi::Api::Client
|
|
56
50
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
57
51
|
"Unable to get Keystone's URL from the response, fallback failed!" unless match && match[2]
|
58
52
|
|
59
|
-
@keystone_url = match[2]
|
53
|
+
@keystone_url = match[2]
|
54
|
+
end
|
55
|
+
|
56
|
+
def set_auth_token(tenant = nil)
|
57
|
+
response = @env_ref.class.get @keystone_url
|
58
|
+
Occi::Api::Log.debug response.inspect
|
59
|
+
|
60
|
+
raise ::Occi::Api::Client::Errors::AuthnError,
|
61
|
+
"Unable to get Keystone API version from the response, fallback failed!" if (400..599).include?(response.code)
|
62
|
+
|
63
|
+
# multiple choices, sort them by version id
|
64
|
+
if response.code == 300
|
65
|
+
versions = response['versions']['values'].sort_by { |v| v['id']}
|
66
|
+
else
|
67
|
+
# assume a single version
|
68
|
+
versions = [response['version']]
|
69
|
+
end
|
70
|
+
|
71
|
+
versions.each do |v|
|
72
|
+
match = KEYSTONE_VERSION_REGEXP.match(v['id'])
|
73
|
+
raise ::Occi::Api::Client::Errors::AuthnError,
|
74
|
+
"Unable to get Keystone API version from the response, fallback failed!" unless match && match[1]
|
75
|
+
if match[1] == '2'
|
76
|
+
handler_class = KeystoneV2
|
77
|
+
elsif match[1] == '3'
|
78
|
+
handler_class = KeystoneV3
|
79
|
+
end
|
80
|
+
v['links'].each do |link|
|
81
|
+
begin
|
82
|
+
if link['rel'] == 'self'
|
83
|
+
keystone_url = link['href'].chomp('/')
|
84
|
+
keystone_handler = handler_class.new(keystone_url, @env_ref, @options)
|
85
|
+
token = keystone_handler.set_auth_token(tenant)
|
86
|
+
# found a working keystone, stop looking
|
87
|
+
return
|
88
|
+
end
|
89
|
+
rescue ::Occi::Api::Client::Errors::AuthnError
|
90
|
+
# ignore and try with next link
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
class KeystoneV2
|
99
|
+
def initialize(base_url, env_ref, options = {})
|
100
|
+
@base_url = base_url
|
101
|
+
@env_ref = env_ref
|
102
|
+
@options = options
|
60
103
|
end
|
61
104
|
|
62
105
|
def set_auth_token(tenant = nil)
|
106
|
+
if !tenant.blank?
|
107
|
+
# get a scoped token for the specified tenant directly
|
108
|
+
authenticate ENV['ROCCI_CLIENT_KEYSTONE_TENANT']
|
109
|
+
else
|
110
|
+
# get an unscoped token, use the unscoped token
|
111
|
+
# for tenant discovery and get a scoped token
|
112
|
+
authenticate
|
113
|
+
get_first_working_tenant
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def authenticate(tenant = nil)
|
63
118
|
response = @env_ref.class.post(
|
64
|
-
"#{@
|
119
|
+
"#{@base_url}/tokens",
|
65
120
|
:body => get_keystone_req(tenant),
|
66
121
|
:headers => get_req_headers
|
67
122
|
)
|
@@ -99,7 +154,7 @@ module Occi::Api::Client
|
|
99
154
|
|
100
155
|
def get_first_working_tenant
|
101
156
|
response = @env_ref.class.get(
|
102
|
-
"#{@
|
157
|
+
"#{@base_url}/tenants",
|
103
158
|
:headers => get_req_headers
|
104
159
|
)
|
105
160
|
Occi::Api::Log.debug response.inspect
|
@@ -110,7 +165,7 @@ module Occi::Api::Client
|
|
110
165
|
response['tenants'].each do |tenant|
|
111
166
|
begin
|
112
167
|
Occi::Api::Log.debug "Authenticating for tenant #{tenant['name'].inspect}"
|
113
|
-
|
168
|
+
authenticate(tenant['name'])
|
114
169
|
|
115
170
|
# found a working tenant, stop looking
|
116
171
|
break
|
@@ -120,6 +175,115 @@ module Occi::Api::Client
|
|
120
175
|
end
|
121
176
|
end
|
122
177
|
|
178
|
+
def get_req_headers
|
179
|
+
headers = @env_ref.class.headers.clone
|
180
|
+
headers['Content-Type'] = "application/json"
|
181
|
+
headers['Accept'] = headers['Content-Type']
|
182
|
+
|
183
|
+
headers
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
class KeystoneV3
|
188
|
+
def initialize(base_url, env_ref, options = {})
|
189
|
+
@base_url = base_url
|
190
|
+
@env_ref = env_ref
|
191
|
+
@options = options
|
192
|
+
end
|
193
|
+
|
194
|
+
def set_auth_token(tenant = nil)
|
195
|
+
if @options[:original_type] == "x509"
|
196
|
+
voms_authenticate(tenant)
|
197
|
+
elsif @options[:username] && @options[:password]
|
198
|
+
passwd_authenticate(tenant)
|
199
|
+
else
|
200
|
+
raise ::Occi::Api::Client::Errors::AuthnError,
|
201
|
+
"Unable to request a token from Keystone! Chosen " \
|
202
|
+
"AuthN is not supported, fallback failed!"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def passwd_authenticate(tenant = nil)
|
207
|
+
raise ::Occi::Api::Client::Errors::AuthnError,
|
208
|
+
"Needs to be implemented, check http://developer.openstack.org/api-ref-identity-v3.html#authenticatePasswordUnscoped"
|
209
|
+
end
|
210
|
+
|
211
|
+
def voms_authenticate(tenant = nil)
|
212
|
+
set_voms_unscoped_token
|
213
|
+
|
214
|
+
if !tenant.blank?
|
215
|
+
set_scoped_token(tenant)
|
216
|
+
else
|
217
|
+
get_first_working_project
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def set_voms_unscoped_token
|
222
|
+
response = @env_ref.class.post(
|
223
|
+
# egi.eu and voms below should be configurable
|
224
|
+
"#{@base_url}/OS-FEDERATION/identity_providers/egi.eu/protocols/mapped/voms",
|
225
|
+
)
|
226
|
+
Occi::Api::Log.debug response.inspect
|
227
|
+
|
228
|
+
if response.success?
|
229
|
+
@env_ref.class.headers['X-Auth-Token'] = response.headers['x-subject-token']
|
230
|
+
else
|
231
|
+
raise ::Occi::Api::Client::Errors::AuthnError,
|
232
|
+
"Unable to get a token from Keystone, fallback failed!"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def get_first_working_project
|
237
|
+
response = @env_ref.class.get(
|
238
|
+
"#{@base_url}/projects",
|
239
|
+
:headers => get_req_headers
|
240
|
+
)
|
241
|
+
Occi::Api::Log.debug response.inspect
|
242
|
+
|
243
|
+
raise ::Occi::Api::Client::Errors::AuthnError,
|
244
|
+
"Keystone didn't return any projects, fallback failed!" if response['projects'].blank?
|
245
|
+
|
246
|
+
response['projects'].each do |project|
|
247
|
+
begin
|
248
|
+
Occi::Api::Log.debug "Authenticating for project #{project['name'].inspect}"
|
249
|
+
set_scoped_token(project['id'])
|
250
|
+
|
251
|
+
# found a working project, stop looking
|
252
|
+
break
|
253
|
+
rescue ::Occi::Api::Client::Errors::AuthnError
|
254
|
+
# ignoring and trying the next tenant
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def set_scoped_token(project)
|
260
|
+
body = {
|
261
|
+
"auth" => {
|
262
|
+
"identity" => {
|
263
|
+
"methods" => ["token"],
|
264
|
+
"token" => {"id" => @env_ref.class.headers['X-Auth-Token'] }
|
265
|
+
},
|
266
|
+
"scope" => {
|
267
|
+
"project" => {"id" => project}
|
268
|
+
}
|
269
|
+
}
|
270
|
+
}
|
271
|
+
response = @env_ref.class.post(
|
272
|
+
"#{@base_url}/auth/tokens",
|
273
|
+
:body => body,
|
274
|
+
:headers => get_req_headers
|
275
|
+
)
|
276
|
+
|
277
|
+
Occi::Api::Log.debug response.inspect
|
278
|
+
|
279
|
+
if response.success?
|
280
|
+
@env_ref.class.headers['X-Auth-Token'] = response.headers['x-subject-token']
|
281
|
+
else
|
282
|
+
raise ::Occi::Api::Client::Errors::AuthnError,
|
283
|
+
"Unable to get a token from Keystone, fallback failed!"
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
123
287
|
def get_req_headers
|
124
288
|
headers = @env_ref.class.headers.clone
|
125
289
|
headers['Content-Type'] = "application/json"
|
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.6
|
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: 2016-
|
13
|
+
date: 2016-06-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: occi-core
|