4 # Copyright 2017 RIFT.IO Inc
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
10 # http://www.apache.org/licenses/LICENSE-2.0
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.
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)
30 import tornado
.httpclient
32 import Cryptodome
.PublicKey
.RSA
as RSA
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
,
51 from gi
.repository
.RwKeyspec
import quoted_key
# noqa
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-----"""
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
90 -----END PUBLIC KEY-----"""
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-----"""
121 'rw-rbac-platform:super-admin', 'rw-project:project-admin',
122 'rw-project-mano:catalog-admin', 'rw-project:project-oper'
130 self
, private_key
=None, public_key
=None,
131 iss
=None, sub
=None, aud
=None):
136 self
.keyjar
= keyio
.KeyJar()
138 self
._add
_key
_to
_keyjar
(private_key
)
140 self
._add
_key
_to
_keyjar
(public_key
, owner
=self
.iss
)
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
)
148 self
.keyjar
.add_kb(owner
, kb
)
152 jwt
= oic_jwt
.JWT(self
.keyjar
, iss
=self
.iss
)
153 jws
= jwt
.pack(sub
=self
.sub
, aud
=self
.aud
)
156 def verify(self
, jws
):
158 jwt
= oic_jwt
.JWT(self
.keyjar
)
159 return jwt
.unpack(jws
)
161 TOKEN_URL
= "https://{}:8009/token"
162 REVOKE_URL
= "https://{}:8009/revoke"
163 REST_GET_LOG_CONFIG
= "https://{}:8008/api/running/logging"
171 self
.access_token
= None
172 _
, self
.cert
, _
= certs
.get_bootstrap_cert_and_key()
176 print("\n=== Done with Tests ===")
179 @pytest.fixture(scope
="session")
187 @pytest.mark
.incremental
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
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."""
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
)
212 '/rw-openidc-provider:openidc-provider-config/' +
213 'rw-openidc-provider:openidc-client' +
214 '[rw-openidc-provider:client-id={}]'.format(quoted_key(client_id
))
217 RwOpenidcProviderYang
.
218 YangData_RwOpenidcProvider_OpenidcProviderConfig_OpenidcClient
.
220 'client_id': client_id
,
221 'client_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
)
228 def test_get_token(self
, state
, confd_host
):
230 jwt
= Jwt(private_key
=PRIVATE_KEY
, iss
="111",
231 sub
="test", aud
="https://{}:8009".format(confd_host
))
234 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
238 req
= tornado
.httpclient
.HTTPRequest(
239 url
=TOKEN_URL
.format(confd_host
),
241 headers
={"Content-Type": "application/x-www-form-urlencoded"},
243 body
=urllib
.parse
.urlencode(body_tuple
)
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"]
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
),
257 "Authorization": "Bearer " + state
.access_token
,
258 "Accept": "application/json",
262 client
= tornado
.httpclient
.HTTPClient()
263 resp
= client
.fetch(req
)
264 assert resp
.code
== 200 or resp
.code
== 204
266 def test_revoke_token(self
, state
, confd_host
):
267 """Revoke a token."""
268 assert state
.access_token
is not None
270 ("token", state
.access_token
),
271 ("token_type_hint", "access_token"),
273 req
= tornado
.httpclient
.HTTPRequest(
274 url
=REVOKE_URL
.format(confd_host
),
277 "Authorization": "Bearer " + state
.access_token
,
278 "Content-Type": "application/x-www-form-urlencoded",
281 body
=urllib
.parse
.urlencode(body_tuple
)
283 client
= tornado
.httpclient
.HTTPClient()
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
),
292 "Authorization": "Bearer " + state
.access_token
,
293 "Accept": "application/json",
297 client
= tornado
.httpclient
.HTTPClient()
298 with pytest
.raises(tornado
.httpclient
.HTTPError
) as excinfo
:
300 assert excinfo
.value
.code
== 401
301 state
.access_token
= None
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
))
309 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
313 req
= tornado
.httpclient
.HTTPRequest(
314 url
=TOKEN_URL
.format(confd_host
),
316 headers
={"Content-Type": "application/x-www-form-urlencoded"},
318 body
=urllib
.parse
.urlencode(body_tuple
)
320 client
= tornado
.httpclient
.HTTPClient()
321 with pytest
.raises(tornado
.httpclient
.HTTPError
) as excinfo
:
323 assert excinfo
.value
.code
== 400
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
))
331 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
335 req
= tornado
.httpclient
.HTTPRequest(
336 url
=TOKEN_URL
.format(confd_host
),
338 headers
={"Content-Type": "application/x-www-form-urlencoded"},
340 body
=urllib
.parse
.urlencode(body_tuple
)
342 client
= tornado
.httpclient
.HTTPClient()
343 with pytest
.raises(tornado
.httpclient
.HTTPError
) as excinfo
:
345 assert excinfo
.value
.code
== 400
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
))
353 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
357 req
= tornado
.httpclient
.HTTPRequest(
358 url
=TOKEN_URL
.format(confd_host
),
360 headers
={"Content-Type": "application/x-www-form-urlencoded"},
362 body
=urllib
.parse
.urlencode(body_tuple
)
364 client
= tornado
.httpclient
.HTTPClient()
365 with pytest
.raises(tornado
.httpclient
.HTTPError
) as excinfo
:
367 assert excinfo
.value
.code
== 400
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
)
388 rift
.auto
.mano
.assign_project_role_to_user(
389 rw_project_proxy
, role
, user_name
,
390 'default', user_domain
, rw_rbac_int_proxy
)
392 '/rw-openidc-provider:openidc-provider-config/' +
393 'rw-openidc-provider:openidc-client[rw-openidc-provider:' +
394 'client-id={}]'.format(quoted_key(client_id
))
396 # Generate PEM keys for some, while for others its openssh keys
397 logger
.debug('Generate private & public keys for the user')
399 key_format
= 'OpenSSH'
402 private_key
, public_key
= self
.generate_keys(key_format
)
404 RwOpenidcProviderYang
.
405 YangData_RwOpenidcProvider_OpenidcProviderConfig_OpenidcClient
.
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
))
419 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
422 # Get the token using the signature
423 req
= tornado
.httpclient
.HTTPRequest(
424 url
=TOKEN_URL
.format(confd_host
),
426 headers
={"Content-Type": "application/x-www-form-urlencoded"},
428 body
=urllib
.parse
.urlencode(body_tuple
)
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')))
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)
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
,
471 """Test with an expired token."""
472 # Set the expiry time for the token as 'expiry_timeout' seconds.
474 user_name
= 'expired_token_user'
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
)
482 openidc_provider_xpath
= '/rw-openidc-provider:openidc-provider-config'
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
)
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
496 '/rw-openidc-provider:openidc-provider-config/' +
497 'rw-openidc-provider:openidc-client' +
498 '[rw-openidc-provider:client-id={}]'.format(quoted_key(client_id
))
501 RwOpenidcProviderYang
.
502 YangData_RwOpenidcProvider_OpenidcProviderConfig_OpenidcClient
.
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
))
516 ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
519 logger
.debug('Get the token using the signature')
520 req
= tornado
.httpclient
.HTTPRequest(
521 url
=TOKEN_URL
.format(confd_host
),
523 headers
={"Content-Type": "application/x-www-form-urlencoded"},
525 body
=urllib
.parse
.urlencode(body_tuple
)
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)
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)