diff options
author | Zuul <zuul@review.opendev.org> | 2019-10-15 21:00:02 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2019-10-15 21:00:02 +0000 |
commit | adac77a47ce1408e661e851e92a657ecfed3b911 (patch) | |
tree | 33ad7a6c0e6ef8644ca1d2961a558705eedcfb83 | |
parent | 05bb44663745d5132f5f0db098bc699cc32be356 (diff) | |
parent | 35ef93d037baf4e704f23ee20f58d11b1d4ccbe7 (diff) | |
download | heat-adac77a47ce1408e661e851e92a657ecfed3b911.tar.gz |
Merge "Add dedicated auth endpoint config for servers" into stable/stein
-rw-r--r-- | heat/common/config.py | 9 | ||||
-rw-r--r-- | heat/engine/clients/os/keystone/fake_keystoneclient.py | 3 | ||||
-rw-r--r-- | heat/engine/clients/os/keystone/heat_keystoneclient.py | 23 | ||||
-rw-r--r-- | heat/engine/resources/server_base.py | 6 | ||||
-rw-r--r-- | heat/engine/resources/signal_responder.py | 3 | ||||
-rw-r--r-- | heat/tests/clients/test_heat_client.py | 46 | ||||
-rw-r--r-- | releasenotes/notes/add-dedicated-auth-endpoint-config-for-servers-b20f7eb351f619d0.yaml | 16 |
7 files changed, 102 insertions, 4 deletions
diff --git a/heat/common/config.py b/heat/common/config.py index c4c9e1d2e..8e39719c8 100644 --- a/heat/common/config.py +++ b/heat/common/config.py @@ -88,7 +88,14 @@ service_opts = [ cfg.IntOpt('num_engine_workers', help=_('Number of heat-engine processes to fork and run. ' 'Will default to either to 4 or number of CPUs on ' - 'the host, whichever is greater.'))] + 'the host, whichever is greater.')), + cfg.StrOpt('server_keystone_endpoint_type', + choices=['', 'public', 'internal', 'admin'], + default='', + help=_('If set, is used to control which authentication ' + 'endpoint is used by user-controlled servers to make ' + 'calls back to Heat. ' + 'If unset www_authenticate_uri is used.'))] engine_opts = [ cfg.ListOpt('plugin_dirs', diff --git a/heat/engine/clients/os/keystone/fake_keystoneclient.py b/heat/engine/clients/os/keystone/fake_keystoneclient.py index 6e594ecfb..524d09a8e 100644 --- a/heat/engine/clients/os/keystone/fake_keystoneclient.py +++ b/heat/engine/clients/os/keystone/fake_keystoneclient.py @@ -121,3 +121,6 @@ class FakeKeystoneClient(object): def stack_domain_user_token(self, user_id, project_id, password): return 'adomainusertoken' + + def server_keystone_endpoint_url(self, fallback_endpoint): + return fallback_endpoint diff --git a/heat/engine/clients/os/keystone/heat_keystoneclient.py b/heat/engine/clients/os/keystone/heat_keystoneclient.py index 2b3999dbb..edd05c768 100644 --- a/heat/engine/clients/os/keystone/heat_keystoneclient.py +++ b/heat/engine/clients/os/keystone/heat_keystoneclient.py @@ -552,6 +552,29 @@ class KsClientWrapper(object): self._check_stack_domain_user(user_id, project_id, 'enable') self.domain_admin_client.users.update(user=user_id, enabled=True) + def server_keystone_endpoint_url(self, fallback_endpoint): + ks_endpoint_type = cfg.CONF.server_keystone_endpoint_type + if ((ks_endpoint_type == 'public') or ( + ks_endpoint_type == 'internal') or + (ks_endpoint_type == 'admin')): + if (hasattr(self.context, 'auth_plugin') and + hasattr(self.context.auth_plugin, 'get_access')): + try: + auth_ref = self.context.auth_plugin.get_access( + self.session) + if hasattr(auth_ref, "service_catalog"): + unversioned_sc_auth_uri = ( + auth_ref.service_catalog.get_urls( + service_type='identity', + interface=ks_endpoint_type)) + if len(unversioned_sc_auth_uri) > 0: + sc_auth_uri = ( + unversioned_sc_auth_uri[0] + "/v3") + return sc_auth_uri + except ks_exception.Unauthorized: + LOG.error("Keystone client authentication failed") + return fallback_endpoint + class KeystoneClient(object): """Keystone Auth Client. diff --git a/heat/engine/resources/server_base.py b/heat/engine/resources/server_base.py index 983efe298..5f0b5d00c 100644 --- a/heat/engine/resources/server_base.py +++ b/heat/engine/resources/server_base.py @@ -84,7 +84,8 @@ class BaseServer(stack_user.StackUser): occ.update({'heat': { 'user_id': self._get_user_id(), 'password': self.password, - 'auth_url': self.context.auth_url, + 'auth_url': self.keystone().server_keystone_endpoint_url( + fallback_endpoint=self.context.auth_url), 'project_id': self.stack.stack_user_project_id, 'stack_id': self.stack.identifier().stack_path(), 'resource_name': self.name, @@ -96,7 +97,8 @@ class BaseServer(stack_user.StackUser): occ.update({'zaqar': { 'user_id': self._get_user_id(), 'password': self.password, - 'auth_url': self.context.auth_url, + 'auth_url': self.keystone().server_keystone_endpoint_url( + fallback_endpoint=self.context.auth_url), 'project_id': self.stack.stack_user_project_id, 'queue_id': queue_id, 'region_name': region_name}}) diff --git a/heat/engine/resources/signal_responder.py b/heat/engine/resources/signal_responder.py index 23c1f9c76..b9127d9f1 100644 --- a/heat/engine/resources/signal_responder.py +++ b/heat/engine/resources/signal_responder.py @@ -103,7 +103,8 @@ class SignalResponder(stack_user.StackUser): if self.password is None: self.password = password_gen.generate_openstack_password() self._create_user() - return {'auth_url': self.keystone().v3_endpoint, + return {'auth_url': self.keystone().server_keystone_endpoint_url( + fallback_endpoint=self.keystone().v3_endpoint), 'username': self.physical_resource_name(), 'user_id': self._get_user_id(), 'password': self.password, diff --git a/heat/tests/clients/test_heat_client.py b/heat/tests/clients/test_heat_client.py index ffe017796..c5fb9f003 100644 --- a/heat/tests/clients/test_heat_client.py +++ b/heat/tests/clients/test_heat_client.py @@ -1435,6 +1435,52 @@ class KeystoneClientTest(common.HeatTestCase): self.assertIsNone(heat_ks_client.delete_stack_domain_project( project_id='aprojectid')) + def test_server_keystone_endpoint_url_config(self): + """Return non fallback url path.""" + cfg.CONF.set_override('server_keystone_endpoint_type', 'public') + ctx = utils.dummy_context() + ctx.trust_id = None + heat_ks_client = heat_keystoneclient.KeystoneClient(ctx) + fallback_url = 'http://server.fallback.test:5000/v3' + auth_ref = heat_ks_client.context.auth_plugin.get_access( + heat_ks_client.session) + auth_ref.service_catalog.get_urls = mock.MagicMock() + auth_ref.service_catalog.get_urls.return_value = [ + 'http://server.public.test:5000'] + self.assertEqual( + heat_ks_client.server_keystone_endpoint_url(fallback_url), + 'http://server.public.test:5000/v3') + cfg.CONF.clear_override('server_keystone_endpoint_type') + + def test_server_keystone_endpoint_url_no_config(self): + """Return fallback as no config option specified.""" + ctx = utils.dummy_context() + ctx.trust_id = None + heat_ks_client = heat_keystoneclient.KeystoneClient(ctx) + cfg.CONF.clear_override('server_keystone_endpoint_type') + fallback_url = 'http://server.fallback.test:5000/v3' + self.assertEqual(heat_ks_client.server_keystone_endpoint_url( + fallback_url), fallback_url) + + def test_server_keystone_endpoint_url_auth_exception(self): + """Authorization call fails, return fallback.""" + cfg.CONF.set_override('server_keystone_endpoint_type', 'public') + ctx = utils.dummy_context() + ctx.trust_id = None + heat_ks_client = heat_keystoneclient.KeystoneClient(ctx) + auth_ref = heat_ks_client.context.auth_plugin.get_access( + heat_ks_client.session) + auth_ref.service_catalog.get_urls = mock.MagicMock() + auth_ref.service_catalog.get_urls.return_value = [ + 'http://server.public.test:5000'] + heat_ks_client.context.auth_plugin.get_access = mock.MagicMock() + heat_ks_client.context.auth_plugin.get_access.side_effect = ( + kc_exception.Unauthorized) + fallback_url = 'http://server.fallback.test:5000/v3' + self.assertEqual(heat_ks_client.server_keystone_endpoint_url( + fallback_url), fallback_url) + cfg.CONF.clear_override('server_keystone_endpoint_type') + class KeystoneClientTestDomainName(KeystoneClientTest): def setUp(self): diff --git a/releasenotes/notes/add-dedicated-auth-endpoint-config-for-servers-b20f7eb351f619d0.yaml b/releasenotes/notes/add-dedicated-auth-endpoint-config-for-servers-b20f7eb351f619d0.yaml new file mode 100644 index 000000000..52d93f8da --- /dev/null +++ b/releasenotes/notes/add-dedicated-auth-endpoint-config-for-servers-b20f7eb351f619d0.yaml @@ -0,0 +1,16 @@ +--- +features: + - | + Added a new config option server_keystone_endpoint_type to specify + the keystone authentication endpoint (public/internal/admin) + to pass into cloud-init data. + If left unset the original behavior should remain unchanged. + + This feature allows the deployer to unambiguously specify the + keystone endpoint passed to user provisioned servers, and is particularly + useful where the deployment network architecture requires the heat + service to interact with the internal endpoint, + but user provisioned servers only have access to the external network. + + For more information see + http://lists.openstack.org/pipermail/openstack-discuss/2019-February/002925.html |