From 203787c37facb4d77405edfac3d970f2612ac7a2 Mon Sep 17 00:00:00 2001 From: wangxiyuan Date: Thu, 22 Mar 2018 19:51:31 +0800 Subject: [PATCH] Clean up token extra code Originally, the "extra" in token data is generated by auth plugin and then will be return to users within token data. In Kilo, the "extra" in token data was deprecated[1], after that if the auth plugin generate the "extra", a warning log will be raised. To stop the warning, the auth plugins should stop generating "extra" field. After two releases, in Mitaka, the "extra" in token data was removed[2], but the "extra" was still created by default as an empty dict {}. Actually, "extra" should not be created any more in Mitaka because Keystone has warned the auth plugins for two releases. Now in Rocky, it's safe enough to remove the "extra" from token issue flow at all since it has never been used from Mitaka. The only concern for the out tree plugins about the removal is that if they still put "extra" into auth_context, Keystone will raise KeyError. But can it be happened? Only if the out tree plugins ignore the warning in Kilo, and still contain "extra" but never use them from Mitaka. For most auth plugins which follow the Keystone deprecation step, this patch is a silent change. [1]: https://review.openstack.org/#/c/162662 [2]: https://review.openstack.org/#/c/249480 Change-Id: I828cc0ad3ac265abdfea2e1571806add128ae51e --- doc/source/api_curl_examples.rst | 544 +++++++++++++++++------- doc/source/contributor/auth-plugins.rst | 8 +- keystone/auth/controllers.py | 3 +- keystone/auth/plugins/base.py | 7 +- keystone/auth/plugins/token.py | 4 - keystone/tests/unit/test_auth_plugin.py | 8 +- keystone/tests/unit/test_v3.py | 2 +- 7 files changed, 394 insertions(+), 182 deletions(-) diff --git a/doc/source/api_curl_examples.rst b/doc/source/api_curl_examples.rst index 450e91cf58..3eeed4b560 100644 --- a/doc/source/api_curl_examples.rst +++ b/doc/source/api_curl_examples.rst @@ -98,10 +98,10 @@ and supported media types: Tokens ====== -Default scope -------------- +Unscoped +-------- -Get a token with default scope (may be unscoped): +Get an unscoped token: .. code-block:: bash @@ -131,60 +131,28 @@ Example response: X-Subject-Token: MIIFvgY... Vary: X-Auth-Token Content-Type: application/json - Content-Length: 1025 - Date: Tue, 10 Jun 2014 20:55:16 GMT + Content-Length: 312 + Date: Fri, 11 May 2018 03:15:01 GMT { "token": { - "methods": ["password"], - "roles": [{ - "id": "9fe2ff9ee4384b1894a90878d3e92bab", - "name": "_member_" - }, { - "id": "c703057be878458588961ce9a0ce686b", - "name": "admin" - }], - "expires_at": "2014-06-10T2:55:16.806001Z", - "project": { - "domain": { - "id": "default", - "name": "Default" - }, - "id": "8538a3f13f9541b28c2620eb19065e45", - "name": "admin" - }, - "catalog": [{ - "endpoints": [{ - "url": "http://localhost:3537/v2.0", - "region": "RegionOne", - "interface": "admin", - "id": "29beb2f1567642eb810b042b6719ea88" - }, { - "url": "http://localhost:5000/v2.0", - "region": "RegionOne", - "interface": "internal", - "id": "8707e3735d4415c97ae231b4841eb1c" - }, { - "url": "http://localhost:5000/v2.0", - "region": "RegionOne", - "interface": "public", - "id": "ef303187fc8d41668f25199c298396a5" - }], - "type": "identity", - "id": "bd73972c0e14fb69bae8ff76e112a90", - "name": "keystone" - }], - "extras": {}, - "user": { - "domain": { - "id": "default", - "name": "Default" - }, - "id": "3ec3164f750146be97f21559ee4d9c51", - "name": "admin" - }, - "audit_ids": ["yRt0UrxJSs6-WYJgwEMMmg"], - "issued_at": "201406-10T20:55:16.806027Z" + "issued_at": "2018-05-11T03:15:01.000000Z", + "audit_ids": [ + "0PKh_BDKTWqqaFONE-Sxbg" + ], + "methods": [ + "password" + ], + "expires_at": "2018-05-11T04:15:01.000000Z", + "user": { + "password_expires_at": null, + "domain": { + "id": "default", + "name": "Default" + }, + "id": "9a7e43333cc44ef4b988f05fc3d3a49d", + "name": "admin" + } } } @@ -212,7 +180,7 @@ Get a project-scoped token: }, "scope": { "project": { - "name": "demo", + "name": "admin", "domain": { "id": "default" } } } @@ -228,57 +196,203 @@ Example response: X-Subject-Token: MIIFfQ... Vary: X-Auth-Token Content-Type: application/json - Content-Length: 960 - Date: Tue, 10 Jun 2014 20:40:14 GMT + Content-Length: 3518 + Date: Fri, 11 May 2018 03:38:39 GMT { "token": { - "audit_ids": ["ECwrVNWbSCqmEgPnu0YCRw"], - "methods": ["password"], - "roles": [{ - "id": "c703057be878458588961ce9a0ce686b", - "name": "admin" - }], - "expires_at": "2014-06-10T21:40:14.360795Z", - "project": { - "domain": { - "id": "default", - "name": "Default" + "is_domain": false, + "methods": [ + "password" + ], + "roles": [ + { + "id": "b57680c826b44b5ca6122d0f792c3184", + "name": "Member" + }, + { + "id": "3a7bd258345f47479a26aea11a6cc2bb", + "name": "admin" + } + ], + "expires_at": "2018-05-11T04:38:39.000000Z", + "project": { + "domain": { + "id": "default", + "name": "Default" + }, + "id": "3a705b9f56bb439381b43c4fe59dccce", + "name": "admin" }, - "id": "3d4c2c82bd5948f0bcab0cf3a7c9b48c", - "name": "demo" - }, - "catalog": [{ - "endpoints": [{ - "url": "http://localhost:35357/v2.0", - "region": "RegionOne", - "interface": "admin", - "id": "29beb2f1567642eb810b042b6719ea88" - }, { - "url": "http://localhost:5000/v2.0", - "region": "RegionOne", - "interface": "internal", - "id": "87057e3735d4415c97ae231b4841eb1c" - }, { - "url": "http://localhost:5000/v2.0", - "region": "RegionOne", - "interface": "public", - "id": "ef303187fc8d41668f25199c298396a5" - }], - "type": "identity", - "id": "bd7397d2c0e14fb69bae8ff76e112a90", - "name": "keystone" - }], - "extras": {}, - "user": { - "domain": { - "id": "default", - "name": "Default" + "catalog": [ + { + "endpoints": [ + { + "url": "http://localhost/identity", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "30a91932e4e94a8ca4dc145bb1bb6b4b" + }, + { + "url": "http://localhost/identity", + "interface": "admin", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "94d4768735104c9091f0468e7d31c189" + } + ], + "type": "identity", + "id": "09af9253500b41ef976a07322b2fa388", + "name": "keystone" + }, + { + "endpoints": [ + { + "url": "http://localhost/volume/v2/3a705b9f56bb439381b43c4fe59dccce", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "1c4ffe935e7643d99b55938cb12bc38d" + } + ], + "type": "volumev2", + "id": "413a44234e1a4c3781d4a3c7a7e4c895", + "name": "cinderv2" + }, + { + "endpoints": [ + { + "url": "http://localhost/image", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "33237fdd1a744d0fb40f9127f21ddad4" + } + ], + "type": "image", + "id": "4d473252145546d2aa589605f1e177c7", + "name": "glance" + }, + { + "endpoints": [ + { + "url": "http://localhost/placement", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "1a421e2f97684d3f86ab4d2cc9c86362" + } + ], + "type": "placement", + "id": "5dcecbdd4a1d44d0855c560301b27bb5", + "name": "placement" + }, + { + "endpoints": [ + { + "url": "http://localhost/compute/v2.1", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "8e7ea663cc41477c9629cc710bbb1c7d" + } + ], + "type": "compute", + "id": "87d49efa8fb64006bdb123d223ddcae2", + "name": "nova" + }, + { + "endpoints": [ + { + "url": "http://localhost/volume/v1/3a705b9f56bb439381b43c4fe59dccce", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "97a2c0ac7e304316a1eb58a3757e6ef8" + } + ], + "type": "volume", + "id": "9408080f1970482aa0e38bc2d4ea34b7", + "name": "cinder" + }, + { + "endpoints": [ + { + "url": "http://localhost:8080/v1/AUTH_3a705b9f56bb439381b43c4fe59dccce", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "d0d823615b0747a9aeca8b83fba105f0" + }, + { + "url": "http://localhost:8080", + "interface": "admin", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "e4cb86d9232349f091e0a02390deeb79" + } + ], + "type": "object-store", + "id": "957ba1fe8b0443f0afe64bfd0858ba5e", + "name": "swift" + }, + { + "endpoints": [ + { + "url": "http://localhost:9696/", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "aa4a0e61cdc54372967ee9e2298f1d53" + } + ], + "type": "network", + "id": "960fbc66bfcb4fa7900023f647fdc3a5", + "name": "neutron" + }, + { + "endpoints": [ + { + "url": "http://localhost/volume/v3/3a705b9f56bb439381b43c4fe59dccce", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "0c38045a91c34d798e0d2008fee7521d" + } + ], + "type": "volumev3", + "id": "98adb083914f423d9cb74ad5527e37cb", + "name": "cinderv3" + }, + { + "endpoints": [ + { + "url": "http://localhost/compute/v2/3a705b9f56bb439381b43c4fe59dccce", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "id": "562e12b9ee9549e8b857218ccf2ae321" + } + ], + "type": "compute_legacy", + "id": "a31e688016614430b28cddddf12d7b88", + "name": "nova_legacy" + } + ], + "user": { + "password_expires_at": null, + "domain": { + "id": "default", + "name": "Default" + }, + "id": "9a7e43333cc44ef4b988f05fc3d3a49d", + "name": "admin" }, - "id": "3ec3164f750146be97f21559ee4d9c51", - "name": "admin" - }, - "issued_at": "2014-06-10T20:40:14.360822Z" + "audit_ids": [ + "TbdrnW4MQDq_GPAVN9-JOQ" + ], + "issued_at": "2018-05-11T03:38:39.000000Z" } } @@ -322,53 +436,159 @@ Example response: X-Subject-Token: MIIFNg... Vary: X-Auth-Token Content-Type: application/json - Content-Length: 889 - Date: Tue, 10 Jun 2014 20:52:59 GMT + Content-Length: 2590 + Date: Fri, 11 May 2018 03:37:09 GMT { "token": { - "domain": { - "id": "default", - "name": "Default" - }, - "methods": ["password"], - "roles": [{ - "id": "c703057be878458588961ce9a0ce686b", - "name": "admin" - }], - "expires_at": "2014-06-10T21:52:58.852167Z", - "catalog": [{ - "endpoints": [{ - "url": "http://localhost:35357/v2.0", - "region": "RegionOne", - "interface": "admin", - "id": "29beb2f1567642eb810b042b6719ea88" - }, { - "url": "http://localhost:5000/v2.0", - "region": "RegionOne", - "interface": "internal", - "id": "87057e3735d4415c97ae231b4841eb1c" - }, { - "url": "http://localhost:5000/v2.0", - "region": "RegionOne", - "interface": "public", - "id": "ef303187fc8d41668f25199c298396a5" - }], - "type": "identity", - "id": "bd7397d2c0e14fb69bae8ff76e112a90", - "name": "keystone" - }], - "extras": {}, - "user": { "domain": { - "id": "default", - "name": "Default" + "id": "default", + "name": "Default" }, - "id": "3ec3164f750146be97f21559ee4d9c51", - "name": "admin" - }, - "audit_ids": ["Xpa6Uyn-T9S6mTREudUH3w"], - "issued_at": "2014-06-10T20:52:58.852194Z" + "methods": [ + "password" + ], + "roles": [ + { + "id": "b57680c826b44b5ca6122d0f792c3184", + "name": "Member" + }, + { + "id": "3a7bd258345f47479a26aea11a6cc2bb", + "name": "admin" + } + ], + "expires_at": "2018-05-11T04:37:09.000000Z", + "catalog": [ + { + "endpoints": [ + { + "region_id": "RegionOne", + "url": "http://localhost/identity", + "region": "RegionOne", + "interface": "public", + "id": "30a91932e4e94a8ca4dc145bb1bb6b4b" + }, + { + "region_id": "RegionOne", + "url": "http://localhost/identity", + "region": "RegionOne", + "interface": "admin", + "id": "94d4768735104c9091f0468e7d31c189" + } + ], + "type": "identity", + "id": "09af9253500b41ef976a07322b2fa388", + "name": "keystone" + }, + { + "endpoints": [], + "type": "volumev2", + "id": "413a44234e1a4c3781d4a3c7a7e4c895", + "name": "cinderv2" + }, + { + "endpoints": [ + { + "region_id": "RegionOne", + "url": "http://localhost/image", + "region": "RegionOne", + "interface": "public", + "id": "33237fdd1a744d0fb40f9127f21ddad4" + } + ], + "type": "image", + "id": "4d473252145546d2aa589605f1e177c7", + "name": "glance" + }, + { + "endpoints": [ + { + "region_id": "RegionOne", + "url": "http://localhost/placement", + "region": "RegionOne", + "interface": "public", + "id": "1a421e2f97684d3f86ab4d2cc9c86362" + } + ], + "type": "placement", + "id": "5dcecbdd4a1d44d0855c560301b27bb5", + "name": "placement" + }, + { + "endpoints": [ + { + "region_id": "RegionOne", + "url": "http://localhost/compute/v2.1", + "region": "RegionOne", + "interface": "public", + "id": "8e7ea663cc41477c9629cc710bbb1c7d" + } + ], + "type": "compute", + "id": "87d49efa8fb64006bdb123d223ddcae2", + "name": "nova" + }, + { + "endpoints": [], + "type": "volume", + "id": "9408080f1970482aa0e38bc2d4ea34b7", + "name": "cinder" + }, + { + "endpoints": [ + { + "region_id": "RegionOne", + "url": "http://localhost:8080", + "region": "RegionOne", + "interface": "admin", + "id": "e4cb86d9232349f091e0a02390deeb79" + } + ], + "type": "object-store", + "id": "957ba1fe8b0443f0afe64bfd0858ba5e", + "name": "swift" + }, + { + "endpoints": [ + { + "region_id": "RegionOne", + "url": "http://localhost:9696/", + "region": "RegionOne", + "interface": "public", + "id": "aa4a0e61cdc54372967ee9e2298f1d53" + } + ], + "type": "network", + "id": "960fbc66bfcb4fa7900023f647fdc3a5", + "name": "neutron" + }, + { + "endpoints": [], + "type": "volumev3", + "id": "98adb083914f423d9cb74ad5527e37cb", + "name": "cinderv3" + }, + { + "endpoints": [], + "type": "compute_legacy", + "id": "a31e688016614430b28cddddf12d7b88", + "name": "nova_legacy" + } + ], + "user": { + "password_expires_at": null, + "domain": { + "id": "default", + "name": "Default" + }, + "id": "9a7e43333cc44ef4b988f05fc3d3a49d", + "name": "admin" + }, + "audit_ids": [ + "Sfc8_kywQx-tWNkEVqA1Iw" + ], + "issued_at": "2018-05-11T03:37:09.000000Z" } } @@ -403,26 +623,30 @@ Example response: X-Subject-Token: MIIFxw... Vary: X-Auth-Token Content-Type: application/json - Content-Length: 1034 - Date: Tue, 10 Jun 2014 21:00:05 GMT + Content-Length: 347 + Date: Fri, 11 May 2018 03:41:29 GMT { "token": { - "methods": ["token", "password"], - "expires_at": "2015-05-28T07:43:44.808209Z", - "extras": {}, - "user": { - "domain": { - "id": "default", - "name": "Default" - }, - "id": "753867c25c3340ffad1abc22d488c31a", - "name": "admin" - }, - "audit_ids": ["ZE0OPSuzTmCXHo0eIOYltw", - "xxIQCkHOQOywL0oY6CTppQ" - ], - "issued_at": "2015-05-28T07:19:23.763532Z" + "issued_at": "2018-05-11T03:41:29.000000Z", + "audit_ids": [ + "zS_C_KROTFeZm-VlG1LjbA", + "RAjE82q8Rz-Cd50ogCpx3Q" + ], + "methods": [ + "token", + "password" + ], + "expires_at": "2018-05-11T04:40:00.000000Z", + "user": { + "password_expires_at": null, + "domain": { + "id": "default", + "name": "Default" + }, + "id": "9a7e43333cc44ef4b988f05fc3d3a49d", + "name": "admin" + } } } diff --git a/doc/source/contributor/auth-plugins.rst b/doc/source/contributor/auth-plugins.rst index fbf6fe4043..8f0f7a16ea 100644 --- a/doc/source/contributor/auth-plugins.rst +++ b/doc/source/contributor/auth-plugins.rst @@ -47,16 +47,14 @@ parameters. * ``context`` - keystone's request context * ``auth_payload`` - the content of the authentication for a given method * ``auth_context`` - user authentication context, a dictionary shared by all - plugins. It contains ``method_names`` and ``extras`` by default. - ``method_names`` is a list and ``extras`` is a dictionary. + plugins. It contains ``method_names`` and ``bind`` by default. + ``method_names`` is a list and ``bind`` is a dictionary. If successful, the ``authenticate()`` method must provide a valid ``user_id`` in ``auth_context`` and return ``None``. ``method_name`` is used to convey any additional authentication methods in case authentication is for re-scoping. For example, if the authentication is for re-scoping, a plugin must append the -previous method names into ``method_names``. Also, a plugin may add any -additional information into ``extras``. Anything in ``extras`` will be conveyed -in the token's ``extras`` field. +previous method names into ``method_names``. If authentication requires multiple steps, the ``authenticate()`` method must return the payload in the form of a dictionary for the next authentication diff --git a/keystone/auth/controllers.py b/keystone/auth/controllers.py index 0375153fc5..caf3ef66a8 100644 --- a/keystone/auth/controllers.py +++ b/keystone/auth/controllers.py @@ -65,8 +65,7 @@ class Auth(controller.V3Controller): try: auth_info = core.AuthInfo.create(auth=auth) - auth_context = core.AuthContext(extras={}, - method_names=[], + auth_context = core.AuthContext(method_names=[], bind={}) self.authenticate(request, auth_info, auth_context) if auth_context.get('access_token_id'): diff --git a/keystone/auth/plugins/base.py b/keystone/auth/plugins/base.py index d4bbca2783..4ae71c4525 100644 --- a/keystone/auth/plugins/base.py +++ b/keystone/auth/plugins/base.py @@ -47,13 +47,10 @@ class AuthMethodHandler(provider_api.ProviderAPIMixin, object): in case authentication is for re-scoping. For example, if the authentication is for re-scoping, plugin must append the previous method names into ``method_names``; NOTE: This behavior is exclusive - to the re-scope type action. Also, plugin may add any additional - information into ``extras``. Anything in ``extras`` will be conveyed in - the token's ``extras`` attribute. Here's an example of - ``response_data`` on successful authentication:: + to the re-scope type action. Here's an example of ``response_data`` on + successful authentication:: { - "extras": {}, "methods": [ "password", "token" diff --git a/keystone/auth/plugins/token.py b/keystone/auth/plugins/token.py index 769a03e01a..b6d630b58e 100644 --- a/keystone/auth/plugins/token.py +++ b/keystone/auth/plugins/token.py @@ -118,10 +118,6 @@ def token_authenticate(request, token): response_data.setdefault('expires_at', token.expires_at) response_data['audit_id'] = token_audit_id response_data.setdefault('user_id', token.user_id) - # TODO(morganfainberg: determine if token 'extras' can be removed - # from the response_data - # response_data.setdefault('extras', {}).update( - # token.get('extras', {})) return response_data diff --git a/keystone/tests/unit/test_auth_plugin.py b/keystone/tests/unit/test_auth_plugin.py index 59fb007a2b..42ae4cc5d1 100644 --- a/keystone/tests/unit/test_auth_plugin.py +++ b/keystone/tests/unit/test_auth_plugin.py @@ -83,7 +83,7 @@ class TestAuthPlugin(unit.SQLDriverOverrides, unit.TestCase): 'test': 'test'} auth_data = {'identity': auth_data} auth_info = auth.core.AuthInfo.create(auth_data) - auth_context = auth.core.AuthContext(extras={}, method_names=[]) + auth_context = auth.core.AuthContext(method_names=[]) try: self.api.authenticate(self.make_request(), auth_info, auth_context) except exception.AdditionalAuthRequired as e: @@ -98,7 +98,7 @@ class TestAuthPlugin(unit.SQLDriverOverrides, unit.TestCase): 'response': EXPECTED_RESPONSE} auth_data = {'identity': auth_data} auth_info = auth.core.AuthInfo.create(auth_data) - auth_context = auth.core.AuthContext(extras={}, method_names=[]) + auth_context = auth.core.AuthContext(method_names=[]) self.api.authenticate(self.make_request(), auth_info, auth_context) self.assertEqual(DEMO_USER_ID, auth_context['user_id']) @@ -108,7 +108,7 @@ class TestAuthPlugin(unit.SQLDriverOverrides, unit.TestCase): 'response': uuid.uuid4().hex} auth_data = {'identity': auth_data} auth_info = auth.core.AuthInfo.create(auth_data) - auth_context = auth.core.AuthContext(extras={}, method_names=[]) + auth_context = auth.core.AuthContext(method_names=[]) self.assertRaises(exception.Unauthorized, self.api.authenticate, self.make_request(), @@ -160,7 +160,6 @@ class TestMapped(unit.TestCase): } auth_info = auth.core.AuthInfo.create(auth_data) auth_context = auth.core.AuthContext( - extras={}, method_names=[], user_id=uuid.uuid4().hex) self.api.authenticate(request, auth_info, auth_context) @@ -178,7 +177,6 @@ class TestMapped(unit.TestCase): auth_data = {'identity': auth_data} auth_context = auth.core.AuthContext( - extras={}, method_names=[], user_id=uuid.uuid4().hex) diff --git a/keystone/tests/unit/test_v3.py b/keystone/tests/unit/test_v3.py index f52b949c84..447be08e16 100644 --- a/keystone/tests/unit/test_v3.py +++ b/keystone/tests/unit/test_v3.py @@ -1235,7 +1235,7 @@ class RestfulTestCase(unit.SQLDriverOverrides, rest.RestfulTestCase, auth_data = self.build_authentication_request( kerberos=kerberos)['auth'] auth_info = auth.core.AuthInfo.create(auth_data) - auth_context = auth.core.AuthContext(extras={}, method_names=[]) + auth_context = auth.core.AuthContext(method_names=[]) return self.make_request(environ=environment), auth_info, auth_context def build_external_auth_environ(self, remote_user, remote_domain=None):