def test_delete_an_operational_attribute_with_delattr(self, user): """ Try to delete an operational attribute with --delattr """ command = user.make_command( 'config_mod', **dict(delattr=u'creatorsName=cn=directory manager')) with raises_exact( errors.DatabaseError(desc='Server is unwilling to perform', info='')): command()
def execute(self, *keys, **options): ldap = self.api.Backend.ldap2 cn = str(uuid.uuid4()) gtype = options.get('type') if not gtype: gtype = 'group' if options.get('users') else 'hostgroup' types = { 'group': ('user', 'users', DN(api.env.container_user, api.env.basedn)), 'hostgroup': ('host', 'hosts', DN(api.env.container_host, api.env.basedn)), } obj_name, opt_name, basedn = types[gtype] obj = self.api.Object[obj_name] names = options.get(opt_name) if names: for name in names: try: obj.get_dn_if_exists(name) except errors.NotFound: obj.handle_not_found(name) search_filter = ldap.make_filter_from_attr(obj.primary_key.name, names, rules=ldap.MATCH_ANY) else: search_filter = '(%s=*)' % obj.primary_key.name task_dn = DN(('cn', cn), REBUILD_TASK_CONTAINER) entry = ldap.make_entry(task_dn, objectclass=['top', 'extensibleObject'], cn=[cn], basedn=[basedn], filter=[search_filter], scope=['sub'], ttl=[3600]) ldap.add_entry(entry) summary = _('Automember rebuild membership task started') result = {'dn': task_dn} if not options.get('no_wait'): summary = _('Automember rebuild membership task completed') result = {} start_time = time.time() while True: try: task = ldap.get_entry(task_dn) except errors.NotFound: break if 'nstaskexitcode' in task: if str(task.single_value['nstaskexitcode']) == '0': summary = task.single_value['nstaskstatus'] break else: raise errors.DatabaseError( desc=task.single_value['nstaskstatus'], info=_("Task DN = '%s'" % task_dn)) time.sleep(1) if time.time() > (start_time + 60): raise errors.TaskTimeout(task=_('Automember'), task_dn=task_dn) return dict(result=result, summary=unicode(summary), value=pkey_to_value(None, options))
class test_range(Declarative): mockldap = None @pytest.fixture(autouse=True, scope="class") def range_setup(self, request, declarative_setup): cls = request.cls def fin(): cls.mockldap = MockLDAP() cls.mockldap.del_entry(domain2_dn) cls.mockldap.del_entry(domain3_dn) cls.mockldap.del_entry(domain4_dn) cls.mockldap.del_entry(domain5_dn) cls.mockldap.del_entry(domain6_dn) cls.mockldap.del_entry(domain7_dn) cls.mockldap.del_entry(domain1range1_dn) cls.mockldap.del_entry(domain2range1_dn) cls.mockldap.del_entry(domain2range2_dn) cls.mockldap.del_entry(domain3range1_dn) cls.mockldap.del_entry(domain3range2_dn) cls.mockldap.del_entry(domain4range1_dn) cls.mockldap.del_entry(domain5range1_dn) cls.mockldap.del_entry(domain5range2_dn) cls.mockldap.del_entry(domain6range1_dn) cls.mockldap.del_entry(domain7range1_dn) cls.mockldap.del_entry(trust_container_dn) cls.mockldap.del_entry(trust_local_dn) cls.mockldap.del_entry(smb_cont_dn) cls.mockldap.unbind() fin() cls.mockldap = MockLDAP() cls.mockldap.add_entry(trust_container_dn, trust_container_add) cls.mockldap.add_entry(smb_cont_dn, smb_cont_add) cls.mockldap.add_entry(trust_local_dn, trust_local_add) cls.mockldap.add_entry(domain2_dn, domain2_add) cls.mockldap.add_entry(domain3_dn, domain3_add) cls.mockldap.add_entry(domain4_dn, domain4_add) cls.mockldap.add_entry(domain5_dn, domain5_add) cls.mockldap.add_entry(domain6_dn, domain6_add) cls.mockldap.add_entry(domain7_dn, domain7_add) cls.mockldap.add_entry(domain1range1_dn, domain1range1_add) cls.mockldap.add_entry(domain2range1_dn, domain2range1_add) cls.mockldap.add_entry(domain2range2_dn, domain2range2_add) cls.mockldap.add_entry(domain3range1_dn, domain3range1_add) cls.mockldap.add_entry(domain3range2_dn, domain3range2_add) cls.mockldap.add_entry(domain4range1_dn, domain4range1_add) cls.mockldap.add_entry(domain5range1_dn, domain5range1_add) cls.mockldap.add_entry(domain5range2_dn, domain5range2_add) cls.mockldap.add_entry(domain6range1_dn, domain6range1_add) cls.mockldap.unbind() request.addfinalizer(fin) cleanup_commands = [ ('idrange_del', [ testrange1, testrange2, testrange3, testrange4, testrange5, testrange6, testrange7, testrange8, testrange9 ], { 'continue': True }), ('user_del', [user1], {}), ('group_del', [group1], {}), ] # Basic tests. tests = [ dict( desc='Create ID range %r' % (testrange1), command=('idrange_add', [testrange1], dict(ipabaseid=testrange1_base_id, ipaidrangesize=testrange1_size, ipabaserid=testrange1_base_rid, ipasecondarybaserid=testrange1_secondary_base_rid)), expected=dict( result=dict( dn=DN(('cn', testrange1), ('cn', 'ranges'), ('cn', 'etc'), api.env.basedn), cn=[testrange1], objectclass=[u'ipaIDrange', u'ipadomainidrange'], ipabaseid=[unicode(testrange1_base_id)], ipabaserid=[unicode(testrange1_base_rid)], ipasecondarybaserid=[ unicode(testrange1_secondary_base_rid) ], ipaidrangesize=[unicode(testrange1_size)], iparangetyperaw=[u'ipa-local'], iparangetype=[u'local domain range'], ), value=testrange1, summary=u'Added ID range "%s"' % (testrange1), ), ), dict( desc='Retrieve ID range %r' % (testrange1), command=('idrange_show', [testrange1], dict()), expected=dict( result=dict( dn=DN(('cn', testrange1), ('cn', 'ranges'), ('cn', 'etc'), api.env.basedn), cn=[testrange1], ipabaseid=[unicode(testrange1_base_id)], ipabaserid=[unicode(testrange1_base_rid)], ipasecondarybaserid=[ unicode(testrange1_secondary_base_rid) ], ipaidrangesize=[unicode(testrange1_size)], iparangetyperaw=[u'ipa-local'], iparangetype=[u'local domain range'], ), value=testrange1, summary=None, ), ), # Checks for modifications leaving objects outside of the range. dict( desc='Create user %r in ID range %r' % (user1, testrange1), command=('user_add', [user1], dict(givenname=u'Test', sn=u'User1', uidnumber=user1_uid)), expected=dict( value=user1, summary=u'Added user "%s"' % user1, result=get_user_result( user1, u'Test', u'User1', 'add', uidnumber=[unicode(user1_uid)], gidnumber=[unicode(user1_uid)], ), ), ), dict( desc='Create group %r in ID range %r' % (group1, testrange1), command=('group_add', [group1], dict(description=u'Test desc 1', gidnumber=group1_gid)), expected=dict( value=group1, summary=u'Added group "%s"' % group1, result=dict( cn=[group1], description=[u'Test desc 1'], gidnumber=[unicode(group1_gid)], objectclass=objectclasses.group + [u'posixgroup'], ipauniqueid=[fuzzy_uuid], dn=DN(('cn', group1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn), ), ), ), dict( desc='Try to modify ID range %r to get out bounds object #1' % (testrange1), command=('idrange_mod', [testrange1], dict(ipabaseid=user1_uid + 1)), expected=errors.ExecutionError(message=IPA_LOCAL_RANGE_MOD_ERR), ), dict( desc='Try to modify ID range %r to get out bounds object #2' % (testrange1), command=('idrange_mod', [testrange1], dict(ipaidrangesize=100)), expected=errors.ExecutionError(message=IPA_LOCAL_RANGE_MOD_ERR), ), dict( desc='Try to modify ID range %r to get out bounds object #3' % (testrange1), command=('idrange_mod', [testrange1], dict(ipabaseid=100, ipaidrangesize=100)), expected=errors.ExecutionError(message=IPA_LOCAL_RANGE_MOD_ERR), ), dict(desc='Modify ID range %r' % (testrange1), command=('idrange_mod', [testrange1], dict(ipaidrangesize=90000)), expected=errors.ExecutionError(message=IPA_LOCAL_RANGE_MOD_ERR)), dict( desc='Try to delete ID range %r with active IDs inside it' % testrange1, command=('idrange_del', [testrange1], {}), expected=errors.ValidationError( name='ipabaseid,ipaidrangesize', error=u'range modification leaving objects with ID out of the' u' defined range is not allowed'), ), dict( desc='Delete user %r' % user1, command=('user_del', [user1], {}), expected=dict( result=dict(failed=[]), value=[user1], summary=u'Deleted user "%s"' % user1, ), ), dict( desc='Delete group %r' % group1, command=('group_del', [group1], {}), expected=dict( result=dict(failed=[]), value=[group1], summary=u'Deleted group "%s"' % group1, ), ), # Framework validation: mod local idrange with auto-private-groups # is prohibited dict(desc=('Try to modify local range %r with --auto-private-groups' % (testrange1)), command=('idrange_mod', [testrange1], dict(ipaautoprivategroups='true')), expected=errors.ExecutionError(message=IPA_LOCAL_RANGE_MOD_ERR)), dict( desc='Delete ID range %r' % testrange1, command=('idrange_del', [testrange1], {}), expected=dict( result=dict(failed=[]), value=[testrange1], summary=u'Deleted ID range "%s"' % testrange1, ), ), # Tests for overlapping local ranges. dict( desc='Create ID range %r' % (testrange2), command=('idrange_add', [testrange2], dict(ipabaseid=testrange2_base_id, ipaidrangesize=testrange2_size, ipabaserid=testrange2_base_rid, ipasecondarybaserid=testrange2_secondary_base_rid)), expected=dict( result=dict( dn=DN(('cn', testrange2), ('cn', 'ranges'), ('cn', 'etc'), api.env.basedn), cn=[testrange2], objectclass=[u'ipaIDrange', u'ipadomainidrange'], ipabaseid=[unicode(testrange2_base_id)], ipabaserid=[unicode(testrange2_base_rid)], ipasecondarybaserid=[ unicode(testrange2_secondary_base_rid) ], ipaidrangesize=[unicode(testrange2_size)], iparangetyperaw=[u'ipa-local'], iparangetype=[u'local domain range'], ), value=testrange2, summary=u'Added ID range "%s"' % (testrange2), ), ), dict( desc= 'Try to modify ID range %r so that its rid ranges are overlapping themselves' % (testrange2), command=('idrange_mod', [testrange2], dict(ipabaserid=(testrange2_secondary_base_rid))), expected=errors.ExecutionError(message=IPA_LOCAL_RANGE_MOD_ERR), ), dict( desc='Try to create ID range %r with overlapping rid range' % (testrange3), command=('idrange_add', [testrange3], dict(ipabaseid=testrange3_base_id, ipaidrangesize=testrange3_size, ipabaserid=testrange3_base_rid, ipasecondarybaserid=testrange3_secondary_base_rid)), expected=errors.DatabaseError( desc='Constraint violation', info= 'New primary rid range overlaps with existing primary rid range.' ), ), dict( desc= 'Try to create ID range %r with overlapping secondary rid range' % (testrange4), command=('idrange_add', [testrange4], dict(ipabaseid=testrange4_base_id, ipaidrangesize=testrange4_size, ipabaserid=testrange4_base_rid, ipasecondarybaserid=testrange4_secondary_base_rid)), expected=errors.DatabaseError( desc='Constraint violation', info= 'New secondary rid range overlaps with existing secondary rid range.' ), ), dict( desc= 'Try to create ID range %r with primary range overlapping secondary rid range' % (testrange5), command=('idrange_add', [testrange5], dict(ipabaseid=testrange5_base_id, ipaidrangesize=testrange5_size, ipabaserid=testrange5_base_rid, ipasecondarybaserid=testrange5_secondary_base_rid)), expected=errors.DatabaseError( desc='Constraint violation', info= 'New primary rid range overlaps with existing secondary rid range.' ), ), dict( desc='Try to create ID range %r with overlapping id range' % (testrange6), command=('idrange_add', [testrange6], dict(ipabaseid=testrange6_base_id, ipaidrangesize=testrange6_size, ipabaserid=testrange6_base_rid, ipasecondarybaserid=testrange6_secondary_base_rid)), expected=errors.DatabaseError( desc='Constraint violation', info='New base range overlaps with existing base range.'), ), dict( desc= 'Try to create ID range %r with rid ranges overlapping themselves' % (testrange7), command=('idrange_add', [testrange7], dict(ipabaseid=testrange7_base_id, ipaidrangesize=testrange7_size, ipabaserid=testrange7_base_rid, ipasecondarybaserid=testrange7_secondary_base_rid)), expected=errors.ValidationError( name='ID Range setup', error='Primary RID range and secondary RID range cannot overlap' ), ), dict( desc='Delete ID range %r' % testrange2, command=('idrange_del', [testrange2], {}), expected=dict( result=dict(failed=[]), value=[testrange2], summary=u'Deleted ID range "%s"' % testrange2, ), ), # Testing framework validation: --dom-sid/--dom-name and secondary RID # base cannot be used together dict( desc='Create ID range %r' % (testrange8), command=('idrange_add', [testrange8], dict(ipabaseid=testrange8_base_id, ipaidrangesize=testrange8_size, ipabaserid=testrange8_base_rid, ipasecondarybaserid=testrange8_secondary_base_rid, ipanttrusteddomainsid=domain1_sid)), expected=errors.ValidationError( name='ID Range setup', error='Options dom-sid/dom-name and ' 'secondary-rid-base cannot be used together'), ), # Testing framework validation: --auto-private-groups is prohibited # with ipa-local range dict( desc='Local ID range %r with auto-private-groups' % (testrange8), command=('idrange_add', [testrange8], dict(ipabaseid=testrange8_base_id, ipaidrangesize=testrange8_size, ipaautoprivategroups='true')), expected=errors.ValidationError( name='ID Range setup', error='IPA Range type must be one of ipa-ad-trust ' 'or ipa-ad-trust-posix when ' 'auto-private-groups is specified'), ), # Testing framework validation: --rid-base is prohibited with ipa-ad-posix dict( desc='Try to create ipa-ad-trust-posix ID range %r with base RID' % (domain7range1), command=('idrange_add', [domain7range1], dict(ipabaseid=domain7range1_base_id, ipaidrangesize=domain7range1_size, ipabaserid=domain7range1_base_rid, iparangetype=domain7range1_type, ipanttrusteddomainsid=domain7_sid)), expected=errors.ValidationError( name='ID Range setup', error='Option rid-base must not be used when IPA range ' 'type is ipa-ad-trust-posix'), ), # Testing framework validation: --auto-private-groups can only be # one of true, false, hybrid dict( desc=('Create ID range %r with bogus --auto-private-groups' % (domain7range1)), command=('idrange_add', [domain7range1], dict(ipabaseid=domain7range1_base_id, ipaidrangesize=domain7range1_size, iparangetype=domain7range1_type, ipanttrusteddomainsid=domain7_sid, ipaautoprivategroups='bogus')), expected=errors.ValidationError( name='auto_private_groups', error="must be one of 'true', 'false', 'hybrid'"), ), dict( desc='Create ID range %r' % (domain7range1), command=('idrange_add', [domain7range1], dict(ipabaseid=domain7range1_base_id, ipaidrangesize=domain7range1_size, iparangetype=domain7range1_type, ipanttrusteddomainsid=domain7_sid)), expected=dict( result=dict( dn=unicode(domain7range1_dn), cn=[domain7range1], objectclass=[u'ipaIDrange', u'ipatrustedaddomainrange'], ipabaseid=[unicode(domain7range1_base_id)], ipaidrangesize=[unicode(domain7range1_size)], ipanttrusteddomainsid=[unicode(domain7_sid)], iparangetyperaw=[u'ipa-ad-trust-posix'], iparangetype=[ u'Active Directory trust range with POSIX attributes' ], ), value=unicode(domain7range1), summary=u'Added ID range "%s"' % (domain7range1), ), ), dict( desc='Try to modify ipa-ad-trust-posix ID range %r with base RID' % (domain7range1), command=('idrange_mod', [domain7range1], dict(ipabaserid=domain7range1_base_rid)), expected=errors.ValidationError( name='ID Range setup', error='Option rid-base must not be used when IPA range ' 'type is ipa-ad-trust-posix'), ), # Testing prohibition of deletion of ranges belonging to active # trusted domains. dict( desc='Delete non-active AD trusted range %r' % domain1range1, command=('idrange_del', [domain1range1], {}), expected=dict( result=dict(failed=[]), value=[domain1range1], summary=u'Deleted ID range "%s"' % domain1range1, ), ), dict( desc='Try to delete active AD trusted range %r' % domain2range1, command=('idrange_del', [domain2range1], {}), expected=errors.DependentEntry(label='Active Trust domain', key=domain2range1, dependent=domain2), ), # Testing base range overlaps for ranges of different types and # different domains # - Base range overlaps # 1. ipa-ad-trust-posix type ranges from the same forest can overlap # on base ranges, use domain3range1 and domain3range2 dict( desc=('Modify ipa-ad-trust-posix range %r to overlap on base range' ' with posix range from the same domain' % (domain3range2)), command=('idrange_mod', [domain3range2], dict(ipabaseid=domain3range1_base_id)), expected=dict( messages=(messages.ServiceRestartRequired( service=services.knownservices['sssd'].systemd_name, server=domain3range2).to_dict(), ), result=dict( cn=[domain3range2], ipabaseid=[unicode(domain3range1_base_id)], ipaidrangesize=[unicode(domain3range2_size)], ipanttrusteddomainsid=[unicode(domain3_sid)], iparangetyperaw=[u'ipa-ad-trust-posix'], iparangetype=[ u'Active Directory trust range with POSIX ' 'attributes' ], ), value=domain3range2, summary=u'Modified ID range "%s"' % (domain3range2), ), ), # 2. ipa-ad-trust-posix type ranges from different forests cannot # overlap on base ranges, use domain3range1 and domain4range1 dict( desc=('Modify ipa-ad-trust-posix range %r to overlap on base range' ' with posix range from different domain' % (domain3range1)), command=('idrange_mod', [domain3range1], dict(ipabaseid=domain4range1_base_id)), expected=errors.DatabaseError( desc='Constraint violation', info='New base range overlaps with existing base range.'), ), # 3. ipa-ad-trust ranges from same forest cannot overlap on base ranges, # use domain5range1 and domain5range2 dict( desc=('Modify ipa-ad-trust range %r to overlap on base range' ' with posix range from the same domain' % (domain5range1)), command=('idrange_mod', [domain5range1], dict(ipabaseid=domain5range2_base_id)), expected=errors.DatabaseError( desc='Constraint violation', info='New base range overlaps with existing base range.'), ), # 4. ipa-ad-trust ranges from different forests cannot overlap on base # ranges, use domain5range1 and domain6range1 dict( desc=('Modify ipa-ad-trust range %r to overlap on base range' ' with posix range from different domain' % (domain5range1)), command=('idrange_mod', [domain5range1], dict(ipabaseid=domain6range1_base_id)), expected=errors.DatabaseError( desc='Constraint violation', info='New base range overlaps with existing base range.'), ), # - RID range overlaps # 1. Overlaps on base RID ranges are allowed for ranges from different # domains, use domain2range1 and domain5range1 dict( desc=('Modify ipa-ad-trust range %r to overlap on base RID' ' range with nonposix range from different domain' % (domain2range1)), command=('idrange_mod', [domain2range1], dict(ipabaserid=domain5range1_base_rid)), expected=dict( messages=(messages.ServiceRestartRequired( service=services.knownservices['sssd'].systemd_name, server=domain2range1).to_dict(), ), result=dict( cn=[domain2range1], ipabaseid=[unicode(domain2range1_base_id)], ipabaserid=[unicode(domain5range1_base_rid)], ipaidrangesize=[unicode(domain2range1_size)], ipanttrusteddomainsid=[unicode(domain2_sid)], iparangetyperaw=[u'ipa-ad-trust'], iparangetype=[u'Active Directory domain range'], ), value=domain2range1, summary=u'Modified ID range "%s"' % (domain2range1), ), ), # 2. ipa-ad-trust ranges from the same forest cannot overlap on base # RID ranges, use domain5range1 and domain5range2 dict( desc=('Modify ipa-ad-trust range %r to overlap on base RID range' ' with range from the same domain' % (domain2range1)), command=('idrange_mod', [domain2range1], dict(ipabaserid=domain2range2_base_rid)), expected=errors.DatabaseError( desc='Constraint violation', info='New primary rid range overlaps with existing primary rid ' 'range.'), ), dict( desc=('Modify ipa-ad-trust range %r with --auto-private-groups=' 'true' % (domain2range1)), command=('idrange_mod', [domain2range1], dict(ipaautoprivategroups='true')), expected=dict( messages=(messages.ServiceRestartRequired( service=services.knownservices['sssd'].systemd_name, server=domain2range1).to_dict(), ), result=dict( cn=[domain2range1], ipabaseid=[unicode(domain2range1_base_id)], ipabaserid=[unicode(domain5range1_base_rid)], ipaidrangesize=[unicode(domain2range1_size)], ipanttrusteddomainsid=[unicode(domain2_sid)], iparangetyperaw=[u'ipa-ad-trust'], ipaautoprivategroups=[u'true'], iparangetype=[u'Active Directory domain range'], ), value=domain2range1, summary=u'Modified ID range "%s"' % (domain2range1), ), ), dict( desc=('Modify ipa-ad-trust range %r with --auto-private-groups=' 'false' % (domain2range1)), command=('idrange_mod', [domain2range1], dict(ipaautoprivategroups='false')), expected=dict( messages=(messages.ServiceRestartRequired( service=services.knownservices['sssd'].systemd_name, server=domain2range1).to_dict(), ), result=dict( cn=[domain2range1], ipabaseid=[unicode(domain2range1_base_id)], ipabaserid=[unicode(domain5range1_base_rid)], ipaidrangesize=[unicode(domain2range1_size)], ipanttrusteddomainsid=[unicode(domain2_sid)], iparangetyperaw=[u'ipa-ad-trust'], ipaautoprivategroups=[u'false'], iparangetype=[u'Active Directory domain range'], ), value=domain2range1, summary=u'Modified ID range "%s"' % (domain2range1), ), ), dict( desc=('Modify ipa-ad-trust range %r with --auto-private-groups=' 'hybrid' % (domain2range1)), command=('idrange_mod', [domain2range1], dict(ipaautoprivategroups='hybrid')), expected=dict( messages=(messages.ServiceRestartRequired( service=services.knownservices['sssd'].systemd_name, server=domain2range1).to_dict(), ), result=dict( cn=[domain2range1], ipabaseid=[unicode(domain2range1_base_id)], ipabaserid=[unicode(domain5range1_base_rid)], ipaidrangesize=[unicode(domain2range1_size)], ipanttrusteddomainsid=[unicode(domain2_sid)], iparangetyperaw=[u'ipa-ad-trust'], ipaautoprivategroups=[u'hybrid'], iparangetype=[u'Active Directory domain range'], ), value=domain2range1, summary=u'Modified ID range "%s"' % (domain2range1), ), ), dict( desc=('Modify ipa-ad-trust range %r with --auto-private-groups=' '<empty>' % (domain2range1)), command=('idrange_mod', [domain2range1], dict(ipaautoprivategroups='')), expected=dict( messages=(messages.ServiceRestartRequired( service=services.knownservices['sssd'].systemd_name, server=domain2range1).to_dict(), ), result=dict( cn=[domain2range1], ipabaseid=[unicode(domain2range1_base_id)], ipabaserid=[unicode(domain5range1_base_rid)], ipaidrangesize=[unicode(domain2range1_size)], ipanttrusteddomainsid=[unicode(domain2_sid)], iparangetyperaw=[u'ipa-ad-trust'], iparangetype=[u'Active Directory domain range'], ), value=domain2range1, summary=u'Modified ID range "%s"' % (domain2range1), ), ), # Test for bug 6404 # if dom-name is empty, add should not fail dict( desc='Create ID range %r' % (testrange9), command=('idrange_add', [testrange9], dict(ipanttrusteddomainname=None, ipabaseid=testrange9_base_id, ipaidrangesize=testrange9_size, ipabaserid=testrange9_base_rid, ipasecondarybaserid=testrange9_secondary_base_rid)), expected=dict( result=dict( dn=DN(('cn', testrange9), ('cn', 'ranges'), ('cn', 'etc'), api.env.basedn), cn=[testrange9], objectclass=[u'ipaIDrange', u'ipadomainidrange'], ipabaseid=[unicode(testrange9_base_id)], ipabaserid=[unicode(testrange9_base_rid)], ipasecondarybaserid=[ unicode(testrange9_secondary_base_rid) ], ipaidrangesize=[unicode(testrange9_size)], iparangetyperaw=[u'ipa-local'], iparangetype=[u'local domain range'], ), value=testrange9, summary=u'Added ID range "%s"' % (testrange9), ), ), dict( desc='Delete ID range %r' % testrange9, command=('idrange_del', [testrange9], {}), expected=dict( result=dict(failed=[]), value=[testrange9], summary=u'Deleted ID range "%s"' % testrange9, ), ), ]
class test_attr(Declarative): cleanup_commands = [ ('user_del', [user1], {}), ] tests = [ dict( desc='Try to add user %r with single-value attribute set via ' 'option and --addattr' % user1, command=('user_add', [user1], dict(givenname=u'Test', sn=u'User1', addattr=u'sn=User2')), expected=errors.OnlyOneValueAllowed(attr='sn'), ), dict( desc='Create %r' % user1, command=('user_add', [user1], dict(givenname=u'Test', sn=u'User1', setattr=None)), expected=dict( value=user1, summary=u'Added user "tuser1"', result=dict( gecos=[u'Test User1'], givenname=[u'Test'], homedirectory=[u'/home/tuser1'], krbprincipalname=[u'tuser1@' + api.env.realm], loginshell=[u'/bin/sh'], objectclass=objectclasses.user, sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'%s@%s' % (user1, api.env.domain)], displayname=[u'Test User1'], cn=[u'Test User1'], initials=[u'TU'], ipauniqueid=[fuzzy_uuid], krbpwdpolicyreference=[ DN(('cn', 'global_policy'), ('cn', api.env.realm), ('cn', 'kerberos'), api.env.basedn) ], mepmanagedentry=[ DN(('cn', user1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn) ], memberof_group=[u'ipausers'], dn=DN(('uid', 'tuser1'), ('cn', 'users'), ('cn', 'accounts'), api.env.basedn), has_keytab=False, has_password=False, ), ), ), dict( desc='Change givenname, add mail %r' % user1, command=('user_mod', [user1], dict(setattr=(u'givenname=Finkle', u'[email protected]'))), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**'], memberof_group=[u'ipausers'], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Add another mail %r' % user1, command=('user_mod', [user1], dict(addattr=u'[email protected]')), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Add two phone numbers at once %r' % user1, command=('user_mod', [user1], dict(setattr=u'telephoneNumber=410-555-1212', addattr=u'telephoneNumber=301-555-1212')), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], telephonenumber=[u'410-555-1212', u'301-555-1212'], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Go from two phone numbers to one %r' % user1, command=('user_mod', [user1], dict(setattr=u'telephoneNumber=301-555-1212')), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], telephonenumber=[u'301-555-1212'], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Add two more phone numbers %r' % user1, command=('user_mod', [user1], dict(addattr=(u'telephoneNumber=703-555-1212', u'telephoneNumber=202-888-9833'))), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], telephonenumber=[ u'301-555-1212', u'202-888-9833', u'703-555-1212' ], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Delete one phone number for %r' % user1, command=('user_mod', [user1], dict(delattr=u'telephoneNumber=301-555-1212')), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], telephonenumber=[u'202-888-9833', u'703-555-1212'], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict(desc='Try deleting the number again for %r' % user1, command=('user_mod', [user1], dict(delattr=u'telephoneNumber=301-555-1212')), expected=errors.AttrValueNotFound(attr=u'telephonenumber', value=u'301-555-1212')), dict( desc='Add and delete one phone number for %r' % user1, command=('user_mod', [user1], dict(addattr=u'telephoneNumber=301-555-1212', delattr=u'telephoneNumber=202-888-9833')), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], telephonenumber=[u'301-555-1212', u'703-555-1212'], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Add and delete the same phone number for %r' % user1, command=('user_mod', [user1], dict(addattr=(u'telephoneNumber=301-555-1212', u'telephoneNumber=202-888-9833'), delattr=u'telephoneNumber=301-555-1212')), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], telephonenumber=[ u'703-555-1212', u'301-555-1212', u'202-888-9833' ], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Set and delete a phone number for %r' % user1, command=('user_mod', [user1], dict(setattr=(u'telephoneNumber=301-555-1212', u'telephoneNumber=202-888-9833'), delattr=u'telephoneNumber=301-555-1212')), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], telephonenumber=[u'202-888-9833'], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Try setting givenname to None with setattr in %r' % user1, command=('user_mod', [user1], dict(setattr=(u'givenname='))), expected=errors.RequirementError(name='givenname'), ), dict( desc='Try setting givenname to None with option in %r' % user1, command=('user_mod', [user1], dict(givenname=None)), expected=errors.RequirementError(name='first'), ), dict( desc='Make sure setting givenname works with option in %r' % user1, command=('user_mod', [user1], dict(givenname=u'Fred')), expected=dict( result=dict( givenname=[u'Fred'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], telephonenumber=[u'202-888-9833'], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Make sure setting givenname works with setattr in %r' % user1, command=('user_mod', [user1], dict(setattr=u'givenname=Finkle')), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], telephonenumber=[u'202-888-9833'], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Lock %r using setattr' % user1, command=('user_mod', [user1], dict(setattr=u'nsaccountlock=TrUe')), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], telephonenumber=[u'202-888-9833'], nsaccountlock=True, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Unlock %r using addattr&delattr' % user1, command=('user_mod', [user1], dict(addattr=u'nsaccountlock=FaLsE', delattr=u'nsaccountlock=TRUE')), expected=dict( result=dict( givenname=[u'Finkle'], homedirectory=[u'/home/tuser1'], loginshell=[u'/bin/sh'], sn=[u'User1'], uid=[user1], uidnumber=[fuzzy_digits], gidnumber=[fuzzy_digits], mail=[u'*****@*****.**', u'*****@*****.**'], memberof_group=[u'ipausers'], telephonenumber=[u'202-888-9833'], nsaccountlock=False, has_keytab=False, has_password=False, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Try adding a new group search fields config entry', command=('config_mod', [], dict(addattr=u'ipagroupsearchfields=newattr')), expected=errors.OnlyOneValueAllowed(attr='ipagroupsearchfields'), ), dict( desc='Try adding a new cert subject base config entry', command=('config_mod', [], dict(addattr=u'ipacertificatesubjectbase=0=DOMAIN.COM')), expected=errors.ValidationError( name='ipacertificatesubjectbase', error='attribute is not configurable'), ), dict( desc='Try deleting a required config entry', command=('config_mod', [], dict(delattr=u'ipasearchrecordslimit=100')), expected=errors.RequirementError(name='ipasearchrecordslimit'), ), dict( desc='Try setting nonexistent attribute', command=('config_mod', [], dict(setattr=u'invalid_attr=false')), expected=errors.ObjectclassViolation( info='attribute "invalid_attr" not allowed'), ), dict( desc='Try setting out-of-range krbpwdmaxfailure', command=('pwpolicy_mod', [], dict(setattr=u'krbpwdmaxfailure=-1')), expected=errors.ValidationError(name='krbpwdmaxfailure', error='must be at least 0'), ), dict( desc='Try setting out-of-range maxfail', command=('pwpolicy_mod', [], dict(krbpwdmaxfailure=u'-1')), expected=errors.ValidationError(name='maxfail', error='must be at least 0'), ), dict( desc='Try setting non-numeric krbpwdmaxfailure', command=('pwpolicy_mod', [], dict(setattr=u'krbpwdmaxfailure=abc')), expected=errors.ConversionError(name='krbpwdmaxfailure', error='must be an integer'), ), dict( desc='Try setting non-numeric maxfail', command=('pwpolicy_mod', [], dict(krbpwdmaxfailure=u'abc')), expected=errors.ConversionError(name='maxfail', error='must be an integer'), ), dict( desc='Try deleting bogus attribute', command=('config_mod', [], dict(delattr=u'bogusattribute=xyz')), expected=errors.ValidationError( name='bogusattribute', error='No such attribute on this entry'), ), dict( desc='Try deleting empty attribute', command=('config_mod', [], dict(delattr=u'ipaCustomFields=See Also,seealso,false')), expected=errors.ValidationError( name='ipacustomfields', error='No such attribute on this entry'), ), dict( desc='Set and delete one value, plus try deleting a missing one', command=('config_mod', [], dict(delattr=[ u'ipaCustomFields=See Also,seealso,false', u'ipaCustomFields=Country,c,false' ], addattr=u'ipaCustomFields=See Also,seealso,false')), expected=errors.AttrValueNotFound(attr='ipacustomfields', value='Country,c,false'), ), dict( desc='Try to delete an operational attribute with --delattr', command=('config_mod', [], dict(delattr=u'creatorsName=cn=directory manager')), expected=errors.DatabaseError( desc='Server is unwilling to perform', info=''), ), ]
info = '' try: # re-raise the error so we can handle it raise e except ldap.NO_SUCH_OBJECT, e: arg_desc = kw.get('arg_desc', "entry not found") raise errors.NotFound(reason=arg_desc) except ldap.ALREADY_EXISTS, e: raise errors.DuplicateEntry() except ldap.CONSTRAINT_VIOLATION, e: # This error gets thrown by the uniqueness plugin if info.startswith('Another entry with the same attribute value already exists'): raise errors.DuplicateEntry() else: raise errors.DatabaseError(desc=desc,info=info) except ldap.INSUFFICIENT_ACCESS, e: raise errors.ACIError(info=info) except ldap.NO_SUCH_ATTRIBUTE: # this is raised when a 'delete' attribute isn't found. # it indicates the previous attribute was removed by another # update, making the oldentry stale. raise errors.MidairCollision() except ldap.ADMINLIMIT_EXCEEDED, e: raise errors.LimitsExceeded() except ldap.SIZELIMIT_EXCEEDED, e: raise errors.LimitsExceeded() except ldap.TIMELIMIT_EXCEEDED, e: raise errors.LimitsExceeded() except ldap.LDAPError, e: raise errors.DatabaseError(desc=desc,info=info)
class test_attr(Declarative): cleanup_commands = [ ('user_del', [user1], {}), ] tests = [ dict( desc='Try to add user %r with single-value attribute set via ' 'option and --addattr' % user1, command=('user_add', [user1], dict(givenname=u'Test', sn=u'User1', addattr=u'sn=User2')), expected=errors.OnlyOneValueAllowed(attr='sn'), ), dict( desc='Create %r' % user1, command=('user_add', [user1], dict(givenname=u'Test', sn=u'User1', setattr=None)), expected=dict( value=user1, summary=u'Added user "tuser1"', result=get_user_result(user1, u'Test', u'User1', 'add'), ), ), dict( desc='Change givenname, add mail %r' % user1, command=('user_mod', [user1], dict(setattr=(u'givenname=Finkle', u'[email protected]'))), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**'], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Add another mail %r' % user1, command=('user_mod', [user1], dict(addattr=u'[email protected]')), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Add two phone numbers at once %r' % user1, command=('user_mod', [user1], dict(setattr=u'telephoneNumber=410-555-1212', addattr=u'telephoneNumber=301-555-1212')), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], telephonenumber=[u'410-555-1212', u'301-555-1212'], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Go from two phone numbers to one %r' % user1, command=('user_mod', [user1], dict(setattr=u'telephoneNumber=301-555-1212')), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], telephonenumber=[u'301-555-1212'], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Add two more phone numbers %r' % user1, command=('user_mod', [user1], dict(addattr=(u'telephoneNumber=703-555-1212', u'telephoneNumber=202-888-9833'))), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], telephonenumber=[ u'301-555-1212', u'703-555-1212', u'202-888-9833' ], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Delete one phone number for %r' % user1, command=('user_mod', [user1], dict(delattr=u'telephoneNumber=301-555-1212')), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], telephonenumber=[u'703-555-1212', u'202-888-9833'], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict(desc='Try deleting the number again for %r' % user1, command=('user_mod', [user1], dict(delattr=u'telephoneNumber=301-555-1212')), expected=errors.AttrValueNotFound(attr=u'telephonenumber', value=u'301-555-1212')), dict( desc='Add and delete one phone number for %r' % user1, command=('user_mod', [user1], dict(addattr=u'telephoneNumber=301-555-1212', delattr=u'telephoneNumber=202-888-9833')), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], telephonenumber=[u'703-555-1212', u'301-555-1212'], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Add and delete the same phone number for %r' % user1, command=('user_mod', [user1], dict(addattr=(u'telephoneNumber=301-555-1212', u'telephoneNumber=202-888-9833'), delattr=u'telephoneNumber=301-555-1212')), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], telephonenumber=[ u'703-555-1212', u'301-555-1212', u'202-888-9833' ], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Set and delete a phone number for %r' % user1, command=('user_mod', [user1], dict(setattr=(u'telephoneNumber=301-555-1212', u'telephoneNumber=202-888-9833'), delattr=u'telephoneNumber=301-555-1212')), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], telephonenumber=[u'202-888-9833'], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Try setting givenname to None with setattr in %r' % user1, command=('user_mod', [user1], dict(setattr=(u'givenname='))), expected=errors.RequirementError(name='givenname'), ), dict( desc='Try setting givenname to None with option in %r' % user1, command=('user_mod', [user1], dict(givenname=None)), expected=errors.RequirementError(name='first'), ), dict( desc='Make sure setting givenname works with option in %r' % user1, command=('user_mod', [user1], dict(givenname=u'Fred')), expected=dict( result=get_user_result( user1, u'Fred', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], telephonenumber=[u'202-888-9833'], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Make sure setting givenname works with setattr in %r' % user1, command=('user_mod', [user1], dict(setattr=u'givenname=Finkle')), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], telephonenumber=[u'202-888-9833'], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Try to "remove" empty location from %r' % user1, command=('user_mod', [user1], dict(l=None)), expected=errors.EmptyModlist(), ), dict( desc='Lock %r using setattr' % user1, command=('user_mod', [user1], dict(setattr=u'nsaccountlock=TrUe')), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], telephonenumber=[u'202-888-9833'], nsaccountlock=True, ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Unlock %r using addattr&delattr' % user1, command=('user_mod', [user1], dict(addattr=u'nsaccountlock=FaLsE', delattr=u'nsaccountlock=TRUE')), expected=dict( result=get_user_result( user1, u'Finkle', u'User1', 'mod', mail=[u'*****@*****.**', u'*****@*****.**'], telephonenumber=[u'202-888-9833'], ), summary=u'Modified user "tuser1"', value=user1, ), ), dict( desc='Try adding a new group search fields config entry', command=('config_mod', [], dict(addattr=u'ipagroupsearchfields=newattr')), expected=errors.OnlyOneValueAllowed(attr='ipagroupsearchfields'), ), dict( desc='Try adding a new cert subject base config entry', command=('config_mod', [], dict(addattr=u'ipacertificatesubjectbase=0=DOMAIN.COM')), expected=errors.ValidationError( name='ipacertificatesubjectbase', error='attribute is not configurable'), ), dict( desc='Try deleting a required config entry', command=('config_mod', [], dict(delattr=u'ipasearchrecordslimit=100')), expected=errors.RequirementError(name='ipasearchrecordslimit'), ), dict( desc='Try setting nonexistent attribute', command=('config_mod', [], dict(setattr=u'invalid_attr=false')), expected=errors.ObjectclassViolation( info='attribute "invalid_attr" not allowed'), ), dict( desc='Try setting out-of-range krbpwdmaxfailure', command=('pwpolicy_mod', [], dict(setattr=u'krbpwdmaxfailure=-1')), expected=errors.ValidationError(name='krbpwdmaxfailure', error='must be at least 0'), ), dict( desc='Try setting out-of-range maxfail', command=('pwpolicy_mod', [], dict(krbpwdmaxfailure=u'-1')), expected=errors.ValidationError(name='maxfail', error='must be at least 0'), ), dict( desc='Try setting non-numeric krbpwdmaxfailure', command=('pwpolicy_mod', [], dict(setattr=u'krbpwdmaxfailure=abc')), expected=errors.ConversionError(name='krbpwdmaxfailure', error='must be an integer'), ), dict( desc='Try setting non-numeric maxfail', command=('pwpolicy_mod', [], dict(krbpwdmaxfailure=u'abc')), expected=errors.ConversionError(name='maxfail', error='must be an integer'), ), dict( desc='Try deleting bogus attribute', command=('config_mod', [], dict(delattr=u'bogusattribute=xyz')), expected=errors.ValidationError( name='bogusattribute', error='No such attribute on this entry'), ), dict( desc='Try deleting empty attribute', command=('config_mod', [], dict(delattr=u'ipaCustomFields=See Also,seealso,false')), expected=errors.ValidationError( name='ipacustomfields', error='No such attribute on this entry'), ), dict( desc='Set and delete one value, plus try deleting a missing one', command=('config_mod', [], dict(delattr=[ u'ipaCustomFields=See Also,seealso,false', u'ipaCustomFields=Country,c,false' ], addattr=u'ipaCustomFields=See Also,seealso,false')), expected=errors.AttrValueNotFound(attr='ipacustomfields', value='Country,c,false'), ), dict( desc='Try to delete an operational attribute with --delattr', command=('config_mod', [], dict(delattr=u'creatorsName=cn=directory manager')), expected=errors.DatabaseError( desc='Server is unwilling to perform', info=''), ), ]
class test_range(Declarative): @classmethod def setup_class(cls): super(test_range, cls).setup_class() cls.teardown_class() cls.mockldap = MockLDAP() cls.mockldap.add_entry(trust_container_dn, trust_container_add) cls.mockldap.add_entry(smb_cont_dn, smb_cont_add) cls.mockldap.add_entry(trust_local_dn, trust_local_add) cls.mockldap.add_entry(domain2_dn, domain2_add) cls.mockldap.add_entry(domain3_dn, domain3_add) cls.mockldap.add_entry(domain4_dn, domain4_add) cls.mockldap.add_entry(domain5_dn, domain5_add) cls.mockldap.add_entry(domain6_dn, domain6_add) cls.mockldap.add_entry(domain7_dn, domain7_add) cls.mockldap.add_entry(domain1range1_dn, domain1range1_add) cls.mockldap.add_entry(domain2range1_dn, domain2range1_add) cls.mockldap.add_entry(domain2range2_dn, domain2range2_add) cls.mockldap.add_entry(domain3range1_dn, domain3range1_add) cls.mockldap.add_entry(domain3range2_dn, domain3range2_add) cls.mockldap.add_entry(domain4range1_dn, domain4range1_add) cls.mockldap.add_entry(domain5range1_dn, domain5range1_add) cls.mockldap.add_entry(domain5range2_dn, domain5range2_add) cls.mockldap.add_entry(domain6range1_dn, domain6range1_add) cls.mockldap.unbind() @classmethod def teardown_class(cls): cls.mockldap = MockLDAP() cls.mockldap.del_entry(domain2_dn) cls.mockldap.del_entry(domain3_dn) cls.mockldap.del_entry(domain4_dn) cls.mockldap.del_entry(domain5_dn) cls.mockldap.del_entry(domain6_dn) cls.mockldap.del_entry(domain7_dn) cls.mockldap.del_entry(domain1range1_dn) cls.mockldap.del_entry(domain2range1_dn) cls.mockldap.del_entry(domain2range2_dn) cls.mockldap.del_entry(domain3range1_dn) cls.mockldap.del_entry(domain3range2_dn) cls.mockldap.del_entry(domain4range1_dn) cls.mockldap.del_entry(domain5range1_dn) cls.mockldap.del_entry(domain5range2_dn) cls.mockldap.del_entry(domain6range1_dn) cls.mockldap.del_entry(domain7range1_dn) cls.mockldap.del_entry(trust_container_dn) cls.mockldap.del_entry(trust_local_dn) cls.mockldap.del_entry(smb_cont_dn) cls.mockldap.unbind() cleanup_commands = [ ('idrange_del', [ testrange1, testrange2, testrange3, testrange4, testrange5, testrange6, testrange7, testrange8 ], { 'continue': True }), ('user_del', [user1], {}), ('group_del', [group1], {}), ] # Basic tests. tests = [ dict( desc='Create ID range %r' % (testrange1), command=('idrange_add', [testrange1], dict(ipabaseid=testrange1_base_id, ipaidrangesize=testrange1_size, ipabaserid=testrange1_base_rid, ipasecondarybaserid=testrange1_secondary_base_rid)), expected=dict( result=dict( dn=DN(('cn', testrange1), ('cn', 'ranges'), ('cn', 'etc'), api.env.basedn), cn=[testrange1], objectclass=[u'ipaIDrange', u'ipadomainidrange'], ipabaseid=[unicode(testrange1_base_id)], ipabaserid=[unicode(testrange1_base_rid)], ipasecondarybaserid=[ unicode(testrange1_secondary_base_rid) ], ipaidrangesize=[unicode(testrange1_size)], iparangetyperaw=[u'ipa-local'], iparangetype=[u'local domain range'], ), value=testrange1, summary=u'Added ID range "%s"' % (testrange1), ), ), dict( desc='Retrieve ID range %r' % (testrange1), command=('idrange_show', [testrange1], dict()), expected=dict( result=dict( dn=DN(('cn', testrange1), ('cn', 'ranges'), ('cn', 'etc'), api.env.basedn), cn=[testrange1], ipabaseid=[unicode(testrange1_base_id)], ipabaserid=[unicode(testrange1_base_rid)], ipasecondarybaserid=[ unicode(testrange1_secondary_base_rid) ], ipaidrangesize=[unicode(testrange1_size)], iparangetyperaw=[u'ipa-local'], iparangetype=[u'local domain range'], ), value=testrange1, summary=None, ), ), # Checks for modifications leaving objects outside of the range. dict( desc='Create user %r in ID range %r' % (user1, testrange1), command=('user_add', [user1], dict(givenname=u'Test', sn=u'User1', uidnumber=user1_uid)), expected=dict( value=user1, summary=u'Added user "%s"' % user1, result=get_user_result( user1, u'Test', u'User1', 'add', uidnumber=[unicode(user1_uid)], gidnumber=[unicode(user1_uid)], ), ), ), dict( desc='Create group %r in ID range %r' % (group1, testrange1), command=('group_add', [group1], dict(description=u'Test desc 1', gidnumber=group1_gid)), expected=dict( value=group1, summary=u'Added group "%s"' % group1, result=dict( cn=[group1], description=[u'Test desc 1'], gidnumber=[unicode(group1_gid)], objectclass=objectclasses.group + [u'posixgroup'], ipauniqueid=[fuzzy_uuid], dn=DN(('cn', group1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn), ), ), ), dict( desc='Try to modify ID range %r to get out bounds object #1' % (testrange1), command=('idrange_mod', [testrange1], dict(ipabaseid=user1_uid + 1)), expected=errors.ValidationError( name='ipabaseid,ipaidrangesize', error=u'range modification leaving objects with ID out of the' u' defined range is not allowed'), ), dict( desc='Try to modify ID range %r to get out bounds object #2' % (testrange1), command=('idrange_mod', [testrange1], dict(ipaidrangesize=100)), expected=errors.ValidationError( name='ipabaseid,ipaidrangesize', error=u'range modification leaving objects with ID out of the' u' defined range is not allowed'), ), dict( desc='Try to modify ID range %r to get out bounds object #3' % (testrange1), command=('idrange_mod', [testrange1], dict(ipabaseid=100, ipaidrangesize=100)), expected=errors.ValidationError( name='ipabaseid,ipaidrangesize', error=u'range modification leaving objects with ID out of the' u' defined range is not allowed'), ), dict( desc='Modify ID range %r' % (testrange1), command=('idrange_mod', [testrange1], dict(ipaidrangesize=90000)), expected=dict( result=dict( cn=[testrange1], ipabaseid=[unicode(testrange1_base_id)], ipabaserid=[unicode(testrange1_base_rid)], ipasecondarybaserid=[ unicode(testrange1_secondary_base_rid) ], ipaidrangesize=[u'90000'], iparangetyperaw=[u'ipa-local'], iparangetype=[u'local domain range'], ), value=testrange1, summary=u'Modified ID range "%s"' % (testrange1), ), ), dict( desc='Try to delete ID range %r with active IDs inside it' % testrange1, command=('idrange_del', [testrange1], {}), expected=errors.ValidationError( name='ipabaseid,ipaidrangesize', error=u'range modification leaving objects with ID out of the' u' defined range is not allowed'), ), dict( desc='Delete user %r' % user1, command=('user_del', [user1], {}), expected=dict( result=dict(failed=[]), value=[user1], summary=u'Deleted user "%s"' % user1, ), ), dict( desc='Delete group %r' % group1, command=('group_del', [group1], {}), expected=dict( result=dict(failed=[]), value=[group1], summary=u'Deleted group "%s"' % group1, ), ), dict( desc='Delete ID range %r' % testrange1, command=('idrange_del', [testrange1], {}), expected=dict( result=dict(failed=[]), value=[testrange1], summary=u'Deleted ID range "%s"' % testrange1, ), ), # Tests for overlapping local ranges. dict( desc='Create ID range %r' % (testrange2), command=('idrange_add', [testrange2], dict(ipabaseid=testrange2_base_id, ipaidrangesize=testrange2_size, ipabaserid=testrange2_base_rid, ipasecondarybaserid=testrange2_secondary_base_rid)), expected=dict( result=dict( dn=DN(('cn', testrange2), ('cn', 'ranges'), ('cn', 'etc'), api.env.basedn), cn=[testrange2], objectclass=[u'ipaIDrange', u'ipadomainidrange'], ipabaseid=[unicode(testrange2_base_id)], ipabaserid=[unicode(testrange2_base_rid)], ipasecondarybaserid=[ unicode(testrange2_secondary_base_rid) ], ipaidrangesize=[unicode(testrange2_size)], iparangetyperaw=[u'ipa-local'], iparangetype=[u'local domain range'], ), value=testrange2, summary=u'Added ID range "%s"' % (testrange2), ), ), dict( desc= 'Try to modify ID range %r so that its rid ranges are overlapping themselves' % (testrange2), command=('idrange_mod', [testrange2], dict(ipabaserid=(testrange2_secondary_base_rid))), expected=errors.ValidationError( name='ID Range setup', error='Primary RID range and secondary RID range cannot overlap' ), ), dict( desc='Try to create ID range %r with overlapping rid range' % (testrange3), command=('idrange_add', [testrange3], dict(ipabaseid=testrange3_base_id, ipaidrangesize=testrange3_size, ipabaserid=testrange3_base_rid, ipasecondarybaserid=testrange3_secondary_base_rid)), expected=errors.DatabaseError( desc='Constraint violation', info= 'New primary rid range overlaps with existing primary rid range.' ), ), dict( desc= 'Try to create ID range %r with overlapping secondary rid range' % (testrange4), command=('idrange_add', [testrange4], dict(ipabaseid=testrange4_base_id, ipaidrangesize=testrange4_size, ipabaserid=testrange4_base_rid, ipasecondarybaserid=testrange4_secondary_base_rid)), expected=errors.DatabaseError( desc='Constraint violation', info= 'New secondary rid range overlaps with existing secondary rid range.' ), ), dict( desc= 'Try to create ID range %r with primary range overlapping secondary rid range' % (testrange5), command=('idrange_add', [testrange5], dict(ipabaseid=testrange5_base_id, ipaidrangesize=testrange5_size, ipabaserid=testrange5_base_rid, ipasecondarybaserid=testrange5_secondary_base_rid)), expected=errors.DatabaseError( desc='Constraint violation', info= 'New primary rid range overlaps with existing secondary rid range.' ), ), dict( desc='Try to create ID range %r with overlapping id range' % (testrange6), command=('idrange_add', [testrange6], dict(ipabaseid=testrange6_base_id, ipaidrangesize=testrange6_size, ipabaserid=testrange6_base_rid, ipasecondarybaserid=testrange6_secondary_base_rid)), expected=errors.DatabaseError( desc='Constraint violation', info='New base range overlaps with existing base range.'), ), dict( desc= 'Try to create ID range %r with rid ranges overlapping themselves' % (testrange7), command=('idrange_add', [testrange7], dict(ipabaseid=testrange7_base_id, ipaidrangesize=testrange7_size, ipabaserid=testrange7_base_rid, ipasecondarybaserid=testrange7_secondary_base_rid)), expected=errors.ValidationError( name='ID Range setup', error='Primary RID range and secondary RID range cannot overlap' ), ), dict( desc='Delete ID range %r' % testrange2, command=('idrange_del', [testrange2], {}), expected=dict( result=dict(failed=[]), value=[testrange2], summary=u'Deleted ID range "%s"' % testrange2, ), ), # Testing framework validation: --dom-sid/--dom-name and secondary RID # base cannot be used together dict( desc='Create ID range %r' % (testrange8), command=('idrange_add', [testrange8], dict(ipabaseid=testrange8_base_id, ipaidrangesize=testrange8_size, ipabaserid=testrange8_base_rid, ipasecondarybaserid=testrange8_secondary_base_rid, ipanttrusteddomainsid=domain1_sid)), expected=errors.ValidationError( name='ID Range setup', error='Options dom-sid/dom-name and ' 'secondary-rid-base cannot be used together'), ), # Testing framework validation: --rid-base is prohibited with ipa-ad-posix dict( desc='Try to create ipa-ad-trust-posix ID range %r with base RID' % (domain7range1), command=('idrange_add', [domain7range1], dict(ipabaseid=domain7range1_base_id, ipaidrangesize=domain7range1_size, ipabaserid=domain7range1_base_rid, iparangetype=domain7range1_type, ipanttrusteddomainsid=domain7_sid)), expected=errors.ValidationError( name='ID Range setup', error='Option rid-base must not be used when IPA range ' 'type is ipa-ad-trust-posix'), ), dict( desc='Create ID range %r' % (domain7range1), command=('idrange_add', [domain7range1], dict(ipabaseid=domain7range1_base_id, ipaidrangesize=domain7range1_size, iparangetype=domain7range1_type, ipanttrusteddomainsid=domain7_sid)), expected=dict( result=dict( dn=unicode(domain7range1_dn), cn=[domain7range1], objectclass=[u'ipaIDrange', u'ipatrustedaddomainrange'], ipabaseid=[unicode(domain7range1_base_id)], ipaidrangesize=[unicode(domain7range1_size)], ipanttrusteddomainsid=[unicode(domain7_sid)], iparangetyperaw=[u'ipa-ad-trust-posix'], iparangetype=[ u'Active Directory trust range with POSIX attributes' ], ), value=unicode(domain7range1), summary=u'Added ID range "%s"' % (domain7range1), ), ), dict( desc='Try to modify ipa-ad-trust-posix ID range %r with base RID' % (domain7range1), command=('idrange_mod', [domain7range1], dict(ipabaserid=domain7range1_base_rid)), expected=errors.ValidationError( name='ID Range setup', error='Option rid-base must not be used when IPA range ' 'type is ipa-ad-trust-posix'), ), # Testing prohibition of deletion of ranges belonging to active # trusted domains. dict( desc='Delete non-active AD trusted range %r' % domain1range1, command=('idrange_del', [domain1range1], {}), expected=dict( result=dict(failed=[]), value=[domain1range1], summary=u'Deleted ID range "%s"' % domain1range1, ), ), dict( desc='Try to delete active AD trusted range %r' % domain2range1, command=('idrange_del', [domain2range1], {}), expected=errors.DependentEntry(label='Active Trust domain', key=domain2range1, dependent=domain2), ), # Testing base range overlaps for ranges of different types and # different domains # - Base range overlaps # 1. ipa-ad-trust-posix type ranges from the same forest can overlap # on base ranges, use domain3range1 and domain3range2 dict( desc=('Modify ipa-ad-trust-posix range %r to overlap on base range' ' with posix range from the same domain' % (domain3range2)), command=('idrange_mod', [domain3range2], dict(ipabaseid=domain3range1_base_id)), expected=dict( result=dict( cn=[domain3range2], ipabaseid=[unicode(domain3range1_base_id)], ipaidrangesize=[unicode(domain3range2_size)], ipanttrusteddomainsid=[unicode(domain3_sid)], iparangetyperaw=[u'ipa-ad-trust-posix'], iparangetype=[ u'Active Directory trust range with POSIX ' 'attributes' ], ), value=domain3range2, summary=u'Modified ID range "%s"' % (domain3range2), ), ), # 2. ipa-ad-trust-posix type ranges from different forests cannot # overlap on base ranges, use domain3range1 and domain4range1 dict( desc=('Modify ipa-ad-trust-posix range %r to overlap on base range' ' with posix range from different domain' % (domain3range1)), command=('idrange_mod', [domain3range1], dict(ipabaseid=domain4range1_base_id)), expected=errors.DatabaseError( desc='Constraint violation', info='New base range overlaps with existing base range.'), ), # 3. ipa-ad-trust ranges from same forest cannot overlap on base ranges, # use domain5range1 and domain5range2 dict( desc=('Modify ipa-ad-trust range %r to overlap on base range' ' with posix range from the same domain' % (domain5range1)), command=('idrange_mod', [domain5range1], dict(ipabaseid=domain5range2_base_id)), expected=errors.DatabaseError( desc='Constraint violation', info='New base range overlaps with existing base range.'), ), # 4. ipa-ad-trust ranges from different forests cannot overlap on base # ranges, use domain5range1 and domain6range1 dict( desc=('Modify ipa-ad-trust range %r to overlap on base range' ' with posix range from different domain' % (domain5range1)), command=('idrange_mod', [domain5range1], dict(ipabaseid=domain6range1_base_id)), expected=errors.DatabaseError( desc='Constraint violation', info='New base range overlaps with existing base range.'), ), # - RID range overlaps # 1. Overlaps on base RID ranges are allowed for ranges from different # domains, use domain2range1 and domain5range1 dict( desc=('Modify ipa-ad-trust range %r to overlap on base RID' ' range with nonposix range from different domain' % (domain2range1)), command=('idrange_mod', [domain2range1], dict(ipabaserid=domain5range1_base_rid)), expected=dict( result=dict( cn=[domain2range1], ipabaseid=[unicode(domain2range1_base_id)], ipabaserid=[unicode(domain5range1_base_rid)], ipaidrangesize=[unicode(domain2range1_size)], ipanttrusteddomainsid=[unicode(domain2_sid)], iparangetyperaw=[u'ipa-ad-trust'], iparangetype=[u'Active Directory domain range'], ), value=domain2range1, summary=u'Modified ID range "%s"' % (domain2range1), ), ), # 2. ipa-ad-trust ranges from the same forest cannot overlap on base # RID ranges, use domain5range1 and domain5range2 dict( desc=('Modify ipa-ad-trust range %r to overlap on base RID range' ' with range from the same domain' % (domain2range1)), command=('idrange_mod', [domain2range1], dict(ipabaserid=domain2range2_base_rid)), expected=errors.DatabaseError( desc='Constraint violation', info='New primary rid range overlaps with existing primary rid ' 'range.'), ), ]