Example #1
0
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"))
Example #2
0
    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
Example #3
0
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)
        )
Example #4
0
    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
Example #5
0
    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,
            }
        )
Example #6
0
    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'))
Example #7
0
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
Example #8
0
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))
Example #9
0
    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,
            )
Example #10
0
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')
Example #11
0
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")
Example #12
0
    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()
Example #13
0
    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',
        )
Example #14
0
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
Example #15
0
    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
Example #16
0
    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)
Example #17
0
    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)
Example #18
0
def validate_sshpubkey(ugettext, value):
    try:
        SSHPublicKey(value)
    except (ValueError, UnicodeDecodeError):
        return _('invalid SSH public key')
    else:
        return None
Example #19
0
    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
Example #20
0
def validate_hostmask(ugettext, hostmask):
    try:
        netaddr.IPNetwork(hostmask)
    except (ValueError, AddrFormatError):
        return _('invalid hostmask')
    else:
        return None
Example #21
0
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))
Example #22
0
def hostname_validator(ugettext, value):
    try:
        validate_hostname(value)
    except ValueError as e:
        return _('invalid domain-name: %s') % unicode(e)

    return None
Example #23
0
 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
Example #24
0
    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
Example #25
0
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'))
Example #26
0
 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()
Example #27
0
    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)
Example #28
0
    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)
        )
Example #29
0
 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
             )
         )
Example #30
0
    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
Example #31
0
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'),
        ),
    )
Example #32
0
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'),
        ),
    )
Example #33
0
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'),
        ),
    )
Example #34
0
class UnresolvableRecordError(ForwarderValidationError):
    format = _("query '%(owner)s %(rtype)s': %(error)s")
Example #35
0
class DNSSECSignatureMissingError(ForwarderValidationError):
    format = _("answer to query '%(owner)s %(rtype)s' is missing DNSSEC "
               "signatures (no RRSIG data)")
Example #36
0
def validate_sshpubkey_no_options(ugettext, value):
    try:
        pubkey = SSHPublicKey(value)
    except ValueError, UnicodeDecodeError:
        return _('invalid SSH public key')
Example #37
0
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"),
        ),
    )
Example #38
0
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
Example #39
0
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'},
        },
    }
Example #40
0
__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.

""")
Example #41
0
class DNSSECValidationError(ForwarderValidationError):
    format = _("record '%(owner)s %(rtype)s' "
               "failed DNSSEC validation on server %(ip)s")
Example #42
0
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'),
        ),
    )
Example #43
0
class EDNS0UnsupportedError(ForwarderValidationError):
    format = _("query '%(owner)s %(rtype)s' with EDNS0: %(error)s")
Example #44
0
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)
Example #45
0
__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
""")
Example #46
0
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"),
        ),
    )
Example #47
0
def validate_zonemgr(zonemgr):
    assert isinstance(zonemgr, DNSName)
    if any(b'@' in label for label in zonemgr.labels):
        raise ValueError(_('too many \'@\' characters'))
Example #48
0
__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
""")
Example #49
0
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
Example #50
0
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'),
        ),
    )
Example #51
0
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()
Example #52
0
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'),
        ),
    )
Example #53
0
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"),
        ),
    )
Example #54
0
    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
Example #55
0
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'),
        ),
    )
Example #56
0
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'),
        ),
    )
Example #57
0
    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):
Example #58
0
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()
Example #59
0
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:
Example #60
0
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"),
        ),
    )