diff options
-rw-r--r-- | ipalib/errors.py | 17 | ||||
-rw-r--r-- | ipalib/plugins/hbac.py | 44 | ||||
-rw-r--r-- | tests/test_xmlrpc/test_hbac_plugin.py | 75 |
3 files changed, 134 insertions, 2 deletions
diff --git a/ipalib/errors.py b/ipalib/errors.py index efd0d640..0d1304e0 100644 --- a/ipalib/errors.py +++ b/ipalib/errors.py @@ -1221,6 +1221,23 @@ class CertificateOperationError(ExecutionError): format = _('Certificate operation cannot be completed: %(error)s') +class MutuallyExclusiveError(ExecutionError): + """ + **4302** Raised when an operation would result in setting two attributes which are mutually exlusive. + + For example: + + >>> raise MutuallyExclusiveError(reason=u'hosts may not be added when hostcategory=all') + Traceback (most recent call last): + ... + MutuallyExclusiveError: hosts may not be added when hostcategory=all + + """ + + errno = 4302 + format = _('%(reason)s') + + ############################################################################## # 5000 - 5999: Generic errors diff --git a/ipalib/plugins/hbac.py b/ipalib/plugins/hbac.py index 94fa7622..00743aed 100644 --- a/ipalib/plugins/hbac.py +++ b/ipalib/plugins/hbac.py @@ -231,6 +231,22 @@ class hbac_mod(LDAPUpdate): Modify an HBAC rule. """ + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + (dn, entry_attrs) = ldap.get_entry(dn, attrs_list) + if 'usercategory' in options and options['usercategory'].lower() == 'all' and \ + 'memberuser' in entry_attrs: + raise errors.MutuallyExclusiveError(reason="user category cannot be set to 'all' while there are allowed users") + if 'hostcategory' in options and options['hostcategory'].lower() == 'all' and \ + 'memberhost' in entry_attrs: + raise errors.MutuallyExclusiveError(reason="host category cannot be set to 'all' while there are allowed hosts") + if 'sourcehostcategory' in options and options['sourcehostcategory'].lower() == 'all' and \ + 'sourcehost' in entry_attrs: + raise errors.MutuallyExclusiveError(reason="sourcehost category cannot be set to 'all' while there are allowed source hosts") + if 'servicecategory' in options and options['servicecategory'].lower() == 'all' and \ + 'memberservice' in entry_attrs: + raise errors.MutuallyExclusiveError(reason="service category cannot be set to 'all' while there are allowed services") + return dn + api.register(hbac_mod) @@ -382,6 +398,13 @@ class hbac_add_user(LDAPAddMember): member_attributes = ['memberuser'] member_count_out = ('%i object added.', '%i objects added.') + def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + (dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) + if 'usercategory' in entry_attrs and \ + entry_attrs['usercategory'][0].lower() == 'all': + raise errors.MutuallyExclusiveError(reason="users cannot be added when user category='all'") + return dn + api.register(hbac_add_user) @@ -402,6 +425,13 @@ class hbac_add_host(LDAPAddMember): member_attributes = ['memberhost'] member_count_out = ('%i object added.', '%i objects added.') + def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + (dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) + if 'hostcategory' in entry_attrs and \ + entry_attrs['hostcategory'][0].lower() == 'all': + raise errors.MutuallyExclusiveError(reason="hosts cannot be added when host category='all'") + return dn + api.register(hbac_add_host) @@ -422,6 +452,13 @@ class hbac_add_sourcehost(LDAPAddMember): member_attributes = ['sourcehost'] member_count_out = ('%i object added.', '%i objects added.') + def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + (dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) + if 'sourcehostcategory' in entry_attrs and \ + entry_attrs['sourcehostcategory'][0].lower() == 'all': + raise errors.MutuallyExclusiveError(reason="source hosts cannot be added when sourcehost category='all'") + return dn + api.register(hbac_add_sourcehost) @@ -442,6 +479,13 @@ class hbac_add_service(LDAPAddMember): member_attributes = ['memberservice'] member_count_out = ('%i object added.', '%i objects added.') + def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + (dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) + if 'servicecategory' in entry_attrs and \ + entry_attrs['servicecategory'][0].lower() == 'all': + raise errors.MutuallyExclusiveError(reason="services cannot be added when service category='all'") + return dn + api.register(hbac_add_service) diff --git a/tests/test_xmlrpc/test_hbac_plugin.py b/tests/test_xmlrpc/test_hbac_plugin.py index d9083741..2405355c 100644 --- a/tests/test_xmlrpc/test_hbac_plugin.py +++ b/tests/test_xmlrpc/test_hbac_plugin.py @@ -306,6 +306,8 @@ class test_hbac(XMLRPC_test): """ Clear data for HBAC plugin testing. """ + api.Command['hbac_remove_host'](self.rule_name, host=self.test_host) + api.Command['hbac_remove_host'](self.rule_name, hostgroup=self.test_hostgroup) api.Command['user_del'](self.test_user) api.Command['group_del'](self.test_group) api.Command['host_del'](self.test_host) @@ -333,9 +335,78 @@ class test_hbac(XMLRPC_test): # FIXME: Should this be 'enabled' or 'TRUE'? assert_attr_equal(entry, 'ipaenabledflag', 'TRUE') - def test_f_hbac_del(self): + def test_f_hbac_exclusiveuser(self): """ - Test deleting a HBAC rule using `xmlrpc.hbac_remove_sourcehost`. + Test adding a user to an HBAC rule when usercat='all' + """ + api.Command['hbac_mod'](self.rule_name, usercategory=u'all') + try: + api.Command['hbac_add_user'](self.rule_name, users='admin') + except errors.MutuallyExclusiveError: + pass + api.Command['hbac_mod'](self.rule_name, usercategory=u'') + + def test_g_hbac_exclusiveuser(self): + """ + Test setting usercat='all' in an HBAC rule when there are users + """ + api.Command['hbac_add_user'](self.rule_name, users='admin') + try: + api.Command['hbac_mod'](self.rule_name, usercategory=u'all') + except errors.MutuallyExclusiveError: + pass + finally: + api.Command['hbac_remove_user'](self.rule_name, users='admin') + + def test_h_hbac_exclusivehost(self): + """ + Test adding a host to an HBAC rule when hostcat='all' + """ + api.Command['hbac_mod'](self.rule_name, hostcategory=u'all') + try: + api.Command['hbac_add_host'](self.rule_name, host=self.test_host) + except errors.MutuallyExclusiveError: + pass + api.Command['hbac_mod'](self.rule_name, hostcategory=u'') + + def test_i_hbac_exclusivehost(self): + """ + Test setting hostcat='all' in an HBAC rule when there are hosts + """ + api.Command['hbac_add_host'](self.rule_name, host=self.test_host) + try: + api.Command['hbac_mod'](self.rule_name, hostcategory=u'all') + except errors.MutuallyExclusiveError: + pass + finally: + api.Command['hbac_remove_host'](self.rule_name, host=self.test_host) + + def test_j_hbac_exclusiveservice(self): + """ + Test adding a service to an HBAC rule when servicecat='all' + """ + api.Command['hbac_mod'](self.rule_name, servicecategory=u'all') + try: + api.Command['hbac_add_host'](self.rule_name, hbacsvc=self.test_service) + except errors.MutuallyExclusiveError: + pass + api.Command['hbac_mod'](self.rule_name, servicecategory=u'') + + def test_k_hbac_exclusiveservice(self): + """ + Test setting servicecat='all' in an HBAC rule when there are services + """ + api.Command['hbac_add_service'](self.rule_name, hbacsvc=self.test_service) + try: + api.Command['hbac_mod'](self.rule_name, servicecategory=u'all') + except errors.MutuallyExclusiveError: + pass + finally: + api.Command['hbac_remove_service'](self.rule_name, hbacsvc=self.test_service) + + def test_z_hbac_del(self): + """ + Test deleting a HBAC rule using `xmlrpc.hbac_del`. """ assert api.Command['hbac_del'](self.rule_name)['result'] is True # verify that it's gone |