ca-del: require CA to already be disabled

Currently ca-del disables the target CA before deleting it.
Conceptually, this involves two separate permissions: modify and
delete.  A user with delete permission does not necessarily have
modify permission.

As we head toward enforcing IPA permissions in Dogtag, it is
necessary to decouple disablement from deletion, otherwise the
disable operation shall fail if the user does not have modify
permission.  Although it introduces an additional step for
administrators, the process is consistent, required permissions map
1:1 to the operations, and the error messages make it clear what
needs to happen (i.e. disable first).

Part of: https://fedorahosted.org/freeipa/ticket/5011

Reviewed-By: Rob Crittenden <rcritten@redhat.com>
This commit is contained in:
Fraser Tweedale 2017-01-23 11:37:37 +10:00 committed by Rob Crittenden
parent 80794f6b5e
commit 5ab24ddf8a
3 changed files with 32 additions and 4 deletions

View File

@ -342,7 +342,12 @@ class ca_del(LDAPDelete):
ca_id = self.api.Command.ca_show(keys[0])['result']['ipacaid'][0]
with self.api.Backend.ra_lightweight_ca as ca_api:
ca_api.disable_ca(ca_id)
data = ca_api.read_ca(ca_id)
if data['enabled']:
raise errors.ProtectedEntryError(
label=_("CA"),
key=keys[0],
reason=_("Must be disabled first"))
ca_api.delete_ca(ca_id)
return dn

View File

@ -78,7 +78,13 @@ class TestDefaultCA(XMLRPC_test):
def test_default_ca_present(self, default_ca):
default_ca.retrieve()
def test_default_ca_disable(self, default_ca):
"""IPA CA cannot be disabled."""
with pytest.raises(errors.ProtectedEntryError):
default_ca.disable()
def test_default_ca_delete(self, default_ca):
"""IPA CA cannot be deleted."""
with pytest.raises(errors.ProtectedEntryError):
default_ca.delete()
@ -104,7 +110,14 @@ class TestCAbasicCRUD(XMLRPC_test):
)
command()
def test_delete(self, crud_subca):
def test_delete_while_enabled_fails(self, crud_subca):
with pytest.raises(errors.ProtectedEntryError):
crud_subca.delete()
def test_disable(self, crud_subca):
crud_subca.disable()
def test_delete_after_disable_succeeds(self, crud_subca):
crud_subca.delete()
def test_find(self, crud_subca):

View File

@ -6,7 +6,7 @@ from __future__ import absolute_import
import six
from ipapython.dn import DN
from ipatests.test_xmlrpc.tracker.base import Tracker
from ipatests.test_xmlrpc.tracker.base import Tracker, EnableTracker
from ipatests.util import assert_deepequal
from ipatests.test_xmlrpc.xmlrpc_test import (
fuzzy_issuer,
@ -22,7 +22,7 @@ if six.PY3:
unicode = str
class CATracker(Tracker):
class CATracker(Tracker, EnableTracker):
"""Implementation of a Tracker class for CA plugin."""
ldap_keys = {
@ -80,6 +80,16 @@ class CATracker(Tracker):
)
self.exists = True
def make_disable_command(self):
return self.make_command('ca_disable', self.name)
def check_disable(self, result):
assert_deepequal(dict(
result=True,
value=self.name,
summary=f'Disabled CA "{self.name}"',
), result)
def make_delete_command(self):
"""Make function that deletes the plugin entry object."""
return self.make_command('ca_del', self.name)