Enforce project ownership of subCAs
The add-to-project and create CA commands can only be performed by a project administrator when the target CA is either a root CA or a subCA owned by the admin's project. This CR adds checks to enforce this condition. Change-Id: Ifbd7bb471b137a5549a8e627344f8f02adda2ed1 Closes-bug: #1501862
This commit is contained in:
parent
4afaee095a
commit
8bbf06caae
|
@ -17,6 +17,7 @@ from six.moves.urllib import parse
|
|||
|
||||
from barbican import api
|
||||
from barbican.api import controllers
|
||||
from barbican.common import exception as excep
|
||||
from barbican.common import hrefs
|
||||
from barbican.common import quota
|
||||
from barbican.common import resources as res
|
||||
|
@ -144,6 +145,11 @@ class CertificateAuthorityController(controllers.ACLMixin):
|
|||
self.ca.id, external_project_id)
|
||||
project_model = res.get_or_create_project(external_project_id)
|
||||
|
||||
# CA must be a base CA or a subCA owned by this project
|
||||
if (self.ca.project_id is not None and
|
||||
self.ca.project_id != project_model.id):
|
||||
raise excep.UnauthorizedSubCA()
|
||||
|
||||
project_cas = project_model.cas
|
||||
num_cas = len(project_cas)
|
||||
for project_ca in project_cas:
|
||||
|
|
|
@ -200,7 +200,10 @@ def create_subordinate_ca(project_model, name, description, subject_dn,
|
|||
if not parent_ca:
|
||||
raise excep.InvalidParentCA(parent_ca_ref=parent_ca_ref)
|
||||
|
||||
# TODO(alee) check if the parent_ca is accessible for this project
|
||||
# Parent CA must be a base CA or a subCA owned by this project
|
||||
if (parent_ca.project_id is not None and
|
||||
parent_ca.project_id != project_model.id):
|
||||
raise excep.UnauthorizedSubCA()
|
||||
|
||||
# get the parent plugin, raises CertPluginNotFound if missing
|
||||
cert_plugin = cert.CertificatePluginManager().get_plugin_by_name(
|
||||
|
|
|
@ -257,6 +257,16 @@ class WhenTestingCAsResource(utils.BarbicanAPIBaseTestCase):
|
|||
'/cas/bogus_ca/add-to-project', expect_errors=True)
|
||||
self.assertEqual(404, resp.status_int)
|
||||
|
||||
def test_should_raise_add_to_project_on_ca_not_owned_by_project(self):
|
||||
self.create_cas()
|
||||
self.app.extra_environ = {
|
||||
'barbican.context': self._build_context("other_project",
|
||||
user="user1")
|
||||
}
|
||||
resp = self.app.post('/cas/{0}/add-to-project'.format(
|
||||
self.subca.id), expect_errors=True)
|
||||
self.assertEqual(403, resp.status_int)
|
||||
|
||||
def test_should_raise_add_to_project_not_post(self):
|
||||
self.create_cas()
|
||||
resp = self.app.get(
|
||||
|
|
|
@ -908,6 +908,26 @@ class WhenCreatingSubordinateCAs(utils.BaseTestCase):
|
|||
creator_id=self.creator_id
|
||||
)
|
||||
|
||||
def test_should_raise_unauthorized_parent_ca(self):
|
||||
subca = cert_res.create_subordinate_ca(
|
||||
project_model=self.project2,
|
||||
name=self.name,
|
||||
description=self.description,
|
||||
subject_dn=self.subject_name,
|
||||
parent_ca_ref=self.parent_ca_ref,
|
||||
creator_id=self.creator_id
|
||||
)
|
||||
subca_ref = hrefs.convert_certificate_authority_to_href(subca.id)
|
||||
self.assertRaises(
|
||||
excep.UnauthorizedSubCA,
|
||||
cert_res.create_subordinate_ca,
|
||||
project_model=self.project,
|
||||
name=self.name,
|
||||
description=self.description,
|
||||
subject_dn=self.subject_name,
|
||||
parent_ca_ref=subca_ref,
|
||||
creator_id=self.creator_id)
|
||||
|
||||
def test_should_raise_subcas_not_supported(self):
|
||||
self.cert_plugin.supports_create_ca.return_value = False
|
||||
self.assertRaises(
|
||||
|
|
|
@ -252,6 +252,30 @@ class CertificateAuthoritiesTestCase(CATestCommon):
|
|||
resp = self.ca_behaviors.delete_ca(ca_ref=parent_ref)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
|
||||
@depends_on_ca_plugins('snakeoil_ca')
|
||||
def test_fail_to_create_subca_of_snakeoil_not_owned_subca(self):
|
||||
self._fail_to_create_subca_of_not_owned_subca(
|
||||
self.get_snakeoil_root_ca_ref())
|
||||
|
||||
@testtools.skipIf(not dogtag_subcas_enabled, "dogtag subcas not enabled")
|
||||
@depends_on_ca_plugins('dogtag')
|
||||
def test_fail_to_create_subca_of_dogtag_not_owned_subca(self):
|
||||
self._fail_to_create_subca_of_not_owned_subca(
|
||||
self.get_dogtag_root_ca_ref())
|
||||
|
||||
def _fail_to_create_subca_of_not_owned_subca(self, root_ca_ref):
|
||||
parent_model = self.get_subca_model(root_ca_ref)
|
||||
resp, parent_ref = self.ca_behaviors.create_ca(parent_model)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
|
||||
child_model = self.get_sub_subca_model(parent_ref)
|
||||
resp, child_ref = self.ca_behaviors.create_ca(child_model,
|
||||
user_name=admin_a)
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
resp = self.ca_behaviors.delete_ca(ca_ref=parent_ref)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
|
||||
def test_create_subca_with_invalid_parent_ca_id(self):
|
||||
ca_model = self.get_subca_model(
|
||||
'http://localhost:9311/cas/invalid_ref'
|
||||
|
@ -332,6 +356,30 @@ class CertificateAuthoritiesTestCase(CATestCommon):
|
|||
resp = self.ca_behaviors.get_preferred(user_name=admin_a)
|
||||
self.assertEqual(404, resp.status_code)
|
||||
|
||||
@depends_on_ca_plugins('snakeoil_ca')
|
||||
def test_try_and_fail_to_add_to_proj_snakeoil_subca_that_is_not_mine(self):
|
||||
self._try_and_fail_to_add_to_proj_subca_that_is_not_mine(
|
||||
self.get_snakeoil_root_ca_ref()
|
||||
)
|
||||
|
||||
@testtools.skipIf(not dogtag_subcas_enabled, "dogtag subcas not enabled")
|
||||
@depends_on_ca_plugins('dogtag')
|
||||
def test_try_and_fail_to_add_to_proj_dogtag_subca_that_is_not_mine(self):
|
||||
self._try_and_fail_to_add_to_proj_subca_that_is_not_mine(
|
||||
self.get_dogtag_root_ca_ref()
|
||||
)
|
||||
|
||||
def _try_and_fail_to_add_to_proj_subca_that_is_not_mine(self, root_ca_ref):
|
||||
ca_model = self.get_subca_model(root_ca_ref)
|
||||
resp, ca_ref = self.ca_behaviors.create_ca(ca_model, user_name=admin_a)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
|
||||
resp = self.ca_behaviors.add_ca_to_project(ca_ref, user_name=admin_b)
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
resp = self.ca_behaviors.delete_ca(ca_ref=ca_ref, user_name=admin_a)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
|
||||
@depends_on_ca_plugins('snakeoil_ca')
|
||||
def test_create_and_delete_snakeoil_subca(self):
|
||||
self._create_and_delete_subca(
|
||||
|
|
Loading…
Reference in New Issue