From bed64a888a5c02f389d8d744ff2b327082830fbe Mon Sep 17 00:00:00 2001 From: Jan Cholasta Date: Thu, 6 Aug 2015 08:16:22 +0200 Subject: install: Add common base class for server and replica install https://fedorahosted.org/freeipa/ticket/4517 Reviewed-By: Martin Babinsky --- ipaserver/install/server/common.py | 454 +++++++++++++++++++++++++++++ ipaserver/install/server/install.py | 411 ++------------------------ ipaserver/install/server/replicainstall.py | 224 ++++---------- 3 files changed, 525 insertions(+), 564 deletions(-) create mode 100644 ipaserver/install/server/common.py diff --git a/ipaserver/install/server/common.py b/ipaserver/install/server/common.py new file mode 100644 index 000000000..e7fb2acfc --- /dev/null +++ b/ipaserver/install/server/common.py @@ -0,0 +1,454 @@ +# +# Copyright (C) 2015 FreeIPA Contributors see COPYING for license +# + +import os +import sys + +from ipapython.dn import DN +from ipapython.install import common, core +from ipapython.install.core import Knob +from ipalib.util import validate_domain_name +from ipaserver.install import bindinstance + +VALID_SUBJECT_ATTRS = ['st', 'o', 'ou', 'dnqualifier', 'c', + 'serialnumber', 'l', 'title', 'sn', 'givenname', + 'initials', 'generationqualifier', 'dc', 'mail', + 'uid', 'postaladdress', 'postalcode', 'postofficebox', + 'houseidentifier', 'e', 'street', 'pseudonym', + 'incorporationlocality', 'incorporationstate', + 'incorporationcountry', 'businesscategory'] + + +class BaseServerCA(common.Installable, core.Group, core.Composite): + description = "certificate system" + + external_ca = Knob( + bool, False, + description=("Generate a CSR for the IPA CA certificate to be signed " + "by an external CA"), + ) + + external_ca_type = Knob( + {'generic', 'ms-cs'}, None, + description="Type of the external CA", + ) + + external_cert_files = Knob( + (list, str), None, + description=("File containing the IPA CA certificate and the external " + "CA certificate chain"), + cli_name='external-cert-file', + cli_aliases=['external_cert_file', 'external_ca_file'], + cli_metavar='FILE', + ) + + @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") + + dirsrv_cert_files = Knob( + (list, str), None, + description=("File containing the Directory Server SSL certificate " + "and private key"), + cli_name='dirsrv-cert-file', + cli_aliases=['dirsrv_pkcs12'], + cli_metavar='FILE', + ) + + http_cert_files = Knob( + (list, str), None, + description=("File containing the Apache Server SSL certificate and " + "private key"), + cli_name='http-cert-file', + cli_aliases=['http_pkcs12'], + cli_metavar='FILE', + ) + + pkinit_cert_files = Knob( + (list, str), None, + description=("File containing the Kerberos KDC SSL certificate and " + "private key"), + cli_name='pkinit-cert-file', + cli_aliases=['pkinit_pkcs12'], + cli_metavar='FILE', + ) + + dirsrv_pin = Knob( + str, None, + sensitive=True, + description="The password to unlock the Directory Server private key", + cli_aliases=['dirsrv_pin'], + cli_metavar='PIN', + ) + + http_pin = Knob( + str, None, + sensitive=True, + description="The password to unlock the Apache Server private key", + cli_aliases=['http_pin'], + cli_metavar='PIN', + ) + + pkinit_pin = Knob( + str, None, + sensitive=True, + description="The password to unlock the Kerberos KDC private key", + cli_aliases=['pkinit_pin'], + cli_metavar='PIN', + ) + + dirsrv_cert_name = Knob( + str, None, + description="Name of the Directory Server SSL certificate to install", + cli_metavar='NAME', + ) + + http_cert_name = Knob( + str, None, + description="Name of the Apache Server SSL certificate to install", + cli_metavar='NAME', + ) + + pkinit_cert_name = Knob( + str, None, + description="Name of the Kerberos KDC SSL certificate to install", + cli_metavar='NAME', + ) + + ca_cert_files = Knob( + (list, str), None, + description=("File containing CA certificates for the service " + "certificate files"), + cli_name='ca-cert-file', + cli_aliases=['root-ca-file'], + cli_metavar='FILE', + ) + + subject = Knob( + str, None, + description="The certificate subject base (default O=)", + ) + + @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, e: + raise ValueError("invalid subject base format: %s" % e) + + ca_signing_algorithm = Knob( + {'SHA1withRSA', 'SHA256withRSA', 'SHA512withRSA'}, None, + description="Signing algorithm of the IPA CA certificate", + ) + + skip_schema_check = Knob( + bool, False, + description="skip check for updated CA DS schema on the remote master", + ) + + +class BaseServerDNS(common.Installable, core.Group, core.Composite): + description = "DNS" + + forwarders = Knob( + (list, 'ip'), None, + description=("Add a DNS forwarder. This option can be used multiple " + "times"), + cli_name='forwarder', + ) + + no_forwarders = Knob( + bool, False, + description="Do not add any DNS forwarders, use root servers instead", + ) + + reverse_zones = Knob( + (list, str), [], + description=("The reverse DNS zone to use. This option can be used " + "multiple times"), + cli_name='reverse-zone', + cli_metavar='REVERSE_ZONE', + ) + + no_reverse = Knob( + bool, False, + description="Do not create new reverse DNS zone", + ) + + no_dnssec_validation = Knob( + bool, False, + description="Disable DNSSEC validation", + ) + + dnssec_master = Knob( + bool, False, + description="Setup server to be DNSSEC key master", + ) + + disable_dnssec_master = Knob( + bool, False, + description="Disable the DNSSEC master on this server", + ) + + kasp_db_file = Knob( + str, None, + description="Copy OpenDNSSEC metadata from the specified file (will " + "not create a new kasp.db file)", + ) + + force = Knob( + bool, False, + description="Force install", + ) + + zonemgr = Knob( + str, None, + description=("DNS zone manager e-mail address. Defaults to " + "hostmaster@DOMAIN"), + ) + + @zonemgr.validator + def zonemgr(self, value): + # validate the value first + try: + # IDNA support requires unicode + encoding = getattr(sys.stdin, 'encoding', None) + if encoding is None: + encoding = 'utf-8' + value = value.decode(encoding) + bindinstance.validate_zonemgr_str(value) + except ValueError, e: + # FIXME we can do this in better way + # https://fedorahosted.org/freeipa/ticket/4804 + # decode to proper stderr encoding + stderr_encoding = getattr(sys.stderr, 'encoding', None) + if stderr_encoding is None: + stderr_encoding = 'utf-8' + error = unicode(e).encode(stderr_encoding) + raise ValueError(error) + + +class BaseServer(common.Installable, common.Interactive, core.Composite): + realm_name = Knob( + str, None, + description="realm name", + cli_name='realm', + cli_short_name='r', + ) + + domain_name = Knob( + str, None, + description="domain name", + cli_name='domain', + cli_short_name='n', + ) + + @domain_name.validator + def domain_name(self, value): + validate_domain_name(value) + + dm_password = Knob( + str, None, + sensitive=True, + cli_short_name='p', + ) + + admin_password = Knob( + str, None, + sensitive=True, + ) + + mkhomedir = Knob( + bool, False, + description="create home directories for users on their first login", + ) + + host_name = Knob( + str, None, + description="fully qualified name of server", + cli_name='hostname', + ) + + ip_addresses = Knob( + (list, 'ip-local'), None, + description=("Master Server IP Address. This option can be used " + "multiple times"), + cli_name='ip-address', + cli_metavar='IP_ADDRESS', + ) + + no_host_dns = Knob( + bool, False, + description="Do not use DNS for hostname lookup during installation", + ) + + setup_ca = Knob( + bool, False, + description="configure a dogtag CA", + ) + + setup_kra = Knob( + bool, False, + description="configure a dogtag KRA", + ) + + setup_dns = Knob( + bool, False, + description="configure bind with our zone", + ) + + no_ntp = Knob( + bool, False, + description="do not configure ntp", + cli_short_name='N', + ) + + no_pkinit = Knob( + bool, False, + description="disables pkinit setup steps", + ) + + no_ui_redirect = Knob( + bool, False, + description="Do not automatically redirect to the Web UI", + ) + + ssh_trust_dns = Knob( + bool, False, + description="configure OpenSSH client to trust DNS SSHFP records", + ) + + no_ssh = Knob( + bool, False, + description="do not configure OpenSSH client", + ) + + no_sshd = Knob( + bool, False, + description="do not configure OpenSSH server", + ) + + no_dns_sshfp = Knob( + bool, False, + description="Do not automatically create DNS SSHFP records", + ) + + def __init__(self, **kwargs): + super(BaseServer, self).__init__(**kwargs) + + #pylint: disable=no-member + + if not self.uninstalling and 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 any of the key file options are selected, all are required. + cert_file_req = (self.ca.dirsrv_cert_files, self.ca.http_cert_files) + cert_file_opt = (self.ca.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.ca.dirsrv_cert_files and self.ca.dirsrv_pin is None: + raise RuntimeError( + "You must specify --dirsrv-pin with --dirsrv-cert-file") + if self.ca.http_cert_files and self.ca.http_pin is None: + raise RuntimeError( + "You must specify --http-pin with --http-cert-file") + if self.ca.pkinit_cert_files and self.ca.pkinit_pin is None: + raise RuntimeError( + "You must specify --pkinit-pin with --pkinit-cert-file") + + if self.ca.external_cert_files and self.ca.dirsrv_cert_files: + raise RuntimeError( + "Service certificate file options cannot be used with the " + "external CA options.") + + if self.ca.external_ca_type and not self.ca.external_ca: + raise RuntimeError( + "You cannot specify --external-ca-type without --external-ca") + + if not self.setup_dns: + if self.dns.forwarders: + raise RuntimeError( + "You cannot specify a --forwarder option without the " + "--setup-dns option") + if self.dns.no_forwarders: + raise RuntimeError( + "You cannot specify a --no-forwarders option without the " + "--setup-dns option") + if self.dns.reverse_zones: + raise RuntimeError( + "You cannot specify a --reverse-zone option without the " + "--setup-dns option") + if self.dns.no_reverse: + raise RuntimeError( + "You cannot specify a --no-reverse option without the " + "--setup-dns option") + if self.dns.no_dnssec_validation: + raise RuntimeError( + "You cannot specify a --no-dnssec-validation option " + "without the --setup-dns option") + elif self.dns.forwarders and self.dns.no_forwarders: + raise RuntimeError( + "You cannot specify a --forwarder option together with " + "--no-forwarders") + elif not self.dns.forwarders and not self.dns.no_forwarders: + raise RuntimeError( + "You must specify at least one --forwarder option or " + "--no-forwarders option") + elif self.dns.reverse_zones and self.dns.no_reverse: + raise RuntimeError( + "You cannot specify a --reverse-zone option together with " + "--no-reverse") + + # Automatically disable pkinit w/ dogtag until that is supported + self.no_pkinit = True + + self.external_ca = self.ca.external_ca + self.external_ca_type = self.ca.external_ca_type + self.external_cert_files = self.ca.external_cert_files + self.dirsrv_cert_files = self.ca.dirsrv_cert_files + self.http_cert_files = self.ca.http_cert_files + self.pkinit_cert_files = self.ca.pkinit_cert_files + self.dirsrv_pin = self.ca.dirsrv_pin + self.http_pin = self.ca.http_pin + self.pkinit_pin = self.ca.pkinit_pin + self.dirsrv_cert_name = self.ca.dirsrv_cert_name + self.http_cert_name = self.ca.http_cert_name + self.pkinit_cert_name = self.ca.pkinit_cert_name + self.ca_cert_files = self.ca.ca_cert_files + self.subject = self.ca.subject + self.ca_signing_algorithm = self.ca.ca_signing_algorithm + self.skip_schema_check = self.ca.skip_schema_check + + self.forwarders = self.dns.forwarders + self.no_forwarders = self.dns.no_forwarders + self.reverse_zones = self.dns.reverse_zones + self.no_reverse = self.dns.no_reverse + self.no_dnssec_validation = self.dns.no_dnssec_validation + self.dnssec_master = self.dns.dnssec_master + self.disable_dnssec_master = self.dns.disable_dnssec_master + self.kasp_db_file = self.dns.kasp_db_file + self.force = self.dns.force + self.zonemgr = self.dns.zonemgr + + self.unattended = not self.interactive + + ca = core.Component(BaseServerCA) + dns = core.Component(BaseServerDNS) diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py index dcdfa59d0..9137e1a9b 100644 --- a/ipaserver/install/server/install.py +++ b/ipaserver/install/server/install.py @@ -49,15 +49,9 @@ try: except ImportError: _server_trust_ad_installed = False -SYSRESTORE_DIR_PATH = paths.SYSRESTORE +from .common import BaseServer -VALID_SUBJECT_ATTRS = ['st', 'o', 'ou', 'dnqualifier', 'c', - 'serialnumber', 'l', 'title', 'sn', 'givenname', - 'initials', 'generationqualifier', 'dc', 'mail', - 'uid', 'postaladdress', 'postalcode', 'postofficebox', - 'houseidentifier', 'e', 'street', 'pseudonym', - 'incorporationlocality', 'incorporationstate', - 'incorporationcountry', 'businesscategory'] +SYSRESTORE_DIR_PATH = paths.SYSRESTORE def validate_dm_password(password): @@ -1152,243 +1146,18 @@ def uninstall(installer): sys.exit(rv) -class ServerCA(common.Installable, core.Group, core.Composite): - description = "certificate system" - - external_ca = Knob( - bool, False, - description=("Generate a CSR for the IPA CA certificate to be signed " - "by an external CA"), - ) - - external_ca_type = Knob( - {'generic', 'ms-cs'}, None, - description="Type of the external CA", - ) - - external_cert_files = Knob( - (list, str), None, - description=("File containing the IPA CA certificate and the external " - "CA certificate chain"), - cli_name='external-cert-file', - cli_aliases=['external_cert_file', 'external_ca_file'], - cli_metavar='FILE', - ) - - @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") - - no_pkinit = Knob( - bool, False, - description="disables pkinit setup steps", - ) - - dirsrv_cert_files = Knob( - (list, str), None, - description=("File containing the Directory Server SSL certificate " - "and private key"), - cli_name='dirsrv-cert-file', - cli_aliases=['dirsrv_pkcs12'], - cli_metavar='FILE', - ) - - http_cert_files = Knob( - (list, str), None, - description=("File containing the Apache Server SSL certificate and " - "private key"), - cli_name='http-cert-file', - cli_aliases=['http_pkcs12'], - cli_metavar='FILE', - ) +class Server(BaseServer): + realm_name = Knob(BaseServer.realm_name) + domain_name = Knob(BaseServer.domain_name) - pkinit_cert_files = Knob( - (list, str), None, - description=("File containing the Kerberos KDC SSL certificate and " - "private key"), - cli_name='pkinit-cert-file', - cli_aliases=['pkinit_pkcs12'], - cli_metavar='FILE', - ) - - dirsrv_pin = Knob( - str, None, - sensitive=True, - description="The password to unlock the Directory Server private key", - cli_aliases=['dirsrv_pin'], - cli_metavar='PIN', - ) - - http_pin = Knob( - str, None, - sensitive=True, - description="The password to unlock the Apache Server private key", - cli_aliases=['http_pin'], - cli_metavar='PIN', - ) - - pkinit_pin = Knob( - str, None, - sensitive=True, - description="The password to unlock the Kerberos KDC private key", - cli_aliases=['pkinit_pin'], - cli_metavar='PIN', - ) - - dirsrv_cert_name = Knob( - str, None, - description="Name of the Directory Server SSL certificate to install", - cli_metavar='NAME', - ) - - http_cert_name = Knob( - str, None, - description="Name of the Apache Server SSL certificate to install", - cli_metavar='NAME', - ) - - pkinit_cert_name = Knob( - str, None, - description="Name of the Kerberos KDC SSL certificate to install", - cli_metavar='NAME', - ) - - ca_cert_files = Knob( - (list, str), None, - description=("File containing CA certificates for the service " - "certificate files"), - cli_name='ca-cert-file', - cli_aliases=['root-ca-file'], - cli_metavar='FILE', - ) - - subject = Knob( - str, None, - description="The certificate subject base (default O=)", - ) - - @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( - {'SHA1withRSA', 'SHA256withRSA', 'SHA512withRSA'}, None, - description="Signing algorithm of the IPA CA certificate", - ) - - -class ServerDNS(common.Installable, core.Group, core.Composite): - description = "DNS" - - setup_dns = Knob( - bool, False, - description="configure bind with our zone", - ) - - forwarders = Knob( - (list, 'ip'), None, - description=("Add a DNS forwarder. This option can be used multiple " - "times"), - cli_name='forwarder', - ) - - no_forwarders = Knob( - bool, False, - description="Do not add any DNS forwarders, use root servers instead", - ) - - reverse_zones = Knob( - (list, str), [], - description=("The reverse DNS zone to use. This option can be used " - "multiple times"), - cli_name='reverse-zone', - cli_metavar='REVERSE_ZONE', - ) - - no_reverse = Knob( - bool, False, - description="Do not create reverse DNS zone", - ) - - no_dnssec_validation = Knob( - bool, False, - description="Disable DNSSEC validation", - ) - - zonemgr = Knob( - str, None, - description=("DNS zone manager e-mail address. Defaults to " - "hostmaster@DOMAIN"), - ) - - @zonemgr.validator - def zonemgr(self, value): - # validate the value first - try: - # IDNA support requires unicode - encoding = getattr(sys.stdin, 'encoding', None) - if encoding is None: - encoding = 'utf-8' - value = value.decode(encoding) - bindinstance.validate_zonemgr_str(value) - except ValueError as e: - # FIXME we can do this in better way - # https://fedorahosted.org/freeipa/ticket/4804 - # decode to proper stderr encoding - stderr_encoding = getattr(sys.stderr, 'encoding', None) - if stderr_encoding is None: - stderr_encoding = 'utf-8' - error = unicode(e).encode(stderr_encoding) - raise ValueError(error) - - no_host_dns = Knob( - bool, False, - description="Do not use DNS for hostname lookup during installation", - ) - - no_dns_sshfp = Knob( - bool, False, - description="Do not automatically create DNS SSHFP records", - ) - - -class Server(common.Installable, common.Interactive, core.Composite): - realm_name = Knob( - str, None, - description="realm name", - cli_name='realm', - cli_short_name='r', - ) - - domain_name = Knob( - str, None, - description="domain name", - cli_name='domain', - cli_short_name='n', - ) - - @domain_name.validator - def domain_name(self, value): - validate_domain_name(value) + setup_ca = None + setup_kra = None + setup_dns = Knob(BaseServer.setup_dns) dm_password = Knob( - str, None, - sensitive=True, + BaseServer.dm_password, description="Directory Manager password", cli_name='ds-password', - cli_short_name='p', ) @dm_password.validator @@ -1403,8 +1172,7 @@ class Server(common.Installable, common.Interactive, core.Composite): ) admin_password = Knob( - str, None, - sensitive=True, + BaseServer.admin_password, description="admin user kerberos password", cli_short_name='a', ) @@ -1413,16 +1181,8 @@ class Server(common.Installable, common.Interactive, core.Composite): def admin_password(self, value): validate_admin_password(value) - mkhomedir = Knob( - bool, False, - description="create home directories for users on their first login", - ) - - host_name = Knob( - str, None, - description="fully qualified name of server", - cli_name='hostname', - ) + mkhomedir = Knob(BaseServer.mkhomedir) + host_name = Knob(BaseServer.host_name) domainlevel = Knob( int, constants.MAX_DOMAIN_LEVEL, @@ -1443,18 +1203,13 @@ class Server(common.Installable, common.Interactive, core.Composite): constants.MAX_DOMAIN_LEVEL)) ip_addresses = Knob( - (list, 'ip-local'), None, + BaseServer.ip_addresses, description=("Master Server IP Address. This option can be used " "multiple times"), - cli_name='ip-address', - cli_metavar='IP_ADDRESS', ) - no_ntp = Knob( - bool, False, - description="do not configure ntp", - cli_short_name='N', - ) + no_host_dns = Knob(BaseServer.no_host_dns) + no_ntp = Knob(BaseServer.no_ntp) idstart = Knob( int, random.randint(1, 10000) * 200000, @@ -1477,25 +1232,14 @@ class Server(common.Installable, common.Interactive, core.Composite): cli_name='no_hbac_allow', ) - no_ui_redirect = Knob( - bool, False, - description="Do not automatically redirect to the Web UI", - ) - - ssh_trust_dns = Knob( - bool, False, - description="configure OpenSSH client to trust DNS SSHFP records", - ) - - no_ssh = Knob( - bool, False, - description="do not configure OpenSSH client", - ) + # ca + skip_schema_check = None - no_sshd = Knob( - bool, False, - description="do not configure OpenSSH server", - ) + # dns + dnssec_master = None + disable_dnssec_master = None + kasp_db_file = None + force = None def __init__(self, **kwargs): super(Server, self).__init__(**kwargs) @@ -1514,125 +1258,17 @@ class Server(common.Installable, common.Interactive, core.Composite): self._ca_cert = None self._update_hosts_file = False - #pylint: disable=no-member - - if not self.dns.setup_dns: - if self.dns.forwarders: - raise RuntimeError( - "You cannot specify a --forwarder option without the " - "--setup-dns option") - if self.dns.no_forwarders: - raise RuntimeError( - "You cannot specify a --no-forwarders option without the " - "--setup-dns option") - if self.dns.reverse_zones: - raise RuntimeError( - "You cannot specify a --reverse-zone option without the " - "--setup-dns option") - if self.dns.no_reverse: - raise RuntimeError( - "You cannot specify a --no-reverse option without the " - "--setup-dns option") - if self.dns.no_dnssec_validation: - raise RuntimeError( - "You cannot specify a --no-dnssec-validation option " - "without the --setup-dns option") - elif self.dns.forwarders and self.dns.no_forwarders: - raise RuntimeError( - "You cannot specify a --forwarder option together with " - "--no-forwarders") - elif self.dns.reverse_zones and self.dns.no_reverse: - raise RuntimeError( - "You cannot specify a --reverse-zone option together with " - "--no-reverse") - 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.dns.setup_dns: - if not self.dns.forwarders and not self.dns.no_forwarders: - raise RuntimeError( - "You must specify at least one --forwarder option or " - "--no-forwarders option") - - # If any of the key file options are selected, all are required. - cert_file_req = (self.ca.dirsrv_cert_files, self.ca.http_cert_files) - cert_file_opt = (self.ca.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.ca.dirsrv_cert_files and self.ca.dirsrv_pin is None: - raise RuntimeError( - "You must specify --dirsrv-pin with --dirsrv-cert-file") - if self.ca.http_cert_files and self.ca.http_pin is None: - raise RuntimeError( - "You must specify --http-pin with --http-cert-file") - if self.ca.pkinit_cert_files and self.ca.pkinit_pin is None: - raise RuntimeError( - "You must specify --pkinit-pin with --pkinit-cert-file") - - if self.ca.external_cert_files and self.ca.dirsrv_cert_files: - raise RuntimeError( - "Service certificate file options cannot be used with the " - "external CA options.") - - if self.ca.external_ca_type and not self.ca.external_ca: - raise RuntimeError( - "You cannot specify --external-ca-type without --external-ca") if self.idmax < self.idstart: raise RuntimeError( "idmax (%s) cannot be smaller than idstart (%s)" % (self.idmax, self.idstart)) - # Automatically disable pkinit w/ dogtag until that is supported - self.ca.no_pkinit = True - - self.setup_ca = False - self.setup_kra = False - self.external_ca = self.ca.external_ca - self.external_ca_type = self.ca.external_ca_type - self.external_cert_files = self.ca.external_cert_files - self.no_pkinit = self.ca.no_pkinit - self.dirsrv_cert_files = self.ca.dirsrv_cert_files - self.http_cert_files = self.ca.http_cert_files - self.pkinit_cert_files = self.ca.pkinit_cert_files - self.dirsrv_pin = self.ca.dirsrv_pin - self.http_pin = self.ca.http_pin - self.pkinit_pin = self.ca.pkinit_pin - self.dirsrv_cert_name = self.ca.dirsrv_cert_name - self.http_cert_name = self.ca.http_cert_name - self.pkinit_cert_name = self.ca.pkinit_cert_name - self.ca_cert_files = self.ca.ca_cert_files - self.subject = self.ca.subject - self.ca_signing_algorithm = self.ca.ca_signing_algorithm - self.setup_dns = self.dns.setup_dns - self.forwarders = self.dns.forwarders - self.no_forwarders = self.dns.no_forwarders - self.reverse_zones = self.dns.reverse_zones - self.no_reverse = self.dns.no_reverse - self.no_dnssec_validation = self.dns.no_dnssec_validation - self.dnssec_master = False - self.disable_dnssec_master = False - self.kasp_db_file = None - self.force = False - self.zonemgr = self.dns.zonemgr - self.no_host_dns = self.dns.no_host_dns - self.no_dns_sshfp = self.dns.no_dns_sshfp - - self.unattended = not self.interactive - @step() def main(self): install_check(self) @@ -1644,6 +1280,3 @@ class Server(common.Installable, common.Interactive, core.Composite): uninstall_check(self) yield uninstall(self) - - ca = core.Component(ServerCA) - dns = core.Component(ServerDNS) diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index adff9284e..79bbcda59 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -33,6 +33,8 @@ from ipaserver.install.installutils import create_replica_config from ipaserver.install.replication import ( ReplicationManager, replica_conn_check) +from .common import BaseServer + DIRMAN_DN = DN(('cn', 'directory manager')) @@ -653,145 +655,78 @@ def install(installer): remove_replica_info_dir(installer) -class ReplicaCA(common.Installable, core.Group, core.Composite): - description = "certificate system" - - no_pkinit = Knob( - bool, False, - description="disables pkinit setup steps", - ) - - skip_schema_check = Knob( - bool, False, - description="skip check for updated CA DS schema on the remote master", - ) - - -class ReplicaDNS(common.Installable, core.Group, core.Composite): - description = "DNS" - - setup_dns = Knob( - bool, False, - description="configure bind with our zone", - ) - - forwarders = Knob( - (list, 'ip'), None, - description=("Add a DNS forwarder. This option can be used multiple " - "times"), - cli_name='forwarder', - ) - - no_forwarders = Knob( - bool, False, - description="Do not add any DNS forwarders, use root servers instead", - ) - - reverse_zones = Knob( - (list, str), [], - description=("The reverse DNS zone to use. This option can be used " - "multiple times"), - cli_name='reverse-zone', - cli_metavar='REVERSE_ZONE', - ) - - no_reverse = Knob( - bool, False, - description="Do not create new reverse DNS zone", - ) - - no_dnssec_validation = Knob( - bool, False, - description="Disable DNSSEC validation", - ) - - no_host_dns = Knob( - bool, False, - description="Do not use DNS for hostname lookup during installation", - ) - - no_dns_sshfp = Knob( - bool, False, - description="do not automatically create DNS SSHFP records", - ) - - -class Replica(common.Installable, common.Interactive, core.Composite): +class Replica(BaseServer): replica_file = Knob( str, None, description="a file generated by ipa-replica-prepare", ) - setup_ca = Knob( - bool, False, - initializable=False, - description="configure a dogtag CA", - ) + realm_name = None + domain_name = None - setup_kra = Knob( - bool, False, - initializable=False, - description="configure a dogtag KRA", - ) + setup_ca = Knob(BaseServer.setup_ca) + setup_kra = Knob(BaseServer.setup_kra) + setup_dns = Knob(BaseServer.setup_dns) ip_addresses = Knob( - (list, 'ip-local'), None, + BaseServer.ip_addresses, description=("Replica server IP Address. This option can be used " "multiple times"), - cli_name='ip-address', - cli_metavar='IP_ADDRESS', ) - password = Knob( - str, None, - sensitive=True, + dm_password = Knob( + BaseServer.dm_password, description="Directory Manager (existing master) password", - cli_short_name='p', + cli_name='password', + cli_metavar='PASSWORD', ) admin_password = Knob( - str, None, - sensitive=True, + BaseServer.admin_password, description="Admin user Kerberos password used for connection check", cli_short_name='w', ) - mkhomedir = Knob( - bool, False, - description="create home directories for users on their first login", - ) - - no_ntp = Knob( - bool, False, - description="do not configure ntp", - cli_short_name='N', - ) - - no_ui_redirect = Knob( - bool, False, - description="Do not automatically redirect to the Web UI", - ) - - ssh_trust_dns = Knob( - bool, False, - description="configure OpenSSH client to trust DNS SSHFP records", - ) - - no_ssh = Knob( - bool, False, - description="do not configure OpenSSH client", - ) - - no_sshd = Knob( - bool, False, - description="do not configure OpenSSH server", - ) + mkhomedir = Knob(BaseServer.mkhomedir) + host_name = None + no_host_dns = Knob(BaseServer.no_host_dns) + no_ntp = Knob(BaseServer.no_ntp) + no_pkinit = Knob(BaseServer.no_pkinit) + no_ui_redirect = Knob(BaseServer.no_ui_redirect) + ssh_trust_dns = Knob(BaseServer.ssh_trust_dns) + no_ssh = Knob(BaseServer.no_ssh) + no_sshd = Knob(BaseServer.no_sshd) + no_dns_sshfp = Knob(BaseServer.no_dns_sshfp) skip_conncheck = Knob( bool, False, description="skip connection check to remote master", ) + # ca + external_ca = None + external_ca_type = None + external_cert_files = None + dirsrv_cert_files = None + http_cert_files = None + pkinit_cert_files = None + dirsrv_pin = None + http_pin = None + pkinit_pin = None + dirsrv_cert_name = None + http_cert_name = None + pkinit_cert_name = None + ca_cert_files = None + subject = None + ca_signing_algorithm = None + + # dns + dnssec_master = None + disable_dnssec_master = None + kasp_db_file = None + force = None + zonemgr = None + def __init__(self, **kwargs): super(Replica, self).__init__(**kwargs) @@ -799,8 +734,6 @@ class Replica(common.Installable, common.Interactive, core.Composite): self._config = None self._update_hosts_file = False - #pylint: disable=no-member - if self.replica_file is None: raise RuntimeError( "you must provide a file generated by ipa-replica-prepare") @@ -808,69 +741,10 @@ class Replica(common.Installable, common.Interactive, core.Composite): raise RuntimeError( "Replica file %s does not exist" % self.replica_file) - if not self.dns.setup_dns: - if self.dns.forwarders: - raise RuntimeError( - "You cannot specify a --forwarder option without the " - "--setup-dns option") - if self.dns.no_forwarders: - raise RuntimeError( - "You cannot specify a --no-forwarders option without the " - "--setup-dns option") - if self.dns.reverse_zones: - raise RuntimeError( - "You cannot specify a --reverse-zone option without the " - "--setup-dns option") - if self.dns.no_reverse: - raise RuntimeError( - "You cannot specify a --no-reverse option without the " - "--setup-dns option") - if self.dns.no_dnssec_validation: - raise RuntimeError( - "You cannot specify a --no-dnssec-validation option " - "without the --setup-dns option") - elif self.dns.forwarders and self.dns.no_forwarders: - raise RuntimeError( - "You cannot specify a --forwarder option together with " - "--no-forwarders") - elif not self.dns.forwarders and not self.dns.no_forwarders: - raise RuntimeError( - "You must specify at least one --forwarder option or " - "--no-forwarders option") - elif self.dns.reverse_zones and self.dns.no_reverse: - raise RuntimeError( - "You cannot specify a --reverse-zone option together with " - "--no-reverse") - - # Automatically disable pkinit w/ dogtag until that is supported - self.ca.no_pkinit = True - - self.external_ca = False - self.external_cert_files = None - self.no_pkinit = self.ca.no_pkinit - self.skip_schema_check = self.ca.skip_schema_check - - self.setup_dns = self.dns.setup_dns - self.forwarders = self.dns.forwarders - self.no_forwarders = self.dns.no_forwarders - self.reverse_zones = self.dns.reverse_zones - self.no_reverse = self.dns.no_reverse - self.no_dnssec_validation = self.dns.no_dnssec_validation - self.dnssec_master = False - self.disable_dnssec_master = False - self.kasp_db_file = None - self.force = False - self.zonemgr = None - self.no_host_dns = self.dns.no_host_dns - self.no_dns_sshfp = self.dns.no_dns_sshfp - - self.unattended = not self.interactive + self.password = self.dm_password @step() def main(self): install_check(self) yield install(self) - - ca = core.Component(ReplicaCA) - dns = core.Component(ReplicaDNS) -- cgit