From 0bb0d6486d6771ee21bbf897a091b1aa59e01b22 Mon Sep 17 00:00:00 2001 From: Johannes Grassler Date: Fri, 16 Sep 2016 10:01:07 +0200 Subject: [PATCH] Fix CVE-2016-7404 This commit addresses multiple potential vulnerabilities in Magnum. It makes the following changes: * Permissions for /etc/sysconfig/heat-params inside Magnum created instances are tightened to 0600 (used to be 0755). * Certificate retrieval is modified to work without the need for a Keystone trust. * The cluster's Keystone trust id is only passed into instances for clusters where that is actually needed. This prevents the trustee user from consuming the trust in cases where it is not needed. * The configuration setting trust/cluster_user_trust (False by default) is introduced. It needs to be explicitely enabled by the cloud operator to allow clusters that need the trust_id to be passed into instances to work. Without this setting, attempts to create such clusters will fail. Please note, that none of these changes apply to existing clusters. They will have to be deleted and rebuilt to benefit from these changes. (cherry picked from commit e93d82e8b3bc19211efd54edc17aebdca50670c1) Changes for backport: * Moved cluster_user_trust setting to magnum/common/keystone.py * Resolved merge conflicts. * Fixed unit tests with configuration overrides. Change-Id: I408d845ee4fd00d5bcd1e90f0a78f2bba3f2a57a --- devstack/lib/magnum | 1 + etc/magnum/policy.json | 54 ++++++++++--------- magnum/common/keystone.py | 12 +++++ magnum/common/policy.py | 12 +++++ .../handlers/common/trust_manager.py | 13 +++-- magnum/db/sqlalchemy/api.py | 17 +++++- magnum/drivers/common/template_def.py | 16 +++++- .../kubernetes/fragments/make-cert-client.sh | 5 -- .../kubernetes/fragments/make-cert.sh | 5 -- .../fragments/write-heat-params-master.yaml | 2 +- .../fragments/write-heat-params.yaml | 2 +- .../templates/fragments/make-cert-client.yaml | 5 -- .../templates/fragments/make-cert.yaml | 5 -- .../fragments/write-heat-params-master.yaml | 2 +- .../fragments/write-heat-params.yaml | 2 +- .../fragments/write-heat-params.yaml | 2 +- .../templates/fragments/make-cert.py | 6 --- .../fragments/write-heat-params-master.yaml | 2 +- .../fragments/write-heat-params-node.yaml | 2 +- magnum/tests/base.py | 27 ++++++++++ magnum/tests/unit/common/test_keystone.py | 15 ++++++ .../handlers/common/test_trust_manager.py | 3 +- .../handlers/test_cluster_conductor.py | 5 ++ .../handlers/test_k8s_cluster_conductor.py | 14 +++-- .../handlers/test_mesos_cluster_conductor.py | 9 ++-- .../handlers/test_swarm_cluster_conductor.py | 8 ++- 26 files changed, 171 insertions(+), 75 deletions(-) diff --git a/devstack/lib/magnum b/devstack/lib/magnum index 1242f1ac4f..a0c8c6f970 100644 --- a/devstack/lib/magnum +++ b/devstack/lib/magnum @@ -206,6 +206,7 @@ function create_magnum_conf { --os-identity-api-version 3 role add \ --user $trustee_domain_admin_id --domain $trustee_domain_id \ admin + iniset $MAGNUM_CONF trust cluster_user_trust True iniset $MAGNUM_CONF trust trustee_domain_name magnum iniset $MAGNUM_CONF trust trustee_domain_admin_name trustee_domain_admin iniset $MAGNUM_CONF trust trustee_domain_admin_password $MAGNUM_TRUSTEE_DOMAIN_ADMIN_PASSWORD diff --git a/etc/magnum/policy.json b/etc/magnum/policy.json index 2cea1a6e89..437942adf9 100644 --- a/etc/magnum/policy.json +++ b/etc/magnum/policy.json @@ -4,35 +4,37 @@ "default": "rule:admin_or_owner", "admin_api": "rule:context_is_admin", "admin_or_user": "is_admin:True or user_id:%(user_id)s", + "cluster_user": "user_id:%(trustee_user_id)s", + "deny_cluster_user": "not domain_id:%(trustee_domain_id)s", - "bay:create": "rule:default", - "bay:delete": "rule:default", - "bay:detail": "rule:default", - "bay:get": "rule:default", - "bay:get_all": "rule:default", - "bay:update": "rule:default", + "bay:create": "rule:deny_cluster_user", + "bay:delete": "rule:deny_cluster_user", + "bay:detail": "rule:deny_cluster_user", + "bay:get": "rule:deny_cluster_user", + "bay:get_all": "rule:deny_cluster_user", + "bay:update": "rule:deny_cluster_user", - "baymodel:create": "rule:default", - "baymodel:delete": "rule:default", - "baymodel:detail": "rule:default", - "baymodel:get": "rule:default", - "baymodel:get_all": "rule:default", - "baymodel:update": "rule:default", + "baymodel:create": "rule:deny_cluster_user", + "baymodel:delete": "rule:deny_cluster_user", + "baymodel:detail": "rule:deny_cluster_user", + "baymodel:get": "rule:deny_cluster_user", + "baymodel:get_all": "rule:deny_cluster_user", + "baymodel:update": "rule:deny_cluster_user", "baymodel:publish": "rule:admin_or_owner", - "cluster:create": "rule:default", - "cluster:delete": "rule:default", - "cluster:detail": "rule:default", - "cluster:get": "rule:default", - "cluster:get_all": "rule:default", - "cluster:update": "rule:default", + "cluster:create": "rule:deny_cluster_user", + "cluster:delete": "rule:deny_cluster_user", + "cluster:detail": "rule:deny_cluster_user", + "cluster:get": "rule:deny_cluster_user", + "cluster:get_all": "rule:deny_cluster_user", + "cluster:update": "rule:deny_cluster_user", - "clustertemplate:create": "rule:default", - "clustertemplate:delete": "rule:default", - "clustertemplate:detail": "rule:default", - "clustertemplate:get": "rule:default", - "clustertemplate:get_all": "rule:default", - "clustertemplate:update": "rule:default", + "clustertemplate:create": "rule:deny_cluster_user", + "clustertemplate:delete": "rule:deny_cluster_user", + "clustertemplate:detail": "rule:deny_cluster_user", + "clustertemplate:get": "rule:deny_cluster_user", + "clustertemplate:get_all": "rule:deny_cluster_user", + "clustertemplate:update": "rule:deny_cluster_user", "clustertemplate:publish": "rule:admin_or_owner", "rc:create": "rule:default", @@ -42,8 +44,8 @@ "rc:get_all": "rule:default", "rc:update": "rule:default", - "certificate:create": "rule:admin_or_user", - "certificate:get": "rule:admin_or_user", + "certificate:create": "rule:admin_or_user or rule:cluster_user", + "certificate:get": "rule:admin_or_user or rule:cluster_user", "magnum-service:get_all": "rule:admin_api" } diff --git a/magnum/common/keystone.py b/magnum/common/keystone.py index 3e1dc202f7..4dc4249cca 100644 --- a/magnum/common/keystone.py +++ b/magnum/common/keystone.py @@ -31,6 +31,17 @@ CFG_LEGACY_GROUP = 'keystone_authtoken' LOG = logging.getLogger(__name__) trust_opts = [ + cfg.BoolOpt('cluster_user_trust', + default=False, + help=_('This setting controls whether to assign a trust to' + ' the cluster user or not. You will need to set it to' + ' True for clusters with volume_driver=cinder or' + ' registry_enabled=true in the underlying cluster' + ' template to work. This is a potential security risk' + ' since the trust gives instances OpenStack API access' + " to the cluster's project. Note that this setting" + ' does not affect per-cluster trusts assigned to the' + 'Magnum service user.')), cfg.StrOpt('trustee_domain_id', help=_('Id of the domain to create trustee for clusters')), cfg.StrOpt('trustee_domain_name', @@ -249,6 +260,7 @@ class KeystoneClientV3(object): project=trustor_project_id, trustee_user=trustee_user, impersonation=True, + delegation_depth=0, role_names=roles) except Exception: LOG.exception(_LE('Failed to create trust')) diff --git a/magnum/common/policy.py b/magnum/common/policy.py index 980691f7a3..160cf153f0 100644 --- a/magnum/common/policy.py +++ b/magnum/common/policy.py @@ -20,6 +20,8 @@ from oslo_config import cfg from oslo_policy import policy import pecan +from magnum.common import clients +from magnum.common import context from magnum.common import exception @@ -92,10 +94,20 @@ def enforce(context, rule=None, target=None, if target is None: target = {'project_id': context.project_id, 'user_id': context.user_id} + add_policy_attributes(target) return enforcer.enforce(rule, target, credentials, do_raise=do_raise, exc=exc, *args, **kwargs) +def add_policy_attributes(target): + """Adds extra information for policy enforcement to raw target object""" + admin_context = context.make_admin_context() + admin_osc = clients.OpenStackClients(admin_context) + trustee_domain_id = admin_osc.keystone().trustee_domain_id + target['trustee_domain_id'] = trustee_domain_id + return target + + def enforce_wsgi(api_name, act=None): """This is a decorator to simplify wsgi action policy rule check. diff --git a/magnum/conductor/handlers/common/trust_manager.py b/magnum/conductor/handlers/common/trust_manager.py index 287953fbfa..415ff65fdc 100644 --- a/magnum/conductor/handlers/common/trust_manager.py +++ b/magnum/conductor/handlers/common/trust_manager.py @@ -22,15 +22,20 @@ LOG = logging.getLogger(__name__) def create_trustee_and_trust(osc, cluster): try: password = utils.generate_password(length=18) + trustee = osc.keystone().create_trustee( - cluster.uuid, + "%s_%s" % (cluster.uuid, cluster.project_id), password, ) + cluster.trustee_username = trustee.name cluster.trustee_user_id = trustee.id cluster.trustee_password = password - trust = osc.keystone().create_trust(trustee.id) + + trust = osc.keystone().create_trust( + cluster.trustee_user_id) cluster.trust_id = trust.id + except Exception: LOG.exception( _LE('Failed to create trustee and trust for Cluster: %s'), @@ -41,9 +46,11 @@ def create_trustee_and_trust(osc, cluster): def delete_trustee_and_trust(osc, context, cluster): try: + kst = osc.keystone() + # The cluster which is upgraded from Liberty doesn't have trust_id if cluster.trust_id: - osc.keystone().delete_trust(context, cluster) + kst.delete_trust(context, cluster) except Exception: # Exceptions are already logged by keystone().delete_trust pass diff --git a/magnum/db/sqlalchemy/api.py b/magnum/db/sqlalchemy/api.py index 488474545f..db4a0c0474 100644 --- a/magnum/db/sqlalchemy/api.py +++ b/magnum/db/sqlalchemy/api.py @@ -24,6 +24,8 @@ from oslo_utils import uuidutils from sqlalchemy.orm.exc import MultipleResultsFound from sqlalchemy.orm.exc import NoResultFound +from magnum.common import clients +from magnum.common import context as request_context from magnum.common import exception from magnum.db import api from magnum.db.sqlalchemy import models @@ -113,8 +115,21 @@ class Connection(api.Connection): if context.is_admin and context.all_tenants: return query - if context.project_id: + admin_context = request_context.make_admin_context(all_tenants=True) + osc = clients.OpenStackClients(admin_context) + kst = osc.keystone() + + # User in a regular project (not in the trustee domain) + if context.project_id and context.domain_id != kst.trustee_domain_id: query = query.filter_by(project_id=context.project_id) + # Match project ID component in trustee user's user name against + # cluster's project_id to associate per-cluster trustee users who have + # no project information with the project their clusters/cluster models + # reside in. This is equivalent to the project filtering above. + elif context.domain_id == kst.trustee_domain_id: + user_name = kst.client.users.get(context.user_id).name + user_project = user_name.split('_', 2)[1] + query = query.filter_by(project_id=user_project) else: query = query.filter_by(user_id=context.user_id) diff --git a/magnum/drivers/common/template_def.py b/magnum/drivers/common/template_def.py index d956fbaa3b..4e4fe6e5fa 100644 --- a/magnum/drivers/common/template_def.py +++ b/magnum/drivers/common/template_def.py @@ -23,6 +23,7 @@ import six from magnum.common import clients from magnum.common import exception from magnum.i18n import _ +from magnum.i18n import _LE from magnum.i18n import _LW from requests import exceptions as req_exceptions @@ -380,7 +381,20 @@ class BaseTemplateDefinition(TemplateDefinition): extra_params['trustee_user_id'] = cluster.trustee_user_id extra_params['trustee_username'] = cluster.trustee_username extra_params['trustee_password'] = cluster.trustee_password - extra_params['trust_id'] = cluster.trust_id + + # Only pass trust ID into the template when it is needed. + if (cluster_template.volume_driver == 'rexray' or + cluster_template.registry_enabled): + if CONF.trust.cluster_user_trust: + extra_params['trust_id'] = cluster.trust_id + else: + missing_setting = ('trust/cluster_user_trust = True') + msg = _LE('This cluster can only be created with %s in ' + 'magnum.conf') + raise exception.ConfigInvalid(msg % missing_setting) + else: + extra_params['trust_id'] = "" + extra_params['auth_url'] = context.auth_url return super(BaseTemplateDefinition, diff --git a/magnum/drivers/common/templates/kubernetes/fragments/make-cert-client.sh b/magnum/drivers/common/templates/kubernetes/fragments/make-cert-client.sh index d19d8c2744..c17ec5d472 100644 --- a/magnum/drivers/common/templates/kubernetes/fragments/make-cert-client.sh +++ b/magnum/drivers/common/templates/kubernetes/fragments/make-cert-client.sh @@ -49,11 +49,6 @@ auth_json=$(cat << EOF "password": "$TRUSTEE_PASSWORD" } } - }, - "scope": { - "OS-TRUST:trust": { - "id": "$TRUST_ID" - } } } } diff --git a/magnum/drivers/common/templates/kubernetes/fragments/make-cert.sh b/magnum/drivers/common/templates/kubernetes/fragments/make-cert.sh index 1612184aaf..323551e7c1 100644 --- a/magnum/drivers/common/templates/kubernetes/fragments/make-cert.sh +++ b/magnum/drivers/common/templates/kubernetes/fragments/make-cert.sh @@ -71,11 +71,6 @@ auth_json=$(cat << EOF "password": "$TRUSTEE_PASSWORD" } } - }, - "scope": { - "OS-TRUST:trust": { - "id": "$TRUST_ID" - } } } } diff --git a/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params-master.yaml b/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params-master.yaml index 4651ab3db3..dc2d2fac23 100644 --- a/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params-master.yaml +++ b/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params-master.yaml @@ -3,7 +3,7 @@ merge_how: dict(recurse_array)+list(append) write_files: - path: /etc/sysconfig/heat-params owner: "root:root" - permissions: "0644" + permissions: "0600" content: | KUBE_API_PUBLIC_ADDRESS="$KUBE_API_PUBLIC_ADDRESS" KUBE_API_PRIVATE_ADDRESS="$KUBE_API_PRIVATE_ADDRESS" diff --git a/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params.yaml b/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params.yaml index d455a23e4b..adda07026d 100644 --- a/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params.yaml +++ b/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params.yaml @@ -3,7 +3,7 @@ merge_how: dict(recurse_array)+list(append) write_files: - path: /etc/sysconfig/heat-params owner: "root:root" - permissions: "0644" + permissions: "0600" content: | KUBE_ALLOW_PRIV="$KUBE_ALLOW_PRIV" KUBE_MASTER_IP="$KUBE_MASTER_IP" diff --git a/magnum/drivers/k8s_coreos_v1/templates/fragments/make-cert-client.yaml b/magnum/drivers/k8s_coreos_v1/templates/fragments/make-cert-client.yaml index 3c0da542cb..bcbeb07c47 100644 --- a/magnum/drivers/k8s_coreos_v1/templates/fragments/make-cert-client.yaml +++ b/magnum/drivers/k8s_coreos_v1/templates/fragments/make-cert-client.yaml @@ -66,11 +66,6 @@ write_files: "password": "$TRUSTEE_PASSWORD" } } - }, - "scope": { - "OS-TRUST:trust": { - "id": "$TRUST_ID" - } } } } diff --git a/magnum/drivers/k8s_coreos_v1/templates/fragments/make-cert.yaml b/magnum/drivers/k8s_coreos_v1/templates/fragments/make-cert.yaml index 196b8941c2..f087fbee6e 100644 --- a/magnum/drivers/k8s_coreos_v1/templates/fragments/make-cert.yaml +++ b/magnum/drivers/k8s_coreos_v1/templates/fragments/make-cert.yaml @@ -89,11 +89,6 @@ write_files: "password": "$TRUSTEE_PASSWORD" } } - }, - "scope": { - "OS-TRUST:trust": { - "id": "$TRUST_ID" - } } } } diff --git a/magnum/drivers/k8s_coreos_v1/templates/fragments/write-heat-params-master.yaml b/magnum/drivers/k8s_coreos_v1/templates/fragments/write-heat-params-master.yaml index d1875b886a..aa37850679 100644 --- a/magnum/drivers/k8s_coreos_v1/templates/fragments/write-heat-params-master.yaml +++ b/magnum/drivers/k8s_coreos_v1/templates/fragments/write-heat-params-master.yaml @@ -3,7 +3,7 @@ merge_how: dict(recurse_array)+list(append) write_files: - path: /etc/sysconfig/heat-params owner: "root:root" - permissions: "0644" + permissions: "0600" content: | KUBE_API_PUBLIC_ADDRESS="$KUBE_API_PUBLIC_ADDRESS" KUBE_API_PRIVATE_ADDRESS="$KUBE_API_PRIVATE_ADDRESS" diff --git a/magnum/drivers/k8s_coreos_v1/templates/fragments/write-heat-params.yaml b/magnum/drivers/k8s_coreos_v1/templates/fragments/write-heat-params.yaml index 254cd93e74..ae6c8b2727 100644 --- a/magnum/drivers/k8s_coreos_v1/templates/fragments/write-heat-params.yaml +++ b/magnum/drivers/k8s_coreos_v1/templates/fragments/write-heat-params.yaml @@ -3,7 +3,7 @@ merge_how: dict(recurse_array)+list(append) write_files: - path: /etc/sysconfig/heat-params owner: "root:root" - permissions: "0644" + permissions: "0600" content: | KUBE_ALLOW_PRIV="$KUBE_ALLOW_PRIV" KUBE_MASTER_IP="$KUBE_MASTER_IP" diff --git a/magnum/drivers/mesos_ubuntu_v1/templates/fragments/write-heat-params.yaml b/magnum/drivers/mesos_ubuntu_v1/templates/fragments/write-heat-params.yaml index d9a4b91cc8..2716480492 100644 --- a/magnum/drivers/mesos_ubuntu_v1/templates/fragments/write-heat-params.yaml +++ b/magnum/drivers/mesos_ubuntu_v1/templates/fragments/write-heat-params.yaml @@ -3,7 +3,7 @@ merge_how: dict(recurse_array)+list(append) write_files: - path: /etc/sysconfig/heat-params owner: "root:root" - permissions: "0644" + permissions: "0600" content: | MESOS_MASTERS_IPS="$MESOS_MASTERS_IPS" EXECUTOR_REGISTRATION_TIMEOUT="$EXECUTOR_REGISTRATION_TIMEOUT" diff --git a/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/make-cert.py b/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/make-cert.py index c57848c1ac..d51541db9f 100644 --- a/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/make-cert.py +++ b/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/make-cert.py @@ -147,11 +147,6 @@ def get_user_token(config): "password": "%(trustee_password)s" } } - }, - "scope": { - "OS-TRUST:trust": { - "id": "%(trust_id)s" - } } } } @@ -159,7 +154,6 @@ def get_user_token(config): params = { 'trustee_user_id': config['TRUSTEE_USER_ID'], 'trustee_password': config['TRUSTEE_PASSWORD'], - 'trust_id': config['TRUST_ID'] } creds = creds_str % params headers = {'Content-Type': 'application/json'} diff --git a/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/write-heat-params-master.yaml b/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/write-heat-params-master.yaml index 0a3504cbef..435e891be9 100644 --- a/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/write-heat-params-master.yaml +++ b/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/write-heat-params-master.yaml @@ -3,7 +3,7 @@ merge_how: dict(recurse_array)+list(append) write_files: - path: /etc/sysconfig/heat-params owner: "root:root" - permissions: "0644" + permissions: "0600" content: | WAIT_HANDLE_ENDPOINT="$WAIT_HANDLE_ENDPOINT" WAIT_HANDLE_TOKEN="$WAIT_HANDLE_TOKEN" diff --git a/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/write-heat-params-node.yaml b/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/write-heat-params-node.yaml index d201654905..af0b65010b 100644 --- a/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/write-heat-params-node.yaml +++ b/magnum/drivers/swarm_fedora_atomic_v1/templates/fragments/write-heat-params-node.yaml @@ -3,7 +3,7 @@ merge_how: dict(recurse_array)+list(append) write_files: - path: /etc/sysconfig/heat-params owner: "root:root" - permissions: "0644" + permissions: "0600" content: | WAIT_HANDLE_ENDPOINT="$WAIT_HANDLE_ENDPOINT" WAIT_HANDLE_TOKEN="$WAIT_HANDLE_TOKEN" diff --git a/magnum/tests/base.py b/magnum/tests/base.py index 670b04a7fc..d66cba3de0 100644 --- a/magnum/tests/base.py +++ b/magnum/tests/base.py @@ -26,6 +26,7 @@ import pecan import testscenarios from magnum.common import context as magnum_context +from magnum.common import keystone as magnum_keystone from magnum.objects import base as objects_base from magnum.tests import conf_fixture from magnum.tests import fake_notifier @@ -63,11 +64,18 @@ class TestCase(base.BaseTestCase): } } } + + trustee_domain_id = '12345678-9012-3456-7890-123456789abc' + self.context = magnum_context.RequestContext( auth_token_info=token_info, project_id='fake_project', user_id='fake_user') + self.global_mocks = {} + + self.keystone_client = magnum_keystone.KeystoneClientV3(self.context) + self.policy = self.useFixture(policy_fixture.PolicyFixture()) self.useFixture(fixtures.MockPatchObject( @@ -89,9 +97,22 @@ class TestCase(base.BaseTestCase): p = mock.patch.object(magnum_context, 'make_context', side_effect=make_context) + + self.global_mocks['magnum.common.context.make_context'] = p + + q = mock.patch.object(magnum_keystone.KeystoneClientV3, + 'trustee_domain_id', + return_value=trustee_domain_id) + + self.global_mocks[ + 'magnum.common.keystone.KeystoneClientV3.trustee_domain_id'] = q + self.mock_make_context = p.start() self.addCleanup(p.stop) + self.mock_make_trustee_domain_id = q.start() + self.addCleanup(q.stop) + self.useFixture(conf_fixture.ConfFixture()) self.useFixture(fixtures.NestedTempfile()) @@ -104,6 +125,12 @@ class TestCase(base.BaseTestCase): self.addCleanup(reset_pecan) + def start_global(self, name): + self.global_mocks[name].start() + + def stop_global(self, name): + self.global_mocks[name].stop() + def _restore_obj_registry(self): objects_base.MagnumObjectRegistry._registry._obj_classes \ = self._base_test_obj_backup diff --git a/magnum/tests/unit/common/test_keystone.py b/magnum/tests/unit/common/test_keystone.py index 7c6c3df607..3b46937601 100644 --- a/magnum/tests/unit/common/test_keystone.py +++ b/magnum/tests/unit/common/test_keystone.py @@ -55,6 +55,19 @@ class KeystoneClientTest(base.TestCase): admin_tenant_name='service', group=keystone.CFG_LEGACY_GROUP) + # Disable global mocking for trustee_domain_id + self.stop_global( + 'magnum.common.keystone.KeystoneClientV3.trustee_domain_id') + + def tearDown(self): + # Re-enable global mocking for trustee_domain_id. We need this because + # mock blows up when trying to stop an already stopped patch (which it + # will do due to the addCleanup() in base.TestCase). + self.start_global( + 'magnum.common.keystone.KeystoneClientV3.trustee_domain_id') + + super(KeystoneClientTest, self).tearDown() + def test_client_with_password(self, mock_ks): self.ctx.is_admin = True ks_client = keystone.KeystoneClientV3(self.ctx) @@ -136,6 +149,7 @@ class KeystoneClientTest(base.TestCase): ks_client.create_trust(trustee_user='888888') mock_ks.return_value.trusts.create.assert_called_once_with( + delegation_depth=0, trustor_user='123456', project='654321', trustee_user='888888', role_names=['role1', 'role2'], impersonation=True) @@ -152,6 +166,7 @@ class KeystoneClientTest(base.TestCase): ks_client.create_trust(trustee_user='888888') mock_ks.return_value.trusts.create.assert_called_once_with( + delegation_depth=0, trustor_user='123456', project='654321', trustee_user='888888', role_names=['role3'], impersonation=True) diff --git a/magnum/tests/unit/conductor/handlers/common/test_trust_manager.py b/magnum/tests/unit/conductor/handlers/common/test_trust_manager.py index be758c7d59..3860bb8bbc 100644 --- a/magnum/tests/unit/conductor/handlers/common/test_trust_manager.py +++ b/magnum/tests/unit/conductor/handlers/common/test_trust_manager.py @@ -37,6 +37,7 @@ class TrustManagerTestCase(base.BaseTestCase): mock_generate_password.return_value = mock_password mock_cluster = mock.MagicMock() mock_cluster.uuid = 'mock_cluster_uuid' + mock_cluster.project_id = 'mock_cluster_project_id' mock_keystone = mock.MagicMock() mock_trustee = mock.MagicMock() mock_trustee.id = 'mock_trustee_id' @@ -52,7 +53,7 @@ class TrustManagerTestCase(base.BaseTestCase): trust_manager.create_trustee_and_trust(self.osc, mock_cluster) mock_keystone.create_trustee.assert_called_once_with( - mock_cluster.uuid, + '%s_%s' % (mock_cluster.uuid, mock_cluster.project_id), mock_password, ) mock_keystone.create_trust.assert_called_once_with( diff --git a/magnum/tests/unit/conductor/handlers/test_cluster_conductor.py b/magnum/tests/unit/conductor/handlers/test_cluster_conductor.py index 618082f040..78fcfc8a77 100644 --- a/magnum/tests/unit/conductor/handlers/test_cluster_conductor.py +++ b/magnum/tests/unit/conductor/handlers/test_cluster_conductor.py @@ -191,6 +191,11 @@ class TestHandler(db_base.DbTestCase): mock_poller.poll_and_check.return_value = loopingcall.LoopingCallDone() mock_heat_poller_class.return_value = mock_poller osc = mock.sentinel.osc + + def return_keystone(): + return self.keystone_client + + osc.keystone = return_keystone mock_openstack_client_class.return_value = osc def create_stack_side_effect(context, osc, cluster, timeout): diff --git a/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py b/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py index 895d898472..cd9c9d239a 100644 --- a/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py +++ b/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py @@ -173,7 +173,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'trustee_username': 'fake_trustee', 'trustee_password': 'fake_trustee_password', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', - 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', + 'trust_id': '', 'auth_url': 'http://192.168.10.10:5000/v3', 'insecure_registry_url': '10.0.0.1:5000', 'kube_version': 'fake-version', @@ -210,6 +210,10 @@ class TestClusterConductorWithK8s(base.TestCase): 'RegionOne', group='docker_registry') + cfg.CONF.set_override('cluster_user_trust', + True, + group='trust') + (template_path, definition, env_files) = cluster_conductor._extract_template_definition( @@ -311,7 +315,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'ssh_key_name': 'keypair_id', 'tenant_name': 'fake_tenant', 'tls_disabled': False, - 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', + 'trust_id': '', 'trustee_domain_id': 'trustee_domain_id', 'trustee_password': 'fake_trustee_password', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', @@ -372,7 +376,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'trustee_username': 'fake_trustee', 'trustee_password': 'fake_trustee_password', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', - 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', + 'trust_id': '', 'auth_url': 'http://192.168.10.10:5000/v3', 'cluster_uuid': self.cluster_dict['uuid'], 'magnum_url': self.mock_osc.magnum_url.return_value, @@ -429,7 +433,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'trustee_username': 'fake_trustee', 'trustee_password': 'fake_trustee_password', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', - 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', + 'trust_id': '', 'auth_url': 'http://192.168.10.10:5000/v3', 'cluster_uuid': self.cluster_dict['uuid'], 'magnum_url': self.mock_osc.magnum_url.return_value, @@ -585,7 +589,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'trustee_username': 'fake_trustee', 'trustee_password': 'fake_trustee_password', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', - 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', + 'trust_id': '', 'auth_url': 'http://192.168.10.10:5000/v3', 'insecure_registry_url': '10.0.0.1:5000', 'kube_version': 'fake-version', diff --git a/magnum/tests/unit/conductor/handlers/test_mesos_cluster_conductor.py b/magnum/tests/unit/conductor/handlers/test_mesos_cluster_conductor.py index f69af100d2..110f49be2d 100644 --- a/magnum/tests/unit/conductor/handlers/test_mesos_cluster_conductor.py +++ b/magnum/tests/unit/conductor/handlers/test_mesos_cluster_conductor.py @@ -37,6 +37,7 @@ class TestClusterConductorWithMesos(base.TestCase): 'http_proxy': 'http_proxy', 'https_proxy': 'https_proxy', 'no_proxy': 'no_proxy', + 'registry_enabled': False, 'server_type': 'vm', 'volume_driver': 'volume_driver', 'labels': {'rexray_preempt': 'False', @@ -109,7 +110,7 @@ class TestClusterConductorWithMesos(base.TestCase): 'trustee_username': 'fake_trustee', 'trustee_password': 'fake_trustee_password', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', - 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', + 'trust_id': '', 'volume_driver': 'volume_driver', 'auth_url': 'http://192.168.10.10:5000/v3', 'region_name': self.mock_osc.cinder_region_name.return_value, @@ -158,7 +159,7 @@ class TestClusterConductorWithMesos(base.TestCase): 'trustee_username': 'fake_trustee', 'trustee_password': 'fake_trustee_password', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', - 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', + 'trust_id': '', 'auth_url': 'http://192.168.10.10:5000/v3', 'region_name': self.mock_osc.cinder_region_name.return_value, 'username': 'mesos_user', @@ -208,7 +209,7 @@ class TestClusterConductorWithMesos(base.TestCase): 'trustee_username': 'fake_trustee', 'trustee_password': 'fake_trustee_password', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', - 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', + 'trust_id': '', 'volume_driver': 'volume_driver', 'auth_url': 'http://192.168.10.10:5000/v3', 'region_name': self.mock_osc.cinder_region_name.return_value, @@ -260,7 +261,7 @@ class TestClusterConductorWithMesos(base.TestCase): 'trustee_username': 'fake_trustee', 'trustee_password': 'fake_trustee_password', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', - 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', + 'trust_id': '', 'volume_driver': 'volume_driver', 'auth_url': 'http://192.168.10.10:5000/v3', 'region_name': self.mock_osc.cinder_region_name.return_value, diff --git a/magnum/tests/unit/conductor/handlers/test_swarm_cluster_conductor.py b/magnum/tests/unit/conductor/handlers/test_swarm_cluster_conductor.py index 6222e3026b..73986d2791 100644 --- a/magnum/tests/unit/conductor/handlers/test_swarm_cluster_conductor.py +++ b/magnum/tests/unit/conductor/handlers/test_swarm_cluster_conductor.py @@ -68,6 +68,12 @@ class TestClusterConductorWithSwarm(base.TestCase): 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', 'coe_version': 'fake-version' } + + # We need this due to volume_driver=rexray + cfg.CONF.set_override('cluster_user_trust', + True, + group='trust') + osc_patcher = mock.patch('magnum.common.clients.OpenStackClients') self.mock_osc_class = osc_patcher.start() self.addCleanup(osc_patcher.stop) @@ -257,7 +263,7 @@ class TestClusterConductorWithSwarm(base.TestCase): 'trustee_username': 'fake_trustee', 'trustee_password': 'fake_trustee_password', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', - 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de', + 'trust_id': '', 'auth_url': 'http://192.168.10.10:5000/v3', 'swarm_version': 'fake-version', 'rexray_preempt': 'False'