def ca_status(ca_host=None, use_proxy=True): """Return the status of the CA, and the httpd proxy in front of it The returned status can be: - running - starting - Service Temporarily Unavailable """ if ca_host is None: ca_host = api.env.ca_host if use_proxy: # Use port 443 to test the proxy as well ca_port = 443 else: ca_port = 8443 status, reason, headers, body = unauthenticated_https_request( ca_host, ca_port, '/ca/admin/ca/getStatus') if status == 503: # Service temporarily unavailable return reason elif status != 200: raise errors.RemoteRetrieveError( reason=_("Retrieving CA status failed: %s") % reason) doc = xml.dom.minidom.parseString(body) try: item_node = doc.getElementsByTagName("XMLResponse")[0] item_node = item_node.getElementsByTagName("Status")[0] return item_node.childNodes[0].data except IndexError: raise error_from_xml(doc, _("Retrieving CA status failed: %s"))
def pre_callback(self, ldap, dn, entry, entry_attrs, *keys, **options): ca_enabled_check(self.api) context.profile = options['file'] matches = self.PROFILE_ID_PATTERN.findall(options['file']) if len(matches) == 0: # no profileId found, use CLI value as profileId. context.profile = u'profileId=%s\n%s' % (keys[0], context.profile) elif len(matches) > 1: raise errors.ValidationError( name='file', error=_( "Profile data specifies profileId multiple times: " "%(values)s" ) % dict(values=matches) ) elif keys[0] != matches[0]: raise errors.ValidationError( name='file', error=_( "Profile ID '%(cli_value)s' " "does not match profile data '%(file_value)s'" ) % dict(cli_value=keys[0], file_value=matches[0]) ) return dn
def validate_dns_label(dns_label, allow_underscore=False, allow_slash=False): base_chars = "a-z0-9" extra_chars = "" middle_chars = "" if allow_underscore: extra_chars += "_" if allow_slash: middle_chars += "/" middle_chars = middle_chars + "-" # has to be always the last in the regex [....-] label_regex = r"^[%(base)s%(extra)s]([%(base)s%(extra)s%(middle)s]?[%(base)s%(extra)s])*$" % dict( base=base_chars, extra=extra_chars, middle=middle_chars ) regex = re.compile(label_regex, re.IGNORECASE) if not dns_label: raise ValueError(_("empty DNS label")) if len(dns_label) > 63: raise ValueError(_("DNS label cannot be longer that 63 characters")) if not regex.match(dns_label): chars = ", ".join("'%s'" % c for c in extra_chars + middle_chars) chars2 = ", ".join("'%s'" % c for c in middle_chars) raise ValueError( _("only letters, numbers, %(chars)s are allowed. " "DNS label may not start or end with %(chars2)s") % dict(chars=chars, chars2=chars2) )
def check_access(self, operation=None): """ Perform an LDAP query to determine authorization. This should be executed before any actual work is done. """ if self.operation is None and operation is None: raise errors.ACIError(info=_('operation not defined')) if operation is None: operation = self.operation ldap = self.api.Backend.ldap2 self.log.debug("IPA: virtual verify %s" % operation) operationdn = DN(('cn', operation), self.api.env.container_virtual, self.api.env.basedn) try: if not ldap.can_write(operationdn, "objectclass"): raise errors.ACIError( info=_('not allowed to perform operation: %s') % operation) except errors.NotFound: raise errors.ACIError(info=_('No such virtual command')) return True
def _retrieve(self, metaobjectfull_name, name, **kwargs): found = False try: metaobj = self.api.Command[metaobjectfull_name] except KeyError: raise errors.NotFound( reason=_("%(metaobject)s: %(oname)s not found") % { 'metaobject': metaobjectfull_name, 'oname': self.name, } ) if 'command' in self.api.Object: plugin = self.api.Object['command'] found = True elif 'class' in self.api.Object: plugin = self.api.Object['class'] found = True if found: for param in plugin._iter_params(metaobj): if param.name == name: return metaobj, param raise errors.NotFound( reason=_("%(pkey)s: %(oname)s not found") % { 'pkey': name, 'oname': self.name, } )
def execute(self, csr, **kw): ldap = self.api.Backend.ldap2 principal = kw.get('principal') add = kw.get('add') request_type = kw.get('request_type') service = None """ Access control is partially handled by the ACI titled 'Hosts can modify service userCertificate'. This is for the case where a machine binds using a host/ prinicpal. It can only do the request if the target hostname is in the managedBy attribute which is managed using the add/del member commands. Binding with a user principal one needs to be in the request_certs taskgroup (directly or indirectly via role membership). """ bind_principal = getattr(context, 'principal') # Can this user request certs? if not bind_principal.startswith('host/'): self.check_access() # FIXME: add support for subject alt name # Ensure that the hostname in the CSR matches the principal subject_host = get_csr_hostname(csr) if not subject_host: raise errors.ValidationError(name='csr', error=_("No hostname was found in subject of request.")) (servicename, hostname, realm) = split_principal(principal) if subject_host.lower() != hostname.lower(): raise errors.ACIError( info=_("hostname in subject of request '%(subject_host)s' " "does not match principal hostname '%(hostname)s'") % dict( subject_host=subject_host, hostname=hostname)) dn = None service = None # See if the service exists and punt if it doesn't and we aren't # going to add it try: if not principal.startswith('host/'): service = api.Command['service_show'](principal, all=True)['result'] dn = service['dn'] else: hostname = get_host_from_principal(principal) service = api.Command['host_show'](hostname, all=True)['result'] dn = service['dn'] except errors.NotFound, e: if not add: raise errors.NotFound(reason=_("The service principal for " "this request doesn't exist.")) try: service = api.Command['service_add'](principal, **{'force': True})['result'] dn = service['dn'] except errors.ACIError: raise errors.ACIError(info=_('You need to be a member of ' 'the serviceadmin role to add services'))
def get_ca_certchain(ca_host=None): """ Retrieve the CA Certificate chain from the configured Dogtag server. """ if ca_host is None: ca_host = api.env.ca_host chain = None conn = httplib.HTTPConnection( ca_host, api.env.ca_install_port or 8080) conn.request("GET", "/ca/ee/ca/getCertChain") res = conn.getresponse() doc = None if res.status == 200: data = res.read() conn.close() try: doc = xml.dom.minidom.parseString(data) try: item_node = doc.getElementsByTagName("ChainBase64") chain = item_node[0].childNodes[0].data except IndexError: raise error_from_xml( doc, _("Retrieving CA cert chain failed: %s")) finally: if doc: doc.unlink() else: raise errors.RemoteRetrieveError( reason=_("request failed with HTTP status %d") % res.status) return chain
def validate_dns_label(dns_label, allow_underscore=False, allow_slash=False): base_chars = 'a-z0-9' extra_chars = '' middle_chars = '' if allow_underscore: extra_chars += '_' if allow_slash: middle_chars += '/' middle_chars = middle_chars + '-' #has to be always the last in the regex [....-] label_regex = r'''^[%(base)s%(extra)s] # must begin with an alphanumeric # character, or underscore if # allow_underscore is True ([%(base)s%(extra)s%(middle)s]* # can contain all allowed character # classes in the middle [%(base)s%(extra)s])*$ # must end with alphanumeric # character or underscore if # allow_underscore is True ''' % dict(base=base_chars, extra=extra_chars, middle=middle_chars) regex = re.compile(label_regex, re.IGNORECASE | re.VERBOSE) if not dns_label: raise ValueError(_('empty DNS label')) if len(dns_label) > 63: raise ValueError(_('DNS label cannot be longer that 63 characters')) if not regex.match(dns_label): chars = ', '.join("'%s'" % c for c in extra_chars + middle_chars) chars2 = ', '.join("'%s'" % c for c in middle_chars) raise ValueError(_("only letters, numbers, %(chars)s are allowed. " \ "DNS label may not start or end with %(chars2)s") \ % dict(chars=chars, chars2=chars2))
def get_options(self): for option in super(cert_find, self).get_options(): if option.name == 'no_members': option = option.clone(default=True, flags=set(option.flags) | {'no_option'}) elif option.name == 'cacn': # make CA optional, so that user may directly # specify Issuer DN instead option = option.clone(default=None, autofill=None) yield option for owner in self.obj._owners(): yield owner.primary_key.clone_rename( '{0}'.format(owner.name), required=False, multivalue=True, primary_key=False, query=True, cli_name='{0}s'.format(owner.name), doc=(_("Search for certificates with these owner %s.") % owner.object_name_plural), label=owner.object_name, ) yield owner.primary_key.clone_rename( 'no_{0}'.format(owner.name), required=False, multivalue=True, primary_key=False, query=True, cli_name='no_{0}s'.format(owner.name), doc=(_("Search for certificates without these owner %s.") % owner.object_name_plural), label=owner.object_name, )
def validate_sshpubkey_no_options(ugettext, value): try: pubkey = SSHPublicKey(value) except ValueError as UnicodeDecodeError: return _('invalid SSH public key') if pubkey.has_options(): return _('options are not allowed')
def validate_sshpubkey_no_options(ugettext, value): try: pubkey = SSHPublicKey(value) except (ValueError, UnicodeDecodeError): return _("invalid SSH public key") if pubkey.has_options(): return _("options are not allowed")
def _on_finalize(self): # {topic: ["description", mcl, {"subtopic": ["description", mcl, [commands]]}]} # {topic: ["description", mcl, [commands]]} self._topics = {} # [builtin_commands] self._builtins = [] # build help topics for c in self.api.Command(): if c.NO_CLI: continue topic = self._get_module_topic(c.module) topic_name = topic[0] if topic_name: if topic[1] is None: # a module without grouping if topic_name in self._topics: self._topics[topic_name][2].append(c) else: m = '%s.%s' % (self._PLUGIN_BASE_MODULE, topic_name) try: module = sys.modules[m] except KeyError: doc = '' else: doc = ( unicode(_(module.__doc__)) or '' ).strip().split('\n', 1)[0] self._topics[topic_name] = [doc, 0, [c]] mcl = max((self._topics[topic_name][1], len(c.name))) self._topics[topic_name][1] = mcl else: # a module grouped in a topic doc = ( unicode(_(sys.modules[c.module].__doc__)) or '' ).strip().split('\n', 1)[0] mod_name = c.module.rsplit('.',1)[1] if topic_name in self._topics: if mod_name in self._topics[topic_name][2]: self._topics[topic_name][2][mod_name][2].append(c) else: self._topics[topic_name][2][mod_name] = [doc, 0, [c]] self._count_topic_mcl(topic_name, mod_name) # count mcl for for the subtopic mcl = max((self._topics[topic_name][2][mod_name][1], len(c.name))) self._topics[topic_name][2][mod_name][1] = mcl else: self._topics[topic_name] = [unicode(_(topic[1])), 0, {mod_name: [doc, 0, [c]]}] self._count_topic_mcl(topic_name, mod_name) else: self._builtins.append(c) # compute maximum topic length self._mtl = max( len(s) for s in (self._topics.keys() + [c.name for c in self._builtins]) ) super(help, self)._on_finalize()
def get_options(self): for option in super(BaseMetaSearch, self).get_options(): yield option yield Flag( 'pkey_only?', label=_("Primary key only"), doc=_("Results should contain primary key attribute only " "(\"%s\")") % 'name', )
def ipaddr_validator(ugettext, ipaddr, ip_version=None): try: ip = netaddr.IPAddress(str(ipaddr), flags=netaddr.INET_PTON) if ip_version is not None: if ip.version != ip_version: return _("invalid IP address version (is %(value)d, must be " "%(required_value)d)!") % dict( value=ip.version, required_value=ip_version ) except (netaddr.AddrFormatError, ValueError): return _("invalid IP address format") return None
def pre_callback(self, ldap, dn, entry, entry_attrs, *keys, **options): ca_enabled_check() match = self.PROFILE_ID_PATTERN.search(options['file']) if match is None: raise errors.ValidationError(name='file', error=_("Profile ID is not present in profile data")) elif keys[0] != match.group(1): raise errors.ValidationError(name='file', error=_("Profile ID '%(cli_value)s' does not match profile data '%(file_value)s'") % {'cli_value': keys[0], 'file_value': match.group(1)} ) return dn
def forward(self, csr=None, **options): database = options.pop('database', None) private_key = options.pop('private_key', None) csr_profile_id = options.pop('csr_profile_id', None) password_file = options.pop('password_file', None) if csr is None: # Deferred import, ipaclient.csrgen is expensive to load. # see https://pagure.io/freeipa/issue/7484 from ipaclient import csrgen if database: adaptor = csrgen.NSSAdaptor(database, password_file) elif private_key: adaptor = csrgen.OpenSSLAdaptor( key_filename=private_key, password_filename=password_file) else: raise errors.InvocationError( message=u"One of 'database' or 'private_key' is required") pubkey_info = adaptor.get_subject_public_key_info() pubkey_info_b64 = base64.b64encode(pubkey_info) # If csr_profile_id is passed, that takes precedence. # Otherwise, use profile_id. If neither are passed, the default # in cert_get_requestdata will be used. profile_id = csr_profile_id if profile_id is None: profile_id = options.get('profile_id') response = self.api.Command.cert_get_requestdata( profile_id=profile_id, principal=options.get('principal'), public_key_info=pubkey_info_b64) req_info_b64 = response['result']['request_info'] req_info = base64.b64decode(req_info_b64) csr = adaptor.sign_csr(req_info) if not csr: raise errors.CertificateOperationError( error=(_('Generated CSR was empty'))) else: if database is not None or private_key is not None: raise errors.MutuallyExclusiveError(reason=_( "Options 'database' and 'private_key' are not compatible" " with 'csr'")) return super(cert_request, self).forward(csr, **options)
def forward(self, csr=None, **options): database = options.pop('database', None) private_key = options.pop('private_key', None) csr_profile_id = options.pop('csr_profile_id', None) password_file = options.pop('password_file', None) if csr is None: if database: adaptor = csrgen.NSSAdaptor(database, password_file) elif private_key: adaptor = csrgen.OpenSSLAdaptor(private_key, password_file) else: raise errors.InvocationError( message=u"One of 'database' or 'private_key' is required") pubkey_info = adaptor.get_subject_public_key_info() pubkey_info_b64 = base64.b64encode(pubkey_info) # If csr_profile_id is passed, that takes precedence. # Otherwise, use profile_id. If neither are passed, the default # in cert_get_requestdata will be used. profile_id = csr_profile_id if profile_id is None: profile_id = options.get('profile_id') response = self.api.Command.cert_get_requestdata( profile_id=profile_id, principal=options.get('principal'), public_key_info=unicode(pubkey_info_b64)) req_info_b64 = response['result']['request_info'] req_info = base64.b64decode(req_info_b64) csr = adaptor.sign_csr(req_info) if not csr: raise errors.CertificateOperationError( error=(_('Generated CSR was empty'))) # cert_request requires the CSR to be base64-encoded (but PEM # header and footer are not required) csr = unicode(base64.b64encode(csr)) else: if database is not None or private_key is not None: raise errors.MutuallyExclusiveError(reason=_( "Options 'database' and 'private_key' are not compatible" " with 'csr'")) return super(cert_request, self).forward(csr, **options)
def validate_sshpubkey(ugettext, value): try: SSHPublicKey(value) except (ValueError, UnicodeDecodeError): return _('invalid SSH public key') else: return None
def _prepare_syntax_rule( self, syntax_rule, data_rules, description, data_sources): logger.debug('Syntax rule template: %s' % syntax_rule.template) template = self.jinja2.from_string( syntax_rule.template, globals=self.passthrough_globals) is_required = syntax_rule.options.get('required', False) try: prepared_template = template.render(datarules=data_rules) except jinja2.UndefinedError: logger.debug(traceback.format_exc()) raise errors.CSRTemplateError(reason=_( 'Template error when formatting certificate data')) if data_sources: combinator = ' %s ' % syntax_rule.options.get( 'data_source_combinator', 'or') condition = combinator.join(data_sources) prepared_template = self._wrap_conditional( prepared_template, condition) if is_required: prepared_template = self._wrap_required( prepared_template, description) return prepared_template
def validate_hostmask(ugettext, hostmask): try: netaddr.IPNetwork(hostmask) except (ValueError, AddrFormatError): return _('invalid hostmask') else: return None
def check_writable_file(filename): """ Determine if the file is writable. If the file doesn't exist then open the file to test writability. """ if filename is None: raise errors.FileError(reason=_('Filename is empty')) try: if os.path.isfile(filename): if not os.access(filename, os.W_OK): raise errors.FileError(reason=_('Permission denied: %(file)s') % dict(file=filename)) else: fp = open(filename, 'w') fp.close() except (IOError, OSError) as e: raise errors.FileError(reason=str(e))
def hostname_validator(ugettext, value): try: validate_hostname(value) except ValueError as e: return _('invalid domain-name: %s') % unicode(e) return None
def required(self, data, name): if not data: raise errors.CSRTemplateError( reason=_( 'Required CSR generation rule %(name)s is missing data') % {'name': name}) return data
def new_session_id(self, max_retries=5): ''' Returns a new *unique* session id. See `generate_session_id()` for how the session id's are formulated. The scope of the uniqueness of the id is limited to id's generated by this instance of the `SessionManager`. :parameters: max_retries Maximum number of attempts to produce a unique id. :returns: Unique session id as a string. ''' n_retries = 0 while n_retries < max_retries: session_id = self.generate_session_id() if not session_id in self.generated_session_ids: break n_retries += 1 if n_retries >= max_retries: self.error('could not allocate unique new session_id, %d retries exhausted', n_retries) raise errors.ExecutionError(message=_('could not allocate unique new session_id')) self.generated_session_ids.add(session_id) return session_id
def check_principal_realm_in_trust_namespace(api_instance, *keys): """ Check that principal name's suffix does not overlap with UPNs and realm names of trusted forests. :param api_instance: API instance :param suffixes: principal suffixes :raises: ValidationError if the suffix coincides with realm name, UPN suffix or netbios name of trusted domains """ trust_objects = api_instance.Command.trust_find(u'', sizelimit=0)['result'] trust_suffix_namespace = set() for obj in trust_objects: nt_suffixes = obj.get('ipantadditionalsuffixes', []) trust_suffix_namespace.update( set(upn.lower() for upn in nt_suffixes)) if 'ipantflatname' in obj: trust_suffix_namespace.add(obj['ipantflatname'][0].lower()) trust_suffix_namespace.add(obj['cn'][0].lower()) for principal in keys[-1]: realm = principal.realm upn = principal.upn_suffix if principal.is_enterprise else None if realm in trust_suffix_namespace or upn in trust_suffix_namespace: raise errors.ValidationError( name='krbprincipalname', error=_('realm or UPN suffix overlaps with trusted domain ' 'namespace'))
def summary(self): doc = self.doc if not _(doc).msg: cls = type(self) return u'<%s.%s>' % (cls.__module__, cls.__name__) else: return unicode(doc).split('\n\n', 1)[0].strip()
def execute(self, csr, **kw): ca_enabled_check() ldap = self.api.Backend.ldap2 principal = kw.get('principal') add = kw.get('add') request_type = kw.get('request_type') service = None """ Access control is partially handled by the ACI titled 'Hosts can modify service userCertificate'. This is for the case where a machine binds using a host/ prinicpal. It can only do the request if the target hostname is in the managedBy attribute which is managed using the add/del member commands. Binding with a user principal one needs to be in the request_certs taskgroup (directly or indirectly via role membership). """ bind_principal = getattr(context, 'principal') # Can this user request certs? if not bind_principal.startswith('host/'): self.check_access() try: subject = pkcs10.get_subject(csr) extensions = pkcs10.get_extensions(csr) subjectaltname = pkcs10.get_subjectaltname(csr) or () except (NSPRError, PyAsn1Error), e: raise errors.CertificateOperationError( error=_("Failure decoding Certificate Signing Request: %s") % e)
def execute(self, serial_number, **kw): ca_enabled_check() # Make sure that the cert specified by issuer+serial exists. # Will raise NotFound if it does not. resp = api.Command.cert_show(unicode(serial_number), cacn=kw['cacn']) try: self.check_access() except errors.ACIError as acierr: self.debug("Not granted by ACI to revoke certificate, looking at principal") try: cert = x509.load_certificate(resp['result']['certificate']) if not bind_principal_can_manage_cert(cert): raise acierr except errors.NotImplementedError: raise acierr revocation_reason = kw['revocation_reason'] if revocation_reason == 7: raise errors.CertificateOperationError(error=_('7 is not a valid revocation reason')) return dict( # Dogtag lightweight CAs have shared serial number domain, so # we don't tell Dogtag the issuer (but we already checked that # the given serial was issued by the named ca). result=self.Backend.ra.revoke_certificate( str(serial_number), revocation_reason=revocation_reason) )
def __init__(self, api): assert api is not None self.__api = api self.__finalize_called = False self.__finalized = False self.__finalize_lock = threading.RLock() cls = self.__class__ self.name = cls.__name__ self.module = cls.__module__ self.fullname = '%s.%s' % (self.module, self.name) self.bases = tuple( '%s.%s' % (b.__module__, b.__name__) for b in cls.__bases__ ) self.doc = _(cls.__doc__) if not self.doc.msg: self.summary = '<%s>' % self.fullname else: self.summary = unicode(self.doc).split('\n\n', 1)[0].strip() log_mgr.get_logger(self, True) if self.label is None: self.label = text.FixMe(self.name + '.label') if not isinstance(self.label, text.LazyText): raise TypeError( TYPE_ERROR % ( self.fullname + '.label', text.LazyText, type(self.label), self.label ) )
def new_session_id(self, max_retries=5): ''' Returns a new *unique* session id. See `generate_session_id()` for how the session id's are formulated. The scope of the uniqueness of the id is limited to id's generated by this instance of the `SessionManager` and session id's currently stored in the memcache instance. :parameters: max_retries Maximum number of attempts to produce a unique id. :returns: Unique session id as a string. ''' n_retries = 0 while n_retries < max_retries: session_id = super(MemcacheSessionManager, self).new_session_id(max_retries) session_data = self.get_session_data(session_id) if session_data is None: break n_retries += 1 if n_retries >= max_retries: self.error('could not allocate unique new session_id, %d retries exhausted', n_retries) raise errors.ExecutionError(message=_('could not allocate unique new session_id')) return session_id
class user(Object): takes_params = ( parameters.Str( 'uid', primary_key=True, label=_(u'User login'), ), parameters.Str( 'givenname', label=_(u'First name'), ), parameters.Str( 'sn', label=_(u'Last name'), ), parameters.Str( 'cn', label=_(u'Full name'), ), parameters.Str( 'displayname', required=False, label=_(u'Display name'), ), parameters.Str( 'initials', required=False, label=_(u'Initials'), ), parameters.Str( 'homedirectory', required=False, label=_(u'Home directory'), ), parameters.Str( 'gecos', required=False, label=_(u'GECOS'), ), parameters.Str( 'loginshell', required=False, label=_(u'Login shell'), ), parameters.Str( 'krbprincipalname', required=False, label=_(u'Kerberos principal'), ), parameters.DateTime( 'krbprincipalexpiration', required=False, label=_(u'Kerberos principal expiration'), ), parameters.Str( 'mail', required=False, multivalue=True, label=_(u'Email address'), ), parameters.Password( 'userpassword', required=False, label=_(u'Password'), doc=_(u'Prompt to set the user password'), exclude=('webui', ), ), parameters.Flag( 'random', required=False, doc=_(u'Generate a random user password'), ), parameters.Str( 'randompassword', required=False, label=_(u'Random password'), ), parameters.Int( 'uidnumber', required=False, label=_(u'UID'), doc=_(u'User ID Number (system will assign one if not provided)'), ), parameters.Int( 'gidnumber', required=False, label=_(u'GID'), doc=_(u'Group ID Number'), ), parameters.Str( 'street', required=False, label=_(u'Street address'), ), parameters.Str( 'l', required=False, label=_(u'City'), ), parameters.Str( 'st', required=False, label=_(u'State/Province'), ), parameters.Str( 'postalcode', required=False, label=_(u'ZIP'), ), parameters.Str( 'telephonenumber', required=False, multivalue=True, label=_(u'Telephone Number'), ), parameters.Str( 'mobile', required=False, multivalue=True, label=_(u'Mobile Telephone Number'), ), parameters.Str( 'pager', required=False, multivalue=True, label=_(u'Pager Number'), ), parameters.Str( 'facsimiletelephonenumber', required=False, multivalue=True, label=_(u'Fax Number'), ), parameters.Str( 'ou', required=False, label=_(u'Org. Unit'), ), parameters.Str( 'title', required=False, label=_(u'Job Title'), ), parameters.Str( 'manager', required=False, label=_(u'Manager'), ), parameters.Str( 'carlicense', required=False, multivalue=True, label=_(u'Car License'), ), parameters.Bool( 'nsaccountlock', required=False, label=_(u'Account disabled'), ), parameters.Str( 'ipasshpubkey', required=False, multivalue=True, label=_(u'SSH public key'), ), parameters.Str( 'ipauserauthtype', required=False, multivalue=True, label=_(u'User authentication types'), doc=_(u'Types of supported user authentication'), ), parameters.Str( 'userclass', required=False, multivalue=True, label=_(u'Class'), doc= _(u'User category (semantics placed on this attribute are for local interpretation)' ), ), parameters.Str( 'ipatokenradiusconfiglink', required=False, label=_(u'RADIUS proxy configuration'), ), parameters.Str( 'ipatokenradiususername', required=False, label=_(u'RADIUS proxy username'), ), parameters.Str( 'departmentnumber', required=False, multivalue=True, label=_(u'Department Number'), ), parameters.Str( 'employeenumber', required=False, label=_(u'Employee Number'), ), parameters.Str( 'employeetype', required=False, label=_(u'Employee Type'), ), parameters.Str( 'preferredlanguage', required=False, label=_(u'Preferred Language'), ), parameters.Flag( 'has_password', label=_(u'Password'), ), parameters.Str( 'memberof_group', required=False, label=_(u'Member of groups'), ), parameters.Str( 'memberof_role', required=False, label=_(u'Roles'), ), parameters.Str( 'memberof_netgroup', required=False, label=_(u'Member of netgroups'), ), parameters.Str( 'memberof_sudorule', required=False, label=_(u'Member of Sudo rule'), ), parameters.Str( 'memberof_hbacrule', required=False, label=_(u'Member of HBAC rule'), ), parameters.Str( 'memberofindirect_group', required=False, label=_(u'Indirect Member of group'), ), parameters.Str( 'memberofindirect_netgroup', required=False, label=_(u'Indirect Member of netgroup'), ), parameters.Str( 'memberofindirect_role', required=False, label=_(u'Indirect Member of role'), ), parameters.Str( 'memberofindirect_sudorule', required=False, label=_(u'Indirect Member of Sudo rule'), ), parameters.Str( 'memberofindirect_hbacrule', required=False, label=_(u'Indirect Member of HBAC rule'), ), parameters.Flag( 'has_keytab', label=_(u'Kerberos keys available'), ), )
class group_find(Method): __doc__ = _("Search for groups.") takes_args = (parameters.Str( 'criteria', required=False, doc=_(u'A string searched in all relevant object attributes'), ), ) takes_options = ( parameters.Str( 'cn', required=False, cli_name='group_name', label=_(u'Group name'), no_convert=True, ), parameters.Str( 'description', required=False, cli_name='desc', label=_(u'Description'), doc=_(u'Group description'), ), parameters.Int( 'gidnumber', required=False, cli_name='gid', label=_(u'GID'), doc=_(u'GID (use this option to set it manually)'), ), parameters.Int( 'timelimit', required=False, label=_(u'Time Limit'), doc=_(u'Time limit of search in seconds (0 is unlimited)'), ), parameters.Int( 'sizelimit', required=False, label=_(u'Size Limit'), doc=_(u'Maximum number of entries returned (0 is unlimited)'), ), parameters.Flag( 'private', doc=_(u'search for private groups'), default=False, autofill=True, ), parameters.Flag( 'posix', doc=_(u'search for POSIX groups'), default=False, autofill=True, ), parameters.Flag( 'external', doc= _(u'search for groups with support of external non-IPA members from trusted domains' ), default=False, autofill=True, ), parameters.Flag( 'nonposix', doc=_(u'search for non-POSIX groups'), default=False, autofill=True, ), parameters.Flag( 'all', doc= _(u'Retrieve and print all attributes from the server. Affects command output.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'raw', doc= _(u'Print entries as stored on the server. Only affects output format.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'no_members', doc=_(u'Suppress processing of membership attributes.'), exclude=('webui', 'cli'), default=False, autofill=True, ), parameters.Flag( 'pkey_only', required=False, label=_(u'Primary key only'), doc= _(u'Results should contain primary key attribute only ("group-name")' ), default=False, autofill=True, ), parameters.Str( 'user', required=False, multivalue=True, cli_name='users', label=_(u'user'), doc=_(u'Search for groups with these member users.'), ), parameters.Str( 'no_user', required=False, multivalue=True, cli_name='no_users', label=_(u'user'), doc=_(u'Search for groups without these member users.'), ), parameters.Str( 'group', required=False, multivalue=True, cli_name='groups', label=_(u'group'), doc=_(u'Search for groups with these member groups.'), ), parameters.Str( 'no_group', required=False, multivalue=True, cli_name='no_groups', label=_(u'group'), doc=_(u'Search for groups without these member groups.'), ), parameters.Str( 'in_group', required=False, multivalue=True, cli_name='in_groups', label=_(u'group'), doc=_(u'Search for groups with these member of groups.'), ), parameters.Str( 'not_in_group', required=False, multivalue=True, cli_name='not_in_groups', label=_(u'group'), doc=_(u'Search for groups without these member of groups.'), ), parameters.Str( 'in_netgroup', required=False, multivalue=True, cli_name='in_netgroups', label=_(u'netgroup'), doc=_(u'Search for groups with these member of netgroups.'), ), parameters.Str( 'not_in_netgroup', required=False, multivalue=True, cli_name='not_in_netgroups', label=_(u'netgroup'), doc=_(u'Search for groups without these member of netgroups.'), ), parameters.Str( 'in_role', required=False, multivalue=True, cli_name='in_roles', label=_(u'role'), doc=_(u'Search for groups with these member of roles.'), ), parameters.Str( 'not_in_role', required=False, multivalue=True, cli_name='not_in_roles', label=_(u'role'), doc=_(u'Search for groups without these member of roles.'), ), parameters.Str( 'in_hbacrule', required=False, multivalue=True, cli_name='in_hbacrules', label=_(u'HBAC rule'), doc=_(u'Search for groups with these member of HBAC rules.'), ), parameters.Str( 'not_in_hbacrule', required=False, multivalue=True, cli_name='not_in_hbacrules', label=_(u'HBAC rule'), doc=_(u'Search for groups without these member of HBAC rules.'), ), parameters.Str( 'in_sudorule', required=False, multivalue=True, cli_name='in_sudorules', label=_(u'sudo rule'), doc=_(u'Search for groups with these member of sudo rules.'), ), parameters.Str( 'not_in_sudorule', required=False, multivalue=True, cli_name='not_in_sudorules', label=_(u'sudo rule'), doc=_(u'Search for groups without these member of sudo rules.'), ), ) has_output = ( output.Output( 'summary', (unicode, type(None)), doc=_(u'User-friendly description of action performed'), ), output.ListOfEntries('result', ), output.Output( 'count', int, doc=_(u'Number of entries returned'), ), output.Output( 'truncated', bool, doc=_(u'True if not all results were returned'), ), )
class group_remove_member(Method): __doc__ = _("Remove members from a group.") takes_args = (parameters.Str( 'cn', cli_name='group_name', label=_(u'Group name'), no_convert=True, ), ) takes_options = ( parameters.Str( 'ipaexternalmember', required=False, multivalue=True, cli_name='external', label=_(u'External member'), doc=_( u'Members of a trusted domain in DOM\\name or name@domain form' ), ), parameters.Flag( 'all', doc= _(u'Retrieve and print all attributes from the server. Affects command output.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'raw', doc= _(u'Print entries as stored on the server. Only affects output format.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'no_members', doc=_(u'Suppress processing of membership attributes.'), exclude=('webui', 'cli'), default=False, autofill=True, ), parameters.Str( 'user', required=False, multivalue=True, cli_name='users', label=_(u'member user'), doc=_(u'users to remove'), alwaysask=True, ), parameters.Str( 'group', required=False, multivalue=True, cli_name='groups', label=_(u'member group'), doc=_(u'groups to remove'), alwaysask=True, ), ) has_output = ( output.Entry('result', ), output.Output( 'failed', dict, doc=_(u'Members that could not be removed'), ), output.Output( 'completed', int, doc=_(u'Number of members removed'), ), )
class UnresolvableRecordError(ForwarderValidationError): format = _("query '%(owner)s %(rtype)s': %(error)s")
class DNSSECSignatureMissingError(ForwarderValidationError): format = _("answer to query '%(owner)s %(rtype)s' is missing DNSSEC " "signatures (no RRSIG data)")
def validate_sshpubkey_no_options(ugettext, value): try: pubkey = SSHPublicKey(value) except ValueError, UnicodeDecodeError: return _('invalid SSH public key')
class sudocmd_add(Method): __doc__ = _("Create new Sudo Command.") takes_args = (parameters.Str( 'sudocmd', cli_name='command', label=_(u'Sudo Command'), ), ) takes_options = ( parameters.Str( 'description', required=False, cli_name='desc', label=_(u'Description'), doc=_(u'A description of this command'), ), parameters.Str( 'setattr', required=False, multivalue=True, doc= _(u'Set an attribute to a name/value pair. Format is attr=value.\nFor multi-valued attributes, the command replaces the values already present.' ), exclude=('webui', ), ), parameters.Str( 'addattr', required=False, multivalue=True, doc= _(u'Add an attribute/value pair. Format is attr=value. The attribute\nmust be part of the schema.' ), exclude=('webui', ), ), parameters.Flag( 'all', doc= _(u'Retrieve and print all attributes from the server. Affects command output.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'raw', doc= _(u'Print entries as stored on the server. Only affects output format.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'no_members', doc=_(u'Suppress processing of membership attributes.'), exclude=('webui', 'cli'), default=False, autofill=True, ), ) has_output = ( output.Output( 'summary', (unicode, type(None)), doc=_(u'User-friendly description of action performed'), ), output.Entry('result', ), output.PrimaryKey( 'value', doc=_( u"The primary_key value of the entry, e.g. 'jdoe' for a user"), ), )
def validate_profile_id(ugettext, value): """Ensure profile ID matches form required by CA.""" if profile_id_pattern.match(value) is None: return _('invalid Profile ID') else: return None
class certprofile(LDAPObject): """ Certificate Profile object. """ container_dn = api.env.container_certprofile object_name = _('Certificate Profile') object_name_plural = _('Certificate Profiles') object_class = ['ipacertprofile'] default_attributes = [ 'cn', 'description', 'ipacertprofilestoreissued' ] search_attributes = [ 'cn', 'description', 'ipacertprofilestoreissued' ] label = _('Certificate Profiles') label_singular = _('Certificate Profile') takes_params = ( Str('cn', validate_profile_id, primary_key=True, cli_name='id', label=_('Profile ID'), doc=_('Profile ID for referring to this profile'), ), Str('config', label=_('Profile configuration'), flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'}, ), Str('description', required=True, cli_name='desc', label=_('Profile description'), doc=_('Brief description of this profile'), ), Bool('ipacertprofilestoreissued', default=True, cli_name='store', label=_('Store issued certificates'), doc=_('Whether to store certs issued using this profile'), ), ) permission_filter_objectclasses = ['ipacertprofile'] managed_permissions = { 'System: Read Certificate Profiles': { 'replaces_global_anonymous_aci': True, 'ipapermbindruletype': 'all', 'ipapermright': {'read', 'search', 'compare'}, 'ipapermdefaultattr': { 'cn', 'description', 'ipacertprofilestoreissued', 'objectclass', }, }, 'System: Import Certificate Profile': { 'ipapermright': {'add'}, 'replaces': [ '(target = "ldap:///cn=*,cn=certprofiles,cn=ca,$SUFFIX")(version 3.0;acl "permission:Import Certificate Profile";allow (add) groupdn = "ldap:///cn=Import Certificate Profile,cn=permissions,cn=pbac,$SUFFIX";)', ], 'default_privileges': {'CA Administrator'}, }, 'System: Delete Certificate Profile': { 'ipapermright': {'delete'}, 'replaces': [ '(target = "ldap:///cn=*,cn=certprofiles,cn=ca,$SUFFIX")(version 3.0;acl "permission:Delete Certificate Profile";allow (delete) groupdn = "ldap:///cn=Delete Certificate Profile,cn=permissions,cn=pbac,$SUFFIX";)', ], 'default_privileges': {'CA Administrator'}, }, 'System: Modify Certificate Profile': { 'ipapermright': {'write'}, 'ipapermdefaultattr': { 'cn', 'description', 'ipacertprofilestoreissued', }, 'replaces': [ '(targetattr = "cn || description || ipacertprofilestoreissued")(target = "ldap:///cn=*,cn=certprofiles,cn=ca,$SUFFIX")(version 3.0;acl "permission:Modify Certificate Profile";allow (write) groupdn = "ldap:///cn=Modify Certificate Profile,cn=permissions,cn=pbac,$SUFFIX";)', ], 'default_privileges': {'CA Administrator'}, }, }
__doc__ = _(""" Manage Certificate Profiles Certificate Profiles are used by Certificate Authority (CA) in the signing of certificates to determine if a Certificate Signing Request (CSR) is acceptable, and if so what features and extensions will be present on the certificate. The Certificate Profile format is the property-list format understood by the Dogtag or Red Hat Certificate System CA. PROFILE ID SYNTAX: A Profile ID is a string without spaces or punctuation starting with a letter and followed by a sequence of letters, digits or underscore ("_"). EXAMPLES: Import a profile that will not store issued certificates: ipa certprofile-import ShortLivedUserCert \\ --file UserCert.profile --desc "User Certificates" \\ --store=false Delete a certificate profile: ipa certprofile-del ShortLivedUserCert Show information about a profile: ipa certprofile-show ShortLivedUserCert Save profile configuration to a file: ipa certprofile-show caIPAserviceCert --out caIPAserviceCert.cfg Search for profiles that do not store certificates: ipa certprofile-find --store=false PROFILE CONFIGURATION FORMAT: The profile configuration format is the raw property-list format used by Dogtag Certificate System. The XML format is not supported. The following restrictions apply to profiles managed by FreeIPA: - When importing a profile the "profileId" field, if present, must match the ID given on the command line. - The "classId" field must be set to "caEnrollImpl" - The "auth.instance_id" field must be set to "raCertAuth" - The "certReqInputImpl" input class and "certOutputImpl" output class must be used. """)
class DNSSECValidationError(ForwarderValidationError): format = _("record '%(owner)s %(rtype)s' " "failed DNSSEC validation on server %(ip)s")
class user_status(Method): __doc__ = _(""" Lockout status of a user account An account may become locked if the password is entered incorrectly too many times within a specific time period as controlled by password policy. A locked account is a temporary condition and may be unlocked by an administrator. This connects to each IPA master and displays the lockout status on each one. To determine whether an account is locked on a given server you need to compare the number of failed logins and the time of the last failure. For an account to be locked it must exceed the maxfail failures within the failinterval duration as specified in the password policy associated with the user. The failed login counter is modified only when a user attempts a log in so it is possible that an account may appear locked but the last failed login attempt is older than the lockouttime of the password policy. This means that the user may attempt a login again. """) takes_args = (parameters.Str( 'uid', cli_name='login', label=_(u'User login'), default_from=DefaultFrom(lambda givenname, sn: givenname[0] + sn, 'principal'), no_convert=True, ), ) takes_options = ( parameters.Flag( 'all', doc= _(u'Retrieve and print all attributes from the server. Affects command output.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'raw', doc= _(u'Print entries as stored on the server. Only affects output format.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'no_members', doc=_(u'Suppress processing of membership attributes.'), exclude=('webui', 'cli'), default=False, autofill=True, ), ) has_output = ( output.Output( 'summary', (unicode, type(None)), doc=_(u'User-friendly description of action performed'), ), output.ListOfEntries('result', ), output.Output( 'count', int, doc=_(u'Number of entries returned'), ), output.Output( 'truncated', bool, doc=_(u'True if not all results were returned'), ), )
class EDNS0UnsupportedError(ForwarderValidationError): format = _("query '%(owner)s %(rtype)s' with EDNS0: %(error)s")
class subid(LDAPObject): """Subordinate id object.""" container_dn = api.env.container_subids object_name = _("Subordinate id") object_name_plural = _("Subordinate ids") label = _("Subordinate ids") label_singular = _("Subordinate id") object_class = ["ipasubordinateidentry"] possible_objectclasses = [ "ipasubordinategid", "ipasubordinateuid", "ipasubordinateid", ] default_attributes = [ "ipauniqueid", "ipaowner", "ipasubuidnumber", "ipasubuidcount", "ipasubgidnumber", "ipasubgidcount", ] allow_rename = False permission_filter_objectclasses_string = ( "(objectclass=ipasubordinateidentry)") managed_permissions = { # all authenticated principals can read subordinate id information "System: Read Subordinate Id Attributes": { "ipapermbindruletype": "all", "ipapermright": {"read", "search", "compare"}, "ipapermtargetfilter": [ permission_filter_objectclasses_string, ], "ipapermdefaultattr": { "objectclass", "ipauniqueid", "description", "ipaowner", "ipasubuidnumber", "ipasubuidcount", "ipasubgidnumber", "ipasubgidcount", }, }, "System: Read Subordinate Id Count": { "ipapermbindruletype": "all", "ipapermright": {"read", "search", "compare"}, "ipapermtargetfilter": [], "ipapermtarget": DN(container_dn, api.env.basedn), "ipapermdefaultattr": {"numSubordinates"}, }, # user administrators can remove subordinate ids or update the # ipaowner attribute. This enables user admins to remove users # with assigned subids or move them to staging area (--preserve). "System: Manage Subordinate Ids": { "ipapermright": {"write"}, "ipapermtargetfilter": [ permission_filter_objectclasses_string, ], "ipapermdefaultattr": { "description", "ipaowner", # allow user admins to preserve users }, "default_privileges": {"User Administrators"}, }, "System: Remove Subordinate Ids": { "ipapermright": {"delete"}, "ipapermtargetfilter": [ permission_filter_objectclasses_string, ], "default_privileges": {"User Administrators"}, }, } takes_params = ( Str( "ipauniqueid", cli_name="id", label=_("Unique ID"), primary_key=True, flags={"optional_create"}, ), Str( "description?", cli_name="desc", label=_("Description"), doc=_("Subordinate id description"), ), Str( "ipaowner", cli_name="owner", label=_("Owner"), doc=_("Owning user of subordinate id entry"), flags={"no_update"}, ), Int( "ipasubuidnumber?", label=_("SubUID range start"), cli_name="subuid", doc=_("Start value for subordinate user ID (subuid) range"), flags={"no_update"}, minvalue=constants.SUBID_RANGE_START, maxvalue=constants.SUBID_RANGE_MAX, ), Int( "ipasubuidcount?", label=_("SubUID range size"), cli_name="subuidcount", doc=_("Subordinate user ID count"), flags={"no_create", "no_update", "no_search"}, # auto-assigned minvalue=constants.SUBID_COUNT, maxvalue=constants.SUBID_COUNT, ), Int( "ipasubgidnumber?", label=_("SubGID range start"), cli_name="subgid", doc=_("Start value for subordinate group ID (subgid) range"), flags={"no_create", "no_update"}, # auto-assigned minvalue=constants.SUBID_RANGE_START, maxvalue=constants.SUBID_RANGE_MAX, ), Int( "ipasubgidcount?", label=_("SubGID range size"), cli_name="subgidcount", doc=_("Subordinate group ID count"), flags={"no_create", "no_update", "no_search"}, # auto-assigned minvalue=constants.SUBID_COUNT, maxvalue=constants.SUBID_COUNT, ), ) def fixup_objectclass(self, entry_attrs): """Add missing object classes to entry""" has_subuid = "ipasubuidnumber" in entry_attrs has_subgid = "ipasubgidnumber" in entry_attrs candicates = set(self.object_class) if has_subgid: candicates.add("ipasubordinategid") if has_subuid: candicates.add("ipasubordinateuid") if has_subgid and has_subuid: candicates.add("ipasubordinateid") entry_oc = entry_attrs.setdefault("objectclass", []) current_oc = {x.lower() for x in entry_oc} for oc in candicates.difference(current_oc): entry_oc.append(oc) def handle_duplicate_entry(self, *keys): if hasattr(context, "subid_owner_dn"): uid = context.subid_owner_dn[0].value msg = _( '%(oname)s with with name "%(pkey)s" or for user "%(uid)s" ' "already exists.") % { "uid": uid, "pkey": keys[-1] if keys else "", "oname": self.object_name, } raise errors.DuplicateEntry(message=msg) from None else: super().handle_duplicate_entry(*keys) def convert_owner(self, entry_attrs, options): """Change owner from DN to uid string""" if not options.get("raw", False) and "ipaowner" in entry_attrs: userobj = self.api.Object.user entry_attrs["ipaowner"] = [ userobj.get_primary_key_from_dn(entry_attrs["ipaowner"][0]) ] def get_owner_dn(self, *keys, **options): """Get owning user entry entry (username or DN)""" owner = keys[-1] userobj = self.api.Object.user if isinstance(owner, DN): # it's already a DN, validate it's either an active or preserved # user. Ref integrity plugin checks that it's not a dangling DN. user_dns = ( DN(userobj.active_container_dn, self.api.env.basedn), DN(userobj.delete_container_dn, self.api.env.basedn), ) if not owner.endswith(user_dns): raise errors.ValidationError( name="ipaowner", error=_("'%(dn)s is not a valid user") % {"dn": owner}, ) return owner # similar to user.get_either_dn() but with error reporting and # returns an entry ldap = self.backend try: active_dn = userobj.get_dn(owner, **options) entry = ldap.get_entry(active_dn, attrs_list=[]) return entry.dn except errors.NotFound: # fall back to deleted user try: delete_dn = userobj.get_delete_dn(owner, **options) entry = ldap.get_entry(delete_dn, attrs_list=[]) return entry.dn except errors.NotFound: raise userobj.handle_not_found(owner) def handle_subordinate_ids(self, ldap, dn, entry_attrs): """Handle ipaSubordinateId object class""" new_subuid = entry_attrs.single_value.get("ipasubuidnumber") new_subgid = entry_attrs.single_value.get("ipasubgidnumber") if new_subuid is None: new_subuid = DNA_MAGIC # enforce subuid == subgid if new_subgid is not None and new_subgid != new_subuid: raise errors.ValidationError( name="ipasubgidnumber", error=_("subgidnumber must be equal to subuidnumber"), ) self.set_subordinate_ids(ldap, dn, entry_attrs, new_subuid) return True def set_subordinate_ids(self, ldap, dn, entry_attrs, subuid): """Set subuid value of an entry Takes care of objectclass and sibbling attributes """ if "objectclass" not in entry_attrs: _entry_attrs = ldap.get_entry(dn, ["objectclass"]) entry_attrs["objectclass"] = _entry_attrs["objectclass"] entry_attrs["ipasubuidnumber"] = subuid # enforce subuid == subgid for now entry_attrs["ipasubgidnumber"] = subuid # hard-coded constants entry_attrs["ipasubuidcount"] = constants.SUBID_COUNT entry_attrs["ipasubgidcount"] = constants.SUBID_COUNT self.fixup_objectclass(entry_attrs) def get_subid_match_candidate_filter( self, ldap, *, subuid, subgid, extra_filters=(), offset=None, ): """Create LDAP filter to locate matching/overlapping subids""" if subuid is None and subgid is None: raise ValueError("subuid and subgid are both None") if offset is None: # assumes that no subordinate count is larger than SUBID_COUNT offset = constants.SUBID_COUNT - 1 class_filters = "(objectclass=ipasubordinateid)" subid_filters = [] if subuid is not None: subid_filters.append( ldap.combine_filters( [ f"(ipasubuidnumber>={subuid - offset})", f"(ipasubuidnumber<={subuid + offset})", ], rules=ldap.MATCH_ALL, )) if subgid is not None: subid_filters.append( ldap.combine_filters( [ f"(ipasubgidnumber>={subgid - offset})", f"(ipasubgidnumber<={subgid + offset})", ], rules=ldap.MATCH_ALL, )) subid_filters = ldap.combine_filters(subid_filters, rules=ldap.MATCH_ANY) filters = [class_filters, subid_filters] filters.extend(extra_filters) return ldap.combine_filters(filters, rules=ldap.MATCH_ALL)
__doc__ = _(""" Users Manage user entries. All users are POSIX users. IPA supports a wide range of username formats, but you need to be aware of any restrictions that may apply to your particular environment. For example, usernames that start with a digit or usernames that exceed a certain length may cause problems for some UNIX systems. Use 'ipa config-mod' to change the username format allowed by IPA tools. Disabling a user account prevents that user from obtaining new Kerberos credentials. It does not invalidate any credentials that have already been issued. Password management is not a part of this module. For more information about this topic please see: ipa help passwd Account lockout on password failure happens per IPA master. The user-status command can be used to identify which master the user is locked out on. It is on that master the administrator must unlock the user. EXAMPLES: Add a new user: ipa user-add --first=Tim --last=User --password tuser1 Find all users whose entries include the string "Tim": ipa user-find Tim Find all users with "Tim" as the first name: ipa user-find --first=Tim Disable a user account: ipa user-disable tuser1 Enable a user account: ipa user-enable tuser1 Delete a user: ipa user-del tuser1 """)
class group_mod(Method): __doc__ = _("Modify a group.") takes_args = (parameters.Str( 'cn', cli_name='group_name', label=_(u'Group name'), no_convert=True, ), ) takes_options = ( parameters.Str( 'description', required=False, cli_name='desc', label=_(u'Description'), doc=_(u'Group description'), ), parameters.Int( 'gidnumber', required=False, cli_name='gid', label=_(u'GID'), doc=_(u'GID (use this option to set it manually)'), ), parameters.Str( 'setattr', required=False, multivalue=True, doc= _(u'Set an attribute to a name/value pair. Format is attr=value.\nFor multi-valued attributes, the command replaces the values already present.' ), exclude=('webui', ), ), parameters.Str( 'addattr', required=False, multivalue=True, doc= _(u'Add an attribute/value pair. Format is attr=value. The attribute\nmust be part of the schema.' ), exclude=('webui', ), ), parameters.Str( 'delattr', required=False, multivalue=True, doc= _(u'Delete an attribute/value pair. The option will be evaluated\nlast, after all sets and adds.' ), exclude=('webui', ), ), parameters.Flag( 'rights', label=_(u'Rights'), doc= _(u'Display the access rights of this entry (requires --all). See ipa man page for details.' ), default=False, autofill=True, ), parameters.Flag( 'posix', doc=_(u'change to a POSIX group'), default=False, autofill=True, ), parameters.Flag( 'external', doc= _(u'change to support external non-IPA members from trusted domains' ), default=False, autofill=True, ), parameters.Flag( 'all', doc= _(u'Retrieve and print all attributes from the server. Affects command output.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'raw', doc= _(u'Print entries as stored on the server. Only affects output format.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'no_members', doc=_(u'Suppress processing of membership attributes.'), exclude=('webui', 'cli'), default=False, autofill=True, ), parameters.Str( 'rename', required=False, label=_(u'Rename'), doc=_(u'Rename the group object'), no_convert=True, ), ) has_output = ( output.Output( 'summary', (unicode, type(None)), doc=_(u'User-friendly description of action performed'), ), output.Entry('result', ), output.PrimaryKey( 'value', doc=_( u"The primary_key value of the entry, e.g. 'jdoe' for a user"), ), )
def validate_zonemgr(zonemgr): assert isinstance(zonemgr, DNSName) if any(b'@' in label for label in zonemgr.labels): raise ValueError(_('too many \'@\' characters'))
__doc__ = _(r""" Groups of users Manage groups of users. By default, new groups are POSIX groups. You can add the --nonposix option to the group-add command to mark a new group as non-POSIX. You can use the --posix argument with the group-mod command to convert a non-POSIX group into a POSIX group. POSIX groups cannot be converted to non-POSIX groups. Every group must have a description. POSIX groups must have a Group ID (GID) number. Changing a GID is supported but can have an impact on your file permissions. It is not necessary to supply a GID when creating a group. IPA will generate one automatically if it is not provided. EXAMPLES: Add a new group: ipa group-add --desc='local administrators' localadmins Add a new non-POSIX group: ipa group-add --nonposix --desc='remote administrators' remoteadmins Convert a non-POSIX group to posix: ipa group-mod --posix remoteadmins Add a new POSIX group with a specific Group ID number: ipa group-add --gid=500 --desc='unix admins' unixadmins Add a new POSIX group and let IPA assign a Group ID number: ipa group-add --desc='printer admins' printeradmins Remove a group: ipa group-del unixadmins To add the "remoteadmins" group to the "localadmins" group: ipa group-add-member --groups=remoteadmins localadmins Add multiple users to the "localadmins" group: ipa group-add-member --users=test1 --users=test2 localadmins Remove a user from the "localadmins" group: ipa group-remove-member --users=test2 localadmins Display information about a named group. ipa group-show localadmins External group membership is designed to allow users from trusted domains to be mapped to local POSIX groups in order to actually use IPA resources. External members should be added to groups that specifically created as external and non-POSIX. Such group later should be included into one of POSIX groups. An external group member is currently a Security Identifier (SID) as defined by the trusted domain. When adding external group members, it is possible to specify them in either SID, or DOM\name, or name@domain format. IPA will attempt to resolve passed name to SID with the use of Global Catalog of the trusted domain. Example: 1. Create group for the trusted domain admins' mapping and their local POSIX group: ipa group-add --desc='<ad.domain> admins external map' ad_admins_external --external ipa group-add --desc='<ad.domain> admins' ad_admins 2. Add security identifier of Domain Admins of the <ad.domain> to the ad_admins_external group: ipa group-add-member ad_admins_external --external 'AD\Domain Admins' 3. Allow members of ad_admins_external group to be associated with ad_admins POSIX group: ipa group-add-member ad_admins --groups ad_admins_external 4. List members of external members of ad_admins_external group to see their SIDs: ipa group-show ad_admins_external """)
class subid_del(LDAPDelete): __doc__ = _("Delete a subordinate id.") msg_summary = _('Deleted subordinate id "%(value)s"') # internal command, subids cannot be removed NO_CLI = True
class group(Object): takes_params = ( parameters.Str( 'cn', primary_key=True, label=_(u'Group name'), ), parameters.Str( 'description', required=False, label=_(u'Description'), doc=_(u'Group description'), ), parameters.Int( 'gidnumber', required=False, label=_(u'GID'), doc=_(u'GID (use this option to set it manually)'), ), parameters.Str( 'member_user', required=False, label=_(u'Member users'), ), parameters.Str( 'member_group', required=False, label=_(u'Member groups'), ), parameters.Str( 'memberof_group', required=False, label=_(u'Member of groups'), ), parameters.Str( 'memberof_role', required=False, label=_(u'Roles'), ), parameters.Str( 'memberof_netgroup', required=False, label=_(u'Member of netgroups'), ), parameters.Str( 'memberof_sudorule', required=False, label=_(u'Member of Sudo rule'), ), parameters.Str( 'memberof_hbacrule', required=False, label=_(u'Member of HBAC rule'), ), parameters.Str( 'memberindirect_user', required=False, label=_(u'Indirect Member users'), ), parameters.Str( 'memberindirect_group', required=False, label=_(u'Indirect Member groups'), ), parameters.Str( 'memberofindirect_group', required=False, label=_(u'Indirect Member of group'), ), parameters.Str( 'memberofindirect_netgroup', required=False, label=_(u'Indirect Member of netgroup'), ), parameters.Str( 'memberofindirect_role', required=False, label=_(u'Indirect Member of role'), ), parameters.Str( 'memberofindirect_sudorule', required=False, label=_(u'Indirect Member of Sudo rule'), ), parameters.Str( 'memberofindirect_hbacrule', required=False, label=_(u'Indirect Member of HBAC rule'), ), )
class help(frontend.Local): """ Display help for a command or topic. """ takes_args = (Str('command?', cli_name='topic', label=_('Topic or Command'), doc=_('The topic or command name.')), ) takes_options = (Any('outfile?', flags=['no_option']), ) has_output = tuple() topic = None def _get_topic(self, topic): doc = u'' parent_topic = None for package in self.api.packages: module_name = '%s.%s' % (package.__name__, topic) try: module = sys.modules[module_name] except KeyError: try: module = importlib.import_module(module_name) except ImportError: continue if module.__doc__ is not None: doc = unicode(module.__doc__ or '').strip() try: parent_topic = module.topic except AttributeError: pass return doc, parent_topic def _count_topic_mcl(self, topic_name, mod_name): mcl = max((self._topics[topic_name][1], len(mod_name))) self._topics[topic_name][1] = mcl def _on_finalize(self): # {topic: ["description", mcl, {"subtopic": ["description", mcl, [commands]]}]} # {topic: ["description", mcl, [commands]]} self._topics = {} # [builtin_commands] self._builtins = [] # build help topics for c in self.api.Command: if c is not self.api.Command.get_plugin(c.name): continue if c.NO_CLI: continue if c.topic is not None: doc, topic_name = self._get_topic(c.topic) doc = doc.split('\n', 1)[0] if topic_name is None: # a module without grouping topic_name = c.topic if topic_name in self._topics: self._topics[topic_name][2].append(c) else: self._topics[topic_name] = [doc, 0, [c]] mcl = max((self._topics[topic_name][1], len(c.name))) self._topics[topic_name][1] = mcl else: # a module grouped in a topic topic = self._get_topic(topic_name) mod_name = c.topic if topic_name in self._topics: if mod_name in self._topics[topic_name][2]: self._topics[topic_name][2][mod_name][2].append(c) else: self._topics[topic_name][2][mod_name] = [ doc, 0, [c] ] self._count_topic_mcl(topic_name, mod_name) # count mcl for for the subtopic mcl = max((self._topics[topic_name][2][mod_name][1], len(c.name))) self._topics[topic_name][2][mod_name][1] = mcl else: self._topics[topic_name] = [ topic[0].split('\n', 1)[0], 0, { mod_name: [doc, 0, [c]] } ] self._count_topic_mcl(topic_name, mod_name) else: self._builtins.append(c) # compute maximum topic length topics = list(self._topics) + [c.name for c in self._builtins] self._mtl = max(len(s) for s in topics) super(help, self)._on_finalize() def run(self, key=None, outfile=None, **options): if outfile is None: outfile = sys.stdout writer = self._writer(outfile) name = from_cli(key) if key is None: self.api.parser.print_help(outfile) return if name == "topics": self.print_topics(outfile) return if name in self._topics: self.print_commands(name, outfile) elif name in self.Command: cmd = self.Command[name] if cmd.NO_CLI: raise HelpError(topic=name) self.Backend.cli.build_parser(cmd).print_help(outfile) elif any(name in t[2] for t in self._topics.values() if type(t[2]) is dict): self.print_commands(name, outfile) elif name == "commands": mcl = 0 for cmd_plugin in self.Command: if cmd_plugin is not self.Command.get_plugin(cmd_plugin.name): continue if cmd_plugin.NO_CLI: continue mcl = max(mcl, len(cmd_plugin.name)) writer( '%s %s' % (to_cli(cmd_plugin.name).ljust(mcl), cmd_plugin.summary)) else: raise HelpError(topic=name) def _writer(self, outfile): def writer(string=''): try: print(unicode(string), file=outfile) except IOError: pass return writer def print_topics(self, outfile): writer = self._writer(outfile) for t, topic in sorted(self._topics.items()): writer('%s %s' % (to_cli(t).ljust(self._mtl), topic[0])) def print_commands(self, topic, outfile): writer = self._writer(outfile) if topic in self._topics and type(self._topics[topic][2]) is dict: # we want to display topic which has subtopics for subtopic in self._topics[topic][2]: doc = self._topics[topic][2][subtopic][0] mcl = self._topics[topic][1] writer(' %s %s' % (to_cli(subtopic).ljust(mcl), doc)) else: # we want to display subtopic or a topic which has no subtopics if topic in self._topics: mcl = self._topics[topic][1] commands = self._topics[topic][2] else: commands = [] for t in self._topics: if type(self._topics[t][2]) is not dict: continue if topic not in self._topics[t][2]: continue mcl = self._topics[t][2][topic][1] commands = self._topics[t][2][topic][2] break doc, _topic = self._get_topic(topic) if topic not in self.Command and len(commands) == 0: raise HelpError(topic=topic) writer(doc) if commands: writer() writer(_('Topic commands:')) for c in commands: writer(' %s %s' % (to_cli(c.name).ljust(mcl), c.summary)) writer() writer(_('To get command help, use:')) writer(_(' ipa <command> --help')) writer()
class user_find(Method): __doc__ = _("Search for users.") takes_args = (parameters.Str( 'criteria', required=False, doc=_(u'A string searched in all relevant object attributes'), ), ) takes_options = ( parameters.Str( 'uid', required=False, cli_name='login', label=_(u'User login'), default_from=DefaultFrom(lambda givenname, sn: givenname[0] + sn, 'principal'), no_convert=True, ), parameters.Str( 'givenname', required=False, cli_name='first', label=_(u'First name'), ), parameters.Str( 'sn', required=False, cli_name='last', label=_(u'Last name'), ), parameters.Str( 'cn', required=False, label=_(u'Full name'), default_from=DefaultFrom( lambda givenname, sn: '%s %s' % (givenname, sn), 'principal'), ), parameters.Str( 'displayname', required=False, label=_(u'Display name'), default_from=DefaultFrom( lambda givenname, sn: '%s %s' % (givenname, sn), 'principal'), ), parameters.Str( 'initials', required=False, label=_(u'Initials'), default_from=DefaultFrom( lambda givenname, sn: '%c%c' % (givenname[0], sn[0]), 'principal'), ), parameters.Str( 'homedirectory', required=False, cli_name='homedir', label=_(u'Home directory'), ), parameters.Str( 'gecos', required=False, label=_(u'GECOS'), default_from=DefaultFrom( lambda givenname, sn: '%s %s' % (givenname, sn), 'principal'), ), parameters.Str( 'loginshell', required=False, cli_name='shell', label=_(u'Login shell'), ), parameters.Str( 'krbprincipalname', required=False, cli_name='principal', label=_(u'Kerberos principal'), default_from=DefaultFrom( lambda uid: '%s@%s' % (uid.lower(), api.env.realm), 'principal'), no_convert=True, ), parameters.DateTime( 'krbprincipalexpiration', required=False, cli_name='principal_expiration', label=_(u'Kerberos principal expiration'), ), parameters.Str( 'mail', required=False, multivalue=True, cli_name='email', label=_(u'Email address'), ), parameters.Password( 'userpassword', required=False, cli_name='password', label=_(u'Password'), doc=_(u'Prompt to set the user password'), exclude=('webui', ), confirm=True, ), parameters.Int( 'uidnumber', required=False, cli_name='uid', label=_(u'UID'), doc=_(u'User ID Number (system will assign one if not provided)'), ), parameters.Int( 'gidnumber', required=False, label=_(u'GID'), doc=_(u'Group ID Number'), ), parameters.Str( 'street', required=False, label=_(u'Street address'), ), parameters.Str( 'l', required=False, cli_name='city', label=_(u'City'), ), parameters.Str( 'st', required=False, cli_name='state', label=_(u'State/Province'), ), parameters.Str( 'postalcode', required=False, label=_(u'ZIP'), ), parameters.Str( 'telephonenumber', required=False, multivalue=True, cli_name='phone', label=_(u'Telephone Number'), ), parameters.Str( 'mobile', required=False, multivalue=True, label=_(u'Mobile Telephone Number'), ), parameters.Str( 'pager', required=False, multivalue=True, label=_(u'Pager Number'), ), parameters.Str( 'facsimiletelephonenumber', required=False, multivalue=True, cli_name='fax', label=_(u'Fax Number'), ), parameters.Str( 'ou', required=False, cli_name='orgunit', label=_(u'Org. Unit'), ), parameters.Str( 'title', required=False, label=_(u'Job Title'), ), parameters.Str( 'manager', required=False, label=_(u'Manager'), ), parameters.Str( 'carlicense', required=False, multivalue=True, label=_(u'Car License'), ), parameters.Bool( 'nsaccountlock', required=False, label=_(u'Account disabled'), exclude=('cli', 'webui'), ), parameters.Str( 'ipauserauthtype', required=False, multivalue=True, cli_name='user_auth_type', cli_metavar="['password', 'radius', 'otp']", label=_(u'User authentication types'), doc=_(u'Types of supported user authentication'), ), parameters.Str( 'userclass', required=False, multivalue=True, cli_name='class', label=_(u'Class'), doc= _(u'User category (semantics placed on this attribute are for local interpretation)' ), ), parameters.Str( 'ipatokenradiusconfiglink', required=False, cli_name='radius', label=_(u'RADIUS proxy configuration'), ), parameters.Str( 'ipatokenradiususername', required=False, cli_name='radius_username', label=_(u'RADIUS proxy username'), ), parameters.Str( 'departmentnumber', required=False, multivalue=True, label=_(u'Department Number'), ), parameters.Str( 'employeenumber', required=False, label=_(u'Employee Number'), ), parameters.Str( 'employeetype', required=False, label=_(u'Employee Type'), ), parameters.Str( 'preferredlanguage', required=False, label=_(u'Preferred Language'), ), parameters.Int( 'timelimit', required=False, label=_(u'Time Limit'), doc=_(u'Time limit of search in seconds'), ), parameters.Int( 'sizelimit', required=False, label=_(u'Size Limit'), doc=_(u'Maximum number of entries returned'), ), parameters.Flag( 'whoami', label=_(u'Self'), doc=_(u'Display user record for current Kerberos principal'), default=False, autofill=True, ), parameters.Flag( 'all', doc= _(u'Retrieve and print all attributes from the server. Affects command output.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'raw', doc= _(u'Print entries as stored on the server. Only affects output format.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'no_members', doc=_(u'Suppress processing of membership attributes.'), exclude=('webui', 'cli'), default=False, autofill=True, ), parameters.Flag( 'pkey_only', required=False, label=_(u'Primary key only'), doc=_( u'Results should contain primary key attribute only ("login")' ), default=False, autofill=True, ), parameters.Str( 'in_group', required=False, multivalue=True, cli_name='in_groups', label=_(u'group'), doc=_(u'Search for users with these member of groups.'), ), parameters.Str( 'not_in_group', required=False, multivalue=True, cli_name='not_in_groups', label=_(u'group'), doc=_(u'Search for users without these member of groups.'), ), parameters.Str( 'in_netgroup', required=False, multivalue=True, cli_name='in_netgroups', label=_(u'netgroup'), doc=_(u'Search for users with these member of netgroups.'), ), parameters.Str( 'not_in_netgroup', required=False, multivalue=True, cli_name='not_in_netgroups', label=_(u'netgroup'), doc=_(u'Search for users without these member of netgroups.'), ), parameters.Str( 'in_role', required=False, multivalue=True, cli_name='in_roles', label=_(u'role'), doc=_(u'Search for users with these member of roles.'), ), parameters.Str( 'not_in_role', required=False, multivalue=True, cli_name='not_in_roles', label=_(u'role'), doc=_(u'Search for users without these member of roles.'), ), parameters.Str( 'in_hbacrule', required=False, multivalue=True, cli_name='in_hbacrules', label=_(u'HBAC rule'), doc=_(u'Search for users with these member of HBAC rules.'), ), parameters.Str( 'not_in_hbacrule', required=False, multivalue=True, cli_name='not_in_hbacrules', label=_(u'HBAC rule'), doc=_(u'Search for users without these member of HBAC rules.'), ), parameters.Str( 'in_sudorule', required=False, multivalue=True, cli_name='in_sudorules', label=_(u'sudo rule'), doc=_(u'Search for users with these member of sudo rules.'), ), parameters.Str( 'not_in_sudorule', required=False, multivalue=True, cli_name='not_in_sudorules', label=_(u'sudo rule'), doc=_(u'Search for users without these member of sudo rules.'), ), ) has_output = ( output.Output( 'summary', (unicode, type(None)), doc=_(u'User-friendly description of action performed'), ), output.ListOfEntries('result', ), output.Output( 'count', int, doc=_(u'Number of entries returned'), ), output.Output( 'truncated', bool, doc=_(u'True if not all results were returned'), ), )
class radiusproxy_add(Method): __doc__ = _("Add a new RADIUS proxy server.") takes_args = (parameters.Str( 'cn', cli_name='name', label=_(u'RADIUS proxy server name'), ), ) takes_options = ( parameters.Str( 'description', required=False, cli_name='desc', label=_(u'Description'), doc=_(u'A description of this RADIUS proxy server'), ), parameters.Str( 'ipatokenradiusserver', multivalue=True, cli_name='server', label=_(u'Server'), doc=_(u'The hostname or IP (with or without port)'), ), parameters.Password( 'ipatokenradiussecret', cli_name='secret', label=_(u'Secret'), doc=_(u'The secret used to encrypt data'), exclude=('cli', 'webui'), confirm=True, ), parameters.Int( 'ipatokenradiustimeout', required=False, cli_name='timeout', label=_(u'Timeout'), doc=_(u'The total timeout across all retries (in seconds)'), ), parameters.Int( 'ipatokenradiusretries', required=False, cli_name='retries', label=_(u'Retries'), doc=_(u'The number of times to retry authentication'), ), parameters.Str( 'ipatokenusermapattribute', required=False, cli_name='userattr', label=_(u'User attribute'), doc=_(u'The username attribute on the user object'), ), parameters.Str( 'setattr', required=False, multivalue=True, doc= _(u'Set an attribute to a name/value pair. Format is attr=value.\nFor multi-valued attributes, the command replaces the values already present.' ), exclude=('webui', ), ), parameters.Str( 'addattr', required=False, multivalue=True, doc= _(u'Add an attribute/value pair. Format is attr=value. The attribute\nmust be part of the schema.' ), exclude=('webui', ), ), parameters.Flag( 'all', doc= _(u'Retrieve and print all attributes from the server. Affects command output.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'raw', doc= _(u'Print entries as stored on the server. Only affects output format.' ), exclude=('webui', ), default=False, autofill=True, ), ) has_output = ( output.Output( 'summary', (unicode, type(None)), doc=_(u'User-friendly description of action performed'), ), output.Entry('result', ), output.PrimaryKey( 'value', doc=_( u"The primary_key value of the entry, e.g. 'jdoe' for a user"), ), )
def build_parser(self, cmd): parser = CLIOptionParser( usage=' '.join(self.usage_iter(cmd)), description=unicode(cmd.doc), formatter=IPAHelpFormatter(), ) option_groups = {} def _get_option_group(group_name): """Get or create an option group for the given name""" option_group = option_groups.get(group_name) if option_group is None: option_group = optparse.OptionGroup(parser, group_name) parser.add_option_group(option_group) option_groups[group_name] = option_group return option_group for option in cmd.options(): kw = dict( dest=option.name, help=unicode(option.doc), ) if 'no_option' in option.flags: continue if option.password and self.env.interactive: kw['action'] = 'store_true' elif isinstance(option, Flag): if option.default is True: kw['action'] = 'store_false' else: kw['action'] = 'store_true' else: kw['metavar'] = option.cli_metavar cli_name = to_cli(option.cli_name) option_names = ['--%s' % cli_name] if option.cli_short_name: option_names.append('-%s' % option.cli_short_name) opt = optparse.make_option(*option_names, **kw) if option.option_group is None: parser.add_option(opt) else: _get_option_group(option.option_group).add_option(opt) if option.deprecated_cli_aliases: new_kw = dict(kw) new_kw['help'] = _('Same as --%s') % cli_name if isinstance(option, Enum): new_kw['metavar'] = 'VAL' group = _get_option_group(unicode(_('Deprecated options'))) for alias in option.deprecated_cli_aliases: name = '--%s' % alias group.add_option(optparse.make_option(name, **new_kw)) for arg in cmd.args(): name = self.__get_arg_name(arg, format_name=False) if 'no_option' in arg.flags or name is None: continue doc = unicode(arg.doc) parser.add_argument(name, doc) return parser
class radiusproxy(Object): takes_params = ( parameters.Str( 'cn', primary_key=True, label=_(u'RADIUS proxy server name'), ), parameters.Str( 'description', required=False, label=_(u'Description'), doc=_(u'A description of this RADIUS proxy server'), ), parameters.Str( 'ipatokenradiusserver', multivalue=True, label=_(u'Server'), doc=_(u'The hostname or IP (with or without port)'), ), parameters.Password( 'ipatokenradiussecret', label=_(u'Secret'), doc=_(u'The secret used to encrypt data'), ), parameters.Int( 'ipatokenradiustimeout', required=False, label=_(u'Timeout'), doc=_(u'The total timeout across all retries (in seconds)'), ), parameters.Int( 'ipatokenradiusretries', required=False, label=_(u'Retries'), doc=_(u'The number of times to retry authentication'), ), parameters.Str( 'ipatokenusermapattribute', required=False, label=_(u'User attribute'), doc=_(u'The username attribute on the user object'), ), )
class radiusproxy_find(Method): __doc__ = _("Search for RADIUS proxy servers.") takes_args = (parameters.Str( 'criteria', required=False, doc=_(u'A string searched in all relevant object attributes'), ), ) takes_options = ( parameters.Str( 'cn', required=False, cli_name='name', label=_(u'RADIUS proxy server name'), ), parameters.Str( 'description', required=False, cli_name='desc', label=_(u'Description'), doc=_(u'A description of this RADIUS proxy server'), ), parameters.Str( 'ipatokenradiusserver', required=False, multivalue=True, cli_name='server', label=_(u'Server'), doc=_(u'The hostname or IP (with or without port)'), ), parameters.Password( 'ipatokenradiussecret', required=False, cli_name='secret', label=_(u'Secret'), doc=_(u'The secret used to encrypt data'), exclude=('cli', 'webui'), confirm=True, ), parameters.Int( 'ipatokenradiustimeout', required=False, cli_name='timeout', label=_(u'Timeout'), doc=_(u'The total timeout across all retries (in seconds)'), ), parameters.Int( 'ipatokenradiusretries', required=False, cli_name='retries', label=_(u'Retries'), doc=_(u'The number of times to retry authentication'), ), parameters.Str( 'ipatokenusermapattribute', required=False, cli_name='userattr', label=_(u'User attribute'), doc=_(u'The username attribute on the user object'), ), parameters.Int( 'timelimit', required=False, label=_(u'Time Limit'), doc=_(u'Time limit of search in seconds (0 is unlimited)'), ), parameters.Int( 'sizelimit', required=False, label=_(u'Size Limit'), doc=_(u'Maximum number of entries returned (0 is unlimited)'), ), parameters.Flag( 'all', doc= _(u'Retrieve and print all attributes from the server. Affects command output.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'raw', doc= _(u'Print entries as stored on the server. Only affects output format.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'pkey_only', required=False, label=_(u'Primary key only'), doc=_( u'Results should contain primary key attribute only ("name")'), default=False, autofill=True, ), ) has_output = ( output.Output( 'summary', (unicode, type(None)), doc=_(u'User-friendly description of action performed'), ), output.ListOfEntries('result', ), output.Output( 'count', int, doc=_(u'Number of entries returned'), ), output.Output( 'truncated', bool, doc=_(u'True if not all results were returned'), ), )
LDAPSearch, LDAPRetrieve, LDAPQuery, DNA_MAGIC, ) __doc__ = _(""" Subordinate ids Manage subordinate user and group ids for users EXAMPLES: Auto-assign a subordinate id range to current user ipa subid-generate Auto-assign a subordinate id range to user alice: ipa subid-generate --owner=alice Find subordinate ids for user alice: ipa subid-find --owner=alice Match entry by any subordinate uid in range: ipa subid-match --subuid=2147483649 """) register = Registry() @register() class subid(LDAPObject):
if six.PY3: unicode = str __doc__ = _(""" RADIUS Proxy Servers Manage RADIUS Proxy Servers. IPA supports the use of an external RADIUS proxy server for krb5 OTP authentications. This permits a great deal of flexibility when integrating with third-party authentication services. EXAMPLES: Add a new server: ipa radiusproxy-add MyRADIUS --server=radius.example.com:1812 Find all servers whose entries include the string "example.com": ipa radiusproxy-find example.com Examine the configuration: ipa radiusproxy-show MyRADIUS Change the secret: ipa radiusproxy-mod MyRADIUS --secret Delete a configuration: ipa radiusproxy-del MyRADIUS """) register = Registry()
def validate_sshpubkey(ugettext, value): try: SSHPublicKey(value) except ValueError, UnicodeDecodeError: return _('invalid SSH public key') def validate_sshpubkey_no_options(ugettext, value): try: pubkey = SSHPublicKey(value) except ValueError, UnicodeDecodeError: return _('invalid SSH public key') if pubkey.has_options(): return _('options are not allowed') def convert_sshpubkey_post(ldap, dn, entry_attrs): if 'ipasshpubkey' in entry_attrs: pubkeys = entry_attrs['ipasshpubkey'] else: old_entry_attrs = ldap.get_entry(dn, ['ipasshpubkey']) pubkeys = old_entry_attrs[1].get('ipasshpubkey') if not pubkeys: return newpubkeys = [] fingerprints = [] for pubkey in pubkeys: try:
class user_add(Method): __doc__ = _("Add a new user.") takes_args = (parameters.Str( 'uid', cli_name='login', label=_(u'User login'), default_from=DefaultFrom(lambda givenname, sn: givenname[0] + sn, 'principal'), no_convert=True, ), ) takes_options = ( parameters.Str( 'givenname', cli_name='first', label=_(u'First name'), ), parameters.Str( 'sn', cli_name='last', label=_(u'Last name'), ), parameters.Str( 'cn', label=_(u'Full name'), default_from=DefaultFrom( lambda givenname, sn: '%s %s' % (givenname, sn), 'principal'), autofill=True, ), parameters.Str( 'displayname', required=False, label=_(u'Display name'), default_from=DefaultFrom( lambda givenname, sn: '%s %s' % (givenname, sn), 'principal'), autofill=True, ), parameters.Str( 'initials', required=False, label=_(u'Initials'), default_from=DefaultFrom( lambda givenname, sn: '%c%c' % (givenname[0], sn[0]), 'principal'), autofill=True, ), parameters.Str( 'homedirectory', required=False, cli_name='homedir', label=_(u'Home directory'), ), parameters.Str( 'gecos', required=False, label=_(u'GECOS'), default_from=DefaultFrom( lambda givenname, sn: '%s %s' % (givenname, sn), 'principal'), autofill=True, ), parameters.Str( 'loginshell', required=False, cli_name='shell', label=_(u'Login shell'), ), parameters.Str( 'krbprincipalname', required=False, cli_name='principal', label=_(u'Kerberos principal'), default_from=DefaultFrom( lambda uid: '%s@%s' % (uid.lower(), api.env.realm), 'principal'), autofill=True, no_convert=True, ), parameters.DateTime( 'krbprincipalexpiration', required=False, cli_name='principal_expiration', label=_(u'Kerberos principal expiration'), ), parameters.Str( 'mail', required=False, multivalue=True, cli_name='email', label=_(u'Email address'), ), parameters.Password( 'userpassword', required=False, cli_name='password', label=_(u'Password'), doc=_(u'Prompt to set the user password'), exclude=('webui', ), confirm=True, ), parameters.Flag( 'random', required=False, doc=_(u'Generate a random user password'), default=False, autofill=True, ), parameters.Int( 'uidnumber', required=False, cli_name='uid', label=_(u'UID'), doc=_(u'User ID Number (system will assign one if not provided)'), ), parameters.Int( 'gidnumber', required=False, label=_(u'GID'), doc=_(u'Group ID Number'), ), parameters.Str( 'street', required=False, label=_(u'Street address'), ), parameters.Str( 'l', required=False, cli_name='city', label=_(u'City'), ), parameters.Str( 'st', required=False, cli_name='state', label=_(u'State/Province'), ), parameters.Str( 'postalcode', required=False, label=_(u'ZIP'), ), parameters.Str( 'telephonenumber', required=False, multivalue=True, cli_name='phone', label=_(u'Telephone Number'), ), parameters.Str( 'mobile', required=False, multivalue=True, label=_(u'Mobile Telephone Number'), ), parameters.Str( 'pager', required=False, multivalue=True, label=_(u'Pager Number'), ), parameters.Str( 'facsimiletelephonenumber', required=False, multivalue=True, cli_name='fax', label=_(u'Fax Number'), ), parameters.Str( 'ou', required=False, cli_name='orgunit', label=_(u'Org. Unit'), ), parameters.Str( 'title', required=False, label=_(u'Job Title'), ), parameters.Str( 'manager', required=False, label=_(u'Manager'), ), parameters.Str( 'carlicense', required=False, multivalue=True, label=_(u'Car License'), ), parameters.Bool( 'nsaccountlock', required=False, label=_(u'Account disabled'), exclude=('cli', 'webui'), ), parameters.Str( 'ipasshpubkey', required=False, multivalue=True, cli_name='sshpubkey', label=_(u'SSH public key'), no_convert=True, ), parameters.Str( 'ipauserauthtype', required=False, multivalue=True, cli_name='user_auth_type', cli_metavar="['password', 'radius', 'otp']", label=_(u'User authentication types'), doc=_(u'Types of supported user authentication'), ), parameters.Str( 'userclass', required=False, multivalue=True, cli_name='class', label=_(u'Class'), doc= _(u'User category (semantics placed on this attribute are for local interpretation)' ), ), parameters.Str( 'ipatokenradiusconfiglink', required=False, cli_name='radius', label=_(u'RADIUS proxy configuration'), ), parameters.Str( 'ipatokenradiususername', required=False, cli_name='radius_username', label=_(u'RADIUS proxy username'), ), parameters.Str( 'departmentnumber', required=False, multivalue=True, label=_(u'Department Number'), ), parameters.Str( 'employeenumber', required=False, label=_(u'Employee Number'), ), parameters.Str( 'employeetype', required=False, label=_(u'Employee Type'), ), parameters.Str( 'preferredlanguage', required=False, label=_(u'Preferred Language'), ), parameters.Str( 'setattr', required=False, multivalue=True, doc= _(u'Set an attribute to a name/value pair. Format is attr=value.\nFor multi-valued attributes, the command replaces the values already present.' ), exclude=('webui', ), ), parameters.Str( 'addattr', required=False, multivalue=True, doc= _(u'Add an attribute/value pair. Format is attr=value. The attribute\nmust be part of the schema.' ), exclude=('webui', ), ), parameters.Flag( 'noprivate', doc=_(u"Don't create user private group"), default=False, autofill=True, ), parameters.Flag( 'all', doc= _(u'Retrieve and print all attributes from the server. Affects command output.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'raw', doc= _(u'Print entries as stored on the server. Only affects output format.' ), exclude=('webui', ), default=False, autofill=True, ), parameters.Flag( 'no_members', doc=_(u'Suppress processing of membership attributes.'), exclude=('webui', 'cli'), default=False, autofill=True, ), ) has_output = ( output.Output( 'summary', (unicode, type(None)), doc=_(u'User-friendly description of action performed'), ), output.Entry('result', ), output.PrimaryKey( 'value', doc=_( u"The primary_key value of the entry, e.g. 'jdoe' for a user"), ), )