def execute(self, *keys, **options): ''' A stage entry may be taken from the Delete container. In that case we rather do 'MODRDN' than 'ADD'. ''' if options.get('from_delete'): ldap = self.obj.backend staging_dn = self.obj.get_dn(*keys, **options) delete_dn = DN(staging_dn[0], self.obj.delete_container_dn, api.env.basedn) # Check that this value is a Active user try: entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(delete_dn, ['dn']) except errors.NotFound: raise self._exc_wrapper(keys, options, ldap.move_entry_newsuperior)( delete_dn, str(DN(self.obj.stage_container_dn, api.env.basedn))) entry_attrs = entry_to_dict(entry_attrs, **options) entry_attrs['dn'] = delete_dn if self.obj.primary_key and keys[-1] is not None: return dict(result=entry_attrs, value=keys[-1]) return dict(result=entry_attrs, value=u'') else: return super(stageuser_add, self).execute(*keys, **options)
def forward(self, *args, **kwargs): status = {'result': {self.header: 'unknown'}} # Get the sync URI. segments = list(urlparse.urlparse(self.api.env.xmlrpc_uri)) assert segments[0] == 'https' # Ensure encryption. segments[2] = segments[2].replace('/xml', '/session/sync_token') sync_uri = urlparse.urlunparse(segments) # Prepare the query. query = {k: v for k, v in kwargs.items() if k in {x.name for x in self.takes_options}} if args and args[0] is not None: obj = self.api.Object.otptoken query['token'] = DN((obj.primary_key.name, args[0]), obj.container_dn, self.api.env.basedn) query = urllib.urlencode(query) # Sync the token. # pylint: disable=E1101 handler = HTTPSHandler(ca_certs=os.path.join(self.api.env.confdir, 'ca.crt'), cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_TLSv1) rsp = urllib2.build_opener(handler).open(sync_uri, query) if rsp.getcode() == 200: status['result'][self.header] = rsp.info().get(self.header, 'unknown') rsp.close() return status
def __dict_new_entry(self, *args, **options): ldap = self.obj.backend entry_attrs = self.args_options_2_entry(*args, **options) entry_attrs = ldap.make_entry(DN(), entry_attrs) self.process_attr_options(entry_attrs, None, args, options) entry_attrs['objectclass'] = deepcopy(self.obj.object_class) if self.obj.object_class_config: config = ldap.get_ipa_config() entry_attrs['objectclass'] = config.get( self.obj.object_class_config, entry_attrs['objectclass']) return (entry_attrs)
def normalize_manager(self, manager, container): """ Given a userid verify the user's existence (in the appropriate containter) and return the dn. """ if not manager: return None if not isinstance(manager, list): manager = [manager] try: container_dn = DN(container, api.env.basedn) for m in xrange(len(manager)): if isinstance(manager[m], DN) and manager[m].endswith(container_dn): continue entry_attrs = self.backend.find_entry_by_attr( self.primary_key.name, manager[m], self.object_class, [''], container_dn ) manager[m] = entry_attrs.dn except errors.NotFound: raise errors.NotFound(reason=_('manager %(manager)s not found') % dict(manager=manager[m])) return manager
def forward(self, *args, **kwargs): status = {'result': {self.header: 'unknown'}} # Get the sync URI. segments = list(urllib.parse.urlparse(self.api.env.xmlrpc_uri)) assert segments[0] == 'https' # Ensure encryption. segments[2] = segments[2].replace('/xml', '/session/sync_token') # urlunparse *can* take one argument # pylint: disable=too-many-function-args sync_uri = urllib.parse.urlunparse(segments) # Prepare the query. query = { k: v for k, v in kwargs.items() if k in {x.name for x in self.takes_options} } if args and args[0] is not None: obj = self.api.Object.otptoken query['token'] = DN((obj.primary_key.name, args[0]), obj.container_dn, self.api.env.basedn) query = urllib.parse.urlencode(query) # Sync the token. # pylint: disable=E1101 handler = HTTPSHandler(dbdir=paths.IPA_NSSDB_DIR, tls_version_min=api.env.tls_version_min, tls_version_max=api.env.tls_version_max) rsp = urllib.request.build_opener(handler).open(sync_uri, query) if rsp.getcode() == 200: status['result'][self.header] = rsp.info().get( self.header, 'unknown') rsp.close() return status
label=_('Failed logins'), ), Str('krblastsuccessfulauth', label=_('Last successful authentication'), ), Str('krblastfailedauth', label=_('Last failed authentication'), ), Str('now', label=_('Time now'), ), ) UPG_DEFINITION_DN = DN(('cn', 'UPG Definition'), ('cn', 'Definitions'), ('cn', 'Managed Entries'), ('cn', 'etc'), api.env.basedn) # characters to be used for generating random user passwords baseuser_pwdchars = string.digits + string.ascii_letters + '_,.@+-=' def validate_nsaccountlock(entry_attrs): if 'nsaccountlock' in entry_attrs: nsaccountlock = entry_attrs['nsaccountlock'] if not isinstance(nsaccountlock, (bool, Bool)): if not isinstance(nsaccountlock, basestring): raise errors.OnlyOneValueAllowed(attr='nsaccountlock') if nsaccountlock.lower() not in ('true', 'false'): raise errors.ValidationError(name='nsaccountlock', error=_('must be TRUE or FALSE'))
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): # Fill in a default UUID when not specified. if entry_attrs.get('ipatokenuniqueid', None) is None: entry_attrs['ipatokenuniqueid'] = str(uuid.uuid4()) dn = DN("ipatokenuniqueid=%s" % entry_attrs['ipatokenuniqueid'], dn) if not _check_interval(options.get('ipatokennotbefore', None), options.get('ipatokennotafter', None)): raise ValidationError(name='not_after', error='is before the validity start') # Set the object class and defaults for specific token types options['type'] = options['type'].lower() entry_attrs['objectclass'] = otptoken.object_class + ['ipatoken' + options['type']] for ttype, tattrs in TOKEN_TYPES.items(): if ttype != options['type']: for tattr in tattrs: if tattr in entry_attrs: del entry_attrs[tattr] # If owner was not specified, default to the person adding this token. # If managedby was not specified, attempt a sensible default. if 'ipatokenowner' not in entry_attrs or 'managedby' not in entry_attrs: result = self.api.Command.user_find(whoami=True)['result'] if result: cur_uid = result[0]['uid'][0] prev_uid = entry_attrs.setdefault('ipatokenowner', cur_uid) if cur_uid == prev_uid: entry_attrs.setdefault('managedby', result[0]['dn']) # Resolve the owner's dn _normalize_owner(self.api.Object.user, entry_attrs) # Get the issuer for the URI owner = entry_attrs.get('ipatokenowner', None) issuer = api.env.realm if owner is not None: try: issuer = ldap.get_entry(owner, ['krbprincipalname'])['krbprincipalname'][0] except (NotFound, IndexError): pass # Build the URI parameters args = {} args['issuer'] = issuer args['secret'] = base64.b32encode(entry_attrs['ipatokenotpkey']) args['digits'] = entry_attrs['ipatokenotpdigits'] args['algorithm'] = entry_attrs['ipatokenotpalgorithm'] if options['type'] == 'totp': args['period'] = entry_attrs['ipatokentotptimestep'] elif options['type'] == 'hotp': args['counter'] = entry_attrs['ipatokenhotpcounter'] # Build the URI label = urllib.quote(entry_attrs['ipatokenuniqueid']) parameters = urllib.urlencode(args) uri = u'otpauth://%s/%s:%s?%s' % (options['type'], issuer, label, parameters) setattr(context, 'uri', uri) attrs_list.append("objectclass") return dn
def execute(self, *args, **options): ldap = self.obj.backend staging_dn = self.obj.get_dn(*args, **options) assert isinstance(staging_dn, DN) # retrieve the current entry try: entry_attrs = self._exc_wrapper(args, options, ldap.get_entry)(staging_dn, ['*']) except errors.NotFound: self.obj.handle_not_found(*args) entry_attrs = dict((k.lower(), v) for (k, v) in entry_attrs.items()) # Check it does not exist an active entry with the same RDN active_dn = DN(staging_dn[0], api.env.container_user, api.env.basedn) try: test_entry_attrs = self._exc_wrapper(args, options, ldap.get_entry)(active_dn, ['dn']) assert isinstance(staging_dn, DN) raise errors.DuplicateEntry( message=_('active user with name "%(user)s" already exists') % dict(user=args[-1])) except errors.NotFound: pass # Check the original entry is valid self._check_validy(staging_dn, entry_attrs) # Time to build the new entry result_entry = {'dn': active_dn} new_entry_attrs = self.__dict_new_entry() for (attr, values) in entry_attrs.items(): self.__merge_values(args, options, entry_attrs, new_entry_attrs, attr) result_entry[attr] = values # Allow Managed entry plugin to do its work if 'description' in new_entry_attrs and NO_UPG_MAGIC in new_entry_attrs[ 'description']: new_entry_attrs['description'].remove(NO_UPG_MAGIC) if result_entry['description'] == NO_UPG_MAGIC: del result_entry['description'] for (k, v) in new_entry_attrs.items(): self.log.debug("new entry: k=%r and v=%r)" % (k, v)) self._build_new_entry(ldap, staging_dn, entry_attrs, new_entry_attrs) # Add the Active entry entry = ldap.make_entry(active_dn, new_entry_attrs) self._exc_wrapper(args, options, ldap.add_entry)(entry) # Now delete the Staging entry try: self._exc_wrapper(args, options, ldap.delete_entry)(staging_dn) except: try: self.log.error( "Fail to delete the Staging user after activating it %s " % (staging_dn)) self._exc_wrapper(args, options, ldap.delete_entry)(active_dn) except: self.log.error( "Fail to cleanup activation. The user remains active %s" % (active_dn)) pass raise # add the user we just created into the default primary group config = ldap.get_ipa_config() def_primary_group = config.get('ipadefaultprimarygroup') group_dn = self.api.Object['group'].get_dn(def_primary_group) # if the user is already a member of default primary group, # do not raise error # this can happen if automember rule or default group is set try: ldap.add_entry_to_group(active_dn, group_dn) except errors.AlreadyGroupMember: pass # Now retrieve the activated entry result = self.api.Command.user_show( args[-1], all=options.get('all', False), raw=options.get('raw', False), version=options.get('version'), ) result['summary'] = unicode( _('Stage user %s activated' % staging_dn[0].value)) return result
class stageuser(baseuser): """ Stage User object A Stage user is not an Active user and can not be used to bind with. Stage container is: cn=staged users,cn=accounts,cn=provisioning,SUFFIX Stage entry conforms the schema Stage entry RDN attribute is 'uid' Stage entry are disabled (nsAccountLock: True) through cos """ container_dn = baseuser.stage_container_dn label = _('Stage Users') label_singular = _('Stage User') object_name = _('stage user') object_name_plural = _('stage users') managed_permissions = { # # Stage container # # Allowed to create stage user 'System: Add Stage User': { 'ipapermlocation': DN(baseuser.stage_container_dn, api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtarget': DN('uid=*', baseuser.stage_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=*)'}, 'ipapermright': {'add'}, 'ipapermdefaultattr': {'*'}, 'default_privileges': {'Stage User Administrators', 'Stage User Provisioning'}, }, # Allow to read kerberos/password 'System: Read Stage User password': { 'ipapermlocation': DN(baseuser.stage_container_dn, api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtarget': DN('uid=*', baseuser.stage_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=*)'}, 'ipapermright': {'read', 'search', 'compare'}, 'ipapermdefaultattr': { 'userPassword', 'krbPrincipalKey', }, 'default_privileges': {'Stage User Administrators'}, }, # Allow to update stage user 'System: Modify Stage User': { 'ipapermlocation': DN(baseuser.stage_container_dn, api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtarget': DN('uid=*', baseuser.stage_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=*)'}, 'ipapermright': {'write'}, 'ipapermdefaultattr': {'*'}, 'default_privileges': {'Stage User Administrators'}, }, # Allow to delete stage user 'System: Remove Stage User': { 'ipapermlocation': DN(baseuser.stage_container_dn, api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtarget': DN('uid=*', baseuser.stage_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=*)'}, 'ipapermright': {'delete'}, 'ipapermdefaultattr': {'*'}, 'default_privileges': {'Stage User Administrators'}, }, # Allow to read any attributes of stage users 'System: Read Stage Users': { 'ipapermlocation': DN(baseuser.stage_container_dn, api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtarget': DN('uid=*', baseuser.stage_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=*)'}, 'ipapermright': {'read', 'search', 'compare'}, 'ipapermdefaultattr': {'*'}, 'default_privileges': {'Stage User Administrators'}, }, # # Preserve container # # Allow to read Preserved User 'System: Read Preserved Users': { 'ipapermlocation': DN(baseuser.delete_container_dn, api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtarget': DN('uid=*', baseuser.delete_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=posixaccount)'}, 'ipapermright': {'read', 'search', 'compare'}, 'ipapermdefaultattr': {'*'}, 'default_privileges': {'Stage User Administrators'}, }, # Allow to update Preserved User 'System: Modify Preserved Users': { 'ipapermlocation': DN(baseuser.delete_container_dn, api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtarget': DN('uid=*', baseuser.delete_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=posixaccount)'}, 'ipapermright': {'write'}, 'ipapermdefaultattr': {'*'}, 'default_privileges': {'Stage User Administrators'}, }, # Allow to reset Preserved User password 'System: Reset Preserved User password': { 'ipapermlocation': DN(baseuser.delete_container_dn, api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtarget': DN('uid=*', baseuser.delete_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=posixaccount)'}, 'ipapermright': {'read', 'search', 'write'}, 'ipapermdefaultattr': { 'userPassword', 'krbPrincipalKey', 'krbPasswordExpiration', 'krbLastPwdChange' }, 'default_privileges': {'Stage User Administrators'}, }, # Allow to delete preserved user 'System: Remove preserved User': { 'ipapermlocation': DN(baseuser.delete_container_dn, api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtarget': DN('uid=*', baseuser.delete_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=*)'}, 'ipapermright': {'delete'}, 'ipapermdefaultattr': {'*'}, 'default_privileges': {'Stage User Administrators'}, }, # # Active container # # Stage user administrators need write right on RDN when # the active user is deleted (preserved) 'System: Modify User RDN': { 'ipapermlocation': DN(baseuser.active_container_dn, api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtarget': DN('uid=*', baseuser.active_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=posixaccount)'}, 'ipapermright': {'write'}, 'ipapermdefaultattr': {'uid'}, 'default_privileges': {'Stage User Administrators'}, }, # # Cross containers autorization # # Allow to move active user to preserve container (user-del --preserve) # Note: targetfilter is the target parent container 'System: Preserve User': { 'ipapermlocation': DN(api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtargetfrom': DN(baseuser.active_container_dn, api.env.basedn), 'ipapermtargetto': DN(baseuser.delete_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=nsContainer)'}, 'ipapermright': {'moddn'}, 'default_privileges': {'Stage User Administrators'}, }, # Allow to move preserved user to active container (user-undel) # Note: targetfilter is the target parent container 'System: Undelete User': { 'ipapermlocation': DN(api.env.basedn), 'ipapermbindruletype': 'permission', 'ipapermtargetfrom': DN(baseuser.delete_container_dn, api.env.basedn), 'ipapermtargetto': DN(baseuser.active_container_dn, api.env.basedn), 'ipapermtargetfilter': {'(objectclass=nsContainer)'}, 'ipapermright': {'moddn'}, 'default_privileges': {'Stage User Administrators'}, }, }
class otpconfig(LDAPObject): object_name = _('OTP configuration options') default_attributes = [ 'ipatokentotpauthwindow', 'ipatokentotpsyncwindow', 'ipatokenhotpauthwindow', 'ipatokenhotpsyncwindow', ] container_dn = DN(('cn', 'otp'), ('cn', 'etc')) permission_filter_objectclasses = ['ipatokenotpconfig'] managed_permissions = { 'System: Read OTP Configuration': { 'replaces_global_anonymous_aci': True, 'ipapermbindruletype': 'all', 'ipapermright': {'read', 'search', 'compare'}, 'ipapermdefaultattr': { 'ipatokentotpauthwindow', 'ipatokentotpsyncwindow', 'ipatokenhotpauthwindow', 'ipatokenhotpsyncwindow', 'cn', }, }, } label = _('OTP Configuration') label_singular = _('OTP Configuration') takes_params = ( Int( 'ipatokentotpauthwindow', cli_name='totp_auth_window', label=_('TOTP authentication Window'), doc=_('TOTP authentication time variance (seconds)'), minvalue=5, ), Int( 'ipatokentotpsyncwindow', cli_name='totp_sync_window', label=_('TOTP Synchronization Window'), doc=_('TOTP synchronization time variance (seconds)'), minvalue=5, ), Int( 'ipatokenhotpauthwindow', cli_name='hotp_auth_window', label=_('HOTP Authentication Window'), doc=_('HOTP authentication skip-ahead'), minvalue=1, ), Int( 'ipatokenhotpsyncwindow', cli_name='hotp_sync_window', label=_('HOTP Synchronization Window'), doc=_('HOTP synchronization skip-ahead'), minvalue=1, ), ) def get_dn(self, *keys, **kwargs): return self.container_dn + api.env.basedn
def delete_user(self, user): assert isinstance(user, DN) return self._user_status(user, DN(self.delete_container_dn, api.env.basedn))