Merge "Adding Functional Tests and Supporting Fixes for Global Preferred CAs"
This commit is contained in:
commit
9646c5aa96
@ -76,9 +76,8 @@ class CertificateAuthorityController(controllers.ACLMixin):
|
||||
route_table = {
|
||||
'add-to-project': self.add_to_project,
|
||||
'remove-from-project': self.remove_from_project,
|
||||
'set-preferred': self.set_preferred,
|
||||
'set-global-preferred': self.set_global_preferred,
|
||||
'unset-global-preferred': self.unset_global_preferred,
|
||||
'set-preferred': self.set_preferred,
|
||||
}
|
||||
if name in route_table:
|
||||
return route_table[name]
|
||||
@ -228,17 +227,11 @@ class CertificateAuthorityController(controllers.ACLMixin):
|
||||
if not project_ca:
|
||||
_requested_preferred_ca_not_a_project_ca()
|
||||
|
||||
preferred_ca = self.preferred_ca_repo.get_project_entities(
|
||||
project_model.id)
|
||||
if preferred_ca is not None:
|
||||
self.preferred_ca_repo.update_preferred_ca(project_model.id,
|
||||
self.ca)
|
||||
else:
|
||||
preferred_ca = models.PreferredCertificateAuthority(
|
||||
project_model.id, self.ca.id)
|
||||
self.preferred_ca_repo.create_from(preferred_ca)
|
||||
self.preferred_ca_repo.create_or_update_by_project_id(
|
||||
project_model.id, self.ca.id)
|
||||
|
||||
@pecan.expose()
|
||||
@utils.allow_all_content_types
|
||||
@controllers.handle_exceptions(u._('Set global preferred CA'))
|
||||
@controllers.enforce_rbac('certificate_authority:set_global_preferred')
|
||||
def set_global_preferred(self, external_project_id):
|
||||
@ -246,31 +239,9 @@ class CertificateAuthorityController(controllers.ACLMixin):
|
||||
pecan.abort(405)
|
||||
|
||||
LOG.debug("== Set global preferred CA %s", self.ca.id)
|
||||
pref_ca = self.preferred_ca_repo.get_global_preferred_ca()
|
||||
if pref_ca is None:
|
||||
global_preferred_ca = models.PreferredCertificateAuthority(
|
||||
self.preferred_ca_repo.PREFERRED_PROJECT_ID,
|
||||
self.ca.id)
|
||||
self.preferred_ca_repo.create_from(global_preferred_ca)
|
||||
else:
|
||||
self.preferred_ca_repo.update_global_preferred_ca(self.ca)
|
||||
|
||||
@pecan.expose()
|
||||
@controllers.handle_exceptions(u._('Unset global preferred CA'))
|
||||
@controllers.enforce_rbac('certificate_authority:unset_global_preferred')
|
||||
def unset_global_preferred(self, external_project_id):
|
||||
if pecan.request.method != 'POST':
|
||||
pecan.abort(405)
|
||||
LOG.debug("== Unsetting global preferred CA")
|
||||
self._remove_global_preferred_ca(external_project_id)
|
||||
|
||||
def _remove_global_preferred_ca(self, external_project_id):
|
||||
global_preferred_ca = self.preferred_ca_repo.get_project_entities(
|
||||
self.preferred_ca_repo.PREFERRED_PROJECT_ID)
|
||||
if global_preferred_ca:
|
||||
self.preferred_ca_repo.delete_entity_by_id(
|
||||
global_preferred_ca[0].id,
|
||||
external_project_id)
|
||||
project = res.get_or_create_global_preferred_project()
|
||||
self.preferred_ca_repo.create_or_update_by_project_id(
|
||||
project.id, self.ca.id)
|
||||
|
||||
@index.when(method='DELETE')
|
||||
@utils.allow_all_content_types
|
||||
@ -299,7 +270,8 @@ class CertificateAuthoritiesController(controllers.ACLMixin):
|
||||
route_table = {
|
||||
'all': self.get_all,
|
||||
'global-preferred': self.get_global_preferred,
|
||||
'preferred': self.preferred
|
||||
'preferred': self.preferred,
|
||||
'unset-global-preferred': self.unset_global_preferred,
|
||||
}
|
||||
if name in route_table:
|
||||
return route_table[name]
|
||||
@ -437,13 +409,30 @@ class CertificateAuthoritiesController(controllers.ACLMixin):
|
||||
def get_global_preferred(self, external_project_id, **kw):
|
||||
LOG.debug('Start certificate_authorities get_global_preferred CA')
|
||||
|
||||
pref_ca = self.preferred_ca_repo.get_global_preferred_ca()
|
||||
pref_ca = cert_resources.get_global_preferred_ca()
|
||||
if not pref_ca:
|
||||
pecan.abort(404, u._("No global preferred CA defined"))
|
||||
|
||||
ca = self.ca_repo.get(entity_id=pref_ca.ca_id)
|
||||
return ca.to_dict_fields()
|
||||
|
||||
@pecan.expose()
|
||||
@utils.allow_all_content_types
|
||||
@controllers.handle_exceptions(u._('Unset global preferred CA'))
|
||||
@controllers.enforce_rbac('certificate_authorities:unset_global_preferred')
|
||||
def unset_global_preferred(self, external_project_id):
|
||||
if pecan.request.method != 'POST':
|
||||
pecan.abort(405)
|
||||
LOG.debug("== Unsetting global preferred CA")
|
||||
self._remove_global_preferred_ca(external_project_id)
|
||||
|
||||
def _remove_global_preferred_ca(self, external_project_id):
|
||||
global_preferred_ca = cert_resources.get_global_preferred_ca()
|
||||
if global_preferred_ca:
|
||||
self.preferred_ca_repo.delete_entity_by_id(
|
||||
global_preferred_ca.id,
|
||||
external_project_id)
|
||||
|
||||
@pecan.expose(generic=True, template='json')
|
||||
@utils.allow_all_content_types
|
||||
@controllers.handle_exceptions(u._('Retrieve project preferred CA'))
|
||||
|
@ -23,6 +23,12 @@ from barbican.model import repositories
|
||||
|
||||
LOG = utils.getLogger(__name__)
|
||||
|
||||
GLOBAL_PREFERRED_PROJECT_ID = "GLOBAL_PREFERRED"
|
||||
|
||||
|
||||
def get_or_create_global_preferred_project():
|
||||
return get_or_create_project(GLOBAL_PREFERRED_PROJECT_ID)
|
||||
|
||||
|
||||
def get_or_create_project(project_id):
|
||||
"""Returns project with matching project_id.
|
||||
|
@ -982,7 +982,7 @@ class ProjectCertificateAuthority(BASE, SoftDeleteMixIn, ModelBase):
|
||||
'ca_id': self.ca_id}
|
||||
|
||||
|
||||
class PreferredCertificateAuthority(BASE, SoftDeleteMixIn, ModelBase):
|
||||
class PreferredCertificateAuthority(BASE, ModelBase):
|
||||
"""Stores preferred CAs for any project.
|
||||
|
||||
Admins can define a set of CAs available for issuance requests for
|
||||
|
@ -1635,9 +1635,11 @@ class ProjectCertificateAuthorityRepo(BaseRepo):
|
||||
|
||||
|
||||
class PreferredCertificateAuthorityRepo(BaseRepo):
|
||||
"""Repository for the PreferredCertificateAuthority entity."""
|
||||
"""Repository for the PreferredCertificateAuthority entity.
|
||||
|
||||
PREFERRED_PROJECT_ID = "0"
|
||||
PreferredCertificateAuthority entries are not soft delete. So there is no
|
||||
need to have deleted=False filter in queries.
|
||||
"""
|
||||
|
||||
def get_by_create_date(self, offset_arg=None, limit_arg=None,
|
||||
project_id=None, ca_id=None,
|
||||
@ -1654,7 +1656,6 @@ class PreferredCertificateAuthorityRepo(BaseRepo):
|
||||
|
||||
query = session.query(models.PreferredCertificateAuthority)
|
||||
query = query.order_by(models.PreferredCertificateAuthority.created_at)
|
||||
query = query.filter_by(deleted=False)
|
||||
|
||||
if project_id:
|
||||
query = query.filter(
|
||||
@ -1678,22 +1679,26 @@ class PreferredCertificateAuthorityRepo(BaseRepo):
|
||||
|
||||
return entities, offset, limit, total
|
||||
|
||||
def get_global_preferred_ca(self):
|
||||
pref_cas = self.get_project_entities(self.PREFERRED_PROJECT_ID)
|
||||
if len(pref_cas) > 0:
|
||||
return pref_cas[0]
|
||||
return None
|
||||
def create_or_update_by_project_id(self, project_id, ca_id, session=None):
|
||||
"""Create or update preferred CA for a project by project_id.
|
||||
|
||||
def update_global_preferred_ca(self, new_ca):
|
||||
self.update_preferred_ca(self.PREFERRED_PROJECT_ID, new_ca)
|
||||
|
||||
def update_preferred_ca(self, project_id, new_ca):
|
||||
session = self.get_session()
|
||||
query = session.query(models.PreferredCertificateAuthority).filter_by(
|
||||
project_id=project_id)
|
||||
entity = query.one()
|
||||
entity.ca_id = new_ca.id
|
||||
entity.save()
|
||||
:param project_id: ID of project whose preferred CA will be saved
|
||||
:param ca_id: ID of preferred CA
|
||||
:param session: SQLAlchemy session object.
|
||||
:return: None
|
||||
"""
|
||||
session = self.get_session(session)
|
||||
query = session.query(models.PreferredCertificateAuthority)
|
||||
query = query.filter_by(project_id=project_id)
|
||||
try:
|
||||
entity = query.one()
|
||||
except sa_orm.exc.NoResultFound:
|
||||
self.create_from(
|
||||
models.PreferredCertificateAuthority(project_id, ca_id),
|
||||
session=session)
|
||||
else:
|
||||
entity.ca_id = ca_id
|
||||
entity.save(session)
|
||||
|
||||
def _do_entity_name(self):
|
||||
"""Sub-class hook: return entity name, such as for debugging."""
|
||||
@ -1715,7 +1720,7 @@ class PreferredCertificateAuthorityRepo(BaseRepo):
|
||||
:param session: existing db session reference.
|
||||
"""
|
||||
return session.query(models.PreferredCertificateAuthority).filter_by(
|
||||
project_id=project_id).filter_by(deleted=False)
|
||||
project_id=project_id)
|
||||
|
||||
|
||||
class SecretACLRepo(BaseRepo):
|
||||
|
@ -18,6 +18,7 @@ from OpenSSL import crypto
|
||||
|
||||
from barbican.common import exception as excep
|
||||
from barbican.common import hrefs
|
||||
from barbican.common import resources as res
|
||||
import barbican.common.utils as utils
|
||||
from barbican.model import models
|
||||
from barbican.model import repositories as repos
|
||||
@ -315,6 +316,16 @@ def modify_certificate_request(order_model, updated_meta):
|
||||
raise NotImplementedError # pragma: no cover
|
||||
|
||||
|
||||
def get_global_preferred_ca():
|
||||
project = res.get_or_create_global_preferred_project()
|
||||
preferred_ca_repository = repos.get_preferred_ca_repository()
|
||||
cas = preferred_ca_repository.get_project_entities(project.id)
|
||||
if not cas:
|
||||
return None
|
||||
else:
|
||||
return cas[0]
|
||||
|
||||
|
||||
def _get_ca_id(order_meta, project_id):
|
||||
ca_id = order_meta.get(cert.CA_ID)
|
||||
if ca_id:
|
||||
@ -326,7 +337,7 @@ def _get_ca_id(order_meta, project_id):
|
||||
if total > 0:
|
||||
return cas[0].ca_id
|
||||
|
||||
global_ca = preferred_ca_repository.get_global_preferred_ca()
|
||||
global_ca = get_global_preferred_ca()
|
||||
if global_ca:
|
||||
return global_ca.ca_id
|
||||
|
||||
|
@ -352,23 +352,17 @@ class WhenTestingCAsResource(utils.BarbicanAPIBaseTestCase):
|
||||
|
||||
def test_should_unset_global_preferred(self):
|
||||
self.create_cas()
|
||||
resp = self.app.post('/cas/{0}/unset-global-preferred'.format(
|
||||
self.global_preferred_ca.id))
|
||||
resp = self.app.post(
|
||||
'/cas/unset-global-preferred')
|
||||
self.assertEqual(204, resp.status_int)
|
||||
|
||||
def test_should_unset_global_preferred_not_post(self):
|
||||
self.create_cas()
|
||||
resp = self.app.get(
|
||||
'/cas/{0}/unset-global-preferred'.format(self.selected_ca_id),
|
||||
'/cas/unset-global-preferred',
|
||||
expect_errors=True)
|
||||
self.assertEqual(405, resp.status_int)
|
||||
|
||||
def test_should_raise_unset_global_preferred_ca_not_found(self):
|
||||
resp = self.app.post(
|
||||
'/cas/bogus_ca/unset-global-preferred',
|
||||
expect_errors=True)
|
||||
self.assertEqual(404, resp.status_int)
|
||||
|
||||
def test_should_get_projects(self):
|
||||
self.create_cas()
|
||||
resp = self.app.get(
|
||||
@ -456,6 +450,7 @@ class WhenTestingCAsResource(utils.BarbicanAPIBaseTestCase):
|
||||
|
||||
def create_cas(self, set_project_cas=True):
|
||||
self.project = res.get_or_create_project(self.project_id)
|
||||
self.global_project = res.get_or_create_global_preferred_project()
|
||||
project_repo.save(self.project)
|
||||
self.project_ca_ids = []
|
||||
|
||||
@ -505,7 +500,7 @@ class WhenTestingCAsResource(utils.BarbicanAPIBaseTestCase):
|
||||
if ca_id == 1:
|
||||
# set global preferred ca
|
||||
pref_ca = models.PreferredCertificateAuthority(
|
||||
preferred_ca_repo.PREFERRED_PROJECT_ID,
|
||||
self.global_project.id,
|
||||
ca.id)
|
||||
preferred_ca_repo.create_from(pref_ca)
|
||||
preferred_ca_repo.save(pref_ca)
|
||||
|
@ -13,6 +13,7 @@
|
||||
import datetime
|
||||
|
||||
from barbican.common import exception
|
||||
from barbican.common import resources as res
|
||||
from barbican.model import models
|
||||
from barbican.model import repositories
|
||||
from barbican.tests import database_utils
|
||||
@ -334,6 +335,8 @@ class WhenTestingPreferredCARepo(database_utils.RepositoryTestCase):
|
||||
'ca_signing_certificate': 'XXXXX-updated-XXXXX',
|
||||
'intermediates': 'YYYYY'}
|
||||
|
||||
self.global_project = res.get_or_create_global_preferred_project()
|
||||
|
||||
def _add_ca(self, parsed_ca, session):
|
||||
ca = self.ca_repo.create_from(models.CertificateAuthority(parsed_ca),
|
||||
session=session)
|
||||
@ -354,7 +357,7 @@ class WhenTestingPreferredCARepo(database_utils.RepositoryTestCase):
|
||||
def _add_global_preferred_ca(self, ca_id, session):
|
||||
preferred_ca = self.preferred_ca_repo.create_from(
|
||||
models.PreferredCertificateAuthority(
|
||||
self.preferred_ca_repo.PREFERRED_PROJECT_ID,
|
||||
self.global_project.id,
|
||||
ca_id),
|
||||
session)
|
||||
return preferred_ca
|
||||
@ -460,13 +463,28 @@ class WhenTestingPreferredCARepo(database_utils.RepositoryTestCase):
|
||||
session.commit()
|
||||
|
||||
pca = self.preferred_ca_repo.get_project_entities(
|
||||
self.preferred_ca_repo.PREFERRED_PROJECT_ID,
|
||||
self.global_project.id,
|
||||
session)
|
||||
self.assertEqual([ca.id], [s.ca_id for s in pca])
|
||||
|
||||
def test_should_update(self):
|
||||
def test_should_create(self):
|
||||
session = self.ca_repo.get_session()
|
||||
ca = self._add_ca(self.parsed_ca, session)
|
||||
project = self._add_project("project_1", session)
|
||||
|
||||
self.preferred_ca_repo.create_or_update_by_project_id(
|
||||
project.id, ca.id)
|
||||
session.commit()
|
||||
|
||||
self.ca_repo.update_entity(ca, self.parsed_modified_ca, session)
|
||||
def test_should_update(self):
|
||||
session = self.ca_repo.get_session()
|
||||
ca1 = self._add_ca(self.parsed_ca, session)
|
||||
ca2 = self._add_ca(self.parsed_ca2, session)
|
||||
project = self._add_project("project_1", session)
|
||||
|
||||
self.preferred_ca_repo.create_or_update_by_project_id(
|
||||
project.id, ca1.id)
|
||||
session.commit()
|
||||
self.preferred_ca_repo.create_or_update_by_project_id(
|
||||
project.id, ca2.id)
|
||||
session.commit()
|
||||
|
@ -55,6 +55,7 @@
|
||||
"certificate_authorities:post": "rule:admin",
|
||||
"certificate_authorities:get_preferred_ca": "rule:all_users",
|
||||
"certificate_authorities:get_global_preferred_ca": "rule:service_admin",
|
||||
"certificate_authorities:unset_global_preferred": "rule:service_admin",
|
||||
"certificate_authority:delete": "rule:admin",
|
||||
"certificate_authority:get": "rule:all_users",
|
||||
"certificate_authority:get_cacert": "rule:all_users",
|
||||
@ -64,7 +65,6 @@
|
||||
"certificate_authority:remove_from_project": "rule:admin",
|
||||
"certificate_authority:set_preferred": "rule:admin",
|
||||
"certificate_authority:set_global_preferred": "rule:service_admin",
|
||||
"certificate_authority:unset_global_preferred": "rule:service_admin",
|
||||
"secret_acls:put_patch": "rule:secret_project_admin or rule:secret_project_creator",
|
||||
"secret_acls:delete": "rule:secret_project_admin or rule:secret_project_creator",
|
||||
"secret_acls:get": "rule:all_but_audit and rule:secret_project_match",
|
||||
|
@ -154,3 +154,24 @@ class CABehaviors(base_behaviors.BaseBehaviors):
|
||||
response_model_type=ca_models.CAModel,
|
||||
extra_headers=extra_headers, use_auth=use_auth,
|
||||
user_name=user_name)
|
||||
|
||||
def set_global_preferred(self, ca_ref, headers=None,
|
||||
use_auth=True, user_name=None):
|
||||
resp = self.client.post(ca_ref + '/set-global-preferred',
|
||||
extra_headers=headers, use_auth=use_auth,
|
||||
user_name=user_name)
|
||||
return resp
|
||||
|
||||
def unset_global_preferred(self, headers=None,
|
||||
use_auth=True, user_name=None):
|
||||
resp = self.client.post('cas/unset-global-preferred',
|
||||
extra_headers=headers,
|
||||
use_auth=use_auth, user_name=user_name)
|
||||
return resp
|
||||
|
||||
def get_global_preferred(self, extra_headers=None,
|
||||
use_auth=True, user_name=None):
|
||||
return self.client.get('cas/global-preferred',
|
||||
response_model_type=ca_models.CAModel,
|
||||
extra_headers=extra_headers,
|
||||
use_auth=use_auth, user_name=user_name)
|
||||
|
@ -34,6 +34,7 @@ CONF = config.get_config()
|
||||
|
||||
admin_a = CONF.rbac_users.admin_a
|
||||
creator_a = CONF.rbac_users.creator_a
|
||||
service_admin = CONF.identity.service_admin
|
||||
|
||||
order_simple_cmc_request_data = {
|
||||
'type': 'certificate',
|
||||
@ -321,3 +322,76 @@ class ProjectCATestCase(CATestCommon):
|
||||
# before)
|
||||
(resp, cas, final_total, _, __) = self.ca_behaviors.get_cas()
|
||||
self.assertEqual(initial_total, final_total)
|
||||
|
||||
|
||||
class GlobalPreferredCATestCase(CATestCommon):
|
||||
|
||||
def setUp(self):
|
||||
super(GlobalPreferredCATestCase, self).setUp()
|
||||
(_, self.cas, self.num_cas, _, _) = self.ca_behaviors.get_cas()
|
||||
self.ca_ids = [hrefs.get_ca_id_from_ref(ref) for ref in self.cas]
|
||||
|
||||
def tearDown(self):
|
||||
self.ca_behaviors.unset_global_preferred(user_name=service_admin)
|
||||
super(CATestCommon, self).tearDown()
|
||||
|
||||
def test_global_preferred_no_project_admin_access(self):
|
||||
resp = self.ca_behaviors.get_global_preferred()
|
||||
self.assertEqual(403, resp.status_code)
|
||||
resp = self.ca_behaviors.set_global_preferred(ca_ref=self.cas[1])
|
||||
self.assertEqual(403, resp.status_code)
|
||||
resp = self.ca_behaviors.unset_global_preferred()
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
def test_global_preferred_update(self):
|
||||
if self.num_cas < 2:
|
||||
self.skipTest("At least two CAs are required for this test")
|
||||
resp = self.ca_behaviors.set_global_preferred(
|
||||
ca_ref=self.cas[0], user_name=service_admin)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
resp = self.ca_behaviors.get_global_preferred(user_name=service_admin)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(self.ca_ids[0], resp.model.ca_id)
|
||||
|
||||
resp = self.ca_behaviors.set_global_preferred(
|
||||
ca_ref=self.cas[1], user_name=service_admin)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
resp = self.ca_behaviors.get_global_preferred(user_name=service_admin)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(self.ca_ids[1], resp.model.ca_id)
|
||||
|
||||
def test_global_preferred_set_and_unset(self):
|
||||
resp = self.ca_behaviors.unset_global_preferred(
|
||||
user_name=service_admin)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
resp = self.ca_behaviors.get_global_preferred(user_name=service_admin)
|
||||
self.assertEqual(404, resp.status_code)
|
||||
|
||||
resp = self.ca_behaviors.set_global_preferred(
|
||||
ca_ref=self.cas[0], user_name=service_admin)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
resp = self.ca_behaviors.get_global_preferred(user_name=service_admin)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(self.ca_ids[0], resp.model.ca_id)
|
||||
|
||||
resp = self.ca_behaviors.unset_global_preferred(
|
||||
user_name=service_admin)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
resp = self.ca_behaviors.get_global_preferred(user_name=service_admin)
|
||||
self.assertEqual(404, resp.status_code)
|
||||
|
||||
@testtools.skip("Skip test until ca behaviors tracks project cas")
|
||||
def test_global_preferred_affects_project_preferred(self):
|
||||
if self.num_cas < 2:
|
||||
self.skipTest("At least two CAs are required for this test")
|
||||
resp = self.ca_behaviors.get_preferred(user_name=admin_a)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(self.ca_ids[0], resp.model.ca_id)
|
||||
|
||||
resp = self.ca_behaviors.set_global_preferred(
|
||||
ca_ref=self.cas[1], user_name=service_admin)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
|
||||
resp = self.ca_behaviors.get_preferred(user_name=admin_a)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(self.ca_ids[1], resp.model.ca_id)
|
||||
|
@ -29,7 +29,7 @@ retval=$?
|
||||
testr slowest
|
||||
|
||||
# run the tests in parallel
|
||||
SKIP=^\(\?\!\.\*\(ProjectQuotasPagingTestCase\|QuotaEnforcementTestCase\|ListingCAsTestCase\|ProjectCATestCase\)\)
|
||||
SKIP=^\(\?\!\.\*\(ProjectQuotasPagingTestCase\|QuotaEnforcementTestCase\|ListingCAsTestCase\|ProjectCATestCase\|GlobalPreferredCATestCase\)\)
|
||||
testr init
|
||||
testr run $SKIP --parallel --subunit | subunit-trace --no-failure-debug -f
|
||||
retval=$(($retval || $?))
|
||||
|
Loading…
Reference in New Issue
Block a user