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))
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): # The 3 valid calls are # ipa user-add-certmapdata LOGIN --subject xx --issuer yy # ipa user-add-certmapdata LOGIN [DATA] --certificate xx # ipa user-add-certmapdata LOGIN DATA # Check that at least one of the 3 formats is used try: certmapdatas = keys[1] or [] except IndexError: certmapdatas = [] issuer = options.get('issuer') subject = options.get('subject') certificates = options.get('certificate', []) # If only LOGIN is supplied, then we need either subject or issuer or # certificate if (not certmapdatas and not issuer and not subject and not certificates): raise errors.RequirementError(name='ipacertmapdata') # If subject or issuer is provided, other options are not allowed if subject or issuer: if certificates: raise errors.MutuallyExclusiveError( reason=_('cannot specify both subject/issuer ' 'and certificate')) if certmapdatas: raise errors.MutuallyExclusiveError( reason=_('cannot specify both subject/issuer ' 'and ipacertmapdata')) # If subject or issuer is provided, then the other one is required if not subject: raise errors.RequirementError(name='subject') if not issuer: raise errors.RequirementError(name='issuer') # if the command is called with --subject --issuer or --certificate # we need to add ipacertmapdata to the attrs_list in order to # display the resulting value in the command output if 'ipacertmapdata' not in attrs_list: attrs_list.append('ipacertmapdata') self._convert_options_to_certmap( entry_attrs, issuer=issuer, subject=subject, certificates=certificates) return dn
def execute(self, *args, **options): results = [] for arg in args[0]: 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.Command: raise errors.CommandError(name=name) 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) newkw.setdefault('version', options['version']) result = api.Command[name](*a, **newkw) self.info( '%s: batch: %s(%s): SUCCESS', context.principal, 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__), ) results.append(result) return dict(count=len(results) , results=results)
def __gen_lsa_connection(self, binding): if self.creds is None: raise errors.RequirementError(name=_('CIFS credentials object')) try: result = lsa.lsarpc(binding, self.parm, self.creds) return result except RuntimeError, (num, message): raise assess_dcerpc_exception(num=num, message=message)
def _get_method_name(self, name, *params): """Get a method name for XML-RPC introspection commands""" if not params: raise errors.RequirementError(name='method name') elif len(params) > 1: raise errors.MaxArgumentError(name=name, count=1) [method_name] = params return method_name
def interactive_prompt_callback(self, kw): server_list = kw.get('cn') if not server_list: raise errors.RequirementError(name='cn') self.api.Backend.textui.print_plain( _("Removing %(servers)s from replication topology, " "please wait...") % {'servers': ', '.join(server_list)})
def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs): # Check again for GID requirement in case someone tried to clear it # using --setattr. if call_func.__name__ == 'update_entry': if isinstance(exc, errors.ObjectclassViolation): if 'gidNumber' in str(exc) and 'posixGroup' in str(exc): raise errors.RequirementError(name='gidnumber') raise exc
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): # The valid calls are # ipa idp-add --provider provider IDP [client details] # ipa idp-add --dev-auth-uri auth --token-uri token-uri IDP auth = options.get('ipaidpauthendpoint') devauth = options.get('ipaidpdevauthendpoint') token = options.get('ipaidptokenendpoint') userinfo = options.get('ipaidpuserinfoendpoint') jwks = options.get('ipaidpkeysendpoint') provider = options.get('ipaidpprovider') # If the provider is supplied, reject individual endpoints if any([devauth, auth, token, userinfo, jwks]): if provider: raise errors.MutuallyExclusiveError( reason=_('cannot specify both individual endpoints ' 'and IdP provider')) # If there is no --provider, individual endpoints required if not provider and not devauth: raise errors.RequirementError(name='dev-auth-uri or provider') if not provider and not auth: raise errors.RequirementError(name='auth-uri or provider') if not provider and not token: raise errors.RequirementError(name='token-uri or provider') if not provider and not userinfo: raise errors.RequirementError(name='userinfo-uri or provider') # if the command is called with --provider we need to add # ipaidpdevauthendpoint, ipaidpauthendpoint, and ipaidptokenendpoint # to the attrs list in order to display the resulting value in # the command output for endpoint in [ 'ipaidpauthendpoint', 'ipaidpdevauthendpoint', 'ipaidptokenendpoint', 'ipaidpuserinfoendpoint', 'ipaidpkeysendpoint' ]: if endpoint not in attrs_list: attrs_list.append(endpoint) self._convert_provider_to_endpoints(entry_attrs, provider=provider, elements=options) return dn
def test_delete_required_config_entry(self, user): """ Try deleting a required config entry """ command = user.make_command( 'config_mod', **dict(delattr=u'ipasearchrecordslimit=100') ) with raises_exact(errors.RequirementError( name='searchrecordslimit')): command()
def test_create_missing_clientid(self): """ Creation with missing --client-id""" idp_with_provider = IdpTracker('idp_with_provider', ipaidptokenendpoint=google_token, ipaidpdevauthendpoint=google_devauth, ipaidpauthendpoint=google_auth) idp_with_provider.track_create() command = idp_with_provider.make_create_command() with raises_exact(errors.RequirementError(name='client_id')): command()
def test_create_missing_authendpoint(self): """ Creation with missing --dev-auth-uri and --auth-uri""" idp_with_provider = IdpTracker('idp_with_provider', ipaidptokenendpoint=google_token, ipaidpclientid="idpclient1") idp_with_provider.track_create() command = idp_with_provider.make_create_command() with raises_exact( errors.RequirementError(name='dev-auth-uri or provider')): command()
def execute(self, aciname, **kw): if 'attrs' in kw and kw['attrs'] is None: raise errors.RequirementError(name='attrs') kw['aciprefix'] = ACI_PREFIX result = api.Command['aci_mod'](aciname, **kw)['result'] self.obj.postprocess_result(result) return dict( result=result, value=pkey_to_value(aciname, kw), )
def pre_callback(self, ldap, dn, entry_attrs, *keys, **options): assert isinstance(dn, DN) is_protected_group = keys[-1] in PROTECTED_GROUPS if 'rename' in options or 'cn' in entry_attrs: if is_protected_group: raise errors.ProtectedEntryError(label=u'group', key=keys[-1], reason=u'Cannot be renamed') if ('posix' in options and options['posix']) or 'gidnumber' in options: old_entry_attrs = ldap.get_entry(dn, ['objectclass']) dn = old_entry_attrs.dn if 'ipaexternalgroup' in old_entry_attrs['objectclass']: raise errors.ExternalGroupViolation() if 'posixgroup' in old_entry_attrs['objectclass']: if options['posix']: raise errors.AlreadyPosixGroup() else: old_entry_attrs['objectclass'].append('posixgroup') entry_attrs['objectclass'] = old_entry_attrs['objectclass'] if 'gidnumber' not in options: entry_attrs['gidnumber'] = baseldap.DNA_MAGIC if options['external']: if is_protected_group: raise errors.ProtectedEntryError( label=u'group', key=keys[-1], reason=u'Cannot support external non-IPA members') old_entry_attrs = ldap.get_entry(dn, ['objectclass']) dn = old_entry_attrs.dn if 'posixgroup' in old_entry_attrs['objectclass']: raise errors.PosixGroupViolation() if 'ipaexternalgroup' in old_entry_attrs['objectclass']: raise errors.AlreadyExternalGroup() else: old_entry_attrs['objectclass'].append('ipaexternalgroup') entry_attrs['objectclass'] = old_entry_attrs['objectclass'] # Can't check for this in a validator because we lack context if 'gidnumber' in options and options['gidnumber'] is None: raise errors.RequirementError(name='gidnumber') return dn
def execute(self, *keys, **options): if not _murmur_installed and 'base_id' not in options: raise errors.ValidationError(name=_('missing base_id'), error=_('pysss_murmur is not available on the server ' \ 'and no base-id is given.')) if 'trust_type' in options: if options['trust_type'] == u'ad': result = self.execute_ad(*keys, **options) else: raise errors.ValidationError(name=_('trust type'), error=_('only "ad" is supported')) else: raise errors.RequirementError(name=_('trust type')) self.add_range(*keys, **options) trust_filter = "cn=%s" % result['value'] ldap = self.obj.backend (trusts, truncated) = ldap.find_entries(base_dn=DN(api.env.container_trusts, api.env.basedn), filter=trust_filter) result['result'] = trusts[0][1] result['result']['trusttype'] = [ trust_type_string(result['result']['ipanttrusttype'][0]) ] result['result']['trustdirection'] = [ trust_direction_string(result['result']['ipanttrustdirection'][0]) ] result['result']['truststatus'] = [ trust_status_string(result['verified']) ] del result['verified'] return result
-1073741790: access_denied_error, -1073741715: access_denied_error, -1073741614: access_denied_error, -1073741603: errors.ValidationError(name=_('AD domain controller'), error=_('unsupported functional level')), } dcerpc_error_messages = { "NT_STATUS_OBJECT_NAME_NOT_FOUND": errors.NotFound(reason=_('Cannot find specified domain or server name')), "NT_STATUS_INVALID_PARAMETER_MIX": errors.RequirementError( name=_('At least the domain or IP address should be specified')), } def assess_dcerpc_exception(num=None, message=None): """ Takes error returned by Samba bindings and converts it into an IPA error class. """ if num and num in dcerpc_error_codes: return dcerpc_error_codes[num] if message and message in dcerpc_error_messages: return dcerpc_error_messages[message] reason = _('''CIFS server communication error: code "%(num)s", message "%(message)s" (both may be "None")''') % dict( num=num, message=message)
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_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=''), ), ]
class test_raduisproxy(Declarative): cleanup_commands = [ ('radiusproxy_del', [radius1], {}), ('user_del', [user1], {}), ] tests = [ dict( desc='Try to retrieve non-existent %r' % radius1, command=('radiusproxy_show', [radius1], {}), expected=errors.NotFound( reason=u'%s: RADIUS proxy server not found' % radius1), ), dict( desc='Try to update non-existent %r' % radius1, command=('radiusproxy_mod', [radius1], {}), expected=errors.NotFound( reason=_('%s: RADIUS proxy server not found') % radius1), ), dict( desc='Try to delete non-existent %r' % radius1, command=('radiusproxy_del', [radius1], {}), expected=errors.NotFound( reason=_('%s: RADIUS proxy server not found') % radius1), ), dict( desc='Try to add multiple radius proxy server %r' % radius1, command=('radiusproxy_add', [radius1], dict( ipatokenradiusserver=radius1_fqdn, addattr=u'ipatokenradiusserver=radius1_fqdn', ipatokenradiussecret=password1, ), ), expected=errors.OnlyOneValueAllowed(attr='ipatokenradiusserver') ), dict( desc='Create %r' % radius1, command=('radiusproxy_add', [radius1], dict( ipatokenradiusserver=radius1_fqdn, ipatokenradiussecret=password1, ), ), expected=dict( value=radius1, summary=u'Added RADIUS proxy server "%s"' % radius1, result=dict( cn=[radius1], dn=radius1_dn, ipatokenradiussecret=[password1_bytes], ipatokenradiusserver=[radius1_fqdn], objectclass=objectclasses.radiusproxy, ), ), ), dict( desc='Try to create duplicate %r' % radius1, command=('radiusproxy_add', [radius1], dict( ipatokenradiusserver=radius1_fqdn, ipatokenradiussecret=password1, ), ), expected=errors.DuplicateEntry(message=_('RADIUS proxy server ' 'with name "%s" already exists') % radius1), ), dict( desc='Retrieve %r' % radius1, command=('radiusproxy_show', [radius1], {}), expected=dict( value=radius1, summary=None, result=dict( cn=[radius1], dn=radius1_dn, ipatokenradiusserver=[radius1_fqdn], ), ), ), dict( desc='Retrieve %r with all=True' % radius1, command=('radiusproxy_show', [radius1], dict(all=True)), expected=dict( value=radius1, summary=None, result=dict( cn=[radius1], dn=radius1_dn, ipatokenradiussecret=[password1_bytes], ipatokenradiusserver=[radius1_fqdn], objectclass=objectclasses.radiusproxy, ), ), ), ] + [ dict( desc='Set timeout of %s to %s (valid)' % (radius1, num), command=('radiusproxy_mod', [radius1], dict(ipatokenradiustimeout=num)), expected=dict( value=radius1, summary=u'Modified RADIUS proxy server "%s"' % radius1, result=dict( cn=[radius1], ipatokenradiusserver=[radius1_fqdn], ipatokenradiustimeout=[unicode(num)], ), ), ) for num in (1, 100) ] + [ dict( desc='Set timeout of %s to 0 (invalid)' % radius1, command=('radiusproxy_mod', [radius1], dict(ipatokenradiustimeout=0)), expected=errors.ValidationError( name='timeout', error=_('must be at least 1')), ), dict( desc='Unset timeout of %s' % radius1, command=('radiusproxy_mod', [radius1], dict(ipatokenradiustimeout=None)), expected=dict( value=radius1, summary=u'Modified RADIUS proxy server "%s"' % radius1, result=dict( cn=[radius1], ipatokenradiusserver=[radius1_fqdn], ), ), ), ] + [ dict( desc='Set retries of %s to %s (valid)' % (radius1, num), command=('radiusproxy_mod', [radius1], dict(ipatokenradiusretries=num)), expected=dict( value=radius1, summary=u'Modified RADIUS proxy server "%s"' % radius1, result=dict( cn=[radius1], ipatokenradiusserver=[radius1_fqdn], ipatokenradiusretries=[unicode(num)], ), ), ) for num in (0, 4, 10) ] + [ dict( desc='Set retries of %s to %s (invalid)' % (radius1, num), command=('radiusproxy_mod', [radius1], dict(ipatokenradiusretries=num)), expected=errors.ValidationError( name='retries', error=reason), ) for num, reason in ((-1, 'must be at least 0'), (11, 'can be at most 10'), (100, 'can be at most 10')) ] + [ dict( desc='Unset retries of %s' % radius1, command=('radiusproxy_mod', [radius1], dict(ipatokenradiusretries=None)), expected=dict( value=radius1, summary=u'Modified RADIUS proxy server "%s"' % radius1, result=dict( cn=[radius1], ipatokenradiusserver=[radius1_fqdn], ), ), ), ] + [ dict( desc='Set server string of %s to %s (valid)' % (radius1, fqdn), command=('radiusproxy_mod', [radius1], dict(ipatokenradiusserver=fqdn)), expected=dict( value=radius1, summary=u'Modified RADIUS proxy server "%s"' % radius1, result=dict( cn=[radius1], ipatokenradiusserver=[fqdn], ), ), ) for fqdn in (radius1_fqdn + u':12345', radius1_fqdn) ] + [ dict( desc='Set server string of %s to %s (invalid)' % (radius1, fqdn), command=('radiusproxy_mod', [radius1], dict(ipatokenradiusserver=fqdn)), expected=errors.ValidationError(name='ipatokenradiusserver', error=error), ) for fqdn, error in ( (radius1_fqdn + u':0x5a', 'invalid port number'), (radius1_fqdn + u':1:2:3', "only letters, numbers, '_', '-' are allowed. DNS label may not " "start or end with '-'"), (u'bogus', 'not fully qualified'), ) ] + [ dict( desc='Try to unset server string of %s' % radius1, command=('radiusproxy_mod', [radius1], dict(ipatokenradiusserver=None)), expected=errors.RequirementError(name='server'), ), dict( desc='Set userattr of %s to %s (valid)' % (radius1, u'cn'), command=('radiusproxy_mod', [radius1], dict(ipatokenusermapattribute=u'cn')), expected=dict( value=radius1, summary=u'Modified RADIUS proxy server "%s"' % radius1, result=dict( cn=[radius1], ipatokenradiusserver=[radius1_fqdn], ipatokenusermapattribute=[u'cn'], ), ), ), dict( desc='Set userattr of %s to %s (invalid)' % (radius1, u'$%^&*'), command=('radiusproxy_mod', [radius1], dict(ipatokenusermapattribute=u'$%^&*')), expected=errors.ValidationError(name='ipatokenusermapattribute', error=u'invalid attribute name'), ), dict( desc='Unset userattr of %s' % radius1, command=('radiusproxy_mod', [radius1], dict(ipatokenusermapattribute=None)), expected=dict( value=radius1, summary=u'Modified RADIUS proxy server "%s"' % radius1, result=dict( cn=[radius1], ipatokenradiusserver=[radius1_fqdn], ), ), ), dict( desc='Set desc of %s' % radius1, command=('radiusproxy_mod', [radius1], dict(description=u'a virtual radius server')), expected=dict( value=radius1, summary=u'Modified RADIUS proxy server "%s"' % radius1, result=dict( cn=[radius1], ipatokenradiusserver=[radius1_fqdn], description=[u'a virtual radius server'], ), ), ), dict( desc='Unset desc of %s' % radius1, command=('radiusproxy_mod', [radius1], dict(description=None)), expected=dict( value=radius1, summary=u'Modified RADIUS proxy server "%s"' % radius1, result=dict( cn=[radius1], ipatokenradiusserver=[radius1_fqdn], ), ), ), dict( desc='Create "%s"' % user1, command=( 'user_add', [user1], dict(givenname=u'Test', sn=u'User1') ), expected=dict( value=user1, summary=u'Added user "%s"' % user1, result=get_user_result(user1, u'Test', u'User1', 'add'), ), ), dict( desc='Set radiusconfiglink of %r' % user1, command=('user_mod', [user1], dict(ipatokenradiusconfiglink=radius1,)), expected=dict( result=get_user_result(user1, u'Test', u'User1', 'mod', ipatokenradiusconfiglink=[radius1]), value=user1, summary='Modified user "%s"' % user1, ), ), dict( desc='Retrieve %r to verify %s is output' % (radius1, user1), command=('radiusproxy_show', [radius1], {}), expected=dict( value=radius1, summary=None, result=dict( cn=[radius1], dn=radius1_dn, ipatokenradiusserver=[radius1_fqdn], ), ), ), dict( desc='Retrieve %r to verify %s is output' % (user1, radius1), command=('user_show', [user1], {}), expected=dict( value=user1, summary=None, result=get_user_result(user1, u'Test', u'User1', 'show', ipatokenradiusconfiglink=[radius1]), ), ), dict( desc='Delete %r' % radius1, command=('radiusproxy_del', [radius1], {}), expected=dict( value=[radius1], summary=u'Deleted RADIUS proxy server "%s"' % radius1, result=dict(failed=[]), ), ), dict( desc='Retrieve %s to verify link is deleted' % user1, command=('user_show', [user1], {}), expected=dict( value=user1, summary=None, result=get_user_result(user1, u'Test', u'User1', 'show'), ), ), ]
class test_config(Declarative): cleanup_commands = [] tests = [ dict( desc='Try to add an unrelated objectclass to ipauserobjectclasses', command=('config_mod', [], dict(addattr=u'ipauserobjectclasses=ipahost')), expected=dict( result=lambda d: 'ipahost' in d['ipauserobjectclasses'], value=None, summary=None, ), ), dict( desc='Remove the unrelated objectclass from ipauserobjectclasses', command=('config_mod', [], dict(delattr=u'ipauserobjectclasses=ipahost')), expected=dict( result=lambda d: 'ipahost' not in d['ipauserobjectclasses'], value=None, summary=None, ), ), dict( desc='Try to remove ipausersearchfields', command= ('config_mod', [], dict( delattr= u'ipausersearchfields=uid,givenname,sn,telephonenumber,ou,title' )), expected=errors.RequirementError(name='usersearch'), ), dict( desc='Add uppercased attribute to ipausersearchfields', command=( 'config_mod', [], dict( ipausersearchfields= u'uid,givenname,sn,telephonenumber,ou,title,Description')), expected=dict( result=lambda d: (d['ipausersearchfields'] == (u'uid,givenname,sn,telephonenumber,ou,title,description', )), value=None, summary=None, ), ), dict( desc='Remove uppercased attribute from ipausersearchfields', command=('config_mod', [], dict(ipausersearchfields= u'uid,givenname,sn,telephonenumber,ou,title', )), expected=dict( result=lambda d: (d['ipausersearchfields'] == (u'uid,givenname,sn,telephonenumber,ou,title', )), value=None, summary=None, ), ), dict( desc= 'Try to set ipaselinuxusermapdefault not in selinux order list', command=('config_mod', [], dict(ipaselinuxusermapdefault=u'unknown_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='SELinux user map default user not in order list'), ), dict( desc='Try to set invalid ipaselinuxusermapdefault', command=('config_mod', [], dict(ipaselinuxusermapdefault=u'foo')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='Invalid MLS value, must match {}, where max level ' '{}'.format(platformconstants.SELINUX_MLS_REGEX, platformconstants.SELINUX_MLS_MAX)), ), dict( desc='Try to set invalid ipaselinuxusermapdefault with setattr', command=('config_mod', [], dict(setattr=u'ipaselinuxusermapdefault=unknown_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='SELinux user map default user not in order list'), ), dict( desc= 'Try to set ipaselinuxusermaporder without ipaselinuxusermapdefault out of it', command=('config_mod', [], dict(ipaselinuxusermaporder=u'notfound_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermaporder', error='SELinux user map default user not in order list'), ), dict( desc='Try to set invalid ipaselinuxusermaporder', command=('config_mod', [], dict(ipaselinuxusermaporder=u'$')), expected=errors.ValidationError( name='ipaselinuxusermaporder', error='A list of SELinux users delimited by $ expected'), ), dict( desc='Try to set invalid selinux user in ipaselinuxusermaporder', command=('config_mod', [], dict(ipaselinuxusermaporder=u'baduser')), expected=errors.ValidationError( name='ipaselinuxusermaporder', error='SELinux user \'baduser\' is not valid: Invalid MLS ' 'value, must match {}, where max level {}'.format( platformconstants.SELINUX_MLS_REGEX, platformconstants.SELINUX_MLS_MAX)), ), dict( desc='Try to set new selinux order and invalid default user', command=('config_mod', [], dict(ipaselinuxusermaporder=u'foo:s0', ipaselinuxusermapdefault=u'unknown_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='SELinux user map default user not in order list'), ), dict( desc='Set user auth type', command=('config_mod', [], dict(ipauserauthtype=u'password')), expected=dict( result=lambda d: d['ipauserauthtype'] == (u'password', ), value=None, summary=None, ), ), dict( desc='Check user auth type', command=('config_show', [], {}), expected=dict( result=lambda d: d['ipauserauthtype'] == (u'password', ), value=None, summary=None, ), ), dict( desc='Unset user auth type', command=('config_mod', [], dict(ipauserauthtype=None)), expected=dict( result=lambda d: 'ipauserauthtype' not in d, value=None, summary=None, ), ), dict( desc='Set maximum username length higher than limit of 255', command=('config_mod', [], dict(ipamaxusernamelength=256)), expected=errors.ValidationError(name='maxusername', error='can be at most 255'), ), dict( desc='Set maximum username length equal to limit 255', command=('config_mod', [], dict(ipamaxusernamelength=255)), expected=dict( result=lambda d: d['ipamaxusernamelength'] == (u'255', ), value=None, summary=None, ), ), # Cleanup after previous test - returns max username length to 32 dict( desc='Return maximum username length to default value', command=('config_mod', [], dict(ipamaxusernamelength=32)), expected=dict( result=lambda d: d['ipamaxusernamelength'] == (u'32', ), value=None, summary=None, ), ), dict( desc='Check if domain resolution order does not accept SLD', command=('config_mod', [], { 'ipadomainresolutionorder': u'{domain}:{sl_domain}'.format(domain=domain, sl_domain=sl_domain) }), expected=errors.ValidationError( name=u'ipadomainresolutionorder', error=(u"Invalid domain name '{}': " "single label domains are not supported" ).format(sl_domain), ), ), dict( desc='Set the number of search records to -1 (unlimited)', command=( 'config_mod', [], { 'ipasearchrecordslimit': u'-1', }, ), expected={ 'result': lambda d: d['ipasearchrecordslimit'] == (u'-1', ), 'summary': None, 'value': None, }, ), dict( desc='Set the number of search records to greater than 10', command=( 'config_mod', [], { 'ipasearchrecordslimit': u'100', }, ), expected={ 'result': lambda d: d['ipasearchrecordslimit'] == (u'100', ), 'summary': None, 'value': None, }, ), dict( desc='Set the number of search records to lower than -1', command=( 'config_mod', [], { 'ipasearchrecordslimit': u'-10', }, ), expected=errors.ValidationError( name=u'searchrecordslimit', error=u'must be at least 10', ), ), dict( desc='Set the number of search records to lower than 10', command=( 'config_mod', [], { 'ipasearchrecordslimit': u'1', }, ), expected=errors.ValidationError( name=u'searchrecordslimit', error=u'must be at least 10', ), ), dict( desc='Set the number of search records to zero (unlimited)', command=( 'config_mod', [], { 'ipasearchrecordslimit': u'0', }, ), expected={ 'result': lambda d: d['ipasearchrecordslimit'] == (u'-1', ), 'summary': None, 'value': None, }, ), dict( desc='Set the number of search records back to 100', command=( 'config_mod', [], { 'ipasearchrecordslimit': u'100', }, ), expected={ 'result': lambda d: d['ipasearchrecordslimit'] == (u'100', ), 'summary': None, 'value': None, }, ), ]
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): assert isinstance(dn, DN) # then givenname and sn are required attributes if 'givenname' not in entry_attrs: raise errors.RequirementError(name='givenname', error=_('givenname is required')) if 'sn' not in entry_attrs: raise errors.RequirementError(name='sn', error=_('sn is required')) # we don't want an user private group to be created for this user # add NO_UPG_MAGIC description attribute to let the DS plugin know entry_attrs.setdefault('description', []) entry_attrs['description'].append(NO_UPG_MAGIC) # uidNumber/gidNumber entry_attrs.setdefault('uidnumber', baseldap.DNA_MAGIC) entry_attrs.setdefault('gidnumber', baseldap.DNA_MAGIC) if not client_has_capability(options['version'], 'optional_uid_params'): # https://fedorahosted.org/freeipa/ticket/2886 # Old clients say 999 (OLD_DNA_MAGIC) when they really mean # "assign a value dynamically". OLD_DNA_MAGIC = 999 if entry_attrs.get('uidnumber') == OLD_DNA_MAGIC: entry_attrs['uidnumber'] = baseldap.DNA_MAGIC if entry_attrs.get('gidnumber') == OLD_DNA_MAGIC: entry_attrs['gidnumber'] = baseldap.DNA_MAGIC # Check the lenght of the RDN (uid) value config = ldap.get_ipa_config() if 'ipamaxusernamelength' in config: if len(keys[-1]) > int(config.get('ipamaxusernamelength')[0]): raise errors.ValidationError( name=self.obj.primary_key.cli_name, error=_('can be at most %(len)d characters') % dict(len=int(config.get('ipamaxusernamelength')[0]))) default_shell = config.get('ipadefaultloginshell', [platformconstants.DEFAULT_SHELL])[0] entry_attrs.setdefault('loginshell', default_shell) # hack so we can request separate first and last name in CLI full_name = '%s %s' % (entry_attrs['givenname'], entry_attrs['sn']) entry_attrs.setdefault('cn', full_name) # Homedirectory # (order is : option, placeholder (TBD), CLI default value (here in config)) if 'homedirectory' not in entry_attrs: # get home's root directory from config homes_root = config.get('ipahomesrootdir', [paths.HOME_DIR])[0] # build user's home directory based on his uid entry_attrs['homedirectory'] = posixpath.join(homes_root, keys[-1]) # Kerberos principal entry_attrs.setdefault('krbprincipalname', '%s@%s' % (entry_attrs['uid'], api.env.realm)) # If requested, generate a userpassword if 'userpassword' not in entry_attrs and options.get('random'): entry_attrs['userpassword'] = ipa_generate_password( entropy_bits=TMP_PWD_ENTROPY_BITS) # save the password so it can be displayed in post_callback setattr(context, 'randompassword', entry_attrs['userpassword']) # Check the email or create it if 'mail' in entry_attrs: entry_attrs['mail'] = self.obj.normalize_and_validate_email( entry_attrs['mail'], config) else: # No e-mail passed in. If we have a default e-mail domain set # then we'll add it automatically. defaultdomain = config.get('ipadefaultemaildomain', [None])[0] if defaultdomain: entry_attrs['mail'] = self.obj.normalize_and_validate_email( keys[-1], config) # If the manager is defined, check it is a ACTIVE user to validate it if 'manager' in entry_attrs: entry_attrs['manager'] = self.obj.normalize_manager( entry_attrs['manager'], self.obj.active_container_dn) if ('objectclass' in entry_attrs and 'userclass' in entry_attrs and 'ipauser' not in entry_attrs['objectclass']): entry_attrs['objectclass'].append('ipauser') if 'ipatokenradiusconfiglink' in entry_attrs: cl = entry_attrs['ipatokenradiusconfiglink'] if cl: if 'objectclass' not in entry_attrs: _entry = ldap.get_entry(dn, ['objectclass']) entry_attrs['objectclass'] = _entry['objectclass'] if 'ipatokenradiusproxyuser' not in entry_attrs['objectclass']: entry_attrs['objectclass'].append( 'ipatokenradiusproxyuser') answer = self.api.Object['radiusproxy'].get_dn_if_exists(cl) entry_attrs['ipatokenradiusconfiglink'] = answer self.pre_common_callback(ldap, dn, entry_attrs, attrs_list, *keys, **options) return dn
class test_config(Declarative): cleanup_commands = [] tests = [ dict( desc='Try to add an unrelated objectclass to ipauserobjectclasses', command=('config_mod', [], dict(addattr=u'ipauserobjectclasses=ipahost')), expected=dict( result=lambda d: 'ipahost' in d['ipauserobjectclasses'], value=None, summary=None, ), ), dict( desc='Remove the unrelated objectclass from ipauserobjectclasses', command=('config_mod', [], dict(delattr=u'ipauserobjectclasses=ipahost')), expected=dict( result=lambda d: 'ipahost' not in d['ipauserobjectclasses'], value=None, summary=None, ), ), dict( desc='Try to remove ipausersearchfields', command= ('config_mod', [], dict( delattr= u'ipausersearchfields=uid,givenname,sn,telephonenumber,ou,title' )), expected=errors.RequirementError(name='usersearch'), ), dict( desc='Add uppercased attribute to ipausersearchfields', command=( 'config_mod', [], dict( ipausersearchfields= u'uid,givenname,sn,telephonenumber,ou,title,Description')), expected=dict( result=lambda d: (d['ipausersearchfields'] == (u'uid,givenname,sn,telephonenumber,ou,title,description', )), value=None, summary=None, ), ), dict( desc='Remove uppercased attribute from ipausersearchfields', command=('config_mod', [], dict(ipausersearchfields= u'uid,givenname,sn,telephonenumber,ou,title', )), expected=dict( result=lambda d: (d['ipausersearchfields'] == (u'uid,givenname,sn,telephonenumber,ou,title', )), value=None, summary=None, ), ), dict( desc= 'Try to set ipaselinuxusermapdefault not in selinux order list', command=('config_mod', [], dict(ipaselinuxusermapdefault=u'unknown_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='SELinux user map default user not in order list'), ), dict( desc='Try to set invalid ipaselinuxusermapdefault', command=('config_mod', [], dict(ipaselinuxusermapdefault=u'foo')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='Invalid MLS value, must match s[0-15](-s[0-15])'), ), dict( desc='Try to set invalid ipaselinuxusermapdefault with setattr', command=('config_mod', [], dict(setattr=u'ipaselinuxusermapdefault=unknown_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='SELinux user map default user not in order list'), ), dict( desc= 'Try to set ipaselinuxusermaporder without ipaselinuxusermapdefault out of it', command=('config_mod', [], dict(ipaselinuxusermaporder=u'notfound_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermaporder', error='SELinux user map default user not in order list'), ), dict( desc='Try to set invalid ipaselinuxusermaporder', command=('config_mod', [], dict(ipaselinuxusermaporder=u'$')), expected=errors.ValidationError( name='ipaselinuxusermaporder', error='A list of SELinux users delimited by $ expected'), ), dict( desc='Try to set invalid selinux user in ipaselinuxusermaporder', command=('config_mod', [], dict(ipaselinuxusermaporder= u'unconfined_u:s0-s0:c0.c1023$baduser$guest_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermaporder', error='SELinux user \'baduser\' is not valid: Invalid MLS ' 'value, must match s[0-15](-s[0-15])'), ), dict( desc='Try to set new selinux order and invalid default user', command= ('config_mod', [], dict( ipaselinuxusermaporder= u'xguest_u:s0$guest_u:s0$user_u:s0-s0:c0.c1023$staff_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023', ipaselinuxusermapdefault=u'unknown_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='SELinux user map default user not in order list'), ), dict( desc='Set user auth type', command=('config_mod', [], dict(ipauserauthtype=u'password')), expected=dict( result=lambda d: d['ipauserauthtype'] == (u'password', ), value=None, summary=None, ), ), dict( desc='Check user auth type', command=('config_show', [], {}), expected=dict( result=lambda d: d['ipauserauthtype'] == (u'password', ), value=None, summary=None, ), ), dict( desc='Unset user auth type', command=('config_mod', [], dict(ipauserauthtype=None)), expected=dict( result=lambda d: 'ipauserauthtype' not in d, value=None, summary=None, ), ), dict( desc='Set maximum username length higher than limit of 255', command=('config_mod', [], dict(ipamaxusernamelength=256)), expected=errors.ValidationError(name='maxusername', error='can be at most 255'), ), dict( desc='Set maximum username length equal to limit 255', command=('config_mod', [], dict(ipamaxusernamelength=255)), expected=dict( result=lambda d: d['ipamaxusernamelength'] == (u'255', ), value=None, summary=None, ), ), # Cleanup after previous test - returns max username length to 32 dict( desc='Return maximum username length to default value', command=('config_mod', [], dict(ipamaxusernamelength=32)), expected=dict( result=lambda d: d['ipamaxusernamelength'] == (u'32', ), value=None, summary=None, ), ), dict( desc='Check if domain resolution order does not accept SLD', command=('config_mod', [], { 'ipadomainresolutionorder': u'{domain}:{sl_domain}'.format(domain=domain, sl_domain=sl_domain) }), expected=errors.ValidationError( name=u'ipadomainresolutionorder', error=(u"Invalid domain name '{}': " "single label domains are not supported" ).format(sl_domain), ), ), ]
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)
class test_selfservice(Declarative): cleanup_commands = [ ('selfservice_del', [selfservice1], {}), ] tests = [ dict( desc='Try to retrieve non-existent %r' % selfservice1, command=('selfservice_show', [selfservice1], {}), expected=errors.NotFound(reason=u'ACI with name "%s" not found' % selfservice1), ), dict( desc='Try to update non-existent %r' % selfservice1, command=('selfservice_mod', [selfservice1], dict(permissions=u'write')), expected=errors.NotFound(reason=u'ACI with name "%s" not found' % selfservice1), ), dict( desc='Try to delete non-existent %r' % selfservice1, command=('selfservice_del', [selfservice1], {}), expected=errors.NotFound(reason=u'ACI with name "%s" not found' % selfservice1), ), dict( desc='Search for non-existent %r' % selfservice1, command=('selfservice_find', [selfservice1], {}), expected=dict( count=0, truncated=False, summary=u'0 selfservices matched', result=[], ), ), # Note that we add postalCode but expect postalcode. This tests # the attrs normalizer. dict( desc='Create %r' % selfservice1, command=('selfservice_add', [selfservice1], dict( attrs=[u'street', u'c', u'l', u'st', u'postalcode'], permissions=u'write', )), expected=dict( value=selfservice1, summary=u'Added selfservice "%s"' % selfservice1, result=dict( attrs=[u'street', u'c', u'l', u'st', u'postalcode'], permissions=[u'write'], selfaci=True, aciname=selfservice1, ), ), ), dict( desc='Try to create duplicate %r' % selfservice1, command=( 'selfservice_add', [selfservice1], dict( attrs=[u'street', u'c', u'l', u'st', u'postalcode'], permissions=u'write', ), ), expected=errors.DuplicateEntry(), ), dict( desc='Retrieve %r' % selfservice1, command=('selfservice_show', [selfservice1], {}), expected=dict( value=selfservice1, summary=None, result={ 'attrs': [u'street', u'c', u'l', u'st', u'postalcode'], 'permissions': [u'write'], 'selfaci': True, 'aciname': selfservice1, }, ), ), dict( desc='Retrieve %r with --raw' % selfservice1, command=('selfservice_show', [selfservice1], { 'raw': True }), expected=dict( value=selfservice1, summary=None, result={ 'aci': u'(targetattr = "street || c || l || st || postalcode")(version 3.0;acl "selfservice:testself";allow (write) userdn = "ldap:///self";)', }, ), ), dict( desc='Search for %r' % selfservice1, command=('selfservice_find', [selfservice1], {}), expected=dict( count=1, truncated=False, summary=u'1 selfservice matched', result=[ { 'attrs': [u'street', u'c', u'l', u'st', u'postalcode'], 'permissions': [u'write'], 'selfaci': True, 'aciname': selfservice1, }, ], ), ), dict( desc='Search for %r with --pkey-only' % selfservice1, command=('selfservice_find', [selfservice1], { 'pkey_only': True }), expected=dict( count=1, truncated=False, summary=u'1 selfservice matched', result=[ { 'aciname': selfservice1, }, ], ), ), dict( desc='Search for %r with empty attrs and permissions' % selfservice1, command=('selfservice_find', [selfservice1], { 'attrs': None, 'permissions': None }), expected=dict( count=1, truncated=False, summary=u'1 selfservice matched', result=[ { 'attrs': [u'street', u'c', u'l', u'st', u'postalcode'], 'permissions': [u'write'], 'selfaci': True, 'aciname': selfservice1, }, ], ), ), dict( desc='Search for %r with --raw' % selfservice1, command=('selfservice_find', [selfservice1], { 'raw': True }), expected=dict( count=1, truncated=False, summary=u'1 selfservice matched', result=[ { 'aci': u'(targetattr = "street || c || l || st || postalcode")(version 3.0;acl "selfservice:testself";allow (write) userdn = "ldap:///self";)' }, ], ), ), dict( desc='Update %r' % selfservice1, command=('selfservice_mod', [selfservice1], dict(permissions=u'read')), expected=dict( value=selfservice1, summary=u'Modified selfservice "%s"' % selfservice1, result=dict( attrs=[u'street', u'c', u'l', u'st', u'postalcode'], permissions=[u'read'], selfaci=True, aciname=selfservice1, ), ), ), dict( desc='Retrieve %r to verify update' % selfservice1, command=('selfservice_show', [selfservice1], {}), expected=dict( value=selfservice1, summary=None, result={ 'attrs': [u'street', u'c', u'l', u'st', u'postalcode'], 'permissions': [u'read'], 'selfaci': True, 'aciname': selfservice1, }, ), ), dict( desc='Try to update %r with empty permissions' % selfservice1, command=('selfservice_mod', [selfservice1], dict(permissions=None)), expected=errors.RequirementError(name='permissions'), ), dict( desc='Retrieve %r to verify invalid update' % selfservice1, command=('selfservice_show', [selfservice1], {}), expected=dict( value=selfservice1, summary=None, result={ 'attrs': [u'street', u'c', u'l', u'st', u'postalcode'], 'permissions': [u'read'], 'selfaci': True, 'aciname': selfservice1, }, ), ), dict(desc='Delete %r' % selfservice1, command=('selfservice_del', [selfservice1], {}), expected=dict( result=True, value=selfservice1, summary=u'Deleted selfservice "%s"' % selfservice1, )), dict( desc='Create invalid %r' % invalid_selfservice1, command=('selfservice_add', [invalid_selfservice1], dict( attrs=[u'street', u'c', u'l', u'st', u'postalcode'], permissions=u'write', )), expected=errors.ValidationError( name='name', error='May only contain letters, numbers, -, _, and space'), ), ]
def test_set_givenname_to_none_with_option(self, user): """ Try setting givenname to None with option in user """ user.ensure_exists() command = user.make_update_command(dict(givenname=None)) with raises_exact(errors.RequirementError(name='first')): command()
class test_config(Declarative): cleanup_commands = [] tests = [ dict( desc='Try to add an unrelated objectclass to ipauserobjectclasses', command=('config_mod', [], dict(addattr=u'ipauserobjectclasses=ipahost')), expected=dict( result=lambda d: 'ipahost' in d['ipauserobjectclasses'], value=None, summary=None, ), ), dict( desc='Remove the unrelated objectclass from ipauserobjectclasses', command=('config_mod', [], dict(delattr=u'ipauserobjectclasses=ipahost')), expected=dict( result=lambda d: 'ipahost' not in d['ipauserobjectclasses'], value=None, summary=None, ), ), dict( desc='Try to remove ipausersearchfields', command= ('config_mod', [], dict( delattr= u'ipausersearchfields=uid,givenname,sn,telephonenumber,ou,title' )), expected=errors.RequirementError(name='ipausersearchfields'), ), dict( desc= 'Try to set ipaselinuxusermapdefault not in selinux order list', command=('config_mod', [], dict(ipaselinuxusermapdefault=u'unknown_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='SELinux user map default user not in order list'), ), dict( desc='Try to set invalid ipaselinuxusermapdefault', command=('config_mod', [], dict(ipaselinuxusermapdefault=u'foo')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='Invalid MLS value, must match s[0-15](-s[0-15])'), ), dict( desc='Try to set invalid ipaselinuxusermapdefault with setattr', command=('config_mod', [], dict(setattr=u'ipaselinuxusermapdefault=unknown_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='SELinux user map default user not in order list'), ), dict( desc= 'Try to set ipaselinuxusermaporder without ipaselinuxusermapdefault out of it', command=('config_mod', [], dict(ipaselinuxusermaporder=u'notfound_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermaporder', error='SELinux user map default user not in order list'), ), dict( desc='Try to set invalid ipaselinuxusermaporder', command=('config_mod', [], dict(ipaselinuxusermaporder=u'$')), expected=errors.ValidationError( name='ipaselinuxusermaporder', error='A list of SELinux users delimited by $ expected'), ), dict( desc='Try to set invalid selinux user in ipaselinuxusermaporder', command=('config_mod', [], dict(ipaselinuxusermaporder= u'unconfined_u:s0-s0:c0.c1023$baduser$guest_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermaporder', error='SELinux user \'baduser\' is not valid: Invalid MLS ' 'value, must match s[0-15](-s[0-15])'), ), dict( desc='Try to set new selinux order and invalid default user', command= ('config_mod', [], dict( ipaselinuxusermaporder= u'xguest_u:s0$guest_u:s0$user_u:s0-s0:c0.c1023$staff_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023', ipaselinuxusermapdefault=u'unknown_u:s0')), expected=errors.ValidationError( name='ipaselinuxusermapdefault', error='SELinux user map default user not in order list'), ), dict( desc='Set user auth type', command=('config_mod', [], dict(ipauserauthtype=u'password')), expected=dict( result=lambda d: d['ipauserauthtype'] == (u'password', ), value=None, summary=None, ), ), dict( desc='Check user auth type', command=('config_show', [], {}), expected=dict( result=lambda d: d['ipauserauthtype'] == (u'password', ), value=None, summary=None, ), ), dict( desc='Unset user auth type', command=('config_mod', [], dict(ipauserauthtype=None)), expected=dict( result=lambda d: 'ipauserauthtype' not in d, value=None, summary=None, ), ), ]