update from RIFT as of 696b75d2fe9fb046261b08c616f1bcf6c0b54a9b second try
[osm/SO.git] / rwlaunchpad / ra / pytest / ns / rbac / test_tbac_token.py
1 #!/usr/bin/env python3
2 """
3 #
4 # Copyright 2017 RIFT.IO Inc
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 """
19 # RIFT_IO_STANDARD_COPYRIGHT_HEADER(BEGIN)
20 # Author(s): Balaji Rajappa, Vishnu Narayanan K.A
21 # Creation Date: 2017-07-07
22 # RIFT_IO_STANDARD_COPYRIGHT_HEADER(END)
23
24 import gi
25 import json
26 import urllib.parse
27
28 import rift.auto.mano
29 import pytest
30 import tornado.httpclient
31 import time
32 import Cryptodome.PublicKey.RSA as RSA
33
34 import oic.utils.jwt as oic_jwt
35 import oic.utils.keyio as keyio
36 from jwkest.jwk import RSAKey
37 from rift.rwlib.util import certs
38 gi.require_version('RwOpenidcProviderYang', '1.0')
39 gi.require_version('RwRbacInternalYang', '1.0')
40 gi.require_version('RwProjectNsdYang', '1.0')
41 gi.require_version('RwProjectYang', '1.0')
42 gi.require_version('RwKeyspec', '1.0')
43 gi.require_version('RwConmanYang', '1.0')
44 from gi.repository import ( # noqa
45 RwOpenidcProviderYang,
46 RwProjectNsdYang,
47 RwProjectYang,
48 RwRbacInternalYang,
49 RwConmanYang,
50 )
51 from gi.repository.RwKeyspec import quoted_key # noqa
52
53
54 PRIVATE_KEY = """-----BEGIN RSA PRIVATE KEY-----
55 MIIEpAIBAAKCAQEAs9bRFjWofNeWq2qtsvH9iDZXXbv5NQI6avK1hSt+0W0g3SXW
56 hllNenZAhFpXHzZvJk2qEoNIRXIeonX4N62FBLD7ZoWHQDGahkyfhxML4jYA3KUa
57 PWGeUvMlRPkoR4NjHA3zXQvD2FwTtcKCulGYQHRAAyATIcNq0kKZMuMAJxC5A7VD
58 vQVb7vOaN01YxJt+L6KF0v4ZiYdse5yBI/X58i2gnLqy102Oqj2qZygazj5LLdTE
59 sjgsiC9ln6kesbRayXiqi+RnF+BeKKlwGCuUpH+vFGxXmT6Kr4iEiGIHxAs/HZOS
60 9m61z1eHjrce654mpqwbeqhsyQZswyab2IpERwIDAQABAoIBABrnK+gypr3mUnfa
61 QZnfcZoK5w7yq9kuOCb/oAAH/bS+qofqvSjj+x8yyXwDN71Hm2EThTm3wfwBkmuj
62 UjqiDqAhCbrQhucnhIJKvCKsyr5QbdiUKlS8Yb7u+MhUrZ3lHdJ4k8t7kxSu0ZQD
63 QSM2SZx6x4iwJ6yJW1WQ+PIP21n8ejraQ9PzqpuUsNXh05DU8qN/nJHe311D5ZuB
64 UnSHdfGaF+EBbNxPLzV028db+L9m3a+h87uZhyqwRlUXP+swlToVNvF74bs+mflz
65 r5JN6CwRM3VamnwmcnE77D/zyCsP1Js9LgoxhzhdcUwIOYVWRzUUVRCsrtYOSGF7
66 WBzC3WECgYEA0hGtnBw5rryubv0kWDjZoVGvuwDo7BOW1JFXZYJwvweEj7EjWFTY
67 bVk+MYs1huG+0NpNuhw6IYmDPIEkoLVNGuTHBMnA+SzQx/xv719b1OmY0Wl8ikYd
68 Xlmhxr7mjAJX4eqkVTrBGtsi6TCLdk3HnUdpXJQ0k2aUN6hNFJfsmhUCgYEA2ykP
69 hdVzP1ZtXsHEfHSOfRPIzX9gCLETghntAf44MCF+hHZeEVnuTSrfeqELvy5qCarA
70 FgjZ77p7q6R7YP2KBQUc/gzZStjGIOCPv9xI8otXrmQRVXOxWNafeDp+TOPa2o9S
71 2bBovNmN4Kc+ayktATCVuabMbuGiMIPuRY1pR+sCgYEAmdJSEw7j+hy1ihYZJ/Sw
72 /5xmFoQLCtspRgwLOAx07Jzfp6xpGkQ+mouPrA2oq1TgOeSwp8gFlQsxqvtRy9AW
73 XswJI2tsv8jeNKKXgGuOPfCzcxxQEpxW4wC1ImglP35zxbzginxUbIrsHF7ssDsy
74 IOvqrdzkRs8FV2AI2TyKByUCgYEAuhdDdwCnu0BH3g3qKUNPOiVyfAuMH9U8G1yo
75 Quj6DORj6VYYyeLy1dNxr07QCqX+o/a44/zgEQ7ns/cWTGT8rQaKd62xVDx8/62u
76 YdtKlah76zhM/6IdFLIo9o20cNWJH8xTLUT9ql2QexGHjraH4FrAx8M6E2zDqy5b
77 Q/OvUcECgYAjt8XosvUiRpZ1ugMxwAx316IIEgs2u7k4xdQESnVhIOM3Ex5ikXkK
78 I0Hu/2XPH3KO6+6BOhtdZ4qXLf4hikbIisgq3P87Fb2rUElYZjVm3vClYhEzx6ym
79 bSWO/cZTpp9L14qMuWzb13pD20GExPOIBh1m0exvoL3M8JhLShutWw==
80 -----END RSA PRIVATE KEY-----"""
81
82 PUBLIC_KEY = """-----BEGIN PUBLIC KEY-----
83 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs9bRFjWofNeWq2qtsvH9
84 iDZXXbv5NQI6avK1hSt+0W0g3SXWhllNenZAhFpXHzZvJk2qEoNIRXIeonX4N62F
85 BLD7ZoWHQDGahkyfhxML4jYA3KUaPWGeUvMlRPkoR4NjHA3zXQvD2FwTtcKCulGY
86 QHRAAyATIcNq0kKZMuMAJxC5A7VDvQVb7vOaN01YxJt+L6KF0v4ZiYdse5yBI/X5
87 8i2gnLqy102Oqj2qZygazj5LLdTEsjgsiC9ln6kesbRayXiqi+RnF+BeKKlwGCuU
88 pH+vFGxXmT6Kr4iEiGIHxAs/HZOS9m61z1eHjrce654mpqwbeqhsyQZswyab2IpE
89 RwIDAQAB
90 -----END PUBLIC KEY-----"""
91
92 WRONG_PRIVATE_KEY = """-----BEGIN RSA PRIVATE KEY-----
93 MIIEogIBAAKCAQEA230Ic8gqYGrIYPffrgvS9ezrI94+TMwIX0A3nyi6nRBOAzuV
94 OMP0L4OegDLnAkyUC4ZiH6B9uAJ1mbp4WsX0Q2a3FuGzscCfriV0JKRd4256Mj60
95 bGq7xLqR/d62IzLrQ2eJCQe2IspwUIeAW301igwoPIGTfZurQ6drXBcbRVo7adry
96 V3+TGsfQVge95IyVAPm4A7kcJsdQu9HsD7Hp9LIM35B3oHCOF7hHP/MEEAz84Q6q
97 lpWxdTzSnIxDXWxS2BqPInKOIL5egpn69AfJKLj+QPpQymULx3FCeNKeHmSICHtP
98 r0uTckEek0kfFT2W6hIU1w1f+Pkddhc1fY45VQIDAQABAoIBABvOsHZywqOqg659
99 WPJk/xo3JOdLbdsu8lSW/zUD5PinKysPrm0drl8irr8RM+E/sHXxVZcqLyNT9HBA
100 hqUBdVvgtIuKlsiLXe+jQR6vUFHTGlopRZSCxT08YeinAa5d8h59DIh/WJz5xtb9
101 A88Tguf1eFeKFxSP11ff6yMkrkjP1KmvNRoTAC0MU3p/N6UT03roR9v6n4qGPF6p
102 /fy6uhLWSJVl7IGFL18DEODid64ShK37VytnvLAMQp8OzL87OdoUW6qrA+z4FP59
103 XSpXULxn6ayJG3VChT+Y+nb23rC6gzCYYb3qkSwep2xNqfblP8jL2k/NSlbshdiz
104 j3BfK8ECgYEA6D7SMCXZ2hBYu8EBoGRmMLdtM+spps61JOAhgy2i9aNQ/YlKfuS9
105 kvNFqT1DEpQsjcRmZIEVb5uJQJYUDx6zj4eUSzkISvziz43dg4RKpC/ktprp9RQ1
106 8sAQD4n5Xy2chdTQHKfGl4oF5b16wpi0eE97XptDOlLgPhk167woUQUCgYEA8fAt
107 8uZxw0aKkQbF+tYItsWQQP87dJGUeLna4F3T6q5L5WJYCtFqILiFfWwfcjEaOKWV
108 JzKr0f9pLrRxXYdFUxNolOhA1hZCqZu2ZzpSlfsPWhp2WflGi6DqzSByhgVuwHbV
109 pRl0TRE2dQVgpuXxxiURREHoHJPZRc+3sOwU+BECgYAZJXQssmx8J/jzm1pJu5U1
110 ASdZz8Sawxbp/zqhsXdLkXtbeFoQk0PTfXO1d2Sjxldsoi9UAoYHp5ec3qMdX/2h
111 NNThsDMtq2QDhSDO9KwASw9AllVuq9mLhzA1/oJ5w76G3xwJfkEKd29cCMAaAd7I
112 iBKbk8QbtI2DK8ei1qSm4QKBgAPHvPAOqbhjYcbiVDWXIou4ioh5dHRd0fQQ81qO
113 HMGN96Gd58JDg2T/fRZ4mgUuvzojXDFAmW6ujvYr25mag3rI0tmAx4KQ1nnP9Qmn
114 36J4ScUepLrDKlcELKcH2sI9U32uXag2vZp2qmMpsljpPt3ZtmtanEXWCY8Nr9ET
115 30ABAoGAQ63wGwq1LPS6t/zU6CwOlIzGNnHDquO7o1o/h8IPt3BN6yF0NEVItjdi
116 fL2ZwmBCUbO6Y/Jb1kh4a0iohWF33nS3J4Q6wSQUfBMG5jDI7GfuKAgTQl+sMkOM
117 xjyKrWs/y7HtiP/2vf83QVEL8Bxr3WXdXHj1EBHFEMWA576J6mk=
118 -----END RSA PRIVATE KEY-----"""
119
120 roles = (
121 'rw-rbac-platform:super-admin', 'rw-project:project-admin',
122 'rw-project-mano:catalog-admin', 'rw-project:project-oper'
123 )
124
125
126 class Jwt:
127 """Jwt."""
128
129 def __init__(
130 self, private_key=None, public_key=None,
131 iss=None, sub=None, aud=None):
132 """__init___."""
133 self.iss = iss
134 self.sub = sub
135 self.aud = aud
136 self.keyjar = keyio.KeyJar()
137 if private_key:
138 self._add_key_to_keyjar(private_key)
139 if public_key:
140 self._add_key_to_keyjar(public_key, owner=self.iss)
141
142 def _add_key_to_keyjar(self, pkey, owner=''):
143 kb = keyio.KeyBundle()
144 priv_key = RSA.importKey(pkey)
145 key = RSAKey().load_key(priv_key)
146 key.use = "sig"
147 kb.append(key)
148 self.keyjar.add_kb(owner, kb)
149
150 def sign_jwt(self):
151 """sign_jwt."""
152 jwt = oic_jwt.JWT(self.keyjar, iss=self.iss)
153 jws = jwt.pack(sub=self.sub, aud=self.aud)
154 return jws
155
156 def verify(self, jws):
157 """verify."""
158 jwt = oic_jwt.JWT(self.keyjar)
159 return jwt.unpack(jws)
160
161 TOKEN_URL = "https://{}:8009/token"
162 REVOKE_URL = "https://{}:8009/revoke"
163 REST_GET_LOG_CONFIG = "https://{}:8008/api/running/logging"
164
165
166 class State:
167 """State."""
168
169 def __init__(self):
170 """__init___."""
171 self.access_token = None
172 _, self.cert, _ = certs.get_bootstrap_cert_and_key()
173
174 def teardown(self):
175 """teardown."""
176 print("\n=== Done with Tests ===")
177
178
179 @pytest.fixture(scope="session")
180 def state():
181 """state."""
182 st = State()
183 yield st
184 st.teardown()
185
186
187 @pytest.mark.incremental
188 class TestJwtBearer:
189 """TestJwtBearer."""
190
191 def generate_keys(self, key_format='PEM'):
192 """Generate private & public keys."""
193 private = RSA.generate(2048)
194 pri_key = private.exportKey('PEM')
195 private_key = pri_key.decode('utf-8')
196 public = private.publickey()
197 pub_key = public.exportKey(key_format)
198 public_key = pub_key.decode('utf-8')
199 return private_key, public_key
200
201 def test_client_config(
202 self, rw_user_proxy, rbac_user_passwd, user_domain,
203 rbac_platform_proxy, rw_rbac_int_proxy, mgmt_session):
204 """Setting the public key in config."""
205 client_id = '111'
206 rift.auto.mano.create_user(
207 rw_user_proxy, 'test', rbac_user_passwd, user_domain)
208 rift.auto.mano.assign_platform_role_to_user(
209 rbac_platform_proxy, 'rw-rbac-platform:super-admin', 'test',
210 user_domain, rw_rbac_int_proxy)
211 openidc_xpath = (
212 '/rw-openidc-provider:openidc-provider-config/' +
213 'rw-openidc-provider:openidc-client' +
214 '[rw-openidc-provider:client-id={}]'.format(quoted_key(client_id))
215 )
216 config_object = (
217 RwOpenidcProviderYang.
218 YangData_RwOpenidcProvider_OpenidcProviderConfig_OpenidcClient.
219 from_dict({
220 'client_id': client_id,
221 'client_name': 'test',
222 'user_name': 'test',
223 'user_domain': user_domain,
224 'public_key': PUBLIC_KEY}))
225 rw_open_idc_proxy = mgmt_session.proxy(RwOpenidcProviderYang)
226 rw_open_idc_proxy.create_config(openidc_xpath, config_object)
227
228 def test_get_token(self, state, confd_host):
229 """Get the token."""
230 jwt = Jwt(private_key=PRIVATE_KEY, iss="111",
231 sub="test", aud="https://{}:8009".format(confd_host))
232 jws = jwt.sign_jwt()
233 body_tuple = (
234 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
235 ("assertion", jws),
236 )
237
238 req = tornado.httpclient.HTTPRequest(
239 url=TOKEN_URL.format(confd_host),
240 method='POST',
241 headers={"Content-Type": "application/x-www-form-urlencoded"},
242 ca_certs=state.cert,
243 body=urllib.parse.urlencode(body_tuple)
244 )
245 client = tornado.httpclient.HTTPClient()
246 resp = client.fetch(req)
247 token_resp = json.loads(resp.body.decode('utf-8'))
248 assert "access_token" in token_resp
249 state.access_token = token_resp["access_token"]
250
251 def test_api_access(self, state, confd_host):
252 """Test api access."""
253 assert state.access_token is not None
254 req = tornado.httpclient.HTTPRequest(
255 url=REST_GET_LOG_CONFIG.format(confd_host),
256 headers={
257 "Authorization": "Bearer " + state.access_token,
258 "Accept": "application/json",
259 },
260 ca_certs=state.cert,
261 )
262 client = tornado.httpclient.HTTPClient()
263 resp = client.fetch(req)
264 assert resp.code == 200 or resp.code == 204
265
266 def test_revoke_token(self, state, confd_host):
267 """Revoke a token."""
268 assert state.access_token is not None
269 body_tuple = (
270 ("token", state.access_token),
271 ("token_type_hint", "access_token"),
272 )
273 req = tornado.httpclient.HTTPRequest(
274 url=REVOKE_URL.format(confd_host),
275 method='POST',
276 headers={
277 "Authorization": "Bearer " + state.access_token,
278 "Content-Type": "application/x-www-form-urlencoded",
279 },
280 ca_certs=state.cert,
281 body=urllib.parse.urlencode(body_tuple)
282 )
283 client = tornado.httpclient.HTTPClient()
284 client.fetch(req)
285
286 def test_api_access_invalid_token(self, state, confd_host):
287 """Test access with invalid token."""
288 assert state.access_token is not None
289 req = tornado.httpclient.HTTPRequest(
290 url=REST_GET_LOG_CONFIG.format(confd_host),
291 headers={
292 "Authorization": "Bearer " + state.access_token,
293 "Accept": "application/json",
294 },
295 ca_certs=state.cert,
296 )
297 client = tornado.httpclient.HTTPClient()
298 with pytest.raises(tornado.httpclient.HTTPError) as excinfo:
299 client.fetch(req)
300 assert excinfo.value.code == 401
301 state.access_token = None
302
303 def test_invalid_client_id(self, state, confd_host):
304 """Test with invalid client-id."""
305 jwt = Jwt(private_key=PRIVATE_KEY, iss="invalid_client",
306 sub="test", aud="https://{}:8009".format(confd_host))
307 jws = jwt.sign_jwt()
308 body_tuple = (
309 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
310 ("assertion", jws),
311 )
312
313 req = tornado.httpclient.HTTPRequest(
314 url=TOKEN_URL.format(confd_host),
315 method='POST',
316 headers={"Content-Type": "application/x-www-form-urlencoded"},
317 ca_certs=state.cert,
318 body=urllib.parse.urlencode(body_tuple)
319 )
320 client = tornado.httpclient.HTTPClient()
321 with pytest.raises(tornado.httpclient.HTTPError) as excinfo:
322 client.fetch(req)
323 assert excinfo.value.code == 400
324
325 def test_invalid_key(self, state, confd_host):
326 """Test with invalid key."""
327 jwt = Jwt(private_key=WRONG_PRIVATE_KEY, iss="111",
328 sub="test", aud="https://{}:8009".format(confd_host))
329 jws = jwt.sign_jwt()
330 body_tuple = (
331 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
332 ("assertion", jws),
333 )
334
335 req = tornado.httpclient.HTTPRequest(
336 url=TOKEN_URL.format(confd_host),
337 method='POST',
338 headers={"Content-Type": "application/x-www-form-urlencoded"},
339 ca_certs=state.cert,
340 body=urllib.parse.urlencode(body_tuple)
341 )
342 client = tornado.httpclient.HTTPClient()
343 with pytest.raises(tornado.httpclient.HTTPError) as excinfo:
344 client.fetch(req)
345 assert excinfo.value.code == 400
346
347 def test_invalid_user(self, state, confd_host):
348 """Test with invalid user."""
349 jwt = Jwt(private_key=PRIVATE_KEY, iss="111",
350 sub="invalid_user", aud="https://{}:8009".format(confd_host))
351 jws = jwt.sign_jwt()
352 body_tuple = (
353 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
354 ("assertion", jws),
355 )
356
357 req = tornado.httpclient.HTTPRequest(
358 url=TOKEN_URL.format(confd_host),
359 method='POST',
360 headers={"Content-Type": "application/x-www-form-urlencoded"},
361 ca_certs=state.cert,
362 body=urllib.parse.urlencode(body_tuple)
363 )
364 client = tornado.httpclient.HTTPClient()
365 with pytest.raises(tornado.httpclient.HTTPError) as excinfo:
366 client.fetch(req)
367 assert excinfo.value.code == 400
368
369 def test_check_basic_functionality(
370 self, rw_user_proxy, rbac_user_passwd, user_domain, state,
371 rbac_platform_proxy, rw_rbac_int_proxy, mgmt_session,
372 session_class, confd_host, rw_project_proxy, cloud_module,
373 cloud_account, descriptors, fmt_nsd_catalog_xpath, logger):
374 """Check basic functionality."""
375 # Add the users to our config with the public key.
376 logger.debug('Create users and add roles for them')
377 for idx in range(1, 5):
378 client_id = '111{}'.format(idx)
379 user_name = 'test_{}'.format(idx)
380 role = roles[idx - 1]
381 rift.auto.mano.create_user(
382 rw_user_proxy, user_name, rbac_user_passwd, user_domain)
383 if 'platform' in role:
384 rift.auto.mano.assign_platform_role_to_user(
385 rbac_platform_proxy, role, user_name,
386 user_domain, rw_rbac_int_proxy)
387 else:
388 rift.auto.mano.assign_project_role_to_user(
389 rw_project_proxy, role, user_name,
390 'default', user_domain, rw_rbac_int_proxy)
391 openidc_xpath = (
392 '/rw-openidc-provider:openidc-provider-config/' +
393 'rw-openidc-provider:openidc-client[rw-openidc-provider:' +
394 'client-id={}]'.format(quoted_key(client_id))
395 )
396 # Generate PEM keys for some, while for others its openssh keys
397 logger.debug('Generate private & public keys for the user')
398 if idx % 2 == 0:
399 key_format = 'OpenSSH'
400 else:
401 key_format = 'PEM'
402 private_key, public_key = self.generate_keys(key_format)
403 config_object = (
404 RwOpenidcProviderYang.
405 YangData_RwOpenidcProvider_OpenidcProviderConfig_OpenidcClient.
406 from_dict({
407 'client_id': client_id,
408 'client_name': user_name,
409 'user_name': user_name,
410 'user_domain': user_domain,
411 'public_key': public_key}))
412 rw_open_idc_proxy = mgmt_session.proxy(RwOpenidcProviderYang)
413 rw_open_idc_proxy.create_config(openidc_xpath, config_object)
414 # Create the jason web signature
415 jwt = Jwt(private_key=private_key, iss=client_id,
416 sub=user_name, aud="https://{}:8009".format(confd_host))
417 jws = jwt.sign_jwt()
418 body_tuple = (
419 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
420 ("assertion", jws),
421 )
422 # Get the token using the signature
423 req = tornado.httpclient.HTTPRequest(
424 url=TOKEN_URL.format(confd_host),
425 method='POST',
426 headers={"Content-Type": "application/x-www-form-urlencoded"},
427 ca_certs=state.cert,
428 body=urllib.parse.urlencode(body_tuple)
429 )
430 client = tornado.httpclient.HTTPClient()
431 resp = client.fetch(req)
432 token_resp = json.loads(resp.body.decode('utf-8'))
433 assert "access_token" in token_resp
434 access_token = token_resp["access_token"]
435 user_session = rift.auto.mano.get_session(
436 session_class, confd_host, user_name,
437 rbac_user_passwd, access_token=access_token)
438 rw_rbac_internal_proxy = user_session.proxy(RwRbacInternalYang)
439 # According to the role, checking the functionality
440 if role == 'rw-rbac-platform:super-admin':
441 project_pxy = user_session.proxy(RwProjectYang)
442 rift.auto.mano.assign_project_role_to_user(
443 project_pxy, 'rw-project:project-admin', 'oper', 'default',
444 'system', rw_rbac_internal_proxy)
445 elif role == 'rw-project:project-admin':
446 logger.debug('Creating cloud account.')
447 rift.auto.mano.create_cloud_account(
448 user_session, cloud_account)
449 elif role == 'rw-project-mano:catalog-admin':
450 logger.debug('Uploading descriptors')
451 for descriptor in descriptors:
452 rift.auto.descriptor.onboard(
453 user_session, descriptor, project='default')
454 nsd_pxy = user_session.proxy(RwProjectNsdYang)
455 nsd_catalog = nsd_pxy.get_config(
456 fmt_nsd_catalog_xpath.format(
457 project=quoted_key('default')))
458 assert nsd_catalog
459 else:
460 project_xpath = '/project[name={project_name}]/project-state'
461 rw_project_proxy = user_session.proxy(RwProjectYang)
462 project = rw_project_proxy.get_config(
463 project_xpath.format(project_name=quoted_key('default')), list_obj=True)
464 assert project
465
466 def test_with_expired_token(
467 self, state, rw_user_proxy, rbac_user_passwd, user_domain,
468 rbac_platform_proxy, rw_rbac_int_proxy, mgmt_session,
469 session_class, confd_host, cloud_module, cloud_account,
470 logger):
471 """Test with an expired token."""
472 # Set the expiry time for the token as 'expiry_timeout' seconds.
473 client_id = '222'
474 user_name = 'expired_token_user'
475 expiry_timeout = 1
476 rift.auto.mano.create_user(
477 rw_user_proxy, user_name, rbac_user_passwd, user_domain)
478 rift.auto.mano.assign_platform_role_to_user(
479 rbac_platform_proxy, 'rw-rbac-platform:super-admin', user_name,
480 user_domain, rw_rbac_int_proxy)
481
482 openidc_provider_xpath = '/rw-openidc-provider:openidc-provider-config'
483 openidc_provider = (
484 RwOpenidcProviderYang.
485 YangData_RwOpenidcProvider_OpenidcProviderConfig.from_dict({
486 'token_expiry_timeout': expiry_timeout}))
487 pxy = mgmt_session.proxy(RwOpenidcProviderYang)
488 pxy.replace_config(openidc_provider_xpath, openidc_provider)
489
490 # Verify if token_expiry_timeout is set in openidc-provider-config
491 openidc_provider = pxy.get_config(openidc_provider_xpath)
492 assert openidc_provider
493 assert openidc_provider.token_expiry_timeout == expiry_timeout
494 # Set the public key in our config
495 openidc_xpath = (
496 '/rw-openidc-provider:openidc-provider-config/' +
497 'rw-openidc-provider:openidc-client' +
498 '[rw-openidc-provider:client-id={}]'.format(quoted_key(client_id))
499 )
500 config_object = (
501 RwOpenidcProviderYang.
502 YangData_RwOpenidcProvider_OpenidcProviderConfig_OpenidcClient.
503 from_dict({
504 'client_id': client_id,
505 'client_name': user_name,
506 'user_name': user_name,
507 'user_domain': user_domain,
508 'public_key': PUBLIC_KEY}))
509 rw_open_idc_proxy = mgmt_session.proxy(RwOpenidcProviderYang)
510 rw_open_idc_proxy.create_config(openidc_xpath, config_object)
511 # Generate the signature
512 jwt = Jwt(private_key=PRIVATE_KEY, iss=client_id,
513 sub=user_name, aud="https://{}:8009".format(confd_host))
514 jws = jwt.sign_jwt()
515 body_tuple = (
516 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
517 ("assertion", jws),
518 )
519 logger.debug('Get the token using the signature')
520 req = tornado.httpclient.HTTPRequest(
521 url=TOKEN_URL.format(confd_host),
522 method='POST',
523 headers={"Content-Type": "application/x-www-form-urlencoded"},
524 ca_certs=state.cert,
525 body=urllib.parse.urlencode(body_tuple)
526 )
527 client = tornado.httpclient.HTTPClient()
528 resp = client.fetch(req)
529 token_resp = json.loads(resp.body.decode('utf-8'))
530 assert "access_token" in token_resp
531 access_token = token_resp["access_token"]
532 # Wait out the expiry timout
533 user_session = rift.auto.mano.get_session(
534 session_class, confd_host, user_name,
535 rbac_user_passwd, access_token=access_token)
536 time.sleep(expiry_timeout + 5)
537 with pytest.raises(
538 Exception,
539 message='Task done with expired token'):
540 user_conman_pxy = user_session.proxy(RwProjectYang)
541 assert user_conman_pxy.get_config(
542 '/project[name={}]/project-state'.format(quoted_key('default')), list_obj=True)