Merge "Handle auto-generated domains when creating IdPs"
This commit is contained in:
commit
0d554db265
@ -60,11 +60,27 @@ class Manager(manager.Manager):
|
|||||||
super(Manager, self).__init__(CONF.federation.driver)
|
super(Manager, self).__init__(CONF.federation.driver)
|
||||||
|
|
||||||
def create_idp(self, idp_id, idp):
|
def create_idp(self, idp_id, idp):
|
||||||
|
auto_created_domain = False
|
||||||
if not idp.get('domain_id'):
|
if not idp.get('domain_id'):
|
||||||
idp['domain_id'] = self._create_idp_domain(idp_id)
|
idp['domain_id'] = self._create_idp_domain(idp_id)
|
||||||
|
auto_created_domain = True
|
||||||
else:
|
else:
|
||||||
self._assert_valid_domain_id(idp['domain_id'])
|
self._assert_valid_domain_id(idp['domain_id'])
|
||||||
return self.driver.create_idp(idp_id, idp)
|
|
||||||
|
try:
|
||||||
|
return self.driver.create_idp(idp_id, idp)
|
||||||
|
except exception.Conflict:
|
||||||
|
# If there is a conflict storing the Identity Provider in the
|
||||||
|
# backend, then we need to make sure we clean up the domain we just
|
||||||
|
# created for it and raise the Conflict exception afterwards.
|
||||||
|
if auto_created_domain:
|
||||||
|
self._cleanup_idp_domain(idp['domain_id'])
|
||||||
|
raise
|
||||||
|
|
||||||
|
def _cleanup_idp_domain(self, domain_id):
|
||||||
|
domain = {'enabled': False}
|
||||||
|
self.resource_api.update_domain(domain_id, domain)
|
||||||
|
self.resource_api.delete_domain(domain_id)
|
||||||
|
|
||||||
def _create_idp_domain(self, idp_id):
|
def _create_idp_domain(self, idp_id):
|
||||||
domain_id = uuid.uuid4().hex
|
domain_id = uuid.uuid4().hex
|
||||||
|
@ -912,8 +912,7 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||||||
attr = self._fetch_attribute_from_response(resp, 'identity_provider')
|
attr = self._fetch_attribute_from_response(resp, 'identity_provider')
|
||||||
self.assertIdpDomainCreated(attr['id'], attr['domain_id'])
|
self.assertIdpDomainCreated(attr['id'], attr['domain_id'])
|
||||||
|
|
||||||
@utils.wip('This will fail because of bug #1688188')
|
def test_conflicting_idp_cleans_up_auto_generated_domain(self):
|
||||||
def test_conflicting_idp_results_in_unhandled_domain_cleanup(self):
|
|
||||||
# NOTE(lbragstad): Create an identity provider, save its ID, and count
|
# NOTE(lbragstad): Create an identity provider, save its ID, and count
|
||||||
# the number of domains.
|
# the number of domains.
|
||||||
resp = self._create_default_idp()
|
resp = self._create_default_idp()
|
||||||
@ -925,8 +924,8 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||||||
# conflict, this is going to result in a domain getting created for the
|
# conflict, this is going to result in a domain getting created for the
|
||||||
# new identity provider. The domain for the new identity provider is
|
# new identity provider. The domain for the new identity provider is
|
||||||
# going to be created before the conflict is raised from the database
|
# going to be created before the conflict is raised from the database
|
||||||
# layer. The resulting domain is never cleaned up but it should be
|
# layer. This makes sure the domain is cleaned up after a Conflict is
|
||||||
# since the identity provider was never created.
|
# detected.
|
||||||
resp = self.put(
|
resp = self.put(
|
||||||
self.base_url(suffix=idp_id),
|
self.base_url(suffix=idp_id),
|
||||||
body={'identity_provider': self.default_body.copy()},
|
body={'identity_provider': self.default_body.copy()},
|
||||||
@ -935,6 +934,35 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||||||
domains = self.resource_api.list_domains()
|
domains = self.resource_api.list_domains()
|
||||||
self.assertEqual(number_of_domains, len(domains))
|
self.assertEqual(number_of_domains, len(domains))
|
||||||
|
|
||||||
|
def test_conflicting_idp_does_not_delete_existing_domain(self):
|
||||||
|
# Create a new domain
|
||||||
|
domain = unit.new_domain_ref()
|
||||||
|
self.resource_api.create_domain(domain['id'], domain)
|
||||||
|
|
||||||
|
# Create an identity provider and specify the domain
|
||||||
|
body = self.default_body.copy()
|
||||||
|
body['description'] = uuid.uuid4().hex
|
||||||
|
body['domain_id'] = domain['id']
|
||||||
|
resp = self._create_default_idp(body=body)
|
||||||
|
idp = resp.json_body['identity_provider']
|
||||||
|
idp_id = idp['id']
|
||||||
|
self.assertEqual(idp['domain_id'], domain['id'])
|
||||||
|
|
||||||
|
# Create an identity provider with the same domain and ID to ensure a
|
||||||
|
# Conflict is raised and then to verify the existing domain not deleted
|
||||||
|
# below
|
||||||
|
body = self.default_body.copy()
|
||||||
|
body['domain_id'] = domain['id']
|
||||||
|
resp = self.put(
|
||||||
|
self.base_url(suffix=idp_id),
|
||||||
|
body={'identity_provider': body},
|
||||||
|
expected_status=http_client.CONFLICT
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make sure the domain specified in the second request was not deleted,
|
||||||
|
# since it wasn't auto-generated
|
||||||
|
self.assertIsNotNone(self.resource_api.get_domain(domain['id']))
|
||||||
|
|
||||||
def test_create_idp_domain_id_unique_constraint(self):
|
def test_create_idp_domain_id_unique_constraint(self):
|
||||||
# create domain and add domain_id to keys to check
|
# create domain and add domain_id to keys to check
|
||||||
domain = unit.new_domain_ref()
|
domain = unit.new_domain_ref()
|
||||||
|
7
releasenotes/notes/bug_1688188-256e3572295231a1.yaml
Normal file
7
releasenotes/notes/bug_1688188-256e3572295231a1.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
[`bug 1688188 <https://bugs.launchpad.net/keystone/+bug/1688188>`_]
|
||||||
|
When creating an IdP, if a domain was generated for it and a conflict
|
||||||
|
was raised while effectively creating the IdP in the database, the
|
||||||
|
auto-generated domain is now cleaned up.
|
Loading…
Reference in New Issue
Block a user