Browse Source

Merge "Add dedicated auth endpoint config for servers"

changes/97/672897/1
Zuul 2 years ago
committed by Gerrit Code Review
parent
commit
54005a2a9f
  1. 9
      heat/common/config.py
  2. 3
      heat/engine/clients/os/keystone/fake_keystoneclient.py
  3. 23
      heat/engine/clients/os/keystone/heat_keystoneclient.py
  4. 6
      heat/engine/resources/server_base.py
  5. 3
      heat/engine/resources/signal_responder.py
  6. 46
      heat/tests/clients/test_heat_client.py
  7. 16
      releasenotes/notes/add-dedicated-auth-endpoint-config-for-servers-b20f7eb351f619d0.yaml

9
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',

3
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

23
heat/engine/clients/os/keystone/heat_keystoneclient.py

@ -563,6 +563,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.

6
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}})

3
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,

46
heat/tests/clients/test_heat_client.py

@ -1449,6 +1449,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):

16
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
Loading…
Cancel
Save