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
(cherry picked from commit 8bbf06caae
)
This commit is contained in:
parent
588e5d3c48
commit
6845b19f99
|
@ -17,6 +17,7 @@ from six.moves.urllib import parse
|
||||||
|
|
||||||
from barbican import api
|
from barbican import api
|
||||||
from barbican.api import controllers
|
from barbican.api import controllers
|
||||||
|
from barbican.common import exception as excep
|
||||||
from barbican.common import hrefs
|
from barbican.common import hrefs
|
||||||
from barbican.common import quota
|
from barbican.common import quota
|
||||||
from barbican.common import resources as res
|
from barbican.common import resources as res
|
||||||
|
@ -144,6 +145,11 @@ class CertificateAuthorityController(controllers.ACLMixin):
|
||||||
self.ca.id, external_project_id)
|
self.ca.id, external_project_id)
|
||||||
project_model = res.get_or_create_project(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
|
project_cas = project_model.cas
|
||||||
num_cas = len(project_cas)
|
num_cas = len(project_cas)
|
||||||
for project_ca in 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:
|
if not parent_ca:
|
||||||
raise excep.InvalidParentCA(parent_ca_ref=parent_ca_ref)
|
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
|
# get the parent plugin, raises CertPluginNotFound if missing
|
||||||
cert_plugin = cert.CertificatePluginManager().get_plugin_by_name(
|
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)
|
'/cas/bogus_ca/add-to-project', expect_errors=True)
|
||||||
self.assertEqual(404, resp.status_int)
|
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):
|
def test_should_raise_add_to_project_not_post(self):
|
||||||
self.create_cas()
|
self.create_cas()
|
||||||
resp = self.app.get(
|
resp = self.app.get(
|
||||||
|
|
|
@ -908,6 +908,26 @@ class WhenCreatingSubordinateCAs(utils.BaseTestCase):
|
||||||
creator_id=self.creator_id
|
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):
|
def test_should_raise_subcas_not_supported(self):
|
||||||
self.cert_plugin.supports_create_ca.return_value = False
|
self.cert_plugin.supports_create_ca.return_value = False
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
|
|
|
@ -252,6 +252,30 @@ class CertificateAuthoritiesTestCase(CATestCommon):
|
||||||
resp = self.ca_behaviors.delete_ca(ca_ref=parent_ref)
|
resp = self.ca_behaviors.delete_ca(ca_ref=parent_ref)
|
||||||
self.assertEqual(204, resp.status_code)
|
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):
|
def test_create_subca_with_invalid_parent_ca_id(self):
|
||||||
ca_model = self.get_subca_model(
|
ca_model = self.get_subca_model(
|
||||||
'http://localhost:9311/cas/invalid_ref'
|
'http://localhost:9311/cas/invalid_ref'
|
||||||
|
@ -332,6 +356,30 @@ class CertificateAuthoritiesTestCase(CATestCommon):
|
||||||
resp = self.ca_behaviors.get_preferred(user_name=admin_a)
|
resp = self.ca_behaviors.get_preferred(user_name=admin_a)
|
||||||
self.assertEqual(404, resp.status_code)
|
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')
|
@depends_on_ca_plugins('snakeoil_ca')
|
||||||
def test_create_and_delete_snakeoil_subca(self):
|
def test_create_and_delete_snakeoil_subca(self):
|
||||||
self._create_and_delete_subca(
|
self._create_and_delete_subca(
|
||||||
|
|
Loading…
Reference in New Issue