Exemplo n.º 1
0
class SIDInstallInterface(ServiceAdminInstallInterface):
    """
    Interface for the SID generation Installer

    Knobs defined here will be available in:
    * ipa-server-install
    * ipa-replica-install
    * ipa-adtrust-install
    """
    description = "SID generation"
    add_sids = knob(
        None,
        description="Add SIDs for existing users and groups as the final step"
    )
    add_sids = replica_install_only(add_sids)
    netbios_name = knob(
        str,
        None,
        description="NetBIOS name of the IPA domain"
    )
    rid_base = knob(
        int,
        DEFAULT_PRIMARY_RID_BASE,
        description="Start value for mapping UIDs and GIDs to RIDs"
    )
    secondary_rid_base = knob(
        int,
        DEFAULT_SECONDARY_RID_BASE,
        description="Start value of the secondary range for mapping "
                    "UIDs and GIDs to RIDs"
    )
Exemplo n.º 2
0
class ADTrustInstallInterface(SIDInstallInterface):
    """
    Interface for the AD trust installer

    Knobs defined here will be available in:
    * ipa-server-install
    * ipa-replica-install
    * ipa-adtrust-install
    """
    description = "AD trust"

    # the following knobs are provided on top of those specified for
    # admin credentials
    add_agents = knob(
        None,
        description="Add IPA masters to a list of hosts allowed to "
                    "serve information about users from trusted forests"
    )
    add_agents = replica_install_only(add_agents)
    enable_compat = knob(
        None,
        description="Enable support for trusted domains for old clients"
    )
    no_msdcs = knob(
        None,
        description="Deprecated: has no effect",
        deprecated=True
    )
Exemplo n.º 3
0
class DogtagInstallInterface(service.ServiceInstallInterface):
    """
    Interface common to all Dogtag-based service installers
    """

    ca_file = knob(
        str,
        None,
        description="location of CA PKCS#12 file",
        cli_metavar='FILE',
    )
    ca_file = prepare_only(ca_file)
    ca_file = replica_install_only(ca_file)

    pki_config_override = knob(
        str,
        None,
        cli_names='--pki-config-override',
        description="Path to ini file with config overrides.",
    )

    @pki_config_override.validator
    def pki_config_override(self, value):
        if value is not None:
            PKIIniLoader.verify_pki_config_override(value)
Exemplo n.º 4
0
class DogtagInstallInterface(service.ServiceInstallInterface):
    """
    Interface common to all Dogtag-based service installers
    """

    ca_file = knob(
        str,
        None,
        description="location of CA PKCS#12 file",
        cli_metavar='FILE',
    )
    ca_file = prepare_only(ca_file)
    ca_file = replica_install_only(ca_file)
Exemplo n.º 5
0
class ADTrustInstallInterface(ServiceAdminInstallInterface):
    """
    Interface for the AD trust installer

    Knobs defined here will be available in:
    * ipa-server-install
    * ipa-replica-install
    * ipa-adtrust-install
    """
    description = "AD trust"

    # the following knobs are provided on top of those specified for
    # admin credentials
    add_sids = knob(
        None,
        description="Add SIDs for existing users and groups as the final step"
    )
    add_agents = knob(
        None,
        description="Add IPA masters to a list of hosts allowed to "
                    "serve information about users from trusted forests"
    )
    add_agents = replica_install_only(add_agents)
    enable_compat = knob(
        None,
        description="Enable support for trusted domains for old clients"
    )
    netbios_name = knob(
        str,
        None,
        description="NetBIOS name of the IPA domain"
    )
    no_msdcs = knob(
        None,
        description="Deprecated: has no effect",
        deprecated=True
    )
    rid_base = knob(
        int,
        1000,
        description="Start value for mapping UIDs and GIDs to RIDs"
    )
    secondary_rid_base = knob(
        int,
        100000000,
        description="Start value of the secondary range for mapping "
                    "UIDs and GIDs to RIDs"
    )
Exemplo n.º 6
0
class CAInstallInterface(dogtag.DogtagInstallInterface,
                         conncheck.ConnCheckInterface):
    """
    Interface of the CA installer

    Knobs defined here will be available in:
    * ipa-server-install
    * ipa-replica-prepare
    * ipa-replica-install
    * ipa-ca-install
    """
    description = "Certificate system"

    principal = conncheck.ConnCheckInterface.principal
    principal = extend_knob(
        principal,
        description="User allowed to manage replicas",
        cli_names=list(principal.cli_names) + ['-P'],
    )
    principal = enroll_only(principal)
    principal = replica_install_only(principal)

    admin_password = conncheck.ConnCheckInterface.admin_password
    admin_password = extend_knob(
        admin_password,
        description="Admin user Kerberos password used for connection check",
        cli_names=list(admin_password.cli_names) + ['-w'],
    )
    admin_password = enroll_only(admin_password)

    external_ca = knob(
        None,
        description=("Generate a CSR for the IPA CA certificate to be signed "
                     "by an external CA"),
    )
    external_ca = master_install_only(external_ca)

    external_ca_type = knob(x509.ExternalCAType,
                            None,
                            description="Type of the external CA")
    external_ca_type = master_install_only(external_ca_type)

    external_ca_profile = knob(
        type=x509.ExternalCAProfile,
        default=None,
        description=("Specify the certificate profile/template to use at the "
                     "external CA"),
    )
    external_ca_profile = master_install_only(external_ca_profile)

    external_cert_files = knob(
        typing.List[str],
        None,
        description=("File containing the IPA CA certificate and the external "
                     "CA certificate chain"),
        cli_names='--external-cert-file',
        cli_deprecated_names=['--external_cert_file', '--external_ca_file'],
        cli_metavar='FILE',
    )
    external_cert_files = master_install_only(external_cert_files)

    @external_cert_files.validator
    def external_cert_files(self, value):
        if any(not os.path.isabs(path) for path in value):
            raise ValueError("must use an absolute path")

    subject_base = knob(
        str,
        None,
        description=("The certificate subject base (default O=<realm-name>). "
                     "RDNs are in LDAP order (most specific RDN first)."),
        cli_deprecated_names=['--subject'],
    )
    subject_base = master_install_only(subject_base)

    @subject_base.validator
    def subject_base(self, value):
        subject_validator(VALID_SUBJECT_BASE_ATTRS, value)

    ca_subject = knob(
        str,
        None,
        description=("The CA certificate subject DN "
                     "(default CN=Certificate Authority,O=<realm-name>). "
                     "RDNs are in LDAP order (most specific RDN first)."),
    )
    ca_subject = master_install_only(ca_subject)

    @ca_subject.validator
    def ca_subject(self, value):
        subject_validator(VALID_SUBJECT_ATTRS, value)

    ca_signing_algorithm = knob(
        CASigningAlgorithm,
        None,
        description="Signing algorithm of the IPA CA certificate",
    )
    ca_signing_algorithm = master_install_only(ca_signing_algorithm)

    skip_schema_check = knob(
        None,
        description="skip check for updated CA DS schema on the remote master",
    )
    skip_schema_check = enroll_only(skip_schema_check)
    skip_schema_check = replica_install_only(skip_schema_check)
Exemplo n.º 7
0
class ServerInstallInterface(
        ServerCertificateInstallInterface, client.ClientInstallInterface,
        ca.CAInstallInterface, kra.KRAInstallInterface,
        dns.DNSInstallInterface, adtrust.ADTrustInstallInterface,
        conncheck.ConnCheckInterface, ServerUninstallInterface):
    """
    Interface of server installers

    Knobs defined here will be available in:
    * ipa-server-install
    * ipa-replica-prepare
    * ipa-replica-install
    """
    description = "Server"

    kinit_attempts = 1
    fixed_primary = True
    permit = False
    enable_dns_updates = False
    no_krb5_offline_passwords = False
    preserve_sssd = False
    no_sssd = False

    domain_name = client.ClientInstallInterface.domain_name
    domain_name = extend_knob(
        domain_name,
        # pylint: disable=no-member
        cli_names=list(domain_name.cli_names) + ['-n'],
    )

    servers = extend_knob(
        client.ClientInstallInterface.servers,
        description="fully qualified name of IPA server to enroll to",
    )
    servers = enroll_only(servers)

    realm_name = client.ClientInstallInterface.realm_name
    realm_name = extend_knob(
        realm_name,
        cli_names=list(realm_name.cli_names) + ['-r'],
    )

    host_name = extend_knob(
        client.ClientInstallInterface.host_name,
        description="fully qualified name of this host",
    )

    ca_cert_files = extend_knob(
        client.ClientInstallInterface.ca_cert_files,
        description="File containing CA certificates for the service "
        "certificate files",
        cli_deprecated_names='--root-ca-file',
    )
    ca_cert_files = prepare_only(ca_cert_files)

    dm_password = extend_knob(
        client.ClientInstallInterface.dm_password,
        description="Directory Manager password",
    )

    ip_addresses = extend_knob(
        client.ClientInstallInterface.ip_addresses,
        description="Server IP Address. This option can be used multiple "
        "times",
    )

    principal = client.ClientInstallInterface.principal
    principal = extend_knob(
        principal,
        description="User Principal allowed to promote replicas and join IPA "
        "realm",
        cli_names=list(principal.cli_names) + ['-P'],
    )
    principal = replica_install_only(principal)

    admin_password = extend_knob(
        client.ClientInstallInterface.admin_password, )

    master_password = knob(
        str,
        None,
        sensitive=True,
        deprecated=True,
        description="kerberos master password (normally autogenerated)",
    )
    master_password = master_install_only(master_password)

    domain_level = knob(
        int,
        constants.MAX_DOMAIN_LEVEL,
        description="IPA domain level",
        deprecated=True,
    )
    domain_level = master_install_only(domain_level)

    @domain_level.validator
    def domain_level(self, value):
        # Check that Domain Level is within the allowed range
        if value < constants.MIN_DOMAIN_LEVEL:
            raise ValueError("Domain Level cannot be lower than {0}".format(
                constants.MIN_DOMAIN_LEVEL))
        elif value > constants.MAX_DOMAIN_LEVEL:
            raise ValueError("Domain Level cannot be higher than {0}".format(
                constants.MAX_DOMAIN_LEVEL))

    setup_adtrust = knob(None, description="configure AD trust capability")
    setup_ca = knob(
        None,
        description="configure a dogtag CA",
    )
    setup_ca = enroll_only(setup_ca)

    setup_kra = knob(
        None,
        description="configure a dogtag KRA",
    )
    setup_kra = enroll_only(setup_kra)

    setup_dns = knob(
        None,
        description="configure bind with our zone",
    )
    setup_dns = enroll_only(setup_dns)

    idstart = knob(
        int,
        random.randint(1, 10000) * 200000,
        description="The starting value for the IDs range (default random)",
    )
    idstart = master_install_only(idstart)

    idmax = knob(
        int,
        description=("The max value for the IDs range (default: "
                     "idstart+199999)"),
    )
    idmax = master_install_only(idmax)

    @idmax.default_getter
    def idmax(self):
        return self.idstart + 200000 - 1

    no_hbac_allow = knob(
        None,
        description="Don't install allow_all HBAC rule",
        cli_deprecated_names='--no_hbac_allow',
    )
    no_hbac_allow = master_install_only(no_hbac_allow)

    no_pkinit = knob(
        None,
        description="disables pkinit setup steps",
    )
    no_pkinit = prepare_only(no_pkinit)

    no_ui_redirect = knob(
        None,
        description="Do not automatically redirect to the Web UI",
    )
    no_ui_redirect = enroll_only(no_ui_redirect)

    dirsrv_config_file = knob(
        str,
        None,
        description="The path to LDIF file that will be used to modify "
        "configuration of dse.ldif during installation of the "
        "directory server instance",
        cli_metavar='FILE',
    )
    dirsrv_config_file = enroll_only(dirsrv_config_file)

    @dirsrv_config_file.validator
    def dirsrv_config_file(self, value):
        if not os.path.exists(value):
            raise ValueError("File %s does not exist." % value)

    def _is_promote(self):
        """
        :returns: True if domain level options correspond to domain level > 0
        """
        raise NotImplementedError()

    def __init__(self, **kwargs):
        super(ServerInstallInterface, self).__init__(**kwargs)

        # pkinit is not supported on DL0, don't allow related options
        if not self._is_promote():
            if (self.no_pkinit or self.pkinit_cert_files is not None
                    or self.pkinit_pin is not None):
                raise RuntimeError(
                    "pkinit on domain level 0 is not supported. Please "
                    "don't use any pkinit-related options.")
            self.no_pkinit = True

        # If any of the key file options are selected, all are required.
        cert_file_req = (self.dirsrv_cert_files, self.http_cert_files)
        cert_file_opt = (self.pkinit_cert_files, )
        if not self.no_pkinit:
            cert_file_req += cert_file_opt
        if self.no_pkinit and self.pkinit_cert_files:
            raise RuntimeError(
                "--no-pkinit and --pkinit-cert-file cannot be specified "
                "together")
        if any(cert_file_req + cert_file_opt) and not all(cert_file_req):
            raise RuntimeError(
                "--dirsrv-cert-file, --http-cert-file, and --pkinit-cert-file "
                "or --no-pkinit are required if any key file options are used."
            )

        if not self.interactive:
            if self.dirsrv_cert_files and self.dirsrv_pin is None:
                raise RuntimeError(
                    "You must specify --dirsrv-pin with --dirsrv-cert-file")
            if self.http_cert_files and self.http_pin is None:
                raise RuntimeError(
                    "You must specify --http-pin with --http-cert-file")
            if self.pkinit_cert_files and self.pkinit_pin is None:
                raise RuntimeError(
                    "You must specify --pkinit-pin with --pkinit-cert-file")

        if not self.setup_dns:
            if self.forwarders:
                raise RuntimeError(
                    "You cannot specify a --forwarder option without the "
                    "--setup-dns option")
            if self.auto_forwarders:
                raise RuntimeError(
                    "You cannot specify a --auto-forwarders option without "
                    "the --setup-dns option")
            if self.no_forwarders:
                raise RuntimeError(
                    "You cannot specify a --no-forwarders option without the "
                    "--setup-dns option")
            if self.forward_policy:
                raise RuntimeError(
                    "You cannot specify a --forward-policy option without the "
                    "--setup-dns option")
            if self.reverse_zones:
                raise RuntimeError(
                    "You cannot specify a --reverse-zone option without the "
                    "--setup-dns option")
            if self.auto_reverse:
                raise RuntimeError(
                    "You cannot specify a --auto-reverse option without the "
                    "--setup-dns option")
            if self.no_reverse:
                raise RuntimeError(
                    "You cannot specify a --no-reverse option without the "
                    "--setup-dns option")
            if self.no_dnssec_validation:
                raise RuntimeError(
                    "You cannot specify a --no-dnssec-validation option "
                    "without the --setup-dns option")
        elif self.forwarders and self.no_forwarders:
            raise RuntimeError(
                "You cannot specify a --forwarder option together with "
                "--no-forwarders")
        elif self.auto_forwarders and self.no_forwarders:
            raise RuntimeError(
                "You cannot specify a --auto-forwarders option together with "
                "--no-forwarders")
        elif self.reverse_zones and self.no_reverse:
            raise RuntimeError(
                "You cannot specify a --reverse-zone option together with "
                "--no-reverse")
        elif self.auto_reverse and self.no_reverse:
            raise RuntimeError(
                "You cannot specify a --auto-reverse option together with "
                "--no-reverse")

        if not self.setup_adtrust:
            if self.add_agents:
                raise RuntimeError(
                    "You cannot specify an --add-agents option without the "
                    "--setup-adtrust option")

            if self.enable_compat:
                raise RuntimeError(
                    "You cannot specify an --enable-compat option without the "
                    "--setup-adtrust option")

            if self.netbios_name:
                raise RuntimeError(
                    "You cannot specify a --netbios-name option without the "
                    "--setup-adtrust option")

            if self.no_msdcs:
                raise RuntimeError(
                    "You cannot specify a --no-msdcs option without the "
                    "--setup-adtrust option")

        if not hasattr(self, 'replica_file'):
            if self.external_cert_files and self.dirsrv_cert_files:
                raise RuntimeError(
                    "Service certificate file options cannot be used with the "
                    "external CA options.")

            if self.external_ca_type and not self.external_ca:
                raise RuntimeError(
                    "You cannot specify --external-ca-type without "
                    "--external-ca")

            if self.external_ca_profile and not self.external_ca:
                raise RuntimeError(
                    "You cannot specify --external-ca-profile without "
                    "--external-ca")

            if self.uninstalling:
                if (self.realm_name or self.admin_password
                        or self.master_password):
                    raise RuntimeError(
                        "In uninstall mode, -a, -r and -P options are not "
                        "allowed")
            elif not self.interactive:
                if (not self.realm_name or not self.dm_password
                        or not self.admin_password):
                    raise RuntimeError(
                        "In unattended mode you need to provide at least -r, "
                        "-p and -a options")
                if self.setup_dns:
                    if (not self.forwarders and not self.no_forwarders
                            and not self.auto_forwarders):
                        raise RuntimeError(
                            "You must specify at least one of --forwarder, "
                            "--auto-forwarders, or --no-forwarders options")

            any_ignore_option_true = any(
                [self.ignore_topology_disconnect, self.ignore_last_of_role])
            if any_ignore_option_true and not self.uninstalling:
                raise RuntimeError(
                    "'--ignore-topology-disconnect/--ignore-last-of-role' "
                    "options can be used only during uninstallation")

            if self.idmax < self.idstart:
                raise RuntimeError(
                    "idmax (%s) cannot be smaller than idstart (%s)" %
                    (self.idmax, self.idstart))
        else:
            # replica installers
            if self.replica_file is None:
                if self.servers and not self.domain_name:
                    raise RuntimeError(
                        "The --server option cannot be used without providing "
                        "domain via the --domain option")

            else:
                if not os.path.isfile(self.replica_file):
                    raise RuntimeError("Replica file %s does not exist" %
                                       self.replica_file)

                if any(cert_file_req + cert_file_opt):
                    raise RuntimeError(
                        "You cannot specify any of --dirsrv-cert-file, "
                        "--http-cert-file, or --pkinit-cert-file together "
                        "with replica file")

                CLIKnob = collections.namedtuple('CLIKnob', ('value', 'name'))

                conflicting_knobs = (
                    CLIKnob(self.realm_name, '--realm'),
                    CLIKnob(self.domain_name, '--domain'),
                    CLIKnob(self.host_name, '--hostname'),
                    CLIKnob(self.servers, '--server'),
                    CLIKnob(self.principal, '--principal'),
                )

                if any([k.value is not None for k in conflicting_knobs]):
                    conflicting_knob_names = [
                        knob.name for knob in conflicting_knobs
                        if knob.value is not None
                    ]

                    raise RuntimeError(
                        "You cannot specify '{0}' option(s) with replica file."
                        .format(", ".join(conflicting_knob_names)))

            if self.setup_dns:
                if (not self.forwarders and not self.no_forwarders
                        and not self.auto_forwarders):
                    raise RuntimeError(
                        "You must specify at least one of --forwarder, "
                        "--auto-forwarders, or --no-forwarders options")
Exemplo n.º 8
0
class ServerInstallInterface(client.ClientInstallInterface,
                             ca.CAInstallInterface, kra.KRAInstallInterface,
                             dns.DNSInstallInterface,
                             conncheck.ConnCheckInterface):
    """
    Interface of server installers

    Knobs defined here will be available in:
    * ipa-server-install
    * ipa-replica-prepare
    * ipa-replica-install
    """

    force_join = False
    kinit_attempts = 1
    fixed_primary = True
    ntp_servers = None
    force_ntpd = False
    permit = False
    enable_dns_updates = False
    no_krb5_offline_passwords = False
    preserve_sssd = False

    domain_name = knob(
        bases=client.ClientInstallInterface.domain_name,
        # pylint: disable=no-member
        cli_names=(list(client.ClientInstallInterface.domain_name.cli_names) +
                   ['-n']),
    )

    servers = knob(
        bases=client.ClientInstallInterface.servers,
        description="fully qualified name of IPA server to enroll to",
    )
    servers = enroll_only(servers)

    realm_name = knob(
        bases=client.ClientInstallInterface.realm_name,
        cli_names=(list(client.ClientInstallInterface.realm_name.cli_names) +
                   ['-r']),
    )

    host_name = knob(
        bases=client.ClientInstallInterface.host_name,
        description="fully qualified name of this host",
    )

    ca_cert_files = knob(
        bases=client.ClientInstallInterface.ca_cert_files,
        description="File containing CA certificates for the service "
        "certificate files",
        cli_deprecated_names='--root-ca-file',
    )
    ca_cert_files = prepare_only(ca_cert_files)

    dm_password = knob(
        bases=client.ClientInstallInterface.dm_password,
        description="Directory Manager password",
    )

    ip_addresses = knob(
        bases=client.ClientInstallInterface.ip_addresses,
        description="Server IP Address. This option can be used multiple "
        "times",
    )

    principal = knob(
        bases=client.ClientInstallInterface.principal,
        description="User Principal allowed to promote replicas and join IPA "
        "realm",
        cli_names=(list(client.ClientInstallInterface.principal.cli_names) +
                   ['-P']),
    )
    principal = replica_install_only(principal)

    master_password = knob(
        str,
        None,
        sensitive=True,
        deprecated=True,
        description="kerberos master password (normally autogenerated)",
    )
    master_password = master_install_only(master_password)

    domain_level = knob(
        int,
        constants.MAX_DOMAIN_LEVEL,
        description="IPA domain level",
        deprecated=True,
    )
    domain_level = master_install_only(domain_level)

    @domain_level.validator
    def domain_level(self, value):
        # Check that Domain Level is within the allowed range
        if value < constants.MIN_DOMAIN_LEVEL:
            raise ValueError("Domain Level cannot be lower than {0}".format(
                constants.MIN_DOMAIN_LEVEL))
        elif value > constants.MAX_DOMAIN_LEVEL:
            raise ValueError("Domain Level cannot be higher than {0}".format(
                constants.MAX_DOMAIN_LEVEL))

    setup_ca = knob(
        None,
        description="configure a dogtag CA",
    )
    setup_ca = enroll_only(setup_ca)

    setup_kra = knob(
        None,
        description="configure a dogtag KRA",
    )
    setup_kra = enroll_only(setup_kra)

    setup_dns = knob(
        None,
        description="configure bind with our zone",
    )
    setup_dns = enroll_only(setup_dns)

    idstart = knob(
        int,
        random.randint(1, 10000) * 200000,
        description="The starting value for the IDs range (default random)",
    )
    idstart = master_install_only(idstart)

    idmax = knob(
        int,
        description=("The max value for the IDs range (default: "
                     "idstart+199999)"),
    )
    idmax = master_install_only(idmax)

    @idmax.default_getter
    def idmax(self):
        return self.idstart + 200000 - 1

    no_hbac_allow = knob(
        None,
        description="Don't install allow_all HBAC rule",
        cli_deprecated_names='--no_hbac_allow',
    )
    no_hbac_allow = master_install_only(no_hbac_allow)

    ignore_topology_disconnect = knob(
        None,
        description="do not check whether server uninstall disconnects the "
        "topology (domain level 1+)",
    )
    ignore_topology_disconnect = master_install_only(
        ignore_topology_disconnect)

    ignore_last_of_role = knob(
        None,
        description="do not check whether server uninstall removes last "
        "CA/DNS server or DNSSec master (domain level 1+)",
    )
    ignore_last_of_role = master_install_only(ignore_last_of_role)

    no_pkinit = knob(
        None,
        description="disables pkinit setup steps",
    )
    no_pkinit = prepare_only(no_pkinit)

    no_ui_redirect = knob(
        None,
        description="Do not automatically redirect to the Web UI",
    )
    no_ui_redirect = enroll_only(no_ui_redirect)

    ssh_trust_dns = knob(
        None,
        description="configure OpenSSH client to trust DNS SSHFP records",
    )
    ssh_trust_dns = enroll_only(ssh_trust_dns)

    no_ssh = knob(
        None,
        description="do not configure OpenSSH client",
    )
    no_ssh = enroll_only(no_ssh)

    no_sshd = knob(
        None,
        description="do not configure OpenSSH server",
    )
    no_sshd = enroll_only(no_sshd)

    no_dns_sshfp = knob(
        None,
        description="Do not automatically create DNS SSHFP records",
    )
    no_dns_sshfp = enroll_only(no_dns_sshfp)

    dirsrv_config_file = knob(
        str,
        None,
        description="The path to LDIF file that will be used to modify "
        "configuration of dse.ldif during installation of the "
        "directory server instance",
        cli_metavar='FILE',
    )
    dirsrv_config_file = enroll_only(dirsrv_config_file)

    @dirsrv_config_file.validator
    def dirsrv_config_file(self, value):
        if not os.path.exists(value):
            raise ValueError("File %s does not exist." % value)

    dirsrv_cert_files = knob(
        # pylint: disable=invalid-sequence-index
        typing.List[str],
        None,
        description=("File containing the Directory Server SSL certificate "
                     "and private key"),
        cli_names='--dirsrv-cert-file',
        cli_deprecated_names='--dirsrv_pkcs12',
        cli_metavar='FILE',
    )
    dirsrv_cert_files = prepare_only(dirsrv_cert_files)

    http_cert_files = knob(
        # pylint: disable=invalid-sequence-index
        typing.List[str],
        None,
        description=("File containing the Apache Server SSL certificate and "
                     "private key"),
        cli_names='--http-cert-file',
        cli_deprecated_names='--http_pkcs12',
        cli_metavar='FILE',
    )
    http_cert_files = prepare_only(http_cert_files)

    pkinit_cert_files = knob(
        # pylint: disable=invalid-sequence-index
        typing.List[str],
        None,
        description=("File containing the Kerberos KDC SSL certificate and "
                     "private key"),
        cli_names='--pkinit-cert-file',
        cli_deprecated_names='--pkinit_pkcs12',
        cli_metavar='FILE',
    )
    pkinit_cert_files = prepare_only(pkinit_cert_files)

    dirsrv_pin = knob(
        str,
        None,
        sensitive=True,
        description="The password to unlock the Directory Server private key",
        cli_deprecated_names='--dirsrv_pin',
        cli_metavar='PIN',
    )
    dirsrv_pin = prepare_only(dirsrv_pin)

    http_pin = knob(
        str,
        None,
        sensitive=True,
        description="The password to unlock the Apache Server private key",
        cli_deprecated_names='--http_pin',
        cli_metavar='PIN',
    )
    http_pin = prepare_only(http_pin)

    pkinit_pin = knob(
        str,
        None,
        sensitive=True,
        description="The password to unlock the Kerberos KDC private key",
        cli_deprecated_names='--pkinit_pin',
        cli_metavar='PIN',
    )
    pkinit_pin = prepare_only(pkinit_pin)

    dirsrv_cert_name = knob(
        str,
        None,
        description="Name of the Directory Server SSL certificate to install",
        cli_metavar='NAME',
    )
    dirsrv_cert_name = prepare_only(dirsrv_cert_name)

    http_cert_name = knob(
        str,
        None,
        description="Name of the Apache Server SSL certificate to install",
        cli_metavar='NAME',
    )
    http_cert_name = prepare_only(http_cert_name)

    pkinit_cert_name = knob(
        str,
        None,
        description="Name of the Kerberos KDC SSL certificate to install",
        cli_metavar='NAME',
    )
    pkinit_cert_name = prepare_only(pkinit_cert_name)

    def __init__(self, **kwargs):
        super(ServerInstallInterface, self).__init__(**kwargs)

        # If any of the key file options are selected, all are required.
        cert_file_req = (self.dirsrv_cert_files, self.http_cert_files)
        cert_file_opt = (self.pkinit_cert_files, )
        if any(cert_file_req + cert_file_opt) and not all(cert_file_req):
            raise RuntimeError(
                "--dirsrv-cert-file and --http-cert-file are required if any "
                "key file options are used.")

        if not self.interactive:
            if self.dirsrv_cert_files and self.dirsrv_pin is None:
                raise RuntimeError(
                    "You must specify --dirsrv-pin with --dirsrv-cert-file")
            if self.http_cert_files and self.http_pin is None:
                raise RuntimeError(
                    "You must specify --http-pin with --http-cert-file")
            if self.pkinit_cert_files and self.pkinit_pin is None:
                raise RuntimeError(
                    "You must specify --pkinit-pin with --pkinit-cert-file")

        if not self.setup_dns:
            if self.forwarders:
                raise RuntimeError(
                    "You cannot specify a --forwarder option without the "
                    "--setup-dns option")
            if self.auto_forwarders:
                raise RuntimeError(
                    "You cannot specify a --auto-forwarders option without "
                    "the --setup-dns option")
            if self.no_forwarders:
                raise RuntimeError(
                    "You cannot specify a --no-forwarders option without the "
                    "--setup-dns option")
            if self.forward_policy:
                raise RuntimeError(
                    "You cannot specify a --forward-policy option without the "
                    "--setup-dns option")
            if self.reverse_zones:
                raise RuntimeError(
                    "You cannot specify a --reverse-zone option without the "
                    "--setup-dns option")
            if self.auto_reverse:
                raise RuntimeError(
                    "You cannot specify a --auto-reverse option without the "
                    "--setup-dns option")
            if self.no_reverse:
                raise RuntimeError(
                    "You cannot specify a --no-reverse option without the "
                    "--setup-dns option")
            if self.no_dnssec_validation:
                raise RuntimeError(
                    "You cannot specify a --no-dnssec-validation option "
                    "without the --setup-dns option")
        elif self.forwarders and self.no_forwarders:
            raise RuntimeError(
                "You cannot specify a --forwarder option together with "
                "--no-forwarders")
        elif self.auto_forwarders and self.no_forwarders:
            raise RuntimeError(
                "You cannot specify a --auto-forwarders option together with "
                "--no-forwarders")
        elif self.reverse_zones and self.no_reverse:
            raise RuntimeError(
                "You cannot specify a --reverse-zone option together with "
                "--no-reverse")
        elif self.auto_reverse and self.no_reverse:
            raise RuntimeError(
                "You cannot specify a --auto-reverse option together with "
                "--no-reverse")

        if not hasattr(self, 'replica_file'):
            if self.external_cert_files and self.dirsrv_cert_files:
                raise RuntimeError(
                    "Service certificate file options cannot be used with the "
                    "external CA options.")

            if self.external_ca_type and not self.external_ca:
                raise RuntimeError(
                    "You cannot specify --external-ca-type without "
                    "--external-ca")

            if self.uninstalling:
                if (self.realm_name or self.admin_password
                        or self.master_password):
                    raise RuntimeError(
                        "In uninstall mode, -a, -r and -P options are not "
                        "allowed")
            elif not self.interactive:
                if (not self.realm_name or not self.dm_password
                        or not self.admin_password):
                    raise RuntimeError(
                        "In unattended mode you need to provide at least -r, "
                        "-p and -a options")
                if self.setup_dns:
                    if (not self.forwarders and not self.no_forwarders
                            and not self.auto_forwarders):
                        raise RuntimeError(
                            "You must specify at least one of --forwarder, "
                            "--auto-forwarders, or --no-forwarders options")

            any_ignore_option_true = any(
                [self.ignore_topology_disconnect, self.ignore_last_of_role])
            if any_ignore_option_true and not self.uninstalling:
                raise RuntimeError(
                    "'--ignore-topology-disconnect/--ignore-last-of-role' "
                    "options can be used only during uninstallation")

            if self.idmax < self.idstart:
                raise RuntimeError(
                    "idmax (%s) cannot be smaller than idstart (%s)" %
                    (self.idmax, self.idstart))
        else:
            cert_file_req = (self.dirsrv_cert_files, self.http_cert_files)
            cert_file_opt = (self.pkinit_cert_files, )

            if self.replica_file is None:
                # If any of the PKCS#12 options are selected, all are required.
                if any(cert_file_req +
                       cert_file_opt) and not all(cert_file_req):
                    raise RuntimeError(
                        "--dirsrv-cert-file and --http-cert-file are required "
                        "if any PKCS#12 options are used")

                if self.servers and not self.domain_name:
                    raise RuntimeError(
                        "The --server option cannot be used without providing "
                        "domain via the --domain option")

            else:
                if not ipautil.file_exists(self.replica_file):
                    raise RuntimeError("Replica file %s does not exist" %
                                       self.replica_file)

                if any(cert_file_req + cert_file_opt):
                    raise RuntimeError(
                        "You cannot specify any of --dirsrv-cert-file, "
                        "--http-cert-file, or --pkinit-cert-file together "
                        "with replica file")

                CLIKnob = collections.namedtuple('CLIKnob', ('value', 'name'))

                conflicting_knobs = (
                    CLIKnob(self.realm_name, '--realm'),
                    CLIKnob(self.domain_name, '--domain'),
                    CLIKnob(self.host_name, '--hostname'),
                    CLIKnob(self.servers, '--server'),
                    CLIKnob(self.principal, '--principal'),
                )

                if any([k.value is not None for k in conflicting_knobs]):
                    conflicting_knob_names = [
                        knob.name for knob in conflicting_knobs
                        if knob.value is not None
                    ]

                    raise RuntimeError(
                        "You cannot specify '{0}' option(s) with replica file."
                        .format(", ".join(conflicting_knob_names)))

            if self.setup_dns:
                if (not self.forwarders and not self.no_forwarders
                        and not self.auto_forwarders):
                    raise RuntimeError(
                        "You must specify at least one of --forwarder, "
                        "--auto-forwarders, or --no-forwarders options")

        # Automatically enable pkinit w/ dogtag
        self.no_pkinit = not self.setup_ca
Exemplo n.º 9
0
class CAInstallInterface(dogtag.DogtagInstallInterface,
                         conncheck.ConnCheckInterface):
    """
    Interface of the CA installer

    Knobs defined here will be available in:
    * ipa-server-install
    * ipa-replica-prepare
    * ipa-replica-install
    * ipa-ca-install
    """

    principal = knob(
        bases=conncheck.ConnCheckInterface.principal,
        description="User allowed to manage replicas",
        cli_names=(list(conncheck.ConnCheckInterface.principal.cli_names) +
                   ['-P']),
    )
    principal = enroll_only(principal)
    principal = replica_install_only(principal)

    admin_password = knob(
        bases=conncheck.ConnCheckInterface.admin_password,
        description="Admin user Kerberos password used for connection check",
        cli_names=(
            list(conncheck.ConnCheckInterface.admin_password.cli_names) +
            ['-w']),
    )
    admin_password = enroll_only(admin_password)

    external_ca = knob(
        None,
        description=("Generate a CSR for the IPA CA certificate to be signed "
                     "by an external CA"),
    )
    external_ca = master_install_only(external_ca)

    external_ca_type = knob(
        ExternalCAType,
        None,
        description="Type of the external CA",
    )
    external_ca_type = master_install_only(external_ca_type)

    external_cert_files = knob(
        # pylint: disable=invalid-sequence-index
        typing.List[str],
        None,
        description=("File containing the IPA CA certificate and the external "
                     "CA certificate chain"),
        cli_names='--external-cert-file',
        cli_deprecated_names=['--external_cert_file', '--external_ca_file'],
        cli_metavar='FILE',
    )
    external_cert_files = master_install_only(external_cert_files)

    @external_cert_files.validator
    def external_cert_files(self, value):
        if any(not os.path.isabs(path) for path in value):
            raise ValueError("must use an absolute path")

    subject = knob(
        str,
        None,
        description="The certificate subject base (default O=<realm-name>)",
    )
    subject = master_install_only(subject)

    @subject.validator
    def subject(self, value):
        v = unicode(value, 'utf-8')
        if any(ord(c) < 0x20 for c in v):
            raise ValueError("must not contain control characters")
        if '&' in v:
            raise ValueError("must not contain an ampersand (\"&\")")
        try:
            dn = DN(v)
            for rdn in dn:
                if rdn.attr.lower() not in VALID_SUBJECT_ATTRS:
                    raise ValueError("invalid attribute: \"%s\"" % rdn.attr)
        except ValueError as e:
            raise ValueError("invalid subject base format: %s" % e)

    ca_signing_algorithm = knob(
        CASigningAlgorithm,
        None,
        description="Signing algorithm of the IPA CA certificate",
    )
    ca_signing_algorithm = master_install_only(ca_signing_algorithm)

    skip_schema_check = knob(
        None,
        description="skip check for updated CA DS schema on the remote master",
    )
    skip_schema_check = enroll_only(skip_schema_check)
    skip_schema_check = replica_install_only(skip_schema_check)