示例#1
0
    def _validate_request(self, request):
        """
        Check that an individual request in a batch is parseable and the
        commands exists.
        """
        if 'method' not in request:
            raise errors.RequirementError(name='method')
        if 'params' not in request:
            raise errors.RequirementError(name='params')
        name = request['method']
        if (name not in self.api.Command
                or isinstance(self.api.Command[name], Local)):
            raise errors.CommandError(name=name)

        # If params are not formated as a tuple(list, dict)
        # the following lines will raise an exception
        # that triggers an internal server error
        # Raise a ConversionError instead to report the issue
        # to the client
        try:
            a, kw = request['params']
            newkw = dict((str(k), v) for k, v in kw.items())
            api.Command[name].args_options_2_params(*a, **newkw)
        except (AttributeError, ValueError, TypeError):
            raise errors.ConversionError(
                name='params', error=_(u'must contain a tuple (list, dict)'))
        except Exception as e:
            raise errors.ConversionError(name='params', error=str(e))
示例#2
0
def verify_trusted_domain_object_type(validator, desired_type, name_or_sid):

    object_type = validator.get_trusted_domain_object_type(name_or_sid)

    if object_type == desired_type:
        # In case SSSD returns the same type as the type being
        # searched, no problems here.
        return True

    elif desired_type == 'user' and object_type == 'both':
        # Type both denotes users with magic private groups.
        # Overriding attributes for such users is OK.
        return True

    elif desired_type == 'group' and object_type == 'both':
        # However, overriding attributes for magic private groups
        # does not make sense. One should override the GID of
        # the user itself.

        raise errors.ConversionError(
            name='identifier',
            error=_('You are trying to reference a magic private group '
                    'which is not allowed to be overridden. '
                    'Try overriding the GID attribute of the '
                    'corresponding user instead.')
            )

    return False
示例#3
0
 def test_update_gid_string(self, stageduser):
     stageduser.ensure_exists()
     command = stageduser.make_update_command(
         updates={u'gidnumber': u'text'})
     with raises_exact(errors.ConversionError(
             message=u'invalid \'gidnumber\': must be an integer')):
         command()
示例#4
0
 def test_create_uid_string(self, stageduser):
     stageduser.ensure_missing()
     command = stageduser.make_create_command(
         options={u'uidnumber': u'text'})
     with raises_exact(errors.ConversionError(
             message=u'invalid \'uid\': must be an integer')):
         command()
示例#5
0
 def test_set_nonnumeric_maxfail(self, user):
     """ Try setting non-numeric maxfail """
     command = user.make_command(
         'pwpolicy_mod', **dict(krbpwdmaxfailure=u'abc')
     )
     with raises_exact(errors.ConversionError(
             name='maxfail', error='must be an integer')):
         command()
示例#6
0
 def test_add_certmap_multiple_issuer(self, certmap_user):
     certmap_user.ensure_exists()
     cmd = certmap_user.make_command('user_add_certmapdata',
                                     certmap_user.name)
     with raises_exact(
             errors.ConversionError(name='issuer',
                                    error=u"Only one value is allowed")):
         cmd(issuer=(u'CN=issuer1', u'CN=issuer2'), subject=u'CN=subject')
示例#7
0
 def test_create_krbprincipal_malformed(self, stageduser):
     stageduser.ensure_missing()
     command = stageduser.make_create_command(
         options={u'krbprincipalname': invalidrealm2})
     with raises_exact(errors.ConversionError(
             name='principal', error="Malformed principal: '{}'".format(
                 invalidrealm2))):
         command()
示例#8
0
    def test_create_with_malformed_principal(self):
        """ Try to create user with wrongly formed principal """
        testuser = UserTracker(
            name=u'tuser1', givenname=u'Test', sn=u'Tuser1',
            krbprincipalname=u'tuser1@[email protected]'
        )

        command = testuser.make_create_command()
        with raises_exact(errors.ConversionError(
                name='principal', error="Malformed principal: '{}'".format(
                    testuser.kwargs['krbprincipalname']))):
            command()
def create_dict(desc, param, param_name, value, error):
    cmd_args = dict()
    cmd_args[param] = value
    if value != u'abc123':
        return dict(desc=desc,
                    command=('krbtpolicy_mod', [user1], cmd_args),
                    expected=errors.ValidationError(name=param_name,
                                                    error=error))
    else:
        return dict(desc=desc,
                    command=('krbtpolicy_mod', [user1], cmd_args),
                    expected=errors.ConversionError(name=param_name,
                                                    error=error))
示例#10
0
    def test_set_invalid_principal_expiration(self, user):
        """ Try to set incorrent principal expiration value for user """
        user.ensure_exists()
        command = user.make_update_command(
            dict(krbprincipalexpiration=invalid_expiration_string))

        with raises_exact(
                errors.ConversionError(
                    name='principal_expiration',
                    error=(
                        u'does not match any of accepted formats: '
                        '%Y%m%d%H%M%SZ, %Y-%m-%dT%H:%M:%SZ, %Y-%m-%dT%H:%MZ, '
                        '%Y-%m-%dZ, %Y-%m-%d %H:%M:%SZ, %Y-%m-%d %H:%MZ'))):
            command()
示例#11
0
 def test_invalid_name(self, location_invalid):
     command = location_invalid.make_create_command()
     with raises_exact(
             errors.ConversionError(name=u'name',
                                    error=u"empty DNS label")):
         command()
示例#12
0
    def execute(self, methods=None, **options):
        results = []
        for arg in (methods or []):
            params = dict()
            name = None
            try:
                if 'method' not in arg:
                    raise errors.RequirementError(name='method')
                if 'params' not in arg:
                    raise errors.RequirementError(name='params')
                name = arg['method']
                if (name not in self.api.Command
                        or isinstance(self.api.Command[name], Local)):
                    raise errors.CommandError(name=name)

                # If params are not formated as a tuple(list, dict)
                # the following lines will raise an exception
                # that triggers an internal server error
                # Raise a ConversionError instead to report the issue
                # to the client
                try:
                    a, kw = arg['params']
                    newkw = dict((str(k), v) for k, v in kw.items())
                    params = api.Command[name].args_options_2_params(
                        *a, **newkw)
                except (AttributeError, ValueError, TypeError):
                    raise errors.ConversionError(
                        name='params',
                        error=_(u'must contain a tuple (list, dict)'))
                newkw.setdefault('version', options['version'])

                result = api.Command[name](*a, **newkw)
                self.info('%s: batch: %s(%s): SUCCESS',
                          getattr(context, 'principal', 'UNKNOWN'), name,
                          ', '.join(api.Command[name]._repr_iter(**params)))
                result['error'] = None
            except Exception as e:
                if isinstance(e, errors.RequirementError) or \
                    isinstance(e, errors.CommandError):
                    self.info(
                        '%s: batch: %s',
                        context.principal,  # pylint: disable=no-member
                        e.__class__.__name__)
                else:
                    self.info(
                        '%s: batch: %s(%s): %s',
                        context.principal,
                        name,  # pylint: disable=no-member
                        ', '.join(api.Command[name]._repr_iter(**params)),
                        e.__class__.__name__)
                if isinstance(e, errors.PublicError):
                    reported_error = e
                else:
                    reported_error = errors.InternalError()
                result = dict(
                    error=reported_error.strerror,
                    error_code=reported_error.errno,
                    error_name=unicode(type(reported_error).__name__),
                    error_kw=reported_error.kw,
                )
            results.append(result)
        return dict(count=len(results), results=results)
示例#13
0
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=''),
        ),
    ]
示例#14
0
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=''),
        ),
    ]