class automountkey_show(LDAPRetrieve): __doc__ = _('Display an automount key.') takes_options = LDAPRetrieve.takes_options + ( IA5Str( 'automountkey', cli_name='key', label=_('Key'), doc=_('Automount key name.'), ), IA5Str( 'automountinformation?', cli_name='info', label=_('Mount information'), ), ) def get_args(self): for key in self.obj.get_ancestor_primary_keys(): yield key def execute(self, *keys, **options): keys += (self.obj.get_pk(options['automountkey'], options.get('automountinformation', None)), ) options[self.obj.primary_key.name] = self.obj.get_pk( options['automountkey'], options.get('automountinformation', None)) result = super(automountkey_show, self).execute(*keys, **options) result['value'] = pkey_to_value(options['automountkey'], options) return result
class automountmap(LDAPObject): """ Automount map object. """ parent_object = 'automountlocation' container_dn = api.env.container_automount object_name = _('automount map') object_name_plural = _('automount maps') object_class = ['automountmap'] default_attributes = ['automountmapname', 'description'] takes_params = ( IA5Str( 'automountmapname', cli_name='map', label=_('Map'), doc=_('Automount map name.'), primary_key=True, ), Str( 'description?', cli_name='desc', label=_('Description'), ), ) label = _('Automount Maps') label_singular = _('Automount Map')
class automountkey_mod(LDAPUpdate): __doc__ = _('Modify an automount key.') msg_summary = _('Modified automount key "%(value)s"') internal_options = ['newautomountkey'] takes_options = LDAPUpdate.takes_options + (IA5Str( 'newautomountinformation?', cli_name='newinfo', label=_('New mount information'), ), ) def get_args(self): for key in self.obj.get_ancestor_primary_keys(): yield key def pre_callback(self, ldap, dn, entry_attrs, *keys, **options): assert isinstance(dn, DN) if 'newautomountkey' in options: entry_attrs['automountkey'] = options['newautomountkey'] if 'newautomountinformation' in options: entry_attrs['automountinformation'] = options[ 'newautomountinformation'] return dn def execute(self, *keys, **options): ldap = self.api.Backend.ldap2 key = options['automountkey'] info = options.get('automountinformation', None) keys += (self.obj.get_pk(key, info), ) # handle RDN changes if 'rename' in options or 'newautomountinformation' in options: new_key = options.get('rename', key) new_info = options.get('newautomountinformation', info) if new_key == DIRECT_MAP_KEY and not new_info: # automountinformation attribute of existing LDAP object needs # to be retrieved so that RDN can be generated dn = self.obj.get_dn(*keys, **options) (dn_, entry_attrs_) = ldap.get_entry(dn, ['automountinformation']) new_info = entry_attrs_.get('automountinformation', [])[0] # automounkey attribute cannot be overwritten so that get_dn() # still works right options['newautomountkey'] = new_key new_rdn = self.obj.get_pk(new_key, new_info) if new_rdn != keys[-1]: options['rename'] = new_rdn result = super(automountkey_mod, self).execute(*keys, **options) result['value'] = options['automountkey'] return result
class automountmap(LDAPObject): """ Automount map object. """ parent_object = 'automountlocation' container_dn = api.env.container_automount object_name = _('automount map') object_name_plural = _('automount maps') object_class = ['automountmap'] permission_filter_objectclasses = ['automountmap'] default_attributes = ['automountmapname', 'description'] takes_params = ( IA5Str( 'automountmapname', cli_name='map', label=_('Map'), doc=_('Automount map name.'), primary_key=True, ), Str( 'description?', cli_name='desc', label=_('Description'), ), ) managed_permissions = { 'System: Add Automount Maps': { 'ipapermright': {'add'}, 'replaces': [ '(target = "ldap:///automountmapname=*,cn=automount,$SUFFIX")(version 3.0;acl "permission:Add Automount maps";allow (add) groupdn = "ldap:///cn=Add Automount maps,cn=permissions,cn=pbac,$SUFFIX";)', ], 'default_privileges': {'Automount Administrators'}, }, 'System: Modify Automount Maps': { 'ipapermright': {'write'}, 'ipapermdefaultattr': {'automountmapname', 'description'}, 'replaces': [ '(targetattr = "automountmapname || description")(target = "ldap:///automountmapname=*,cn=automount,$SUFFIX")(version 3.0;acl "permission:Modify Automount maps";allow (write) groupdn = "ldap:///cn=Modify Automount maps,cn=permissions,cn=pbac,$SUFFIX";)', ], 'default_privileges': {'Automount Administrators'}, }, 'System: Remove Automount Maps': { 'ipapermright': {'delete'}, 'replaces': [ '(target = "ldap:///automountmapname=*,cn=automount,$SUFFIX")(version 3.0;acl "permission:Remove Automount maps";allow (delete) groupdn = "ldap:///cn=Remove Automount maps,cn=permissions,cn=pbac,$SUFFIX";)', ], 'default_privileges': {'Automount Administrators'}, }, } label = _('Automount Maps') label_singular = _('Automount Map')
class automountkey_del(LDAPDelete): __doc__ = _('Delete an automount key.') msg_summary = _('Deleted automount key "%(value)s"') takes_options = LDAPDelete.takes_options + ( IA5Str( 'automountkey', cli_name='key', label=_('Key'), doc=_('Automount key name.'), ), IA5Str( 'automountinformation?', cli_name='info', label=_('Mount information'), ), ) def get_options(self): for option in super(automountkey_del, self).get_options(): if option.name == 'continue': # TODO: hide for now - remove in future major release yield option.clone(exclude='webui', flags=['no_option', 'no_output']) else: yield option def get_args(self): for key in self.obj.get_ancestor_primary_keys(): yield key def execute(self, *keys, **options): keys += (self.obj.get_pk(options['automountkey'], options.get('automountinformation', None)), ) options[self.obj.primary_key.name] = self.obj.get_pk( options['automountkey'], options.get('automountinformation', None)) result = super(automountkey_del, self).execute(*keys, **options) result['value'] = pkey_to_value([options['automountkey']], options) return result
class config(LDAPObject): """ IPA configuration object """ object_name = _('configuration options') default_attributes = [ 'ipamaxusernamelength', 'ipahomesrootdir', 'ipadefaultloginshell', 'ipadefaultprimarygroup', 'ipadefaultemaildomain', 'ipasearchtimelimit', 'ipasearchrecordslimit', 'ipausersearchfields', 'ipagroupsearchfields', 'ipamigrationenabled', 'ipacertificatesubjectbase', 'ipapwdexpadvnotify', 'ipaselinuxusermaporder', 'ipaselinuxusermapdefault', 'ipaconfigstring', 'ipakrbauthzdata', 'ipauserauthtype' ] container_dn = DN(('cn', 'ipaconfig'), ('cn', 'etc')) permission_filter_objectclasses = ['ipaguiconfig'] managed_permissions = { 'System: Read Global Configuration': { 'replaces_global_anonymous_aci': True, 'ipapermbindruletype': 'all', 'ipapermright': {'read', 'search', 'compare'}, 'ipapermdefaultattr': { 'cn', 'objectclass', 'ipacertificatesubjectbase', 'ipaconfigstring', 'ipadefaultemaildomain', 'ipadefaultloginshell', 'ipadefaultprimarygroup', 'ipagroupobjectclasses', 'ipagroupsearchfields', 'ipahomesrootdir', 'ipakrbauthzdata', 'ipamaxusernamelength', 'ipamigrationenabled', 'ipapwdexpadvnotify', 'ipaselinuxusermapdefault', 'ipaselinuxusermaporder', 'ipasearchrecordslimit', 'ipasearchtimelimit', 'ipauserauthtype', 'ipauserobjectclasses', 'ipausersearchfields', 'ipacustomfields', }, }, } label = _('Configuration') label_singular = _('Configuration') takes_params = ( Int('ipamaxusernamelength', cli_name='maxusername', label=_('Maximum username length'), minvalue=1, maxvalue=255, ), IA5Str('ipahomesrootdir', cli_name='homedirectory', label=_('Home directory base'), doc=_('Default location of home directories'), ), Str('ipadefaultloginshell', cli_name='defaultshell', label=_('Default shell'), doc=_('Default shell for new users'), ), Str('ipadefaultprimarygroup', cli_name='defaultgroup', label=_('Default users group'), doc=_('Default group for new users'), ), Str('ipadefaultemaildomain?', cli_name='emaildomain', label=_('Default e-mail domain'), doc=_('Default e-mail domain'), ), Int('ipasearchtimelimit', cli_name='searchtimelimit', label=_('Search time limit'), doc=_('Maximum amount of time (seconds) for a search (-1 or 0 is unlimited)'), minvalue=-1, ), Int('ipasearchrecordslimit', cli_name='searchrecordslimit', label=_('Search size limit'), doc=_('Maximum number of records to search (-1 or 0 is unlimited)'), minvalue=-1, ), IA5Str('ipausersearchfields', cli_name='usersearch', label=_('User search fields'), doc=_('A comma-separated list of fields to search in when searching for users'), ), IA5Str('ipagroupsearchfields', cli_name='groupsearch', label='Group search fields', doc=_('A comma-separated list of fields to search in when searching for groups'), ), Bool('ipamigrationenabled', cli_name='enable_migration', label=_('Enable migration mode'), doc=_('Enable migration mode'), ), DNParam('ipacertificatesubjectbase', cli_name='subject', label=_('Certificate Subject base'), doc=_('Base for certificate subjects (OU=Test,O=Example)'), flags=['no_update'], ), Str('ipagroupobjectclasses+', cli_name='groupobjectclasses', label=_('Default group objectclasses'), doc=_('Default group objectclasses (comma-separated list)'), ), Str('ipauserobjectclasses+', cli_name='userobjectclasses', label=_('Default user objectclasses'), doc=_('Default user objectclasses (comma-separated list)'), ), Int('ipapwdexpadvnotify', cli_name='pwdexpnotify', label=_('Password Expiration Notification (days)'), doc=_('Number of days\'s notice of impending password expiration'), minvalue=0, ), StrEnum('ipaconfigstring*', cli_name='ipaconfigstring', label=_('Password plugin features'), doc=_('Extra hashes to generate in password plug-in'), values=(u'AllowNThash', u'KDC:Disable Last Success', u'KDC:Disable Lockout', u'KDC:Disable Default Preauth for SPNs'), ), Str('ipaselinuxusermaporder', label=_('SELinux user map order'), doc=_('Order in increasing priority of SELinux users, delimited by $'), ), Str('ipaselinuxusermapdefault?', label=_('Default SELinux user'), doc=_('Default SELinux user when no match is found in SELinux map rule'), ), StrEnum('ipakrbauthzdata*', cli_name='pac_type', label=_('Default PAC types'), doc=_('Default types of PAC supported for services'), values=(u'MS-PAC', u'PAD', u'nfs:NONE'), ), StrEnum('ipauserauthtype*', cli_name='user_auth_type', label=_('Default user authentication types'), doc=_('Default types of supported user authentication'), values=(u'password', u'radius', u'otp', u'disabled'), ), Str( 'ipa_master_server*', label=_('IPA masters'), doc=_('List of all IPA masters'), flags={'virtual_attribute', 'no_create', 'no_update'} ), Str( 'ca_server_server*', label=_('IPA CA servers'), doc=_('IPA servers configured as certificate authority'), flags={'virtual_attribute', 'no_create', 'no_update'} ), Str( 'ntp_server_server*', label=_('IPA NTP servers'), doc=_('IPA servers with enabled NTP'), flags={'virtual_attribute', 'no_create', 'no_update'} ), Str( 'ca_renewal_master_server?', label=_('IPA CA renewal master'), doc=_('Renewal master for IPA certificate authority'), flags={'virtual_attribute', 'no_create'} ) ) def get_dn(self, *keys, **kwargs): return DN(('cn', 'ipaconfig'), ('cn', 'etc'), api.env.basedn) def show_servroles_attributes(self, entry_attrs, **options): if options.get('raw', False): return backend = self.api.Backend.serverroles for role in ("CA server", "IPA master", "NTP server"): config = backend.config_retrieve(role) entry_attrs.update(config)
class automountkey(LDAPObject): __doc__ = _('Automount key object.') parent_object = 'automountmap' container_dn = api.env.container_automount object_name = _('automount key') object_name_plural = _('automount keys') object_class = ['automount'] permission_filter_objectclasses = ['automount'] default_attributes = [ 'automountkey', 'automountinformation', 'description' ] rdn_is_primary_key = True rdn_separator = ' ' takes_params = ( IA5Str( 'automountkey', cli_name='key', label=_('Key'), doc=_('Automount key name.'), flags=('req_update', ), ), IA5Str( 'automountinformation', cli_name='info', label=_('Mount information'), ), Str( 'description', label=_('description'), primary_key=True, required=False, flags=['no_create', 'no_update', 'no_search', 'no_output'], exclude='webui', ), ) managed_permissions = { 'System: Add Automount Keys': { 'ipapermright': {'add'}, 'replaces': [ '(target = "ldap:///automountkey=*,automountmapname=*,cn=automount,$SUFFIX")(version 3.0;acl "permission:Add Automount keys";allow (add) groupdn = "ldap:///cn=Add Automount keys,cn=permissions,cn=pbac,$SUFFIX";)', '(targetfilter = "(objectclass=automount)")(target = "ldap:///automountmapname=*,cn=automount,$SUFFIX")(version 3.0;acl "permission:Add Automount keys";allow (add) groupdn = "ldap:///cn=Add Automount keys,cn=permissions,cn=pbac,$SUFFIX";)', ], 'default_privileges': {'Automount Administrators'}, }, 'System: Modify Automount Keys': { 'ipapermright': {'write'}, 'ipapermdefaultattr': { 'automountinformation', 'automountkey', 'description', }, 'replaces': [ '(targetattr = "automountkey || automountinformation || description")(targetfilter = "(objectclass=automount)")(target = "ldap:///automountmapname=*,cn=automount,$SUFFIX")(version 3.0;acl "permission:Modify Automount keys";allow (write) groupdn = "ldap:///cn=Modify Automount keys,cn=permissions,cn=pbac,$SUFFIX";)', ], 'default_privileges': {'Automount Administrators'}, }, 'System: Remove Automount Keys': { 'ipapermright': {'delete'}, 'replaces': [ '(target = "ldap:///automountkey=*,automountmapname=*,cn=automount,$SUFFIX")(version 3.0;acl "permission:Remove Automount keys";allow (delete) groupdn = "ldap:///cn=Remove Automount keys,cn=permissions,cn=pbac,$SUFFIX";)', '(targetfilter = "(objectclass=automount)")(target = "ldap:///automountmapname=*,cn=automount,$SUFFIX")(version 3.0;acl "permission:Remove Automount keys";allow (delete) groupdn = "ldap:///cn=Remove Automount keys,cn=permissions,cn=pbac,$SUFFIX";)', ], 'default_privileges': {'Automount Administrators'}, }, } num_parents = 2 label = _('Automount Keys') label_singular = _('Automount Key') already_exists_msg = _( 'The key,info pair must be unique. A key named %(key)s with info %(info)s already exists' ) key_already_exists_msg = _('key named %(key)s already exists') object_not_found_msg = _( 'The automount key %(key)s with info %(info)s does not exist') def get_dn(self, *keys, **kwargs): # all commands except for create send pk in keys, too # create cannot due to validation in frontend.py ldap = self.backend if len(keys) == self.num_parents: try: pkey = kwargs[self.primary_key.name] except KeyError: raise ValueError('Not enough keys and pkey not in kwargs') parent_keys = keys else: pkey = keys[-1] parent_keys = keys[:-1] parent_dn = self.api.Object[self.parent_object].get_dn(*parent_keys) dn = self.backend.make_dn_from_attr(self.primary_key.name, pkey, parent_dn) # If we're doing an add then just return the dn we created, there # is no need to check for it. if kwargs.get('add_operation', False): return dn # We had an older mechanism where description consisted of # 'automountkey automountinformation' so we could support multiple # direct maps. This made showing keys nearly impossible since it # required automountinfo to show, which if you had you didn't need # to look at the key. We still support existing entries but now # only create this type of dn when the key is /- # # First we look with the information given, then try to search for # the right entry. try: dn = ldap.get_entry(dn, ['*']).dn except errors.NotFound: if kwargs.get('automountinformation', False): sfilter = '(&(automountkey=%s)(automountinformation=%s))' % \ (kwargs['automountkey'], kwargs['automountinformation']) else: sfilter = '(automountkey=%s)' % kwargs['automountkey'] basedn = DN(('automountmapname', parent_keys[1]), ('cn', parent_keys[0]), self.container_dn, api.env.basedn) attrs_list = ['*'] entries, truncated = ldap.find_entries(sfilter, attrs_list, basedn, ldap.SCOPE_ONELEVEL) if len(entries) > 1: raise errors.NotFound(reason=_( 'More than one entry with key %(key)s found, use --info to select specific entry.' ) % dict(key=pkey)) if truncated: raise errors.LimitsExceeded() dn = entries[0].dn return dn def handle_not_found(self, *keys): pkey = keys[-1] key = pkey.split(self.rdn_separator)[0] info = self.rdn_separator.join(pkey.split(self.rdn_separator)[1:]) raise errors.NotFound(reason=self.object_not_found_msg % { 'key': key, 'info': info, }) def handle_duplicate_entry(self, *keys): pkey = keys[-1] key = pkey.split(self.rdn_separator)[0] info = self.rdn_separator.join(pkey.split(self.rdn_separator)[1:]) if info: raise errors.DuplicateEntry(message=self.already_exists_msg % { 'key': key, 'info': info, }) else: raise errors.DuplicateEntry(message=self.key_already_exists_msg % { 'key': key, }) def get_pk(self, key, info=None): if key == DIRECT_MAP_KEY and info: return self.rdn_separator.join((key, info)) else: return key def check_key_uniqueness(self, location, map, **keykw): info = None key = keykw.get('automountkey') if key is None: return entries = self.methods.find(location, map, automountkey=key)['result'] if len(entries) > 0: if key == DIRECT_MAP_KEY: info = keykw.get('automountinformation') entries = self.methods.find(location, map, **keykw)['result'] if len(entries) > 0: self.handle_duplicate_entry(location, map, self.get_pk(key, info)) else: return self.handle_duplicate_entry(location, map, self.get_pk(key, info))
class config(LDAPObject): """ IPA configuration object """ object_name = _('configuration options') default_attributes = [ 'ipamaxusernamelength', 'ipahomesrootdir', 'ipadefaultloginshell', 'ipadefaultprimarygroup', 'ipadefaultemaildomain', 'ipasearchtimelimit', 'ipasearchrecordslimit', 'ipausersearchfields', 'ipagroupsearchfields', 'ipamigrationenabled', 'ipacertificatesubjectbase', 'ipapwdexpadvnotify', 'ipaselinuxusermaporder', 'ipaselinuxusermapdefault', 'ipaconfigstring', 'ipakrbauthzdata', 'ipauserauthtype', 'ipadomainresolutionorder' ] container_dn = DN(('cn', 'ipaconfig'), ('cn', 'etc')) permission_filter_objectclasses = ['ipaguiconfig'] managed_permissions = { 'System: Read Global Configuration': { 'replaces_global_anonymous_aci': True, 'ipapermbindruletype': 'all', 'ipapermright': {'read', 'search', 'compare'}, 'ipapermdefaultattr': { 'cn', 'objectclass', 'ipacertificatesubjectbase', 'ipaconfigstring', 'ipadefaultemaildomain', 'ipadefaultloginshell', 'ipadefaultprimarygroup', 'ipadomainresolutionorder', 'ipagroupobjectclasses', 'ipagroupsearchfields', 'ipahomesrootdir', 'ipakrbauthzdata', 'ipamaxusernamelength', 'ipamigrationenabled', 'ipapwdexpadvnotify', 'ipaselinuxusermapdefault', 'ipaselinuxusermaporder', 'ipasearchrecordslimit', 'ipasearchtimelimit', 'ipauserauthtype', 'ipauserobjectclasses', 'ipausersearchfields', 'ipacustomfields', }, }, } label = _('Configuration') label_singular = _('Configuration') takes_params = ( Int('ipamaxusernamelength', cli_name='maxusername', label=_('Maximum username length'), minvalue=1, maxvalue=255, ), IA5Str('ipahomesrootdir', cli_name='homedirectory', label=_('Home directory base'), doc=_('Default location of home directories'), ), Str('ipadefaultloginshell', cli_name='defaultshell', label=_('Default shell'), doc=_('Default shell for new users'), ), Str('ipadefaultprimarygroup', cli_name='defaultgroup', label=_('Default users group'), doc=_('Default group for new users'), ), Str('ipadefaultemaildomain?', cli_name='emaildomain', label=_('Default e-mail domain'), doc=_('Default e-mail domain'), ), Int('ipasearchtimelimit', cli_name='searchtimelimit', label=_('Search time limit'), doc=_('Maximum amount of time (seconds) for a search (-1 or 0 is unlimited)'), minvalue=-1, ), Int('ipasearchrecordslimit', cli_name='searchrecordslimit', label=_('Search size limit'), doc=_('Maximum number of records to search (-1 or 0 is unlimited)'), minvalue=-1, ), IA5Str('ipausersearchfields', cli_name='usersearch', label=_('User search fields'), doc=_('A comma-separated list of fields to search in when searching for users'), ), IA5Str('ipagroupsearchfields', cli_name='groupsearch', label=_('Group search fields'), doc=_('A comma-separated list of fields to search in when searching for groups'), ), Bool('ipamigrationenabled', cli_name='enable_migration', label=_('Enable migration mode'), doc=_('Enable migration mode'), ), DNParam('ipacertificatesubjectbase', cli_name='subject', label=_('Certificate Subject base'), doc=_('Base for certificate subjects (OU=Test,O=Example)'), flags=['no_update'], ), Str('ipagroupobjectclasses+', cli_name='groupobjectclasses', label=_('Default group objectclasses'), doc=_('Default group objectclasses (comma-separated list)'), ), Str('ipauserobjectclasses+', cli_name='userobjectclasses', label=_('Default user objectclasses'), doc=_('Default user objectclasses (comma-separated list)'), ), Int('ipapwdexpadvnotify', cli_name='pwdexpnotify', label=_('Password Expiration Notification (days)'), doc=_('Number of days\'s notice of impending password expiration'), minvalue=0, ), StrEnum('ipaconfigstring*', cli_name='ipaconfigstring', label=_('Password plugin features'), doc=_('Extra hashes to generate in password plug-in'), values=(u'AllowNThash', u'KDC:Disable Last Success', u'KDC:Disable Lockout', u'KDC:Disable Default Preauth for SPNs'), ), Str('ipaselinuxusermaporder', label=_('SELinux user map order'), doc=_('Order in increasing priority of SELinux users, delimited by $'), ), Str('ipaselinuxusermapdefault?', label=_('Default SELinux user'), doc=_('Default SELinux user when no match is found in SELinux map rule'), ), StrEnum('ipakrbauthzdata*', cli_name='pac_type', label=_('Default PAC types'), doc=_('Default types of PAC supported for services'), values=(u'MS-PAC', u'PAD', u'nfs:NONE'), ), StrEnum('ipauserauthtype*', cli_name='user_auth_type', label=_('Default user authentication types'), doc=_('Default types of supported user authentication'), values=(u'password', u'radius', u'otp', u'disabled'), ), Str( 'ipa_master_server*', label=_('IPA masters'), doc=_('List of all IPA masters'), flags={'virtual_attribute', 'no_create', 'no_update'} ), Str( 'ca_server_server*', label=_('IPA CA servers'), doc=_('IPA servers configured as certificate authority'), flags={'virtual_attribute', 'no_create', 'no_update'} ), Str( 'ntp_server_server*', label=_('IPA NTP servers'), doc=_('IPA servers with enabled NTP'), flags={'virtual_attribute', 'no_create', 'no_update'} ), Str( 'ca_renewal_master_server?', label=_('IPA CA renewal master'), doc=_('Renewal master for IPA certificate authority'), flags={'virtual_attribute', 'no_create'} ), Str( 'pkinit_server_server*', label=_('IPA master capable of PKINIT'), doc=_('IPA master which can process PKINIT requests'), flags={'virtual_attribute', 'no_create', 'no_update'} ), Str( 'ipadomainresolutionorder?', cli_name='domain_resolution_order', label=_('Domain resolution order'), doc=_('colon-separated list of domains used for short name' ' qualification') ) ) def get_dn(self, *keys, **kwargs): return DN(('cn', 'ipaconfig'), ('cn', 'etc'), api.env.basedn) def update_entry_with_role_config(self, role_name, entry_attrs): backend = self.api.Backend.serverroles try: role_config = backend.config_retrieve(role_name) except errors.EmptyResult: # No role config means current user identity # has no rights to see it, return with no action return for key, value in role_config.items(): try: entry_attrs.update({key: value}) except errors.EmptyResult: # An update that doesn't change an entry is fine here # Just ignore and move to the next key pair pass def show_servroles_attributes(self, entry_attrs, *roles, **options): if options.get('raw', False): return for role in roles: self.update_entry_with_role_config(role, entry_attrs) def gather_trusted_domains(self): """ Aggregate all trusted domains into a dict keyed by domain names with values corresponding to domain status (enabled/disabled) """ command = self.api.Command try: ad_forests = command.trust_find(sizelimit=0)['result'] except errors.NotFound: return {} trusted_domains = {} for forest_name in [a['cn'][0] for a in ad_forests]: forest_domains = command.trustdomain_find( forest_name, sizelimit=0)['result'] trusted_domains.update( { dom['cn'][0]: dom['domain_enabled'][0] for dom in forest_domains if 'domain_enabled' in dom } ) return trusted_domains def _validate_single_domain(self, attr_name, domain, known_domains): """ Validate a single domain from domain resolution order :param attr_name: name of attribute that holds domain resolution order :param domain: domain name :param known_domains: dict of domains known to IPA keyed by domain name and valued by boolean value corresponding to domain status (enabled/disabled) :raises: ValidationError if the domain name is empty, syntactically invalid or corresponds to a disable domain NotFound if a syntactically correct domain name unknown to IPA is supplied (not IPA domain and not any of trusted domains) """ if not domain: raise errors.ValidationError( name=attr_name, error=_("Empty domain is not allowed") ) try: validate_domain_name(domain) except ValueError as e: raise errors.ValidationError( name=attr_name, error=_("Invalid domain name '%(domain)s': %(e)s") % dict(domain=domain, e=e)) if domain not in known_domains: raise errors.NotFound( reason=_("Server has no information about domain '%(domain)s'") % dict(domain=domain) ) if not known_domains[domain]: raise errors.ValidationError( name=attr_name, error=_("Disabled domain '%(domain)s' is not allowed") % dict(domain=domain) ) def validate_domain_resolution_order(self, entry_attrs): """ Validate domain resolution order, e.g. split by the delimiter (colon) and check each domain name for non-emptiness, syntactic correctness, and status (enabled/disabled). supplying empty order (':') bypasses validations and allows to specify empty attribute value. """ attr_name = 'ipadomainresolutionorder' if attr_name not in entry_attrs: return domain_resolution_order = entry_attrs[attr_name] # setting up an empty string means that the previous configuration has # to be cleaned up/removed. So, do nothing and let it pass if not domain_resolution_order: return # empty resolution order is signalized by single separator, do nothing # and let it pass if domain_resolution_order == DOMAIN_RESOLUTION_ORDER_SEPARATOR: return submitted_domains = domain_resolution_order.split( DOMAIN_RESOLUTION_ORDER_SEPARATOR) known_domains = self.gather_trusted_domains() # add FreeIPA domain to the list of domains. This one is always enabled known_domains.update({self.api.env.domain: True}) for domain in submitted_domains: self._validate_single_domain(attr_name, domain, known_domains)
class config(LDAPObject): """ IPA configuration object """ object_name = _('configuration options') default_attributes = [ 'ipamaxusernamelength', 'ipahomesrootdir', 'ipadefaultloginshell', 'ipadefaultprimarygroup', 'ipadefaultemaildomain', 'ipasearchtimelimit', 'ipasearchrecordslimit', 'ipausersearchfields', 'ipagroupsearchfields', 'ipamigrationenabled', 'ipacertificatesubjectbase', 'ipapwdexpadvnotify', 'ipaselinuxusermaporder', 'ipaselinuxusermapdefault', 'ipaconfigstring', 'ipakrbauthzdata', ] label = _('Configuration') label_singular = _('Configuration') takes_params = ( Int( 'ipamaxusernamelength', cli_name='maxusername', label=_('Maximum username length'), minvalue=1, ), IA5Str( 'ipahomesrootdir', cli_name='homedirectory', label=_('Home directory base'), doc=_('Default location of home directories'), ), Str( 'ipadefaultloginshell', cli_name='defaultshell', label=_('Default shell'), doc=_('Default shell for new users'), ), Str( 'ipadefaultprimarygroup', cli_name='defaultgroup', label=_('Default users group'), doc=_('Default group for new users'), ), Str( 'ipadefaultemaildomain?', cli_name='emaildomain', label=_('Default e-mail domain'), doc=_('Default e-mail domain'), ), Int( 'ipasearchtimelimit', validate_searchtimelimit, cli_name='searchtimelimit', label=_('Search time limit'), doc= _('Maximum amount of time (seconds) for a search (> 0, or -1 for unlimited)' ), minvalue=-1, ), Int( 'ipasearchrecordslimit', cli_name='searchrecordslimit', label=_('Search size limit'), doc=_('Maximum number of records to search (-1 is unlimited)'), minvalue=-1, ), IA5Str( 'ipausersearchfields', cli_name='usersearch', label=_('User search fields'), doc= _('A comma-separated list of fields to search in when searching for users' ), ), IA5Str( 'ipagroupsearchfields', cli_name='groupsearch', label='Group search fields', doc= _('A comma-separated list of fields to search in when searching for groups' ), ), Bool( 'ipamigrationenabled', cli_name='enable_migration', label=_('Enable migration mode'), doc=_('Enable migration mode'), ), DNParam( 'ipacertificatesubjectbase', cli_name='subject', label=_('Certificate Subject base'), doc=_('Base for certificate subjects (OU=Test,O=Example)'), flags=['no_update'], ), Str( 'ipagroupobjectclasses+', cli_name='groupobjectclasses', label=_('Default group objectclasses'), doc=_('Default group objectclasses (comma-separated list)'), csv=True, ), Str( 'ipauserobjectclasses+', cli_name='userobjectclasses', label=_('Default user objectclasses'), doc=_('Default user objectclasses (comma-separated list)'), csv=True, ), Int( 'ipapwdexpadvnotify', cli_name='pwdexpnotify', label=_('Password Expiration Notification (days)'), doc=_('Number of days\'s notice of impending password expiration'), minvalue=0, ), StrEnum( 'ipaconfigstring*', cli_name='ipaconfigstring', label=_('Password plugin features'), doc=_('Extra hashes to generate in password plug-in'), values=(u'AllowLMhash', u'AllowNThash', u'KDC:Disable Last Success', u'KDC:Disable Lockout'), csv=True, ), Str( 'ipaselinuxusermaporder', label=_('SELinux user map order'), doc=_( 'Order in increasing priority of SELinux users, delimited by $' ), ), Str( 'ipaselinuxusermapdefault?', label=_('Default SELinux user'), doc= _('Default SELinux user when no match is found in SELinux map rule' ), ), StrEnum( 'ipakrbauthzdata*', cli_name='pac_type', label=_('Default PAC types'), doc=_('Default types of PAC supported for services'), values=(u'MS-PAC', u'PAD'), csv=True, ), ) def get_dn(self, *keys, **kwargs): return DN(('cn', 'ipaconfig'), ('cn', 'etc'))