def __localinit(self): """If a CA certificate is provided then it is assumed that we are doing SSL client authentication with proxy auth. If a CA certificate is not present then it is assumed that we are using a forwarded kerberos ticket for SASL auth. SASL provides its own encryption. """ if self.cacert is not None: IPAEntryLDAPObject.__init__(self,'ldaps://%s' % format_netloc(self.host, self.port)) else: if self.ldapi: IPAEntryLDAPObject.__init__(self,'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % "-".join(self.realm.split("."))) else: IPAEntryLDAPObject.__init__(self,'ldap://%s' % format_netloc(self.host, self.port))
def _httplib_request( protocol, host, port, path, connection_factory, request_body): """ :param request_body: Request body :param connection_factory: Connection class to use. Will be called with the host and port arguments. Perform a HTTP(s) request. """ if isinstance(host, unicode): host = host.encode('utf-8') uri = '%s://%s%s' % (protocol, ipautil.format_netloc(host, port), path) root_logger.debug('request %r', uri) root_logger.debug('request body %r', request_body) try: conn = connection_factory(host, port) conn.request('POST', uri, body=request_body, headers={'Content-type': 'application/x-www-form-urlencoded'}, ) res = conn.getresponse() http_status = res.status http_reason_phrase = unicode(res.reason, 'utf-8') http_headers = res.msg.dict http_body = res.read() conn.close() except Exception, e: raise NetworkError(uri=uri, error=str(e))
def get_url_list(self, xmlrpc_uri): """ Create a list of urls consisting of the available IPA servers. """ # the configured URL defines what we use for the discovered servers (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(xmlrpc_uri) servers = [] name = '_ldap._tcp.%s.' % self.env.domain rs = dnsclient.query(name, dnsclient.DNS_C_IN, dnsclient.DNS_T_SRV) for r in rs: if r.dns_type == dnsclient.DNS_T_SRV: rsrv = r.rdata.server.rstrip('.') servers.append('https://%s%s' % (ipautil.format_netloc(rsrv), path)) servers = list(set(servers)) # the list/set conversion won't preserve order so stick in the # local config file version here. cfg_server = xmlrpc_uri if cfg_server in servers: # make sure the configured master server is there just once and # it is the first one servers.remove(cfg_server) servers.insert(0, cfg_server) else: servers.insert(0, cfg_server) return servers
def get_url_list(self, rpc_uri): """ Create a list of urls consisting of the available IPA servers. """ # the configured URL defines what we use for the discovered servers (_scheme, _netloc, path, _params, _query, _fragment) = urllib.parse.urlparse(rpc_uri) servers = [] name = "_ldap._tcp.%s." % self.env.domain try: answers = resolver.query(name, rdatatype.SRV) except DNSException: answers = [] for answer in answers: server = str(answer.target).rstrip(".") servers.append("https://%s%s" % (ipautil.format_netloc(server), path)) servers = list(set(servers)) # the list/set conversion won't preserve order so stick in the # local config file version here. cfg_server = rpc_uri if cfg_server in servers: # make sure the configured master server is there just once and # it is the first one servers.remove(cfg_server) servers.insert(0, cfg_server) else: servers.insert(0, cfg_server) return servers
def __init__(self, subsystem, fqdn, domain, subject_base, ca_subject, admin_user, admin_password, dm_password, pki_config_override=None): self.pki_config_override = pki_config_override self.defaults = dict( # pretty much static ipa_ca_pem_file=paths.IPA_CA_CRT, # variable ipa_ca_subject=ca_subject, ipa_subject_base=subject_base, ipa_fqdn=fqdn, ipa_ocsp_uri="http://{}.{}/ca/ocsp".format( IPA_CA_RECORD, ipautil.format_netloc(domain)), ipa_admin_cert_p12=paths.DOGTAG_ADMIN_P12, ipa_admin_user=admin_user, pki_admin_password=admin_password, pki_ds_password=dm_password, # Dogtag's pkiparser defines these config vars by default: pki_dns_domainname=domain, pki_hostname=fqdn, pki_subsystem=subsystem.upper(), pki_subsystem_type=subsystem.lower(), home_dir=os.path.expanduser("~"), # for softhsm2 testing softhsm2_so=paths.LIBSOFTHSM2_SO )
def get_url_list(self, rpc_uri): """ Create a list of urls consisting of the available IPA servers. """ # the configured URL defines what we use for the discovered servers (_scheme, _netloc, path, _params, _query, _fragment ) = urllib.parse.urlparse(rpc_uri) servers = [] name = '_ldap._tcp.%s.' % self.env.domain try: answers = query_srv(name) except DNSException: answers = [] for answer in answers: server = str(answer.target).rstrip(".") servers.append('https://%s%s' % (ipautil.format_netloc(server), path)) # make sure the configured master server is there just once and # it is the first one. if rpc_uri in servers: servers.remove(rpc_uri) servers.insert(0, rpc_uri) return servers
def http_request(host, port, url, **kw): """ :param url: The URL to post to. :param kw: Keyword arguments to encode into POST body. :return: (http_status, http_reason_phrase, http_headers, http_body) as (integer, unicode, dict, str) Perform an HTTP request. """ if isinstance(host, unicode): host = host.encode('utf-8') uri = 'http://%s%s' % (ipautil.format_netloc(host, port), url) post = urlencode(kw) root_logger.info('request %r', uri) root_logger.debug('request post %r', post) conn = httplib.HTTPConnection(host, port) try: conn.request('POST', url, body=post, headers={'Content-type': 'application/x-www-form-urlencoded'}, ) res = conn.getresponse() http_status = res.status http_reason_phrase = unicode(res.reason, 'utf-8') http_headers = res.msg.dict http_body = res.read() conn.close() except NSPRError, e: raise NetworkError(uri=uri, error=str(e))
def setUp(self): self.conn = None self.ldapuri = 'ldap://%s' % ipautil.format_netloc(api.env.host) self.ccache = '/tmp/krb5cc_%d' % os.getuid() nss.nss_init_nodb() self.dn = DN(('krbprincipalname','ldap/%s@%s' % (api.env.host, api.env.realm)), ('cn','services'),('cn','accounts'),api.env.basedn)
def setup(self): self.conn = None self.ldapuri = "ldap://%s" % ipautil.format_netloc(api.env.host) self.ccache = paths.TMP_KRB5CC % os.getuid() nss.nss_init_nodb() self.dn = DN( ("krbprincipalname", "ldap/%s@%s" % (api.env.host, api.env.realm)), ("cn", "services"), ("cn", "accounts"), api.env.basedn, )
def https_request( host, port, url, secdir, password, nickname, operation, args, **kw): """ :param url: The URL to post to. :param operation: GET, POST, (PUT and DELETE not yet implemented) :param args: arguments for GET command line, or for POST :param kw: Keyword arguments to encode into POST body. :return: (http_status, http_reason_phrase, http_headers, http_body) as (integer, unicode, dict, str) Perform a client authenticated HTTPS request """ if isinstance(host, six.text_type): host = host.encode('utf-8') uri = 'https://%s%s' % (ipautil.format_netloc(host, port), url) logging.info('sslget %r', uri) request_headers = {"Content-type": "application/xml", "Accept": "application/xml"} if operation == "POST": if args is not None: post = args elif kw is not None: post = urlencode(kw) request_headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"} conn = None try: conn = nsslib.NSSConnection(host, port, dbdir=secdir) conn.set_debuglevel(0) conn.connect() conn.sock.set_client_auth_data_callback(nsslib.client_auth_data_callback, nickname, password, nss.get_default_certdb()) if operation == "GET": url = url + "?" + args conn.request("GET", url) elif operation == "POST": conn.request("POST", url, post, request_headers) res = conn.getresponse() http_status = res.status http_reason_phrase = six.text_type(res.reason, 'utf-8') http_headers = res.msg.dict http_body = res.read() except Exception as e: raise NetworkError(uri=uri, error=str(e)) finally: if conn is not None: conn.close() return http_status, http_reason_phrase, http_headers, http_body
def _httplib_request( protocol, host, port, path, connection_factory, request_body, method='POST', headers=None, connection_options=None): """ :param request_body: Request body :param connection_factory: Connection class to use. Will be called with the host and port arguments. :param method: HTTP request method (default: 'POST') :param connection_options: a dictionary that will be passed to connection_factory as keyword arguments. Perform a HTTP(s) request. """ if connection_options is None: connection_options = {} uri = u'%s://%s%s' % (protocol, ipautil.format_netloc(host, port), path) logger.debug('request %s %s', method, uri) logger.debug('request body %r', request_body) headers = headers or {} if ( method == 'POST' and 'content-type' not in (str(k).lower() for k in headers) ): headers['content-type'] = 'application/x-www-form-urlencoded' try: conn = connection_factory(host, port, **connection_options) conn.request(method, path, body=request_body, headers=headers) res = conn.getresponse() http_status = res.status http_headers = res.msg http_body = res.read() conn.close() except Exception as e: logger.debug("httplib request failed:", exc_info=True) raise NetworkError(uri=uri, error=str(e)) encoding = res.getheader('Content-Encoding') if encoding == 'gzip': http_body = gzip_decompress(http_body) elif encoding == 'deflate': http_body = zlib.decompress(http_body) logger.debug('response status %d', http_status) logger.debug('response headers %s', http_headers) logger.debug('response body (decoded): %r', http_body) return http_status, http_headers, http_body
def wait_until_running(self): # We must not wait for the httpd proxy if httpd is not set up yet. # Unfortunately, knownservices.httpd.is_installed() can return # false positives, so check for existence of our configuration file. # TODO: Use a cleaner solution use_proxy = True if not (os.path.exists('/etc/httpd/conf.d/ipa.conf') and os.path.exists(paths.HTTPD_IPA_PKI_PROXY_CONF)): root_logger.debug( 'The httpd proxy is not installed, wait on local port') use_proxy = False root_logger.debug('Waiting until the CA is running') timeout = float(api.env.startup_timeout) op_timeout = time.time() + timeout while time.time() < op_timeout: try: # FIXME https://fedorahosted.org/freeipa/ticket/4716 # workaround # # status = dogtag.ca_status(use_proxy=use_proxy) # port = 8443 if use_proxy: port = 443 url = "https://%(host_port)s%(path)s" % { "host_port": ipautil.format_netloc(api.env.ca_host, port), "path": "/ca/admin/ca/getStatus" } args = [ paths.BIN_WGET, '-S', '-O', '-', '--timeout=30', '--no-check-certificate', url ] stdout, stderr, returncode = ipautil.run(args) status = dogtag._parse_ca_status(stdout) # end of workaround except Exception as e: status = 'check interrupted due to error: %s' % e root_logger.debug('The CA status is: %s' % status) if status == 'running': break root_logger.debug('Waiting for CA to start...') time.sleep(1) else: raise RuntimeError('CA did not start in %ss' % timeout)
def http_request(host, port, url, operation, args): """ :param url: The URL to post to. :param operation: GET, POST, (PUT and DELETE not yet implemented) :param args: arguments for GET command line, or for POST :return: (http_status, http_reason_phrase, http_headers, http_body) as (integer, unicode, dict, str) Perform an HTTP request. """ if isinstance(host, six.text_type): host = host.encode('utf-8') uri = 'http://%s%s' % (ipautil.format_netloc(host, port), url) logging.info('request %r', uri) request_headers = {"Content-type": "application/xml", "Accept": "application/xml"} if operation == "POST": if args is not None: post = args else: post = "" conn = http_client.HTTPConnection(host, port) try: if operation == "GET": if args is not None: url = url + "?" + args conn.request("GET", url) elif operation == "POST": conn.request("POST", url, post, request_headers) res = conn.getresponse() http_status = res.status http_reason_phrase = six.text_type(res.reason, 'utf-8') http_headers = res.msg.dict http_body = res.read() except NSPRError as e: raise NetworkError(uri=uri, error=str(e)) finally: if conn is not None: conn.close() logging.debug('request status %d', http_status) logging.debug('request reason_phrase %r', http_reason_phrase) logging.debug('request headers %s', http_headers) logging.debug('request body %r', http_body) return http_status, http_reason_phrase, http_headers, http_body
def _httplib_request( protocol, host, port, path, connection_factory, request_body, method='POST', headers=None): """ :param request_body: Request body :param connection_factory: Connection class to use. Will be called with the host and port arguments. :param method: HTTP request method (default: 'POST') Perform a HTTP(s) request. """ if isinstance(host, unicode): host = host.encode('utf-8') uri = '%s://%s%s' % (protocol, ipautil.format_netloc(host, port), path) root_logger.debug('request %r', uri) root_logger.debug('request body %r', request_body) headers = headers or {} if ( method == 'POST' and 'content-type' not in (str(k).lower() for k in headers) ): headers['content-type'] = 'application/x-www-form-urlencoded' try: conn = connection_factory(host, port) conn.request(method, uri, body=request_body, headers=headers) res = conn.getresponse() http_status = res.status http_reason_phrase = unicode(res.reason, 'utf-8') http_headers = res.msg.dict http_body = res.read() conn.close() except Exception as e: raise NetworkError(uri=uri, error=str(e)) root_logger.debug('request status %d', http_status) root_logger.debug('request reason_phrase %r', http_reason_phrase) root_logger.debug('request headers %s', http_headers) root_logger.debug('request body %r', http_body) return http_status, http_reason_phrase, http_headers, http_body
def _configure_clone(self, subsystem_config, security_domain_hostname, clone_pkcs12_path): subsystem_config.update( # Security domain registration pki_security_domain_hostname=security_domain_hostname, pki_security_domain_https_port=443, pki_security_domain_user=self.admin_user, pki_security_domain_password=self.admin_password, # Clone pki_clone=True, pki_clone_pkcs12_path=clone_pkcs12_path, pki_clone_pkcs12_password=self.dm_password, pki_clone_replication_security="TLS", pki_clone_replication_master_port=self.master_replication_port, pki_clone_replication_clone_port=389, pki_clone_replicate_schema=False, pki_clone_uri="https://%s" % ipautil.format_netloc( self.master_host, 443), )
def wait_until_running(self): root_logger.debug('Waiting until the CA is running') timeout = float(api.env.startup_timeout) op_timeout = time.time() + timeout while time.time() < op_timeout: try: # FIXME https://fedorahosted.org/freeipa/ticket/4716 # workaround # # status = dogtag.ca_status(use_proxy=use_proxy) # port = 8443 url = "https://%(host_port)s%(path)s" % { "host_port": ipautil.format_netloc(api.env.ca_host, port), "path": "/ca/admin/ca/getStatus" } args = [ paths.BIN_WGET, '-S', '-O', '-', '--timeout=30', '--no-check-certificate', url ] stdout, stderr, returncode = ipautil.run(args) status = dogtag._parse_ca_status(stdout) # end of workaround except Exception as e: status = 'check interrupted due to error: %s' % e root_logger.debug('The CA status is: %s' % status) if status == 'running': break root_logger.debug('Waiting for CA to start...') time.sleep(1) else: raise RuntimeError('CA did not start in %ss' % timeout)
def https_request(host, port, url, secdir, password, nickname, **kw): """ :param url: The URL to post to. :param kw: Keyword arguments to encode into POST body. :return: (http_status, http_reason_phrase, http_headers, http_body) as (integer, unicode, dict, str) Perform a client authenticated HTTPS request """ if isinstance(host, unicode): host = host.encode('utf-8') uri = 'https://%s%s' % (ipautil.format_netloc(host, port), url) post = urlencode(kw) root_logger.debug('https_request %r', uri) root_logger.debug('https_request post %r', post) request_headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"} try: conn = nsslib.NSSConnection(host, port, dbdir=secdir, tls_version_min=api.env.tls_version_min, tls_version_max=api.env.tls_version_max) conn.set_debuglevel(0) conn.connect() conn.sock.set_client_auth_data_callback(nsslib.client_auth_data_callback, nickname, password, nss.get_default_certdb()) conn.request("POST", url, post, request_headers) res = conn.getresponse() http_status = res.status http_reason_phrase = unicode(res.reason, 'utf-8') http_headers = res.msg.dict http_body = res.read() conn.close() except Exception, e: raise NetworkError(uri=uri, error=str(e))
def promote_check(installer): options = installer installer._enrollment_performed = False installer._top_dir = tempfile.mkdtemp("ipa") # check selinux status, http and DS ports, NTP conflicting services common_check(options.no_ntp) client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if not client_fstore.has_files(): # One-step replica installation if options.password and options.admin_password: raise ScriptError("--password and --admin-password options are " "mutually exclusive") ensure_enrolled(installer) else: if (options.domain_name or options.server or options.realm_name or options.host_name or options.password or options.keytab): print("IPA client is already configured on this system, ignoring " "the --domain, --server, --realm, --hostname, --password " "and --keytab options.") # The NTP configuration can not be touched on pre-installed client: if options.no_ntp or options.ntp_servers or options.ntp_pool: raise ScriptError( "NTP configuration cannot be updated during promotion") sstore = sysrestore.StateFile(paths.SYSRESTORE) fstore = sysrestore.FileStore(paths.SYSRESTORE) env = Env() env._bootstrap(context='installer', confdir=paths.ETC_IPA, log=None) env._finalize_core(**dict(constants.DEFAULT_CONFIG)) # pylint: disable=no-member xmlrpc_uri = 'https://{}/ipa/xml'.format(ipautil.format_netloc(env.host)) api.bootstrap(in_server=True, context='installer', confdir=paths.ETC_IPA, ldap_uri=ipaldap.realm_to_ldapi_uri(env.realm), xmlrpc_uri=xmlrpc_uri) # pylint: enable=no-member api.finalize() config = ReplicaConfig() config.realm_name = api.env.realm config.host_name = api.env.host config.domain_name = api.env.domain config.master_host_name = api.env.server if not api.env.ca_host or api.env.ca_host == api.env.host: # ca_host has not been configured explicitly, prefer source master config.ca_host_name = api.env.server else: # default to ca_host from IPA config config.ca_host_name = api.env.ca_host config.kra_host_name = config.ca_host_name config.ca_ds_port = 389 config.setup_ca = options.setup_ca config.setup_kra = options.setup_kra config.dir = installer._top_dir config.basedn = api.env.basedn config.hidden_replica = options.hidden_replica http_pkcs12_file = None http_pkcs12_info = None http_ca_cert = None dirsrv_pkcs12_file = None dirsrv_pkcs12_info = None dirsrv_ca_cert = None pkinit_pkcs12_file = None pkinit_pkcs12_info = None pkinit_ca_cert = None if options.http_cert_files: if options.http_pin is None: options.http_pin = installutils.read_password( "Enter Apache Server private key unlock", confirm=False, validate=False, retry=False) if options.http_pin is None: raise ScriptError( "Apache Server private key unlock password required") http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12( cert_files=options.http_cert_files, key_password=options.http_pin, key_nickname=options.http_cert_name, ca_cert_files=options.ca_cert_files, host_name=config.host_name) http_pkcs12_info = (http_pkcs12_file.name, http_pin) if options.dirsrv_cert_files: if options.dirsrv_pin is None: options.dirsrv_pin = installutils.read_password( "Enter Directory Server private key unlock", confirm=False, validate=False, retry=False) if options.dirsrv_pin is None: raise ScriptError( "Directory Server private key unlock password required") dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12( cert_files=options.dirsrv_cert_files, key_password=options.dirsrv_pin, key_nickname=options.dirsrv_cert_name, ca_cert_files=options.ca_cert_files, host_name=config.host_name) dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) if options.pkinit_cert_files: if options.pkinit_pin is None: options.pkinit_pin = installutils.read_password( "Enter Kerberos KDC private key unlock", confirm=False, validate=False, retry=False) if options.pkinit_pin is None: raise ScriptError( "Kerberos KDC private key unlock password required") pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12( cert_files=options.pkinit_cert_files, key_password=options.pkinit_pin, key_nickname=options.pkinit_cert_name, ca_cert_files=options.ca_cert_files, realm_name=config.realm_name) pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin) if (options.http_cert_files and options.dirsrv_cert_files and http_ca_cert != dirsrv_ca_cert): raise RuntimeError("Apache Server SSL certificate and Directory " "Server SSL certificate are not signed by the same" " CA certificate") if (options.http_cert_files and options.pkinit_cert_files and http_ca_cert != pkinit_ca_cert): raise RuntimeError("Apache Server SSL certificate and PKINIT KDC " "certificate are not signed by the same CA " "certificate") installutils.verify_fqdn(config.host_name, options.no_host_dns) installutils.verify_fqdn(config.master_host_name, options.no_host_dns) ccache = os.environ['KRB5CCNAME'] kinit_keytab('host/{env.host}@{env.realm}'.format(env=api.env), paths.KRB5_KEYTAB, ccache) cafile = paths.IPA_CA_CRT if not os.path.isfile(cafile): raise RuntimeError("CA cert file is not available! Please reinstall" "the client and try again.") ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name) xmlrpc_uri = 'https://{}/ipa/xml'.format( ipautil.format_netloc(config.master_host_name)) remote_api = create_api(mode=None) remote_api.bootstrap(in_server=True, context='installer', confdir=paths.ETC_IPA, ldap_uri=ldapuri, xmlrpc_uri=xmlrpc_uri) remote_api.finalize() installer._remote_api = remote_api with rpc_client(remote_api) as client: check_remote_version(client, parse_version(api.env.version)) check_remote_fips_mode(client, api.env.fips_mode) conn = remote_api.Backend.ldap2 replman = None try: # Try out authentication conn.connect(ccache=ccache) replman = ReplicationManager(config.realm_name, config.master_host_name, None) promotion_check_ipa_domain(conn, remote_api.env.basedn) # Make sure that domain fulfills minimal domain level # requirement domain_level = current_domain_level(remote_api) check_domain_level_is_supported(domain_level) if domain_level < constants.MIN_DOMAIN_LEVEL: raise RuntimeError( "Cannot promote this client to a replica. The domain level " "must be raised to {mindomainlevel} before the replica can be " "installed".format( mindomainlevel=constants.MIN_DOMAIN_LEVEL )) # Check authorization result = remote_api.Command['hostgroup_find']( cn=u'ipaservers', host=[unicode(api.env.host)] )['result'] add_to_ipaservers = not result if add_to_ipaservers: if options.password and not options.admin_password: raise errors.ACIError(info="Not authorized") if installer._ccache is None: del os.environ['KRB5CCNAME'] else: os.environ['KRB5CCNAME'] = installer._ccache try: installutils.check_creds(options, config.realm_name) installer._ccache = os.environ.get('KRB5CCNAME') finally: os.environ['KRB5CCNAME'] = ccache conn.disconnect() conn.connect(ccache=installer._ccache) try: result = remote_api.Command['hostgroup_show']( u'ipaservers', all=True, rights=True )['result'] if 'w' not in result['attributelevelrights']['member']: raise errors.ACIError(info="Not authorized") finally: conn.disconnect() conn.connect(ccache=ccache) # Check that we don't already have a replication agreement if replman.get_replication_agreement(config.host_name): msg = ("A replication agreement for this host already exists. " "It needs to be removed.\n" "Run this command:\n" " %% ipa-replica-manage del {host} --force" .format(host=config.host_name)) raise ScriptError(msg, rval=3) # Detect if the other master can handle replication managers # cn=replication managers,cn=sysaccounts,cn=etc,$SUFFIX dn = DN(('cn', 'replication managers'), ('cn', 'sysaccounts'), ('cn', 'etc'), ipautil.realm_to_suffix(config.realm_name)) try: conn.get_entry(dn) except errors.NotFound: msg = ("The Replication Managers group is not available in " "the domain. Replica promotion requires the use of " "Replication Managers to be able to replicate data. " "Upgrade the peer master or use the ipa-replica-prepare " "command on the master and use a prep file to install " "this replica.") logger.error("%s", msg) raise ScriptError(rval=3) dns_masters = remote_api.Object['dnsrecord'].get_dns_masters() if dns_masters: if not options.no_host_dns: logger.debug('Check forward/reverse DNS resolution') resolution_ok = ( check_dns_resolution(config.master_host_name, dns_masters) and check_dns_resolution(config.host_name, dns_masters)) if not resolution_ok and installer.interactive: if not ipautil.user_input("Continue?", False): raise ScriptError(rval=0) else: logger.debug('No IPA DNS servers, ' 'skipping forward/reverse resolution check') entry_attrs = conn.get_ipa_config() subject_base = entry_attrs.get('ipacertificatesubjectbase', [None])[0] if subject_base is not None: config.subject_base = DN(subject_base) # Find any server with a CA ca_host = find_providing_server( 'CA', conn, [config.ca_host_name] ) if ca_host is not None: config.ca_host_name = ca_host ca_enabled = True if options.dirsrv_cert_files: logger.error("Certificates could not be provided when " "CA is present on some master.") raise ScriptError(rval=3) else: if options.setup_ca: logger.error("The remote master does not have a CA " "installed, can't set up CA") raise ScriptError(rval=3) ca_enabled = False if not options.dirsrv_cert_files: logger.error("Cannot issue certificates: a CA is not " "installed. Use the --http-cert-file, " "--dirsrv-cert-file options to provide " "custom certificates.") raise ScriptError(rval=3) # Find any server with a KRA kra_host = find_providing_server( 'KRA', conn, [config.kra_host_name] ) if kra_host is not None: config.kra_host_name = kra_host kra_enabled = True else: if options.setup_kra: logger.error("There is no active KRA server in the domain, " "can't setup a KRA clone") raise ScriptError(rval=3) kra_enabled = False if ca_enabled: options.realm_name = config.realm_name options.host_name = config.host_name ca.install_check(False, config, options) if kra_enabled: try: kra.install_check(remote_api, config, options) except RuntimeError as e: raise ScriptError(e) if options.setup_dns: dns.install_check(False, remote_api, True, options, config.host_name) config.ips = dns.ip_addresses else: config.ips = installutils.get_server_ip_address( config.host_name, not installer.interactive, False, options.ip_addresses) # check addresses here, dns module is doing own check no_matching_interface_for_ip_address_warning(config.ips) if options.setup_adtrust: adtrust.install_check(False, options, remote_api) except errors.ACIError: logger.debug("%s", traceback.format_exc()) raise ScriptError("\nInsufficient privileges to promote the server." "\nPossible issues:" "\n- A user has insufficient privileges" "\n- This client has insufficient privileges " "to become an IPA replica") except errors.LDAPError: logger.debug("%s", traceback.format_exc()) raise ScriptError("\nUnable to connect to LDAP server %s" % config.master_host_name) finally: if replman and replman.conn: replman.conn.unbind() if conn.isconnected(): conn.disconnect() # check connection if not options.skip_conncheck: if add_to_ipaservers: # use user's credentials when the server host is not ipaservers if installer._ccache is None: del os.environ['KRB5CCNAME'] else: os.environ['KRB5CCNAME'] = installer._ccache try: replica_conn_check( config.master_host_name, config.host_name, config.realm_name, options.setup_ca, 389, options.admin_password, principal=options.principal, ca_cert_file=cafile) finally: if add_to_ipaservers: os.environ['KRB5CCNAME'] = ccache installer._ca_enabled = ca_enabled installer._kra_enabled = kra_enabled installer._ca_file = cafile installer._fstore = fstore installer._sstore = sstore installer._config = config installer._add_to_ipaservers = add_to_ipaservers installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info installer._http_pkcs12_file = http_pkcs12_file installer._http_pkcs12_info = http_pkcs12_info installer._pkinit_pkcs12_file = pkinit_pkcs12_file installer._pkinit_pkcs12_info = pkinit_pkcs12_info
def create_ipa_conf(fstore, config, ca_enabled, master=None): """ Create /etc/ipa/default.conf master configuration :param fstore: sysrestore file store used for backup and restore of the server configuration :param config: replica config :param ca_enabled: True if the topology includes a CA :param master: if set, the xmlrpc_uri parameter will use the provided master instead of this host """ # Save client file on Domain Level 1 target_fname = paths.IPA_DEFAULT_CONF fstore.backup_file(target_fname) ipaconf = IPAChangeConf("IPA Replica Install") ipaconf.setOptionAssignment(" = ") ipaconf.setSectionNameDelimiters(("[", "]")) if master: xmlrpc_uri = 'https://{0}/ipa/xml'.format( ipautil.format_netloc(master)) else: xmlrpc_uri = 'https://{0}/ipa/xml'.format( ipautil.format_netloc(config.host_name)) ldapi_uri = ipaldap.realm_to_ldapi_uri(config.realm_name) # [global] section gopts = [ ipaconf.setOption('basedn', str(config.basedn)), ipaconf.setOption('host', config.host_name), ipaconf.setOption('realm', config.realm_name), ipaconf.setOption('domain', config.domain_name), ipaconf.setOption('xmlrpc_uri', xmlrpc_uri), ipaconf.setOption('ldap_uri', ldapi_uri), ipaconf.setOption('mode', 'production') ] if ca_enabled: gopts.extend([ ipaconf.setOption('enable_ra', 'True'), ipaconf.setOption('ra_plugin', 'dogtag'), ipaconf.setOption('dogtag_version', '10') ]) if not config.setup_ca: gopts.append(ipaconf.setOption('ca_host', config.ca_host_name)) else: gopts.extend([ ipaconf.setOption('enable_ra', 'False'), ipaconf.setOption('ra_plugin', 'None') ]) opts = [ ipaconf.setSection('global', gopts), {'name': 'empty', 'type': 'empty'} ] ipaconf.newConf(target_fname, opts) # the new file must be readable for httpd # Also, umask applies when creating a new file but we want 0o644 here os.chmod(target_fname, 0o644)
def install_check(installer): options = installer dirsrv_pkcs12_file = installer._dirsrv_pkcs12_file http_pkcs12_file = installer._http_pkcs12_file pkinit_pkcs12_file = installer._pkinit_pkcs12_file dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info http_pkcs12_info = installer._http_pkcs12_info pkinit_pkcs12_info = installer._pkinit_pkcs12_info external_cert_file = installer._external_cert_file external_ca_file = installer._external_ca_file http_ca_cert = installer._ca_cert tasks.check_ipv6_stack_enabled() tasks.check_selinux_status() if options.master_password: msg = ("WARNING:\noption '-P/--master-password' is deprecated. " "KDC master password of sufficient strength is autogenerated " "during IPA server installation and should not be set " "manually.") print(textwrap.fill(msg, width=79, replace_whitespace=False)) installer._installation_cleanup = True print("\nThe log file for this installation can be found in " "/var/log/ipaserver-install.log") if (not options.external_ca and not options.external_cert_files and is_ipa_configured()): installer._installation_cleanup = False raise ScriptError( "IPA server is already configured on this system.\n" "If you want to reinstall the IPA server, please uninstall " "it first using 'ipa-server-install --uninstall'.") client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if client_fstore.has_files(): installer._installation_cleanup = False raise ScriptError( "IPA client is already configured on this system.\n" "Please uninstall it before configuring the IPA server, " "using 'ipa-client-install --uninstall'") fstore = sysrestore.FileStore(SYSRESTORE_DIR_PATH) sstore = sysrestore.StateFile(SYSRESTORE_DIR_PATH) # This will override any settings passed in on the cmdline if ipautil.file_exists(paths.ROOT_IPA_CACHE): if options.dm_password is not None: dm_password = options.dm_password else: dm_password = read_password("Directory Manager", confirm=False) if dm_password is None: raise ScriptError("Directory Manager password required") try: cache_vars = read_cache(dm_password) options.__dict__.update(cache_vars) if cache_vars.get('external_ca', False): options.external_ca = False options.interactive = False except Exception as e: raise ScriptError("Cannot process the cache file: %s" % str(e)) # We only set up the CA if the PKCS#12 options are not given. if options.dirsrv_cert_files: setup_ca = False else: setup_ca = True options.setup_ca = setup_ca if not setup_ca and options.ca_subject: raise ScriptError( "--ca-subject cannot be used with CA-less installation") if not setup_ca and options.subject_base: raise ScriptError( "--subject-base cannot be used with CA-less installation") if not setup_ca and options.setup_kra: raise ScriptError( "--setup-kra cannot be used with CA-less installation") print("=======================================" "=======================================") print("This program will set up the FreeIPA Server.") print("") print("This includes:") if setup_ca: print(" * Configure a stand-alone CA (dogtag) for certificate " "management") if not options.no_ntp: print(" * Configure the Network Time Daemon (ntpd)") print(" * Create and configure an instance of Directory Server") print(" * Create and configure a Kerberos Key Distribution Center (KDC)") print(" * Configure Apache (httpd)") if options.setup_kra: print(" * Configure KRA (dogtag) for secret management") if options.setup_dns: print(" * Configure DNS (bind)") if options.setup_adtrust: print(" * Configure Samba (smb) and winbind for managing AD trusts") if not options.no_pkinit: print(" * Configure the KDC to enable PKINIT") if options.no_ntp: print("") print("Excluded by options:") print(" * Configure the Network Time Daemon (ntpd)") if installer.interactive: print("") print("To accept the default shown in brackets, press the Enter key.") print("") if not options.external_cert_files: # Make sure the 389-ds ports are available check_dirsrv(not installer.interactive) if not options.no_ntp: try: ipaclient.install.ntpconf.check_timedate_services() except ipaclient.install.ntpconf.NTPConflictingService as e: print( ("WARNING: conflicting time&date synchronization service '%s'" " will be disabled" % e.conflicting_service)) print("in favor of ntpd") print("") except ipaclient.install.ntpconf.NTPConfigurationError: pass # Check to see if httpd is already configured to listen on 443 if httpinstance.httpd_443_configured(): raise ScriptError("Aborting installation") if not options.setup_dns and installer.interactive: if ipautil.user_input( "Do you want to configure integrated DNS " "(BIND)?", False): options.setup_dns = True print("") # check bind packages are installed if options.setup_dns: # Don't require an external DNS to say who we are if we are # setting up a local DNS server. options.no_host_dns = True # check the hostname is correctly configured, it must be as the kldap # utilities just use the hostname as returned by getaddrinfo to set # up some of the standard entries if options.host_name: host_default = options.host_name else: host_default = get_fqdn() try: if not installer.interactive or options.host_name: verify_fqdn(host_default, options.no_host_dns) host_name = host_default else: host_name = read_host_name(host_default, options.no_host_dns) except BadHostError as e: raise ScriptError(e) host_name = host_name.lower() root_logger.debug("will use host_name: %s\n" % host_name) if not options.domain_name: domain_name = read_domain_name(host_name[host_name.find(".") + 1:], not installer.interactive) root_logger.debug("read domain_name: %s\n" % domain_name) try: validate_domain_name(domain_name) except ValueError as e: raise ScriptError("Invalid domain name: %s" % unicode(e)) else: domain_name = options.domain_name domain_name = domain_name.lower() if not options.realm_name: realm_name = read_realm_name(domain_name, not installer.interactive) root_logger.debug("read realm_name: %s\n" % realm_name) else: realm_name = options.realm_name.upper() if not options.subject_base: options.subject_base = installutils.default_subject_base(realm_name) if not options.ca_subject: options.ca_subject = \ installutils.default_ca_subject_dn(options.subject_base) if options.http_cert_files: if options.http_pin is None: options.http_pin = installutils.read_password( "Enter Apache Server private key unlock", confirm=False, validate=False, retry=False) if options.http_pin is None: raise ScriptError( "Apache Server private key unlock password required") http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12( cert_files=options.http_cert_files, key_password=options.http_pin, key_nickname=options.http_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) http_pkcs12_info = (http_pkcs12_file.name, http_pin) if options.dirsrv_cert_files: if options.dirsrv_pin is None: options.dirsrv_pin = read_password( "Enter Directory Server private key unlock", confirm=False, validate=False, retry=False) if options.dirsrv_pin is None: raise ScriptError( "Directory Server private key unlock password required") dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12( cert_files=options.dirsrv_cert_files, key_password=options.dirsrv_pin, key_nickname=options.dirsrv_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) if options.pkinit_cert_files: if options.pkinit_pin is None: options.pkinit_pin = read_password( "Enter Kerberos KDC private key unlock", confirm=False, validate=False, retry=False) if options.pkinit_pin is None: raise ScriptError( "Kerberos KDC private key unlock password required") pkinit_pkcs12_file, pkinit_pin, _pkinit_ca_cert = load_pkcs12( cert_files=options.pkinit_cert_files, key_password=options.pkinit_pin, key_nickname=options.pkinit_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin) if (options.http_cert_files and options.dirsrv_cert_files and http_ca_cert != dirsrv_ca_cert): raise ScriptError( "Apache Server SSL certificate and Directory Server SSL " "certificate are not signed by the same CA certificate") if not options.dm_password: dm_password = read_dm_password() if dm_password is None: raise ScriptError("Directory Manager password required") else: dm_password = options.dm_password if not options.master_password: master_password = ipa_generate_password() else: master_password = options.master_password if not options.admin_password: admin_password = read_admin_password() if admin_password is None: raise ScriptError("IPA admin password required") else: admin_password = options.admin_password # Configuration for ipalib, we will bootstrap and finalize later, after # we are sure we have the configuration file ready. cfg = dict( context='installer', confdir=paths.ETC_IPA, in_server=True, # make sure host name specified by user is used instead of default host=host_name, ) if setup_ca: # we have an IPA-integrated CA cfg['ca_host'] = host_name # Create the management framework config file and finalize api target_fname = paths.IPA_DEFAULT_CONF fd = open(target_fname, "w") fd.write("[global]\n") fd.write("host=%s\n" % host_name) fd.write("basedn=%s\n" % ipautil.realm_to_suffix(realm_name)) fd.write("realm=%s\n" % realm_name) fd.write("domain=%s\n" % domain_name) fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % format_netloc(host_name)) fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % installutils.realm_to_serverid(realm_name)) if setup_ca: fd.write("enable_ra=True\n") fd.write("ra_plugin=dogtag\n") fd.write("dogtag_version=10\n") else: fd.write("enable_ra=False\n") fd.write("ra_plugin=none\n") fd.write("mode=production\n") fd.close() # Must be readable for everyone os.chmod(target_fname, 0o644) api.bootstrap(**cfg) api.finalize() if setup_ca: ca.install_check(False, None, options) if options.setup_kra: kra.install_check(api, None, options) if options.setup_dns: dns.install_check(False, api, False, options, host_name) ip_addresses = dns.ip_addresses else: ip_addresses = get_server_ip_address(host_name, not installer.interactive, False, options.ip_addresses) # check addresses here, dns module is doing own check network_ip_address_warning(ip_addresses) broadcast_ip_address_warning(ip_addresses) if options.setup_adtrust: adtrust.install_check(False, options, api) # installer needs to update hosts file when DNS subsystem will be # installed or custom addresses are used if options.ip_addresses or options.setup_dns: installer._update_hosts_file = True print() print("The IPA Master Server will be configured with:") print("Hostname: %s" % host_name) print("IP address(es): %s" % ", ".join(str(ip) for ip in ip_addresses)) print("Domain name: %s" % domain_name) print("Realm name: %s" % realm_name) print() if options.setup_dns: print("BIND DNS server will be configured to serve IPA domain with:") print("Forwarders: %s" % ("No forwarders" if not options.forwarders else ", ".join( [str(ip) for ip in options.forwarders]))) print('Forward policy: %s' % options.forward_policy) print("Reverse zone(s): %s" % ("No reverse zone" if options.no_reverse or not dns.reverse_zones else ", ".join(str(rz) for rz in dns.reverse_zones))) print() if not options.setup_adtrust: # If domain name and realm does not match, IPA server will not be able # to estabilish trust with Active Directory. Print big fat warning. realm_not_matching_domain = (domain_name.upper() != realm_name) if realm_not_matching_domain: print("WARNING: Realm name does not match the domain name.\n" "You will not be able to estabilish trusts with Active " "Directory unless\nthe realm name of the IPA server matches " "its domain name.\n\n") if installer.interactive and not user_input( "Continue to configure the system with these values?", False): raise ScriptError("Installation aborted") options.realm_name = realm_name options.domain_name = domain_name options.dm_password = dm_password options.master_password = master_password options.admin_password = admin_password options._host_name_overridden = bool(options.host_name) options.host_name = host_name options.ip_addresses = ip_addresses installer._fstore = fstore installer._sstore = sstore installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file installer._http_pkcs12_file = http_pkcs12_file installer._pkinit_pkcs12_file = pkinit_pkcs12_file installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info installer._http_pkcs12_info = http_pkcs12_info installer._pkinit_pkcs12_info = pkinit_pkcs12_info installer._external_cert_file = external_cert_file installer._external_ca_file = external_ca_file installer._ca_cert = http_ca_cert
def promote_check(installer): options = installer installer._enrollment_performed = False installer._top_dir = tempfile.mkdtemp("ipa") # check selinux status, http and DS ports, NTP conflicting services common_check(options.no_ntp) client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if not client_fstore.has_files(): ensure_enrolled(installer) else: if (options.domain_name or options.server or options.realm_name or options.host_name or options.password or options.keytab): print("IPA client is already configured on this system, ignoring " "the --domain, --server, --realm, --hostname, --password " "and --keytab options.") sstore = sysrestore.StateFile(paths.SYSRESTORE) fstore = sysrestore.FileStore(paths.SYSRESTORE) env = Env() env._bootstrap(context='installer', confdir=paths.ETC_IPA, log=None) env._finalize_core(**dict(constants.DEFAULT_CONFIG)) # pylint: disable=no-member xmlrpc_uri = 'https://{}/ipa/xml'.format(ipautil.format_netloc(env.host)) api.bootstrap(in_server=True, context='installer', confdir=paths.ETC_IPA, ldap_uri=installutils.realm_to_ldapi_uri(env.realm), xmlrpc_uri=xmlrpc_uri) # pylint: enable=no-member api.finalize() config = ReplicaConfig() config.realm_name = api.env.realm config.host_name = api.env.host config.domain_name = api.env.domain config.master_host_name = api.env.server config.ca_host_name = api.env.ca_host config.kra_host_name = config.ca_host_name config.ca_ds_port = 389 config.setup_ca = options.setup_ca config.setup_kra = options.setup_kra config.dir = installer._top_dir config.basedn = api.env.basedn http_pkcs12_file = None http_pkcs12_info = None http_ca_cert = None dirsrv_pkcs12_file = None dirsrv_pkcs12_info = None dirsrv_ca_cert = None pkinit_pkcs12_file = None pkinit_pkcs12_info = None pkinit_ca_cert = None if options.http_cert_files: if options.http_pin is None: options.http_pin = installutils.read_password( "Enter Apache Server private key unlock", confirm=False, validate=False, retry=False) if options.http_pin is None: raise ScriptError( "Apache Server private key unlock password required") http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12( cert_files=options.http_cert_files, key_password=options.http_pin, key_nickname=options.http_cert_name, ca_cert_files=options.ca_cert_files, host_name=config.host_name) http_pkcs12_info = (http_pkcs12_file.name, http_pin) if options.dirsrv_cert_files: if options.dirsrv_pin is None: options.dirsrv_pin = installutils.read_password( "Enter Directory Server private key unlock", confirm=False, validate=False, retry=False) if options.dirsrv_pin is None: raise ScriptError( "Directory Server private key unlock password required") dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12( cert_files=options.dirsrv_cert_files, key_password=options.dirsrv_pin, key_nickname=options.dirsrv_cert_name, ca_cert_files=options.ca_cert_files, host_name=config.host_name) dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) if options.pkinit_cert_files: if options.pkinit_pin is None: options.pkinit_pin = installutils.read_password( "Enter Kerberos KDC private key unlock", confirm=False, validate=False, retry=False) if options.pkinit_pin is None: raise ScriptError( "Kerberos KDC private key unlock password required") pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12( cert_files=options.pkinit_cert_files, key_password=options.pkinit_pin, key_nickname=options.pkinit_cert_name, ca_cert_files=options.ca_cert_files, realm_name=config.realm_name) pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin) if (options.http_cert_files and options.dirsrv_cert_files and http_ca_cert != dirsrv_ca_cert): raise RuntimeError("Apache Server SSL certificate and Directory " "Server SSL certificate are not signed by the same" " CA certificate") if (options.http_cert_files and options.pkinit_cert_files and http_ca_cert != pkinit_ca_cert): raise RuntimeError("Apache Server SSL certificate and PKINIT KDC " "certificate are not signed by the same CA " "certificate") installutils.verify_fqdn(config.host_name, options.no_host_dns) installutils.verify_fqdn(config.master_host_name, options.no_host_dns) ccache = os.environ['KRB5CCNAME'] kinit_keytab('host/{env.host}@{env.realm}'.format(env=api.env), paths.KRB5_KEYTAB, ccache) cafile = paths.IPA_CA_CRT if not os.path.isfile(cafile): raise RuntimeError("CA cert file is not available! Please reinstall" "the client and try again.") ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name) xmlrpc_uri = 'https://{}/ipa/xml'.format( ipautil.format_netloc(config.master_host_name)) remote_api = create_api(mode=None) remote_api.bootstrap(in_server=True, context='installer', confdir=paths.ETC_IPA, ldap_uri=ldapuri, xmlrpc_uri=xmlrpc_uri) remote_api.finalize() installer._remote_api = remote_api with rpc_client(remote_api) as client: check_remote_version(client, parse_version(api.env.version)) check_remote_fips_mode(client, api.env.fips_mode) conn = remote_api.Backend.ldap2 replman = None try: # Try out authentication conn.connect(ccache=ccache) replman = ReplicationManager(config.realm_name, config.master_host_name, None) promotion_check_ipa_domain(conn, remote_api.env.basedn) # Make sure that domain fulfills minimal domain level # requirement domain_level = current_domain_level(remote_api) check_domain_level_is_supported(domain_level) if domain_level < constants.MIN_DOMAIN_LEVEL: raise RuntimeError( "Cannot promote this client to a replica. The domain level " "must be raised to {mindomainlevel} before the replica can be " "installed".format(mindomainlevel=constants.MIN_DOMAIN_LEVEL)) # Check authorization result = remote_api.Command['hostgroup_find']( cn=u'ipaservers', host=[unicode(api.env.host)])['result'] add_to_ipaservers = not result if add_to_ipaservers: if options.password and not options.admin_password: raise errors.ACIError(info="Not authorized") if installer._ccache is None: del os.environ['KRB5CCNAME'] else: os.environ['KRB5CCNAME'] = installer._ccache try: installutils.check_creds(options, config.realm_name) installer._ccache = os.environ.get('KRB5CCNAME') finally: os.environ['KRB5CCNAME'] = ccache conn.disconnect() conn.connect(ccache=installer._ccache) try: result = remote_api.Command['hostgroup_show']( u'ipaservers', all=True, rights=True)['result'] if 'w' not in result['attributelevelrights']['member']: raise errors.ACIError(info="Not authorized") finally: conn.disconnect() conn.connect(ccache=ccache) # Check that we don't already have a replication agreement if replman.get_replication_agreement(config.host_name): msg = ("A replication agreement for this host already exists. " "It needs to be removed.\n" "Run this command:\n" " %% ipa-replica-manage del {host} --force".format( host=config.host_name)) raise ScriptError(msg, rval=3) # Detect if the other master can handle replication managers # cn=replication managers,cn=sysaccounts,cn=etc,$SUFFIX dn = DN(('cn', 'replication managers'), ('cn', 'sysaccounts'), ('cn', 'etc'), ipautil.realm_to_suffix(config.realm_name)) try: conn.get_entry(dn) except errors.NotFound: msg = ("The Replication Managers group is not available in " "the domain. Replica promotion requires the use of " "Replication Managers to be able to replicate data. " "Upgrade the peer master or use the ipa-replica-prepare " "command on the master and use a prep file to install " "this replica.") logger.error("%s", msg) raise ScriptError(rval=3) dns_masters = remote_api.Object['dnsrecord'].get_dns_masters() if dns_masters: if not options.no_host_dns: logger.debug('Check forward/reverse DNS resolution') resolution_ok = ( check_dns_resolution(config.master_host_name, dns_masters) and check_dns_resolution(config.host_name, dns_masters)) if not resolution_ok and installer.interactive: if not ipautil.user_input("Continue?", False): raise ScriptError(rval=0) else: logger.debug('No IPA DNS servers, ' 'skipping forward/reverse resolution check') entry_attrs = conn.get_ipa_config() subject_base = entry_attrs.get('ipacertificatesubjectbase', [None])[0] if subject_base is not None: config.subject_base = DN(subject_base) # Find if any server has a CA ca_host = service.find_providing_server('CA', conn, config.ca_host_name) if ca_host is not None: config.ca_host_name = ca_host ca_enabled = True if options.dirsrv_cert_files: logger.error("Certificates could not be provided when " "CA is present on some master.") raise ScriptError(rval=3) else: if options.setup_ca: logger.error("The remote master does not have a CA " "installed, can't set up CA") raise ScriptError(rval=3) ca_enabled = False if not options.dirsrv_cert_files: logger.error("Cannot issue certificates: a CA is not " "installed. Use the --http-cert-file, " "--dirsrv-cert-file options to provide " "custom certificates.") raise ScriptError(rval=3) kra_host = service.find_providing_server('KRA', conn, config.kra_host_name) if kra_host is not None: config.kra_host_name = kra_host kra_enabled = True else: if options.setup_kra: logger.error("There is no KRA server in the domain, " "can't setup a KRA clone") raise ScriptError(rval=3) kra_enabled = False if ca_enabled: options.realm_name = config.realm_name options.host_name = config.host_name ca.install_check(False, config, options) if kra_enabled: try: kra.install_check(remote_api, config, options) except RuntimeError as e: raise ScriptError(e) if options.setup_dns: dns.install_check(False, remote_api, True, options, config.host_name) config.ips = dns.ip_addresses else: config.ips = installutils.get_server_ip_address( config.host_name, not installer.interactive, False, options.ip_addresses) # check addresses here, dns module is doing own check no_matching_interface_for_ip_address_warning(config.ips) if options.setup_adtrust: adtrust.install_check(False, options, remote_api) except errors.ACIError: logger.debug("%s", traceback.format_exc()) raise ScriptError("\nInsufficient privileges to promote the server." "\nPossible issues:" "\n- A user has insufficient privileges" "\n- This client has insufficient privileges " "to become an IPA replica") except errors.LDAPError: logger.debug("%s", traceback.format_exc()) raise ScriptError("\nUnable to connect to LDAP server %s" % config.master_host_name) finally: if replman and replman.conn: replman.conn.unbind() if conn.isconnected(): conn.disconnect() # check connection if not options.skip_conncheck: if add_to_ipaservers: # use user's credentials when the server host is not ipaservers if installer._ccache is None: del os.environ['KRB5CCNAME'] else: os.environ['KRB5CCNAME'] = installer._ccache try: replica_conn_check(config.master_host_name, config.host_name, config.realm_name, options.setup_ca, 389, options.admin_password, principal=options.principal, ca_cert_file=cafile) finally: if add_to_ipaservers: os.environ['KRB5CCNAME'] = ccache installer._ca_enabled = ca_enabled installer._kra_enabled = kra_enabled installer._ca_file = cafile installer._fstore = fstore installer._sstore = sstore installer._config = config installer._add_to_ipaservers = add_to_ipaservers installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info installer._http_pkcs12_file = http_pkcs12_file installer._http_pkcs12_info = http_pkcs12_info installer._pkinit_pkcs12_file = pkinit_pkcs12_file installer._pkinit_pkcs12_info = pkinit_pkcs12_info
def create_ipa_conf(fstore, config, ca_enabled, master=None): """ Create /etc/ipa/default.conf master configuration :param fstore: sysrestore file store used for backup and restore of the server configuration :param config: replica config :param ca_enabled: True if the topology includes a CA :param master: if set, the xmlrpc_uri parameter will use the provided master instead of this host """ # Save client file on Domain Level 1 target_fname = paths.IPA_DEFAULT_CONF fstore.backup_file(target_fname) ipaconf = IPAChangeConf("IPA Replica Install") ipaconf.setOptionAssignment(" = ") ipaconf.setSectionNameDelimiters(("[", "]")) if master: xmlrpc_uri = 'https://{0}/ipa/xml'.format( ipautil.format_netloc(master)) else: xmlrpc_uri = 'https://{0}/ipa/xml'.format( ipautil.format_netloc(config.host_name)) ldapi_uri = 'ldapi://%2fvar%2frun%2fslapd-{0}.socket\n'.format( installutils.realm_to_serverid(config.realm_name)) # [global] section gopts = [ ipaconf.setOption('basedn', str(config.basedn)), ipaconf.setOption('host', config.host_name), ipaconf.setOption('realm', config.realm_name), ipaconf.setOption('domain', config.domain_name), ipaconf.setOption('xmlrpc_uri', xmlrpc_uri), ipaconf.setOption('ldap_uri', ldapi_uri), ipaconf.setOption('mode', 'production') ] if ca_enabled: gopts.extend([ ipaconf.setOption('enable_ra', 'True'), ipaconf.setOption('ra_plugin', 'dogtag'), ipaconf.setOption('dogtag_version', '10') ]) if not config.setup_ca: gopts.append(ipaconf.setOption('ca_host', config.ca_host_name)) else: gopts.extend([ ipaconf.setOption('enable_ra', 'False'), ipaconf.setOption('ra_plugin', 'None') ]) opts = [ ipaconf.setSection('global', gopts), { 'name': 'empty', 'type': 'empty' } ] ipaconf.newConf(target_fname, opts) # the new file must be readable for httpd # Also, umask applies when creating a new file but we want 0o644 here os.chmod(target_fname, 0o644)
def add_new_adtrust_agents(api, options): """ Find out IPA masters which are not part of the cn=adtrust agents and propose them to be added to the list :param api: API instance :param options: parsed CLI options """ potential_agents_cns = retrieve_potential_adtrust_agents(api) if potential_agents_cns: print("") print("WARNING: %d IPA masters are not yet able to serve " "information about users from trusted forests." % len(potential_agents_cns)) print("Installer can add them to the list of IPA masters " "allowed to access information about trusts.") print("If you choose to do so, you also need to restart " "LDAP service on those masters.") print("Refer to ipa-adtrust-install(1) man page for details.") print("") if options.unattended: print("Unattended mode was selected, installer will NOT " "add other IPA masters to the list of allowed to") print("access information about trusted forests!") return new_agents = [] for name in sorted(potential_agents_cns): if ipautil.user_input("IPA master [%s]?" % (name), default=False, allow_empty=False): new_agents.append(name) if new_agents: add_hosts_to_adtrust_agents(api, new_agents) # The method trust_enable_agent was added on API version 2.236 # Specifically request this version in the remote call kwargs = { u'version': u'2.236', u'enable_compat': options.enable_compat } failed_agents = [] for agent in new_agents: # Try to run the ipa-trust-enable-agent script on the agent # If the agent is too old and does not support this, # print a msg logger.info("Execute trust_enable_agent on remote server %s", agent) client = None try: xmlrpc_uri = 'https://{}/ipa/xml'.format( ipautil.format_netloc(agent)) remote_api = create_api(mode=None) remote_api.bootstrap(context='installer', confdir=paths.ETC_IPA, xmlrpc_uri=xmlrpc_uri, fallback=False) client = rpc.jsonclient(remote_api) client.finalize() client.connect() result = client.forward(u'trust_enable_agent', ipautil.fsdecode(agent), **kwargs) except errors.CommandError as e: logger.debug( "Remote server %s does not support agent enablement " "over RPC: %s", agent, e) failed_agents.append(agent) except (errors.PublicError, ConnectionRefusedError) as e: logger.debug( "Remote call to trust_enable_agent failed on server %s: " "%s", agent, e) failed_agents.append(agent) else: for message in result.get('messages'): logger.debug('%s', message['message']) if not int(result['result']): logger.debug( "ipa-trust-enable-agent returned non-zero exit code " " on server %s", agent) failed_agents.append(agent) finally: if client and client.isconnected(): client.disconnect() # if enablement failed on some agents, print a WARNING: if failed_agents: if options.enable_compat: print(""" WARNING: you MUST manually enable the Schema compatibility Plugin and """) print(""" WARNING: you MUST restart (both "ipactl restart" and "systemctl restart sssd") the following IPA masters in order to activate them to serve information about users from trusted forests: """) for x in failed_agents: print(x)
def __spawn_instance(self): """ Create and configure a new KRA instance using pkispawn. Creates a configuration file with IPA-specific parameters and passes it to the base class to call pkispawn """ # Create an empty and secured file (cfg_fd, cfg_file) = tempfile.mkstemp() os.close(cfg_fd) pent = pwd.getpwnam(self.service_user) os.chown(cfg_file, pent.pw_uid, pent.pw_gid) self.tmp_agent_db = tempfile.mkdtemp(prefix="tmp-", dir=paths.VAR_LIB_IPA) tmp_agent_pwd = ipautil.ipa_generate_password() # Create KRA configuration config = RawConfigParser() config.optionxform = str config.add_section("KRA") # Security Domain Authentication config.set("KRA", "pki_security_domain_https_port", "443") config.set("KRA", "pki_security_domain_password", self.admin_password) config.set("KRA", "pki_security_domain_user", self.admin_user) # issuing ca config.set("KRA", "pki_issuing_ca_uri", "https://%s" % ipautil.format_netloc(self.fqdn, 443)) # Server config.set("KRA", "pki_enable_proxy", "True") config.set("KRA", "pki_restart_configured_instance", "False") config.set("KRA", "pki_backup_keys", "True") config.set("KRA", "pki_backup_password", self.admin_password) # Client security database config.set("KRA", "pki_client_database_dir", self.tmp_agent_db) config.set("KRA", "pki_client_database_password", tmp_agent_pwd) config.set("KRA", "pki_client_database_purge", "True") config.set("KRA", "pki_client_pkcs12_password", self.admin_password) # Administrator config.set("KRA", "pki_admin_name", self.admin_user) config.set("KRA", "pki_admin_uid", self.admin_user) config.set("KRA", "pki_admin_email", "root@localhost") config.set("KRA", "pki_admin_password", self.admin_password) config.set("KRA", "pki_admin_nickname", "ipa-ca-agent") config.set("KRA", "pki_admin_subject_dn", str(DN(('cn', 'ipa-ca-agent'), self.subject_base))) config.set("KRA", "pki_import_admin_cert", "True") config.set("KRA", "pki_admin_cert_file", paths.ADMIN_CERT_PATH) config.set("KRA", "pki_client_admin_cert_p12", paths.DOGTAG_ADMIN_P12) # Directory server config.set("KRA", "pki_ds_ldap_port", "389") config.set("KRA", "pki_ds_password", self.dm_password) config.set("KRA", "pki_ds_base_dn", six.text_type(self.basedn)) config.set("KRA", "pki_ds_database", "ipaca") config.set("KRA", "pki_ds_create_new_db", "False") self._use_ldaps_during_spawn(config) # Certificate subject DNs config.set("KRA", "pki_subsystem_subject_dn", str(DN(('cn', 'CA Subsystem'), self.subject_base))) config.set("KRA", "pki_ssl_server_subject_dn", str(DN(('cn', self.fqdn), self.subject_base))) config.set("KRA", "pki_audit_signing_subject_dn", str(DN(('cn', 'KRA Audit'), self.subject_base))) config.set( "KRA", "pki_transport_subject_dn", str(DN(('cn', 'KRA Transport Certificate'), self.subject_base))) config.set( "KRA", "pki_storage_subject_dn", str(DN(('cn', 'KRA Storage Certificate'), self.subject_base))) # Certificate nicknames # Note that both the server certs and subsystem certs reuse # the ca certs. config.set("KRA", "pki_subsystem_nickname", "subsystemCert cert-pki-ca") config.set("KRA", "pki_ssl_server_nickname", "Server-Cert cert-pki-ca") config.set("KRA", "pki_audit_signing_nickname", "auditSigningCert cert-pki-kra") config.set("KRA", "pki_transport_nickname", "transportCert cert-pki-kra") config.set("KRA", "pki_storage_nickname", "storageCert cert-pki-kra") # Shared db settings # Needed because CA and KRA share the same database # We will use the dbuser created for the CA config.set("KRA", "pki_share_db", "True") config.set( "KRA", "pki_share_dbuser_dn", str(DN(('uid', 'pkidbuser'), ('ou', 'people'), ('o', 'ipaca')))) if not (os.path.isdir(paths.PKI_TOMCAT_ALIAS_DIR) and os.path.isfile(paths.PKI_TOMCAT_PASSWORD_CONF)): # generate pin which we know can be used for FIPS NSS database pki_pin = ipautil.ipa_generate_password() config.set("KRA", "pki_pin", pki_pin) else: pki_pin = None _p12_tmpfile_handle, p12_tmpfile_name = tempfile.mkstemp(dir=paths.TMP) if self.clone: krafile = self.pkcs12_info[0] shutil.copy(krafile, p12_tmpfile_name) pent = pwd.getpwnam(self.service_user) os.chown(p12_tmpfile_name, pent.pw_uid, pent.pw_gid) # Security domain registration config.set("KRA", "pki_security_domain_hostname", self.fqdn) config.set("KRA", "pki_security_domain_https_port", "443") config.set("KRA", "pki_security_domain_user", self.admin_user) config.set("KRA", "pki_security_domain_password", self.admin_password) # Clone config.set("KRA", "pki_clone", "True") config.set("KRA", "pki_clone_pkcs12_path", p12_tmpfile_name) config.set("KRA", "pki_clone_pkcs12_password", self.dm_password) config.set("KRA", "pki_clone_setup_replication", "False") config.set( "KRA", "pki_clone_uri", "https://%s" % ipautil.format_netloc(self.master_host, 443)) else: # the admin cert file is needed for the first instance of KRA cert = DogtagInstance.get_admin_cert(self) # First make sure that the directory exists parentdir = os.path.dirname(paths.ADMIN_CERT_PATH) if not os.path.exists(parentdir): os.makedirs(parentdir) with open(paths.ADMIN_CERT_PATH, "w") as admin_path: admin_path.write(cert) # Generate configuration file with open(cfg_file, "w") as f: config.write(f) try: DogtagInstance.spawn_instance(self, cfg_file, nolog_list=(self.dm_password, self.admin_password, pki_pin, tmp_agent_pwd)) finally: os.remove(p12_tmpfile_name) os.remove(cfg_file) shutil.move(paths.KRA_BACKUP_KEYS_P12, paths.KRACERT_P12) self.log.debug("completed creating KRA instance")
def __spawn_instance(self): """ Create and configure a new KRA instance using pkispawn. Creates a configuration file with IPA-specific parameters and passes it to the base class to call pkispawn """ # Create an empty and secured file (cfg_fd, cfg_file) = tempfile.mkstemp() os.close(cfg_fd) pent = pwd.getpwnam(self.service_user) os.chown(cfg_file, pent.pw_uid, pent.pw_gid) self.tmp_agent_db = tempfile.mkdtemp( prefix="tmp-", dir=paths.VAR_LIB_IPA) tmp_agent_pwd = ipautil.ipa_generate_password() # Create a temporary file for the admin PKCS #12 file (admin_p12_fd, admin_p12_file) = tempfile.mkstemp() os.close(admin_p12_fd) # Create KRA configuration config = RawConfigParser() config.optionxform = str config.add_section("KRA") # Security Domain Authentication config.set("KRA", "pki_security_domain_https_port", "443") config.set("KRA", "pki_security_domain_password", self.admin_password) config.set("KRA", "pki_security_domain_user", self.admin_user) # issuing ca config.set("KRA", "pki_issuing_ca_uri", "https://%s" % ipautil.format_netloc(self.fqdn, 443)) # Server config.set("KRA", "pki_enable_proxy", "True") config.set("KRA", "pki_restart_configured_instance", "False") config.set("KRA", "pki_backup_keys", "True") config.set("KRA", "pki_backup_password", self.admin_password) # Client security database config.set("KRA", "pki_client_database_dir", self.tmp_agent_db) config.set("KRA", "pki_client_database_password", tmp_agent_pwd) config.set("KRA", "pki_client_database_purge", "True") config.set("KRA", "pki_client_pkcs12_password", self.admin_password) # Administrator config.set("KRA", "pki_admin_name", self.admin_user) config.set("KRA", "pki_admin_uid", self.admin_user) config.set("KRA", "pki_admin_email", "root@localhost") config.set("KRA", "pki_admin_password", self.admin_password) config.set("KRA", "pki_admin_nickname", "ipa-ca-agent") config.set("KRA", "pki_admin_subject_dn", str(DN(('cn', 'ipa-ca-agent'), self.subject_base))) config.set("KRA", "pki_import_admin_cert", "False") config.set("KRA", "pki_client_admin_cert_p12", admin_p12_file) # Directory server config.set("KRA", "pki_ds_ldap_port", "389") config.set("KRA", "pki_ds_password", self.dm_password) config.set("KRA", "pki_ds_base_dn", six.text_type(self.basedn)) config.set("KRA", "pki_ds_database", "ipaca") config.set("KRA", "pki_ds_create_new_db", "False") self._use_ldaps_during_spawn(config) # Certificate subject DNs config.set("KRA", "pki_subsystem_subject_dn", str(DN(('cn', 'CA Subsystem'), self.subject_base))) config.set("KRA", "pki_sslserver_subject_dn", str(DN(('cn', self.fqdn), self.subject_base))) config.set("KRA", "pki_audit_signing_subject_dn", str(DN(('cn', 'KRA Audit'), self.subject_base))) config.set( "KRA", "pki_transport_subject_dn", str(DN(('cn', 'KRA Transport Certificate'), self.subject_base))) config.set( "KRA", "pki_storage_subject_dn", str(DN(('cn', 'KRA Storage Certificate'), self.subject_base))) # Certificate nicknames # Note that both the server certs and subsystem certs reuse # the ca certs. config.set("KRA", "pki_subsystem_nickname", "subsystemCert cert-pki-ca") config.set("KRA", "pki_sslserver_nickname", "Server-Cert cert-pki-ca") config.set("KRA", "pki_audit_signing_nickname", "auditSigningCert cert-pki-kra") config.set("KRA", "pki_transport_nickname", "transportCert cert-pki-kra") config.set("KRA", "pki_storage_nickname", "storageCert cert-pki-kra") # Shared db settings # Needed because CA and KRA share the same database # We will use the dbuser created for the CA config.set("KRA", "pki_share_db", "True") config.set( "KRA", "pki_share_dbuser_dn", str(DN(('uid', 'pkidbuser'), ('ou', 'people'), ('o', 'ipaca')))) if not (os.path.isdir(paths.PKI_TOMCAT_ALIAS_DIR) and os.path.isfile(paths.PKI_TOMCAT_PASSWORD_CONF)): # generate pin which we know can be used for FIPS NSS database pki_pin = ipautil.ipa_generate_password() config.set("KRA", "pki_pin", pki_pin) else: pki_pin = None _p12_tmpfile_handle, p12_tmpfile_name = tempfile.mkstemp(dir=paths.TMP) if self.clone: krafile = self.pkcs12_info[0] shutil.copy(krafile, p12_tmpfile_name) pent = pwd.getpwnam(self.service_user) os.chown(p12_tmpfile_name, pent.pw_uid, pent.pw_gid) # Security domain registration config.set("KRA", "pki_security_domain_hostname", self.fqdn) config.set("KRA", "pki_security_domain_https_port", "443") config.set("KRA", "pki_security_domain_user", self.admin_user) config.set("KRA", "pki_security_domain_password", self.admin_password) # Clone config.set("KRA", "pki_clone", "True") config.set("KRA", "pki_clone_pkcs12_path", p12_tmpfile_name) config.set("KRA", "pki_clone_pkcs12_password", self.dm_password) config.set("KRA", "pki_clone_setup_replication", "False") config.set( "KRA", "pki_clone_uri", "https://%s" % ipautil.format_netloc(self.master_host, 443)) else: # the admin cert file is needed for the first instance of KRA cert = self.get_admin_cert() # First make sure that the directory exists parentdir = os.path.dirname(paths.ADMIN_CERT_PATH) if not os.path.exists(parentdir): os.makedirs(parentdir) with open(paths.ADMIN_CERT_PATH, "wb") as admin_path: admin_path.write( base64.b64encode(cert.public_bytes(x509.Encoding.DER)) ) # Generate configuration file with open(cfg_file, "w") as f: config.write(f) try: DogtagInstance.spawn_instance( self, cfg_file, nolog_list=(self.dm_password, self.admin_password, pki_pin, tmp_agent_pwd) ) finally: os.remove(p12_tmpfile_name) os.remove(cfg_file) os.remove(admin_p12_file) shutil.move(paths.KRA_BACKUP_KEYS_P12, paths.KRACERT_P12) logger.debug("completed creating KRA instance")
def install_check(installer): options = installer filename = installer.replica_file tasks.check_selinux_status() client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if client_fstore.has_files(): sys.exit("IPA client is already configured on this system.\n" "Please uninstall it first before configuring the replica, " "using 'ipa-client-install --uninstall'.") sstore = sysrestore.StateFile(paths.SYSRESTORE) fstore = sysrestore.FileStore(paths.SYSRESTORE) # Check to see if httpd is already configured to listen on 443 if httpinstance.httpd_443_configured(): sys.exit("Aborting installation") check_dirsrv() if not options.no_ntp: try: ipaclient.ntpconf.check_timedate_services() except ipaclient.ntpconf.NTPConflictingService as e: print(("WARNING: conflicting time&date synchronization service '%s'" " will" % e.conflicting_service)) print("be disabled in favor of ntpd") print("") except ipaclient.ntpconf.NTPConfigurationError: pass # get the directory manager password dirman_password = options.password if not dirman_password: try: dirman_password = get_dirman_password() except KeyboardInterrupt: sys.exit(0) if dirman_password is None: sys.exit("Directory Manager password required") config = create_replica_config(dirman_password, filename, options) installer._top_dir = config.top_dir config.setup_ca = options.setup_ca config.setup_kra = options.setup_kra # Create the management framework config file # Note: We must do this before bootstraping and finalizing ipalib.api old_umask = os.umask(0o22) # must be readable for httpd try: fd = open(paths.IPA_DEFAULT_CONF, "w") fd.write("[global]\n") fd.write("host=%s\n" % config.host_name) fd.write("basedn=%s\n" % str(ipautil.realm_to_suffix(config.realm_name))) fd.write("realm=%s\n" % config.realm_name) fd.write("domain=%s\n" % config.domain_name) fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % ipautil.format_netloc(config.host_name)) fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % installutils.realm_to_serverid(config.realm_name)) if ipautil.file_exists(config.dir + "/cacert.p12"): fd.write("enable_ra=True\n") fd.write("ra_plugin=dogtag\n") fd.write("dogtag_version=%s\n" % dogtag.install_constants.DOGTAG_VERSION) else: fd.write("enable_ra=False\n") fd.write("ra_plugin=none\n") fd.write("mode=production\n") fd.close() finally: os.umask(old_umask) api.bootstrap(in_server=True, context='installer') api.finalize() installutils.verify_fqdn(config.master_host_name, options.no_host_dns) cafile = config.dir + "/ca.crt" if not ipautil.file_exists(cafile): raise RuntimeError("CA cert file is not available. Please run " "ipa-replica-prepare to create a new replica file.") ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name) remote_api = create_api(mode=None) remote_api.bootstrap(in_server=True, context='installer', ldap_uri=ldapuri) remote_api.finalize() conn = remote_api.Backend.ldap2 replman = None try: # Try out the password conn.connect(bind_dn=DIRMAN_DN, bind_pw=config.dirman_password, tls_cacertfile=cafile) replman = ReplicationManager(config.realm_name, config.master_host_name, config.dirman_password) # Check that we don't already have a replication agreement if replman.get_replication_agreement(config.host_name): root_logger.info('Error: A replication agreement for this ' 'host already exists.') print('A replication agreement for this host already exists. ' 'It needs to be removed.') print("Run this on the master that generated the info file:") print((" %% ipa-replica-manage del %s --force" % config.host_name)) sys.exit(3) # Detect the current domain level try: current = remote_api.Command['domainlevel_get']()['result'] except errors.NotFound: # If we're joining an older master, domain entry is not # available current = 0 # Detect if current level is out of supported range # for this IPA version under_lower_bound = current < constants.MIN_DOMAIN_LEVEL above_upper_bound = current > constants.MAX_DOMAIN_LEVEL if under_lower_bound or above_upper_bound: message = ("This version of FreeIPA does not support " "the Domain Level which is currently set for " "this domain. The Domain Level needs to be " "raised before installing a replica with " "this version is allowed to be installed " "within this domain.") root_logger.error(message) print(message) sys.exit(3) # Check pre-existing host entry try: entry = conn.find_entries(u'fqdn=%s' % config.host_name, ['fqdn'], DN(api.env.container_host, api.env.basedn)) except errors.NotFound: pass else: root_logger.info('Error: Host %s already exists on the master ' 'server.' % config.host_name) print(('The host %s already exists on the master server.' % config.host_name)) print("You should remove it before proceeding:") print(" %% ipa host-del %s" % config.host_name) sys.exit(3) dns_masters = remote_api.Object['dnsrecord'].get_dns_masters() if dns_masters: if not options.no_host_dns: master = config.master_host_name root_logger.debug('Check forward/reverse DNS resolution') resolution_ok = ( check_dns_resolution(master, dns_masters) and check_dns_resolution(config.host_name, dns_masters)) if not resolution_ok and installer.interactive: if not ipautil.user_input("Continue?", False): sys.exit(0) else: root_logger.debug('No IPA DNS servers, ' 'skipping forward/reverse resolution check') if options.setup_ca: options.realm_name = config.realm_name options.host_name = config.host_name options.subject = config.subject_base ca.install_check(False, config, options) if config.setup_kra: try: kra.install_check(remote_api, config, options) except RuntimeError as e: print(str(e)) sys.exit(1) except errors.ACIError: sys.exit("\nThe password provided is incorrect for LDAP server " "%s" % config.master_host_name) except errors.LDAPError: sys.exit("\nUnable to connect to LDAP server %s" % config.master_host_name) finally: if replman and replman.conn: replman.conn.unbind() if conn.isconnected(): conn.disconnect() if options.setup_dns: dns.install_check(False, True, options, config.host_name) config.ips = dns.ip_addresses else: config.ips = installutils.get_server_ip_address( config.host_name, not installer.interactive, False, options.ip_addresses) # installer needs to update hosts file when DNS subsystem will be # installed or custom addresses are used if options.setup_dns or options.ip_addresses: installer._update_hosts_file = True # check connection if not options.skip_conncheck: replica_conn_check( config.master_host_name, config.host_name, config.realm_name, options.setup_ca, config.ca_ds_port, options.admin_password) installer._remote_api = remote_api installer._fstore = fstore installer._sstore = sstore installer._config = config
def setup(self): self.ldapuri = 'ldap://%s' % ipautil.format_netloc(api.env.host) self.conn = ldap2(api, ldap_uri=self.ldapuri) self.conn.connect() self.entry = self.conn.make_entry(self.dn1, cn=self.cn1)
def install(options): global dirsrv_pkcs12_info global http_pkcs12_info global pkinit_pkcs12_info global external_cert_file global external_ca_file global http_ca_cert realm_name = options.realm_name domain_name = options.domain_name dm_password = options.dm_password master_password = options.master_password admin_password = options.admin_password host_name = options.host_name ip_addresses = options.ip_address setup_ca = options.setup_ca setup_kra = options.setup_kra global ds global installation_cleanup # Installation has started. No IPA sysrestore items are restored in case of # failure to enable root cause investigation installation_cleanup = False # Configuration for ipalib, we will bootstrap and finalize later, after # we are sure we have the configuration file ready. cfg = dict( context='installer', in_server=True, debug=options.debug ) # Figure out what external CA step we're in. See cainstance.py for more # info on the 3 states. if options.external_cert_files: external = 2 elif options.external_ca: external = 1 else: external = 0 # Create the management framework config file and finalize api target_fname = paths.IPA_DEFAULT_CONF fd = open(target_fname, "w") fd.write("[global]\n") fd.write("host=%s\n" % host_name) fd.write("basedn=%s\n" % ipautil.realm_to_suffix(realm_name)) fd.write("realm=%s\n" % realm_name) fd.write("domain=%s\n" % domain_name) fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % format_netloc(host_name)) fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % installutils.realm_to_serverid(realm_name)) if setup_ca: fd.write("enable_ra=True\n") fd.write("ra_plugin=dogtag\n") fd.write("dogtag_version=%s\n" % dogtag.install_constants.DOGTAG_VERSION) else: fd.write("enable_ra=False\n") fd.write("ra_plugin=none\n") fd.write("enable_kra=%s\n" % setup_kra) fd.write("mode=production\n") fd.close() # Must be readable for everyone os.chmod(target_fname, 0644) if not options.unattended: print "" print "The following operations may take some minutes to complete." print "Please wait until the prompt is returned." print "" system_hostname = get_fqdn() if host_name != system_hostname: root_logger.debug("Chosen hostname (%s) differs from system hostname " "(%s) - change it" % (host_name, system_hostname)) # configure /etc/sysconfig/network to contain the custom hostname tasks.backup_and_replace_hostname(fstore, sstore, host_name) # update `api.env.ca_host` to correct hostname # https://fedorahosted.org/freeipa/ticket/4936 api.env.ca_host = host_name api.bootstrap(**cfg) if setup_ca: # ensure profile backend is available import ipaserver.plugins.dogtag api.finalize() # Create DS user/group if it doesn't exist yet dsinstance.create_ds_user() # Create a directory server instance if external != 2: # Configure ntpd if options.conf_ntp: ipaclient.ntpconf.force_ntpd(sstore) ntp = ntpinstance.NTPInstance(fstore) if not ntp.is_configured(): ntp.create_instance() if options.dirsrv_cert_files: ds = dsinstance.DsInstance(fstore=fstore, domainlevel=options.domainlevel) ds.create_instance(realm_name, host_name, domain_name, dm_password, dirsrv_pkcs12_info, idstart=options.idstart, idmax=options.idmax, subject_base=options.subject, hbac_allow=not options.hbac_allow) else: ds = dsinstance.DsInstance(fstore=fstore, domainlevel=options.domainlevel) ds.create_instance(realm_name, host_name, domain_name, dm_password, idstart=options.idstart, idmax=options.idmax, subject_base=options.subject, hbac_allow=not options.hbac_allow) else: ds = dsinstance.DsInstance(fstore=fstore, domainlevel=options.domainlevel) ds.init_info( realm_name, host_name, domain_name, dm_password, options.subject, 1101, 1100, None) if setup_ca: ca = cainstance.CAInstance(realm_name, certs.NSS_DIR, dogtag_constants=dogtag.install_constants) if external == 0: ca.configure_instance( host_name, domain_name, dm_password, dm_password, subject_base=options.subject, ca_signing_algorithm=options.ca_signing_algorithm) elif external == 1: # stage 1 of external CA installation options.realm_name = realm_name options.domain_name = domain_name options.master_password = master_password options.dm_password = dm_password options.admin_password = admin_password options.host_name = host_name options.unattended = True options.forwarders = dns.dns_forwarders options.reverse_zones = dns.reverse_zones write_cache(vars(options)) ca.configure_instance( host_name, domain_name, dm_password, dm_password, csr_file=paths.ROOT_IPA_CSR, subject_base=options.subject, ca_signing_algorithm=options.ca_signing_algorithm, ca_type=options.external_ca_type) else: # stage 2 of external CA installation ca.configure_instance( host_name, domain_name, dm_password, dm_password, cert_file=external_cert_file.name, cert_chain_file=external_ca_file.name, subject_base=options.subject, ca_signing_algorithm=options.ca_signing_algorithm) # Now put the CA cert where other instances exepct it ca.publish_ca_cert(CACERT) else: # Put the CA cert where other instances expect it x509.write_certificate(http_ca_cert, CACERT) os.chmod(CACERT, 0444) # we now need to enable ssl on the ds ds.enable_ssl() if setup_ca: # We need to ldap_enable the CA now that DS is up and running ca.ldap_enable('CA', host_name, dm_password, ipautil.realm_to_suffix(realm_name), ['caRenewalMaster']) # This is done within stopped_service context, which restarts CA ca.enable_client_auth_to_db(ca.dogtag_constants.CS_CFG_PATH) krb = krbinstance.KrbInstance(fstore) if options.pkinit_cert_files: krb.create_instance(realm_name, host_name, domain_name, dm_password, master_password, setup_pkinit=options.setup_pkinit, pkcs12_info=pkinit_pkcs12_info, subject_base=options.subject) else: krb.create_instance(realm_name, host_name, domain_name, dm_password, master_password, setup_pkinit=options.setup_pkinit, subject_base=options.subject) # The DS instance is created before the keytab, add the SSL cert we # generated ds.add_cert_to_service() memcache = memcacheinstance.MemcacheInstance() memcache.create_instance('MEMCACHE', host_name, dm_password, ipautil.realm_to_suffix(realm_name)) otpd = otpdinstance.OtpdInstance() otpd.create_instance('OTPD', host_name, dm_password, ipautil.realm_to_suffix(realm_name)) # Create a HTTP instance http = httpinstance.HTTPInstance(fstore) if options.http_cert_files: http.create_instance( realm_name, host_name, domain_name, dm_password, pkcs12_info=http_pkcs12_info, subject_base=options.subject, auto_redirect=options.ui_redirect, ca_is_configured=setup_ca) else: http.create_instance( realm_name, host_name, domain_name, dm_password, subject_base=options.subject, auto_redirect=options.ui_redirect, ca_is_configured=setup_ca) tasks.restore_context(paths.CACHE_IPA_SESSIONS) # Export full CA chain ca_db = certs.CertDB(realm_name) os.chmod(CACERT, 0644) ca_db.publish_ca_cert(CACERT) set_subject_in_config(realm_name, dm_password, ipautil.realm_to_suffix(realm_name), options.subject) # Apply any LDAP updates. Needs to be done after the configuration file # is created service.print_msg("Applying LDAP updates") ds.apply_updates() # Restart ds and krb after configurations have been changed service.print_msg("Restarting the directory server") ds.restart() service.print_msg("Restarting the KDC") krb.restart() if setup_ca: service.print_msg("Restarting the certificate server") ca.restart(dogtag.configured_constants().PKI_INSTANCE_NAME) service.print_msg("Importing certificate profiles") cainstance.import_included_profiles() if options.setup_dns: api.Backend.ldap2.connect(autobind=True) dns.install(False, False, options) else: # Create a BIND instance bind = bindinstance.BindInstance(fstore, dm_password) bind.setup(host_name, ip_addresses, realm_name, domain_name, (), options.conf_ntp, (), zonemgr=options.zonemgr, ca_configured=setup_ca, no_dnssec_validation=options.no_dnssec_validation) bind.create_sample_bind_zone() # Restart httpd to pick up the new IPA configuration service.print_msg("Restarting the web server") http.restart() if setup_kra: kra.install(None, options, dm_password) # Set the admin user kerberos password ds.change_admin_password(admin_password) # Call client install script try: args = [paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended", "--domain", domain_name, "--server", host_name, "--realm", realm_name, "--hostname", host_name] if not options.create_sshfp: args.append("--no-dns-sshfp") if options.trust_sshfp: args.append("--ssh-trust-dns") if not options.conf_ssh: args.append("--no-ssh") if not options.conf_sshd: args.append("--no-sshd") if options.mkhomedir: args.append("--mkhomedir") run(args) except Exception, e: sys.exit("Configuration of client side components failed!\n" "ipa-client-install returned: " + str(e))
def toLDAPURL(self): return "ldap://%s/" % format_netloc(self.host, self.port)
def __spawn_instance(self): """ Create and configure a new KRA instance using pkispawn. Creates a configuration file with IPA-specific parameters and passes it to the base class to call pkispawn """ # Create an empty and secured file (cfg_fd, cfg_file) = tempfile.mkstemp() os.close(cfg_fd) pent = pwd.getpwnam(PKI_USER) os.chown(cfg_file, pent.pw_uid, pent.pw_gid) # Create KRA configuration config = ConfigParser.ConfigParser() config.optionxform = str config.add_section("KRA") # Security Domain Authentication config.set("KRA", "pki_security_domain_https_port", "443") config.set("KRA", "pki_security_domain_password", self.admin_password) config.set("KRA", "pki_security_domain_user", "admin") # issuing ca config.set("KRA", "pki_issuing_ca_uri", "https://%s" % ipautil.format_netloc(self.fqdn, 443)) # Server config.set("KRA", "pki_enable_proxy", "True") config.set("KRA", "pki_restart_configured_instance", "False") config.set("KRA", "pki_backup_keys", "True") config.set("KRA", "pki_backup_password", self.admin_password) # Client security database config.set("KRA", "pki_client_database_dir", self.agent_db) config.set("KRA", "pki_client_database_password", self.admin_password) config.set("KRA", "pki_client_database_purge", "False") config.set("KRA", "pki_client_pkcs12_password", self.admin_password) # Administrator config.set("KRA", "pki_admin_name", "admin") config.set("KRA", "pki_admin_uid", "admin") config.set("KRA", "pki_admin_email", "root@localhost") config.set("KRA", "pki_admin_password", self.admin_password) config.set("KRA", "pki_admin_nickname", "ipa-ca-agent") config.set("KRA", "pki_admin_subject_dn", str(DN(('cn', 'ipa-ca-agent'), self.subject_base))) config.set("KRA", "pki_import_admin_cert", "True") config.set("KRA", "pki_admin_cert_file", paths.ADMIN_CERT_PATH) config.set("KRA", "pki_client_admin_cert_p12", paths.DOGTAG_ADMIN_P12) # Directory server config.set("KRA", "pki_ds_ldap_port", str(self.ds_port)) config.set("KRA", "pki_ds_password", self.dm_password) config.set("KRA", "pki_ds_base_dn", self.basedn) config.set("KRA", "pki_ds_database", "ipaca") config.set("KRA", "pki_ds_create_new_db", "False") # Certificate subject DNs config.set("KRA", "pki_subsystem_subject_dn", str(DN(('cn', 'CA Subsystem'), self.subject_base))) config.set("KRA", "pki_ssl_server_subject_dn", str(DN(('cn', self.fqdn), self.subject_base))) config.set("KRA", "pki_audit_signing_subject_dn", str(DN(('cn', 'KRA Audit'), self.subject_base))) config.set( "KRA", "pki_transport_subject_dn", str(DN(('cn', 'KRA Transport Certificate'), self.subject_base))) config.set( "KRA", "pki_storage_subject_dn", str(DN(('cn', 'KRA Storage Certificate'), self.subject_base))) # Certificate nicknames # Note that both the server certs and subsystem certs reuse # the ca certs. config.set("KRA", "pki_subsystem_nickname", "subsystemCert cert-pki-ca") config.set("KRA", "pki_ssl_server_nickname", "Server-Cert cert-pki-ca") config.set("KRA", "pki_audit_signing_nickname", "auditSigningCert cert-pki-kra") config.set("KRA", "pki_transport_nickname", "transportCert cert-pki-kra") config.set("KRA", "pki_storage_nickname", "storageCert cert-pki-kra") # Shared db settings # Needed because CA and KRA share the same database # We will use the dbuser created for the CA config.set("KRA", "pki_share_db", "True") config.set( "KRA", "pki_share_dbuser_dn", str(DN(('uid', 'pkidbuser'), ('ou', 'people'), ('o', 'ipaca')))) _p12_tmpfile_handle, p12_tmpfile_name = tempfile.mkstemp(dir=paths.TMP) if self.clone: krafile = self.pkcs12_info[0] shutil.copy(krafile, p12_tmpfile_name) pent = pwd.getpwnam(PKI_USER) os.chown(p12_tmpfile_name, pent.pw_uid, pent.pw_gid) # create admin cert file if it does not exist cert = DogtagInstance.get_admin_cert(self) with open(paths.ADMIN_CERT_PATH, "w") as admin_path: admin_path.write(cert) # Security domain registration config.set("KRA", "pki_security_domain_hostname", self.master_host) config.set("KRA", "pki_security_domain_https_port", "443") config.set("KRA", "pki_security_domain_user", "admin") config.set("KRA", "pki_security_domain_password", self.admin_password) # Clone config.set("KRA", "pki_clone", "True") config.set("KRA", "pki_clone_pkcs12_path", p12_tmpfile_name) config.set("KRA", "pki_clone_pkcs12_password", self.dm_password) config.set("KRA", "pki_clone_setup_replication", "False") config.set( "KRA", "pki_clone_uri", "https://%s" % ipautil.format_netloc(self.master_host, 443)) # Generate configuration file with open(cfg_file, "wb") as f: config.write(f) try: DogtagInstance.spawn_instance(self, cfg_file) finally: os.remove(p12_tmpfile_name) os.remove(cfg_file) shutil.move(paths.KRA_BACKUP_KEYS_P12, paths.KRACERT_P12) self.log.debug("completed creating KRA instance")
config.setup_ca = options.setup_ca config.setup_kra = options.setup_kra # Create the management framework config file # Note: We must do this before bootstraping and finalizing ipalib.api old_umask = os.umask(022) # must be readable for httpd try: fd = open(paths.IPA_DEFAULT_CONF, "w") fd.write("[global]\n") fd.write("host=%s\n" % config.host_name) fd.write("basedn=%s\n" % str(ipautil.realm_to_suffix(config.realm_name))) fd.write("realm=%s\n" % config.realm_name) fd.write("domain=%s\n" % config.domain_name) fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % ipautil.format_netloc(config.host_name)) fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % installutils.realm_to_serverid(config.realm_name)) if ipautil.file_exists(config.dir + "/cacert.p12"): fd.write("enable_ra=True\n") fd.write("ra_plugin=dogtag\n") fd.write("dogtag_version=%s\n" % dogtag.install_constants.DOGTAG_VERSION) else: fd.write("enable_ra=False\n") fd.write("ra_plugin=none\n") fd.write("mode=production\n") fd.close() finally: os.umask(old_umask)
def install_check(installer): options = installer dirsrv_pkcs12_file = installer._dirsrv_pkcs12_file http_pkcs12_file = installer._http_pkcs12_file pkinit_pkcs12_file = installer._pkinit_pkcs12_file dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info http_pkcs12_info = installer._http_pkcs12_info pkinit_pkcs12_info = installer._pkinit_pkcs12_info external_cert_file = installer._external_cert_file external_ca_file = installer._external_ca_file http_ca_cert = installer._ca_cert if tasks.is_fips_enabled(): raise RuntimeError( "Installing IPA server in FIPS mode is not supported") tasks.check_selinux_status() if options.master_password: msg = ("WARNING:\noption '-P/--master-password' is deprecated. " "KDC master password of sufficient strength is autogenerated " "during IPA server installation and should not be set " "manually.") print(textwrap.fill(msg, width=79, replace_whitespace=False)) installer._installation_cleanup = True print("\nThe log file for this installation can be found in " "/var/log/ipaserver-install.log") if (not options.external_ca and not options.external_cert_files and is_ipa_configured()): installer._installation_cleanup = False raise ScriptError( "IPA server is already configured on this system.\n" "If you want to reinstall the IPA server, please uninstall " "it first using 'ipa-server-install --uninstall'.") client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if client_fstore.has_files(): installer._installation_cleanup = False raise ScriptError( "IPA client is already configured on this system.\n" "Please uninstall it before configuring the IPA server, " "using 'ipa-client-install --uninstall'") fstore = sysrestore.FileStore(SYSRESTORE_DIR_PATH) sstore = sysrestore.StateFile(SYSRESTORE_DIR_PATH) # This will override any settings passed in on the cmdline if ipautil.file_exists(paths.ROOT_IPA_CACHE): if options.dm_password is not None: dm_password = options.dm_password else: dm_password = read_password("Directory Manager", confirm=False) if dm_password is None: raise ScriptError("Directory Manager password required") try: cache_vars = read_cache(dm_password) options.__dict__.update(cache_vars) if cache_vars.get('external_ca', False): options.external_ca = False options.interactive = False except Exception as e: raise ScriptError("Cannot process the cache file: %s" % str(e)) # We only set up the CA if the PKCS#12 options are not given. if options.dirsrv_cert_files: setup_ca = False else: setup_ca = True options.setup_ca = setup_ca # first instance of KRA must be installed by ipa-kra-install options.setup_kra = False print("=======================================" "=======================================") print("This program will set up the FreeIPA Server.") print("") print("This includes:") if setup_ca: print(" * Configure a stand-alone CA (dogtag) for certificate " "management") if not options.no_ntp: print(" * Configure the Network Time Daemon (ntpd)") print(" * Create and configure an instance of Directory Server") print(" * Create and configure a Kerberos Key Distribution Center (KDC)") print(" * Configure Apache (httpd)") if options.setup_dns: print(" * Configure DNS (bind)") if not options.no_pkinit: print(" * Configure the KDC to enable PKINIT") if options.no_ntp: print("") print("Excluded by options:") print(" * Configure the Network Time Daemon (ntpd)") if installer.interactive: print("") print("To accept the default shown in brackets, press the Enter key.") print("") if not options.external_cert_files: # Make sure the 389-ds ports are available check_dirsrv(not installer.interactive) if not options.no_ntp: try: ipaclient.install.ntpconf.check_timedate_services() except ipaclient.install.ntpconf.NTPConflictingService as e: print(("WARNING: conflicting time&date synchronization service '%s'" " will be disabled" % e.conflicting_service)) print("in favor of ntpd") print("") except ipaclient.install.ntpconf.NTPConfigurationError: pass # Check to see if httpd is already configured to listen on 443 if httpinstance.httpd_443_configured(): raise ScriptError("Aborting installation") if not options.setup_dns and installer.interactive: if ipautil.user_input("Do you want to configure integrated DNS " "(BIND)?", False): options.setup_dns = True print("") # check bind packages are installed if options.setup_dns: # Don't require an external DNS to say who we are if we are # setting up a local DNS server. options.no_host_dns = True # check the hostname is correctly configured, it must be as the kldap # utilities just use the hostname as returned by getaddrinfo to set # up some of the standard entries if options.host_name: host_default = options.host_name else: host_default = get_fqdn() try: if not installer.interactive or options.host_name: verify_fqdn(host_default, options.no_host_dns) host_name = host_default else: host_name = read_host_name(host_default, options.no_host_dns) except BadHostError as e: raise ScriptError(e) host_name = host_name.lower() root_logger.debug("will use host_name: %s\n" % host_name) if not options.domain_name: domain_name = read_domain_name(host_name[host_name.find(".")+1:], not installer.interactive) root_logger.debug("read domain_name: %s\n" % domain_name) try: validate_domain_name(domain_name) except ValueError as e: raise ScriptError("Invalid domain name: %s" % unicode(e)) else: domain_name = options.domain_name domain_name = domain_name.lower() if not options.realm_name: realm_name = read_realm_name(domain_name, not installer.interactive) root_logger.debug("read realm_name: %s\n" % realm_name) else: realm_name = options.realm_name.upper() if not options.subject: options.subject = DN(('O', realm_name)) if options.http_cert_files: if options.http_pin is None: options.http_pin = installutils.read_password( "Enter Apache Server private key unlock", confirm=False, validate=False, retry=False) if options.http_pin is None: raise ScriptError( "Apache Server private key unlock password required") http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12( cert_files=options.http_cert_files, key_password=options.http_pin, key_nickname=options.http_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) http_pkcs12_info = (http_pkcs12_file.name, http_pin) if options.dirsrv_cert_files: if options.dirsrv_pin is None: options.dirsrv_pin = read_password( "Enter Directory Server private key unlock", confirm=False, validate=False, retry=False) if options.dirsrv_pin is None: raise ScriptError( "Directory Server private key unlock password required") dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12( cert_files=options.dirsrv_cert_files, key_password=options.dirsrv_pin, key_nickname=options.dirsrv_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) if options.pkinit_cert_files: if not options.no_pkinit: raise ScriptError("Cannot create KDC PKINIT certificate and use " "provided external PKINIT certificate at the " "same time. Please choose one of them.") if options.pkinit_pin is None: options.pkinit_pin = read_password( "Enter Kerberos KDC private key unlock", confirm=False, validate=False, retry=False) if options.pkinit_pin is None: raise ScriptError( "Kerberos KDC private key unlock password required") pkinit_pkcs12_file, pkinit_pin, _pkinit_ca_cert = load_pkcs12( cert_files=options.pkinit_cert_files, key_password=options.pkinit_pin, key_nickname=options.pkinit_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin) if (options.http_cert_files and options.dirsrv_cert_files and http_ca_cert != dirsrv_ca_cert): raise ScriptError( "Apache Server SSL certificate and Directory Server SSL " "certificate are not signed by the same CA certificate") if not options.dm_password: dm_password = read_dm_password() if dm_password is None: raise ScriptError("Directory Manager password required") else: dm_password = options.dm_password if not options.master_password: master_password = ipa_generate_password() else: master_password = options.master_password if not options.admin_password: admin_password = read_admin_password() if admin_password is None: raise ScriptError("IPA admin password required") else: admin_password = options.admin_password # Configuration for ipalib, we will bootstrap and finalize later, after # we are sure we have the configuration file ready. cfg = dict( context='installer', confdir=paths.ETC_IPA, in_server=True, # make sure host name specified by user is used instead of default host=host_name, ) if setup_ca: # we have an IPA-integrated CA cfg['ca_host'] = host_name # Create the management framework config file and finalize api target_fname = paths.IPA_DEFAULT_CONF fd = open(target_fname, "w") fd.write("[global]\n") fd.write("host=%s\n" % host_name) fd.write("basedn=%s\n" % ipautil.realm_to_suffix(realm_name)) fd.write("realm=%s\n" % realm_name) fd.write("domain=%s\n" % domain_name) fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % format_netloc(host_name)) fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % installutils.realm_to_serverid(realm_name)) if setup_ca: fd.write("enable_ra=True\n") fd.write("ra_plugin=dogtag\n") fd.write("dogtag_version=10\n") else: fd.write("enable_ra=False\n") fd.write("ra_plugin=none\n") fd.write("mode=production\n") fd.close() # Must be readable for everyone os.chmod(target_fname, 0o644) api.bootstrap(**cfg) api.finalize() if setup_ca: ca.install_check(False, None, options) kra.install_check(api, None, options) if options.setup_dns: dns.install_check(False, api, False, options, host_name) ip_addresses = dns.ip_addresses else: ip_addresses = get_server_ip_address(host_name, not installer.interactive, False, options.ip_addresses) # check addresses here, dns module is doing own check network_ip_address_warning(ip_addresses) broadcast_ip_address_warning(ip_addresses) # installer needs to update hosts file when DNS subsystem will be # installed or custom addresses are used if options.ip_addresses or options.setup_dns: installer._update_hosts_file = True print() print("The IPA Master Server will be configured with:") print("Hostname: %s" % host_name) print("IP address(es): %s" % ", ".join(str(ip) for ip in ip_addresses)) print("Domain name: %s" % domain_name) print("Realm name: %s" % realm_name) print() if options.setup_dns: print("BIND DNS server will be configured to serve IPA domain with:") print("Forwarders: %s" % ( "No forwarders" if not options.forwarders else ", ".join([str(ip) for ip in options.forwarders]) )) print('Forward policy: %s' % options.forward_policy) print("Reverse zone(s): %s" % ( "No reverse zone" if options.no_reverse or not dns.reverse_zones else ", ".join(str(rz) for rz in dns.reverse_zones) )) print() # If domain name and realm does not match, IPA server will not be able # to estabilish trust with Active Directory. Print big fat warning. realm_not_matching_domain = (domain_name.upper() != realm_name) if realm_not_matching_domain: print("WARNING: Realm name does not match the domain name.\n" "You will not be able to estabilish trusts with Active " "Directory unless\nthe realm name of the IPA server matches " "its domain name.\n\n") if installer.interactive and not user_input( "Continue to configure the system with these values?", False): raise ScriptError("Installation aborted") options.realm_name = realm_name options.domain_name = domain_name options.dm_password = dm_password options.master_password = master_password options.admin_password = admin_password options._host_name_overridden = bool(options.host_name) options.host_name = host_name options.ip_addresses = ip_addresses installer._fstore = fstore installer._sstore = sstore installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file installer._http_pkcs12_file = http_pkcs12_file installer._pkinit_pkcs12_file = pkinit_pkcs12_file installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info installer._http_pkcs12_info = http_pkcs12_info installer._pkinit_pkcs12_info = pkinit_pkcs12_info installer._external_cert_file = external_cert_file installer._external_ca_file = external_ca_file installer._ca_cert = http_ca_cert
def setup(self): self.conn = None self.ldapuri = 'ldap://%s' % ipautil.format_netloc(api.env.host) self.dn = DN( ('krbprincipalname', 'ldap/%s@%s' % (api.env.host, api.env.realm)), ('cn', 'services'), ('cn', 'accounts'), api.env.basedn)
def setUp(self): self.ldapuri = 'ldap://%s' % ipautil.format_netloc(api.env.host) self.conn = ldap2(shared_instance=False, ldap_uri=self.ldapuri) self.conn.connect() self.entry = self.conn.make_entry(self.dn1, cn=self.cn1)
def install_check(installer): options = installer dirsrv_pkcs12_file = installer._dirsrv_pkcs12_file http_pkcs12_file = installer._http_pkcs12_file pkinit_pkcs12_file = installer._pkinit_pkcs12_file dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info http_pkcs12_info = installer._http_pkcs12_info pkinit_pkcs12_info = installer._pkinit_pkcs12_info external_cert_file = installer._external_cert_file external_ca_file = installer._external_ca_file http_ca_cert = installer._ca_cert dirsrv_ca_cert = None pkinit_ca_cert = None tasks.check_ipv6_stack_enabled() tasks.check_selinux_status() check_ldap_conf() mask_str = validate_mask() if mask_str: print("Unexpected system mask: %s, expected 0022" % mask_str) if installer.interactive: if not user_input("Do you want to continue anyway?", True): raise ScriptError( "Unexpected system mask: %s" % mask_str) else: raise ScriptError("Unexpected system mask: %s" % mask_str) if options.master_password: msg = ("WARNING:\noption '-P/--master-password' is deprecated. " "KDC master password of sufficient strength is autogenerated " "during IPA server installation and should not be set " "manually.") print(textwrap.fill(msg, width=79, replace_whitespace=False)) installer._installation_cleanup = True print("\nThe log file for this installation can be found in " "/var/log/ipaserver-install.log") if (not options.external_ca and not options.external_cert_files and is_ipa_configured()): installer._installation_cleanup = False raise ScriptError( "IPA server is already configured on this system.\n" "If you want to reinstall the IPA server, please uninstall " "it first using 'ipa-server-install --uninstall'.") client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if client_fstore.has_files(): installer._installation_cleanup = False raise ScriptError( "IPA client is already configured on this system.\n" "Please uninstall it before configuring the IPA server, " "using 'ipa-client-install --uninstall'") fstore = sysrestore.FileStore(SYSRESTORE_DIR_PATH) sstore = sysrestore.StateFile(SYSRESTORE_DIR_PATH) # This will override any settings passed in on the cmdline if os.path.isfile(paths.ROOT_IPA_CACHE): if options.dm_password is not None: dm_password = options.dm_password else: dm_password = read_password("Directory Manager", confirm=False) if dm_password is None: raise ScriptError("Directory Manager password required") try: cache_vars = read_cache(dm_password) options.__dict__.update(cache_vars) if cache_vars.get('external_ca', False): options.external_ca = False options.interactive = False except Exception as e: raise ScriptError("Cannot process the cache file: %s" % str(e)) # We only set up the CA if the PKCS#12 options are not given. if options.dirsrv_cert_files: setup_ca = False else: setup_ca = True options.setup_ca = setup_ca if not setup_ca and options.ca_subject: raise ScriptError( "--ca-subject cannot be used with CA-less installation") if not setup_ca and options.subject_base: raise ScriptError( "--subject-base cannot be used with CA-less installation") if not setup_ca and options.setup_kra: raise ScriptError( "--setup-kra cannot be used with CA-less installation") print("=======================================" "=======================================") print("This program will set up the FreeIPA Server.") print("Version {}".format(version.VERSION)) print("") print("This includes:") if setup_ca: print(" * Configure a stand-alone CA (dogtag) for certificate " "management") if not options.no_ntp: print(" * Configure the NTP client (chronyd)") print(" * Create and configure an instance of Directory Server") print(" * Create and configure a Kerberos Key Distribution Center (KDC)") print(" * Configure Apache (httpd)") if options.setup_kra: print(" * Configure KRA (dogtag) for secret management") if options.setup_dns: print(" * Configure DNS (bind)") if options.setup_adtrust: print(" * Configure Samba (smb) and winbind for managing AD trusts") if not options.no_pkinit: print(" * Configure the KDC to enable PKINIT") if options.no_ntp: print("") print("Excluded by options:") print(" * Configure the NTP client (chronyd)") if installer.interactive: print("") print("To accept the default shown in brackets, press the Enter key.") print("") if not options.external_cert_files: # Make sure the 389-ds ports are available check_dirsrv(not installer.interactive) if not options.no_ntp: try: timeconf.check_timedate_services() except timeconf.NTPConflictingService as e: print( "WARNING: conflicting time&date synchronization service " "'{}' will be disabled in favor of chronyd\n".format( e.conflicting_service ) ) except timeconf.NTPConfigurationError: pass if not options.setup_dns and installer.interactive: if ipautil.user_input("Do you want to configure integrated DNS " "(BIND)?", False): dns.package_check(ScriptError) options.setup_dns = True print("") # check bind packages are installed if options.setup_dns: # Don't require an external DNS to say who we are if we are # setting up a local DNS server. options.no_host_dns = True # check the hostname is correctly configured, it must be as the kldap # utilities just use the hostname as returned by getaddrinfo to set # up some of the standard entries if options.host_name: host_default = options.host_name else: host_default = get_fqdn() try: if not installer.interactive or options.host_name: verify_fqdn(host_default, options.no_host_dns) host_name = host_default else: host_name = read_host_name(host_default, options.no_host_dns) except BadHostError as e: raise ScriptError(e) host_name = host_name.lower() logger.debug("will use host_name: %s\n", host_name) if not options.domain_name: domain_name = read_domain_name(host_name[host_name.find(".")+1:], not installer.interactive) logger.debug("read domain_name: %s\n", domain_name) try: validate_domain_name(domain_name) except ValueError as e: raise ScriptError("Invalid domain name: %s" % unicode(e)) else: domain_name = options.domain_name domain_name = domain_name.lower() if not options.realm_name: realm_name = read_realm_name(domain_name, not installer.interactive) logger.debug("read realm_name: %s\n", realm_name) try: validate_domain_name(realm_name, entity="realm") except ValueError as e: raise ScriptError("Invalid realm name: {}".format(unicode(e))) else: realm_name = options.realm_name.upper() if not options.subject_base: options.subject_base = installutils.default_subject_base(realm_name) if not options.ca_subject: options.ca_subject = \ installutils.default_ca_subject_dn(options.subject_base) if options.http_cert_files: if options.http_pin is None: options.http_pin = installutils.read_password( "Enter Apache Server private key unlock", confirm=False, validate=False, retry=False) if options.http_pin is None: raise ScriptError( "Apache Server private key unlock password required") http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12( cert_files=options.http_cert_files, key_password=options.http_pin, key_nickname=options.http_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) http_pkcs12_info = (http_pkcs12_file.name, http_pin) if options.dirsrv_cert_files: if options.dirsrv_pin is None: options.dirsrv_pin = read_password( "Enter Directory Server private key unlock", confirm=False, validate=False, retry=False) if options.dirsrv_pin is None: raise ScriptError( "Directory Server private key unlock password required") dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12( cert_files=options.dirsrv_cert_files, key_password=options.dirsrv_pin, key_nickname=options.dirsrv_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) if options.pkinit_cert_files: if options.pkinit_pin is None: options.pkinit_pin = read_password( "Enter Kerberos KDC private key unlock", confirm=False, validate=False, retry=False) if options.pkinit_pin is None: raise ScriptError( "Kerberos KDC private key unlock password required") pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12( cert_files=options.pkinit_cert_files, key_password=options.pkinit_pin, key_nickname=options.pkinit_cert_name, ca_cert_files=options.ca_cert_files, realm_name=realm_name) pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin) if (options.http_cert_files and options.dirsrv_cert_files and http_ca_cert != dirsrv_ca_cert): raise ScriptError( "Apache Server SSL certificate and Directory Server SSL " "certificate are not signed by the same CA certificate") if (options.http_cert_files and options.pkinit_cert_files and http_ca_cert != pkinit_ca_cert): raise ScriptError( "Apache Server SSL certificate and PKINIT KDC " "certificate are not signed by the same CA certificate") if not options.dm_password: dm_password = read_dm_password() if dm_password is None: raise ScriptError("Directory Manager password required") else: dm_password = options.dm_password if not options.master_password: master_password = ipa_generate_password() else: master_password = options.master_password if not options.admin_password: admin_password = read_admin_password() if admin_password is None: raise ScriptError("IPA admin password required") else: admin_password = options.admin_password # Configuration for ipalib, we will bootstrap and finalize later, after # we are sure we have the configuration file ready. cfg = dict( context='installer', confdir=paths.ETC_IPA, in_server=True, # make sure host name specified by user is used instead of default host=host_name, ) if setup_ca: # we have an IPA-integrated CA cfg['ca_host'] = host_name # Create the management framework config file and finalize api target_fname = paths.IPA_DEFAULT_CONF ipaconf = IPAChangeConf("IPA Server Install") ipaconf.setOptionAssignment(" = ") ipaconf.setSectionNameDelimiters(("[", "]")) xmlrpc_uri = 'https://{0}/ipa/xml'.format( ipautil.format_netloc(host_name)) ldapi_uri = ipaldap.realm_to_ldapi_uri(realm_name) # [global] section gopts = [ ipaconf.setOption('host', host_name), ipaconf.setOption('basedn', ipautil.realm_to_suffix(realm_name)), ipaconf.setOption('realm', realm_name), ipaconf.setOption('domain', domain_name), ipaconf.setOption('xmlrpc_uri', xmlrpc_uri), ipaconf.setOption('ldap_uri', ldapi_uri), ipaconf.setOption('mode', 'production') ] if setup_ca: gopts.extend([ ipaconf.setOption('enable_ra', 'True'), ipaconf.setOption('ra_plugin', 'dogtag'), ipaconf.setOption('dogtag_version', '10') ]) else: gopts.extend([ ipaconf.setOption('enable_ra', 'False'), ipaconf.setOption('ra_plugin', 'None') ]) opts = [ ipaconf.setSection('global', gopts), {'name': 'empty', 'type': 'empty'} ] ipaconf.newConf(target_fname, opts) # Must be readable for everyone os.chmod(target_fname, 0o644) api.bootstrap(**cfg) api.finalize() if setup_ca: ca.install_check(False, None, options) if options.setup_kra: kra.install_check(api, None, options) if options.setup_dns: dns.install_check(False, api, False, options, host_name) ip_addresses = dns.ip_addresses else: ip_addresses = get_server_ip_address(host_name, not installer.interactive, False, options.ip_addresses) # check addresses here, dns module is doing own check no_matching_interface_for_ip_address_warning(ip_addresses) instance_name = "-".join(realm_name.split(".")) dirsrv = services.knownservices.dirsrv if (options.external_cert_files and dirsrv.is_installed(instance_name) and not dirsrv.is_running(instance_name)): logger.debug('Starting Directory Server') services.knownservices.dirsrv.start(instance_name) if options.setup_adtrust: adtrust.install_check(False, options, api) # installer needs to update hosts file when DNS subsystem will be # installed or custom addresses are used if options.ip_addresses or options.setup_dns: installer._update_hosts_file = True if not options.no_ntp and not options.unattended and not ( options.ntp_servers or options.ntp_pool): options.ntp_servers, options.ntp_pool = timeconf.get_time_source() print() print("The IPA Master Server will be configured with:") print("Hostname: %s" % host_name) print("IP address(es): %s" % ", ".join(str(ip) for ip in ip_addresses)) print("Domain name: %s" % domain_name) print("Realm name: %s" % realm_name) print() if setup_ca: ca.print_ca_configuration(options) print() if options.setup_dns: print("BIND DNS server will be configured to serve IPA domain with:") print("Forwarders: %s" % ( "No forwarders" if not options.forwarders else ", ".join([str(ip) for ip in options.forwarders]) )) print('Forward policy: %s' % options.forward_policy) print("Reverse zone(s): %s" % ( "No reverse zone" if options.no_reverse or not dns.reverse_zones else ", ".join(str(rz) for rz in dns.reverse_zones) )) print() if not options.setup_adtrust: # If domain name and realm does not match, IPA server will not be able # to establish trust with Active Directory. Print big fat warning. realm_not_matching_domain = (domain_name.upper() != realm_name) if realm_not_matching_domain: print("WARNING: Realm name does not match the domain name.\n" "You will not be able to establish trusts with Active " "Directory unless\nthe realm name of the IPA server matches " "its domain name.\n\n") if options.ntp_servers or options.ntp_pool: if options.ntp_servers: for server in options.ntp_servers: print("NTP server:\t{}".format(server)) if options.ntp_pool: print("NTP pool:\t{}".format(options.ntp_pool)) if installer.interactive and not user_input( "Continue to configure the system with these values?", False): raise ScriptError("Installation aborted") options.realm_name = realm_name options.domain_name = domain_name options.dm_password = dm_password options.master_password = master_password options.admin_password = admin_password options._host_name_overridden = bool(options.host_name) options.host_name = host_name options.ip_addresses = ip_addresses installer._fstore = fstore installer._sstore = sstore installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file installer._http_pkcs12_file = http_pkcs12_file installer._pkinit_pkcs12_file = pkinit_pkcs12_file installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info installer._http_pkcs12_info = http_pkcs12_info installer._pkinit_pkcs12_info = pkinit_pkcs12_info installer._external_cert_file = external_cert_file installer._external_ca_file = external_ca_file installer._ca_cert = http_ca_cert
def __init__(self, dm_password=None, sub_dict={}, online=True, ldapi=False): ''' :parameters: dm_password Directory Manager password sub_dict substitution dictionary online Do an online LDAP update or use an experimental LDIF updater ldapi Bind using ldapi. This assumes autobind is enabled. Data Structure Example: ----------------------- dn_by_rdn_count = { 3: 'cn=config,dc=example,dc=com': 4: 'cn=bob,ou=people,dc=example,dc=com', } all_updates = [ { 'dn': 'cn=config,dc=example,dc=com', 'default': ['attr1':default1'], 'updates': ['action:attr1:value1', 'action:attr2:value2] }, { 'dn': 'cn=bob,ou=people,dc=example,dc=com', 'default': ['attr3':default3'], 'updates': ['action:attr3:value3', 'action:attr4:value4], } ] The default and update lists are "dispositions" Plugins: Plugins has to be specified in update file to be executed, using 'plugin' directive Example: plugin: update_uniqueness_plugins_to_new_syntax Each plugin returns two values: 1. restart: dirsrv will be restarted AFTER this update is applied. 2. updates: A list of updates to be applied. The value of an update is a dictionary with the following possible values: - dn: DN, equal to the dn attribute - updates: list of updates against the dn - default: list of the default entry to be added if it doesn't exist - deleteentry: list of dn's to be deleted (typically single dn) For example, this update file: dn: cn=global_policy,cn=$REALM,cn=kerberos,$SUFFIX replace:krbPwdLockoutDuration:10::600 replace: krbPwdMaxFailure:3::6 Generates this list which contain the update dictionary: [ dict( 'dn': 'cn=global_policy,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com', 'updates': ['replace:krbPwdLockoutDuration:10::600', 'replace:krbPwdMaxFailure:3::6'] ) ] Here is another example showing how a default entry is configured: dn: cn=Managed Entries,cn=etc,$SUFFIX default: objectClass: nsContainer default: objectClass: top default: cn: Managed Entries This generates: [ dict( 'dn': 'cn=Managed Entries,cn=etc,dc=example,dc=com', 'default': ['objectClass:nsContainer', 'objectClass:top', 'cn:Managed Entries' ] ) ] Note that the variable substitution in both examples has been completed. Either may make changes directly in LDAP or can return updates in update format. ''' log_mgr.get_logger(self, True) self.sub_dict = sub_dict self.dm_password = dm_password self.conn = None self.modified = False self.online = online self.ldapi = ldapi self.pw_name = pwd.getpwuid(os.geteuid()).pw_name self.realm = None self.socket_name = (paths.SLAPD_INSTANCE_SOCKET_TEMPLATE % api.env.realm.replace('.', '-')) self.ldapuri = 'ldapi://%s' % ipautil.format_netloc(self.socket_name) suffix = None if sub_dict.get("REALM"): self.realm = sub_dict["REALM"] else: krbctx = krbV.default_context() try: self.realm = krbctx.default_realm suffix = ipautil.realm_to_suffix(self.realm) except krbV.Krb5Error: self.realm = None suffix = None if suffix is not None: assert isinstance(suffix, DN) domain = ipautil.get_domain_name() libarch = self._identify_arch() fqdn = installutils.get_fqdn() if fqdn is None: raise RuntimeError("Unable to determine hostname") if not self.sub_dict.get("REALM") and self.realm is not None: self.sub_dict["REALM"] = self.realm if not self.sub_dict.get("FQDN"): self.sub_dict["FQDN"] = fqdn if not self.sub_dict.get("DOMAIN"): self.sub_dict["DOMAIN"] = domain if not self.sub_dict.get("SUFFIX") and suffix is not None: self.sub_dict["SUFFIX"] = suffix if not self.sub_dict.get("ESCAPED_SUFFIX"): self.sub_dict["ESCAPED_SUFFIX"] = str(suffix) if not self.sub_dict.get("LIBARCH"): self.sub_dict["LIBARCH"] = libarch if not self.sub_dict.get("TIME"): self.sub_dict["TIME"] = int(time.time()) if not self.sub_dict.get("DOMAIN") and domain is not None: self.sub_dict["DOMAIN"] = domain self.api = create_api(mode=None) self.api.bootstrap(in_server=True, context='updates') self.api.finalize() if online: # Try out the connection/password # (This will raise if the server is not available) self.create_connection() self.close_connection() else: raise RuntimeError("Offline updates are not supported.")
def install(filename, options): global config dogtag_constants = dogtag.install_constants # Create the management framework config file # Note: We must do this before bootstraping and finalizing ipalib.api old_umask = os.umask(022) # must be readable for httpd try: fd = open(paths.IPA_DEFAULT_CONF, "w") fd.write("[global]\n") fd.write("host=%s\n" % config.host_name) fd.write("basedn=%s\n" % str(ipautil.realm_to_suffix(config.realm_name))) fd.write("realm=%s\n" % config.realm_name) fd.write("domain=%s\n" % config.domain_name) fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % ipautil.format_netloc(config.host_name)) fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % installutils.realm_to_serverid(config.realm_name)) if ipautil.file_exists(config.dir + "/cacert.p12"): fd.write("enable_ra=True\n") fd.write("ra_plugin=dogtag\n") fd.write("dogtag_version=%s\n" % dogtag_constants.DOGTAG_VERSION) else: fd.write("enable_ra=False\n") fd.write("ra_plugin=none\n") fd.write("enable_kra=%s\n" % config.setup_kra) fd.write("mode=production\n") fd.close() finally: os.umask(old_umask) api.bootstrap(in_server=True, context='installer') api.finalize() # Create DS user/group if it doesn't exist yet dsinstance.create_ds_user() cafile = config.dir + "/ca.crt" ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name) remote_api = create_api(mode=None) remote_api.bootstrap(in_server=True, context='installer', ldap_uri=ldapuri, basedn=DN()) remote_api.finalize() conn = remote_api.Backend.ldap2 replman = None try: try: # Try out the password conn.connect(bind_dn=DIRMAN_DN, bind_pw=config.dirman_password, tls_cacertfile=cafile) replman = ReplicationManager(config.realm_name, config.master_host_name, config.dirman_password) # Check that we don't already have a replication agreement try: (agreement_cn, agreement_dn) = replman.agreement_dn( config.host_name) entry = conn.get_entry(agreement_dn, ['*']) except errors.NotFound: pass else: root_logger.info('Error: A replication agreement for this ' 'host already exists.') print('A replication agreement for this host already exists. ' 'It needs to be removed.') print "Run this on the master that generated the info file:" print(" %% ipa-replica-manage del %s --force" % config.host_name) sys.exit(3) # Detect the current domain level try: current = remote_api.Command['domainlevel_get']()['result'] except errors.NotFound: # If we're joining an older master, domain entry is not # available current = 0 # Detect if current level is out of supported range # for this IPA version under_lower_bound = current < constants.MIN_DOMAIN_LEVEL above_upper_bound = current > constants.MAX_DOMAIN_LEVEL if under_lower_bound or above_upper_bound: message = ("This version of FreeIPA does not support " "the Domain Level which is currently set for " "this domain. The Domain Level needs to be " "raised before installing a replica with " "this version is allowed to be installed " "within this domain.") root_logger.error(message) print(message) sys.exit(3) # Check pre-existing host entry try: entry = conn.find_entries(u'fqdn=%s' % config.host_name, ['fqdn'], DN(api.env.container_host, api.env.basedn)) except errors.NotFound: pass else: root_logger.info('Error: Host %s already exists on the master ' 'server.' % config.host_name) print('The host %s already exists on the master server.' % config.host_name) print "You should remove it before proceeding:" print " %% ipa host-del %s" % config.host_name sys.exit(3) # Install CA cert so that we can do SSL connections with ldap install_ca_cert(conn, api.env.basedn, api.env.realm, cafile) dns_masters = remote_api.Object['dnsrecord'].get_dns_masters() if dns_masters: if not options.no_host_dns: master = config.master_host_name root_logger.debug('Check forward/reverse DNS resolution') resolution_ok = ( check_dns_resolution(master, dns_masters) and check_dns_resolution(config.host_name, dns_masters)) if not resolution_ok and not options.unattended: if not ipautil.user_input("Continue?", False): sys.exit(0) else: root_logger.debug('No IPA DNS servers, ' 'skipping forward/reverse resolution check') except errors.ACIError: sys.exit("\nThe password provided is incorrect for LDAP server " "%s" % config.master_host_name) except errors.LDAPError: sys.exit("\nUnable to connect to LDAP server %s" % config.master_host_name) finally: if replman and replman.conn: replman.conn.unbind() # Configure ntpd if options.conf_ntp: ipaclient.ntpconf.force_ntpd(sstore) ntp = ntpinstance.NTPInstance() ntp.create_instance() # Configure dirsrv ds = install_replica_ds(config) # Always try to install DNS records install_dns_records(config, options, remote_api) finally: if conn.isconnected(): conn.disconnect() if config.setup_ca: options.realm_name = config.realm_name options.domain_name = config.domain_name options.dm_password = config.dirman_password options.host_name = config.host_name ca.install(False, config, options) krb = install_krb(config, setup_pkinit=options.setup_pkinit) http = install_http(config, auto_redirect=options.ui_redirect) otpd = otpdinstance.OtpdInstance() otpd.create_instance('OTPD', config.host_name, config.dirman_password, ipautil.realm_to_suffix(config.realm_name)) # The DS instance is created before the keytab, add the SSL cert we # generated ds.add_cert_to_service() # Apply any LDAP updates. Needs to be done after the replica is synced-up service.print_msg("Applying LDAP updates") ds.apply_updates() if options.setup_kra: kra.install(config, options, config.dirman_password) else: service.print_msg("Restarting the directory server") ds.restart() service.print_msg("Restarting the KDC") krb.restart() if config.setup_ca: dogtag_service = services.knownservices[dogtag_constants.SERVICE_NAME] dogtag_service.restart(dogtag_constants.PKI_INSTANCE_NAME) if options.setup_dns: api.Backend.ldap2.connect(autobind=True) dns.install(False, True, options) # Restart httpd to pick up the new IPA configuration service.print_msg("Restarting the web server") http.restart() # Call client install script try: args = [paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended", "--domain", config.domain_name, "--server", config.host_name, "--realm", config.realm_name] if not options.create_sshfp: args.append("--no-dns-sshfp") if options.trust_sshfp: args.append("--ssh-trust-dns") if not options.conf_ssh: args.append("--no-ssh") if not options.conf_sshd: args.append("--no-sshd") if options.mkhomedir: args.append("--mkhomedir") ipautil.run(args) except Exception, e: print "Configuration of client side components failed!" print "ipa-client-install returned: " + str(e) raise RuntimeError("Failed to configure the client")
def __spawn_instance(self): """ Create and configure a new KRA instance using pkispawn. Creates a configuration file with IPA-specific parameters and passes it to the base class to call pkispawn """ self.tmp_agent_db = tempfile.mkdtemp(prefix="tmp-", dir=paths.VAR_LIB_IPA) tmp_agent_pwd = ipautil.ipa_generate_password() # Create a temporary file for the admin PKCS #12 file (admin_p12_fd, admin_p12_file) = tempfile.mkstemp() os.close(admin_p12_fd) cfg = dict( pki_issuing_ca_uri="https://{}".format( ipautil.format_netloc(self.fqdn, 443)), # Client security database pki_client_database_dir=self.tmp_agent_db, pki_client_database_password=tmp_agent_pwd, pki_client_database_purge=True, pki_client_pkcs12_password=self.admin_password, pki_import_admin_cert=False, pki_client_admin_cert_p12=admin_p12_file, ) if lookup_random_serial_number_version(api) > 0: cfg['pki_key_id_generator'] = 'random' cfg['pki_request_id_generator'] = 'random' if not (os.path.isdir(paths.PKI_TOMCAT_ALIAS_DIR) and os.path.isfile(paths.PKI_TOMCAT_PASSWORD_CONF)): # generate pin which we know can be used for FIPS NSS database pki_pin = ipautil.ipa_generate_password() cfg['pki_server_database_password'] = pki_pin else: pki_pin = None _p12_tmpfile_handle, p12_tmpfile_name = tempfile.mkstemp(dir=paths.TMP) if self.clone: krafile = self.pkcs12_info[0] shutil.copy(krafile, p12_tmpfile_name) self.service_user.chown(p12_tmpfile_name) self._configure_clone( cfg, security_domain_hostname=self.fqdn, clone_pkcs12_path=p12_tmpfile_name, ) cfg.update(pki_clone_setup_replication=False, ) else: # the admin cert file is needed for the first instance of KRA cert = self.get_admin_cert() # First make sure that the directory exists parentdir = os.path.dirname(paths.ADMIN_CERT_PATH) if not os.path.exists(parentdir): os.makedirs(parentdir) with open(paths.ADMIN_CERT_PATH, "wb") as admin_path: admin_path.write( base64.b64encode(cert.public_bytes(x509.Encoding.DER))) # Generate configuration file config = self._create_spawn_config(cfg) with tempfile.NamedTemporaryFile('w', delete=False) as f: config.write(f) self.service_user.chown(f.fileno()) cfg_file = f.name nolog_list = [ self.dm_password, self.admin_password, pki_pin, tmp_agent_pwd ] try: DogtagInstance.spawn_instance(self, cfg_file, nolog_list=nolog_list) finally: os.remove(p12_tmpfile_name) os.remove(cfg_file) os.remove(admin_p12_file) shutil.move(paths.KRA_BACKUP_KEYS_P12, paths.KRACERT_P12) logger.debug("completed creating KRA instance")
def __init__(self, dm_password=None, sub_dict={}, online=True, ldapi=False): ''' :parameters: dm_password Directory Manager password sub_dict substitution dictionary online Do an online LDAP update or use an experimental LDIF updater ldapi Bind using ldapi. This assumes autobind is enabled. Data Structure Example: ----------------------- dn_by_rdn_count = { 3: 'cn=config,dc=example,dc=com': 4: 'cn=bob,ou=people,dc=example,dc=com', } all_updates = [ { 'dn': 'cn=config,dc=example,dc=com', 'default': [ dict(attr='attr1', value='default1'), ], 'updates': [ dict(action='action', attr='attr1', value='value1'), dict(action='replace', attr='attr2', value=['old', 'new']), ] }, { 'dn': 'cn=bob,ou=people,dc=example,dc=com', 'default': [ dict(attr='attr3', value='default3'), ], 'updates': [ dict(action='action', attr='attr3', value='value3'), dict(action='action', attr='attr4', value='value4'), } } ] Please notice the replace action requires two values in list The default and update lists are "dispositions" Plugins: Plugins has to be specified in update file to be executed, using 'plugin' directive Example: plugin: update_uniqueness_plugins_to_new_syntax Each plugin returns two values: 1. restart: dirsrv will be restarted AFTER this update is applied. 2. updates: A list of updates to be applied. The value of an update is a dictionary with the following possible values: - dn: DN, equal to the dn attribute - updates: list of updates against the dn - default: list of the default entry to be added if it doesn't exist - deleteentry: list of dn's to be deleted (typically single dn) For example, this update file: dn: cn=global_policy,cn=$REALM,cn=kerberos,$SUFFIX replace:krbPwdLockoutDuration:10::600 replace: krbPwdMaxFailure:3::6 Generates this list which contain the update dictionary: [ { 'dn': 'cn=global_policy,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com', 'updates': [ dict(action='replace', attr='krbPwdLockoutDuration', value=['10','600']), dict(action='replace', attr='krbPwdMaxFailure', value=['3','6']), ] } ] Here is another example showing how a default entry is configured: dn: cn=Managed Entries,cn=etc,$SUFFIX default: objectClass: nsContainer default: objectClass: top default: cn: Managed Entries This generates: [ { 'dn': 'cn=Managed Entries,cn=etc,dc=example,dc=com', 'default': [ dict(attr='objectClass', value='nsContainer'), dict(attr='objectClass', value='top'), dict(attr='cn', value='Managed Entries'), ] } ] Note that the variable substitution in both examples has been completed. Either may make changes directly in LDAP or can return updates in update format. ''' log_mgr.get_logger(self, True) self.sub_dict = sub_dict self.dm_password = dm_password self.conn = None self.modified = False self.online = online self.ldapi = ldapi self.pw_name = pwd.getpwuid(os.geteuid()).pw_name self.realm = None self.socket_name = ( paths.SLAPD_INSTANCE_SOCKET_TEMPLATE % api.env.realm.replace('.', '-') ) self.ldapuri = 'ldapi://%s' % ipautil.format_netloc( self.socket_name ) suffix = None if sub_dict.get("REALM"): self.realm = sub_dict["REALM"] else: self.realm = api.env.realm suffix = ipautil.realm_to_suffix(self.realm) if self.realm else None if suffix is not None: assert isinstance(suffix, DN) domain = ipautil.get_domain_name() libarch = self._identify_arch() fqdn = installutils.get_fqdn() if fqdn is None: raise RuntimeError("Unable to determine hostname") if not self.sub_dict.get("REALM") and self.realm is not None: self.sub_dict["REALM"] = self.realm if not self.sub_dict.get("FQDN"): self.sub_dict["FQDN"] = fqdn if not self.sub_dict.get("DOMAIN"): self.sub_dict["DOMAIN"] = domain if not self.sub_dict.get("SUFFIX") and suffix is not None: self.sub_dict["SUFFIX"] = suffix if not self.sub_dict.get("ESCAPED_SUFFIX"): self.sub_dict["ESCAPED_SUFFIX"] = str(suffix) if not self.sub_dict.get("LIBARCH"): self.sub_dict["LIBARCH"] = libarch if not self.sub_dict.get("TIME"): self.sub_dict["TIME"] = int(time.time()) if not self.sub_dict.get("DOMAIN") and domain is not None: self.sub_dict["DOMAIN"] = domain if not self.sub_dict.get("MIN_DOMAIN_LEVEL"): self.sub_dict["MIN_DOMAIN_LEVEL"] = str(constants.MIN_DOMAIN_LEVEL) if not self.sub_dict.get("MAX_DOMAIN_LEVEL"): self.sub_dict["MAX_DOMAIN_LEVEL"] = str(constants.MAX_DOMAIN_LEVEL) if not self.sub_dict.get("STRIP_ATTRS"): self.sub_dict["STRIP_ATTRS"] = "%s" % ( " ".join(constants.REPL_AGMT_STRIP_ATTRS),) if not self.sub_dict.get("EXCLUDES"): self.sub_dict["EXCLUDES"] = "(objectclass=*) $ EXCLUDE %s" % ( " ".join(constants.REPL_AGMT_EXCLUDES),) if not self.sub_dict.get("TOTAL_EXCLUDES"): self.sub_dict["TOTAL_EXCLUDES"] = "(objectclass=*) $ EXCLUDE " + \ " ".join(constants.REPL_AGMT_TOTAL_EXCLUDES) self.api = create_api(mode=None) self.api.bootstrap(in_server=True, context='updates') self.api.finalize() if online: # Try out the connection/password # (This will raise if the server is not available) self.create_connection() self.close_connection() else: raise RuntimeError("Offline updates are not supported.")
def ipacheckldap(self, thost, trealm, ca_cert_path=None): """ Given a host and kerberos realm verify that it is an IPA LDAP server hosting the realm. Returns a list [errno, host, realm] or an empty list on error. Errno is an error number: 0 means all ok 1 means we could not check the info in LDAP (may happend when anonymous binds are disabled) 2 means the server is certainly not an IPA server """ lrealms = [] i = 0 #now verify the server is really an IPA server try: ldap_url = "ldap://" + format_netloc(thost, 389) root_logger.debug("Init LDAP connection with: %s", ldap_url) lh = ldap.initialize(ldap_url) if ca_cert_path: ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, True) ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, ca_cert_path) lh.set_option(ldap.OPT_X_TLS_DEMAND, True) lh.start_tls_s() lh.set_option(ldap.OPT_PROTOCOL_VERSION, 3) lh.simple_bind_s("", "") # get IPA base DN root_logger.debug("Search LDAP server for IPA base DN") basedn = get_ipa_basedn(lh) if basedn is None: root_logger.debug("The server is not an IPA server") return [NOT_IPA_SERVER] self.basedn = basedn self.basedn_source = 'From IPA server %s' % ldap_url #search and return known realms root_logger.debug( "Search for (objectClass=krbRealmContainer) in %s (sub)", self.basedn) lret = lh.search_s(str(DN(('cn', 'kerberos'), self.basedn)), ldap.SCOPE_SUBTREE, "(objectClass=krbRealmContainer)") if not lret: #something very wrong return [REALM_NOT_FOUND] for lres in lret: root_logger.debug("Found: %s", lres[0]) for lattr in lres[1]: if lattr.lower() == "cn": lrealms.append(lres[1][lattr][0]) if trealm: for r in lrealms: if trealm == r: return [0, thost, trealm] # must match or something is very wrong return [REALM_NOT_FOUND] else: if len(lrealms) != 1: #which one? we can't attach to a multi-realm server without DNS working return [REALM_NOT_FOUND] else: return [0, thost, lrealms[0]] #we shouldn't get here return [UNKNOWN_ERROR] except LDAPError, err: if isinstance(err, ldap.TIMEOUT): root_logger.debug("LDAP Error: timeout") return [NO_LDAP_SERVER] if isinstance(err, ldap.SERVER_DOWN): root_logger.debug("LDAP Error: server down") return [NO_LDAP_SERVER] if isinstance(err, ldap.INAPPROPRIATE_AUTH): root_logger.debug("LDAP Error: Anonymous access not allowed") return [NO_ACCESS_TO_LDAP] # We should only get UNWILLING_TO_PERFORM if the remote LDAP server # has minssf > 0 and we have attempted a non-TLS connection. if ca_cert_path is None and isinstance(err, ldap.UNWILLING_TO_PERFORM): root_logger.debug( "LDAP server returned UNWILLING_TO_PERFORM. This likely means that minssf is enabled" ) return [NO_TLS_LDAP] root_logger.error( "LDAP Error: %s: %s" % (err.args[0]['desc'], err.args[0].get('info', ''))) return [UNKNOWN_ERROR]
def install_check(installer): options = installer dirsrv_pkcs12_file = installer._dirsrv_pkcs12_file http_pkcs12_file = installer._http_pkcs12_file pkinit_pkcs12_file = installer._pkinit_pkcs12_file dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info http_pkcs12_info = installer._http_pkcs12_info pkinit_pkcs12_info = installer._pkinit_pkcs12_info external_cert_file = installer._external_cert_file external_ca_file = installer._external_ca_file http_ca_cert = installer._ca_cert dirsrv_ca_cert = None pkinit_ca_cert = None tasks.check_ipv6_stack_enabled() tasks.check_selinux_status() check_ldap_conf() mask_str = validate_mask() if mask_str: print("Unexpected system mask: %s, expected 0022" % mask_str) if installer.interactive: if not user_input("Do you want to continue anyway?", True): raise ScriptError( "Unexpected system mask: %s" % mask_str) else: raise ScriptError("Unexpected system mask: %s" % mask_str) if options.master_password: msg = ("WARNING:\noption '-P/--master-password' is deprecated. " "KDC master password of sufficient strength is autogenerated " "during IPA server installation and should not be set " "manually.") print(textwrap.fill(msg, width=79, replace_whitespace=False)) installer._installation_cleanup = True print("\nThe log file for this installation can be found in " "/var/log/ipaserver-install.log") if (not options.external_ca and not options.external_cert_files and is_ipa_configured()): installer._installation_cleanup = False raise ScriptError( "IPA server is already configured on this system.\n" "If you want to reinstall the IPA server, please uninstall " "it first using 'ipa-server-install --uninstall'.") client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if client_fstore.has_files(): installer._installation_cleanup = False raise ScriptError( "IPA client is already configured on this system.\n" "Please uninstall it before configuring the IPA server, " "using 'ipa-client-install --uninstall'") fstore = sysrestore.FileStore(SYSRESTORE_DIR_PATH) sstore = sysrestore.StateFile(SYSRESTORE_DIR_PATH) # This will override any settings passed in on the cmdline if os.path.isfile(paths.ROOT_IPA_CACHE): if options.dm_password is not None: dm_password = options.dm_password else: dm_password = read_password("Directory Manager", confirm=False) if dm_password is None: raise ScriptError("Directory Manager password required") try: cache_vars = read_cache(dm_password) options.__dict__.update(cache_vars) if cache_vars.get('external_ca', False): options.external_ca = False options.interactive = False except Exception as e: raise ScriptError("Cannot process the cache file: %s" % str(e)) # We only set up the CA if the PKCS#12 options are not given. if options.dirsrv_cert_files: setup_ca = False else: setup_ca = True options.setup_ca = setup_ca if not setup_ca and options.ca_subject: raise ScriptError( "--ca-subject cannot be used with CA-less installation") if not setup_ca and options.subject_base: raise ScriptError( "--subject-base cannot be used with CA-less installation") if not setup_ca and options.setup_kra: raise ScriptError( "--setup-kra cannot be used with CA-less installation") print("=======================================" "=======================================") print("This program will set up the FreeIPA Server.") print("Version {}".format(version.VERSION)) print("") print("This includes:") if setup_ca: print(" * Configure a stand-alone CA (dogtag) for certificate " "management") if not options.no_ntp: print(" * Configure the NTP client (chronyd)") print(" * Create and configure an instance of Directory Server") print(" * Create and configure a Kerberos Key Distribution Center (KDC)") print(" * Configure Apache (httpd)") if options.setup_kra: print(" * Configure KRA (dogtag) for secret management") if options.setup_dns: print(" * Configure DNS (bind)") if options.setup_adtrust: print(" * Configure Samba (smb) and winbind for managing AD trusts") if not options.no_pkinit: print(" * Configure the KDC to enable PKINIT") if options.no_ntp: print("") print("Excluded by options:") print(" * Configure the NTP client (chronyd)") if installer.interactive: print("") print("To accept the default shown in brackets, press the Enter key.") print("") if not options.external_cert_files: # Make sure the 389-ds ports are available check_dirsrv(not installer.interactive) if not options.no_ntp: try: ipaclient.install.timeconf.check_timedate_services() except ipaclient.install.timeconf.NTPConflictingService as e: print("WARNING: conflicting time&date synchronization service '{}'" " will be disabled".format(e.conflicting_service)) print("in favor of chronyd") print("") except ipaclient.install.timeconf.NTPConfigurationError: pass if not options.setup_dns and installer.interactive: if ipautil.user_input("Do you want to configure integrated DNS " "(BIND)?", False): options.setup_dns = True print("") # check bind packages are installed if options.setup_dns: # Don't require an external DNS to say who we are if we are # setting up a local DNS server. options.no_host_dns = True # check the hostname is correctly configured, it must be as the kldap # utilities just use the hostname as returned by getaddrinfo to set # up some of the standard entries if options.host_name: host_default = options.host_name else: host_default = get_fqdn() try: if not installer.interactive or options.host_name: verify_fqdn(host_default, options.no_host_dns) host_name = host_default else: host_name = read_host_name(host_default, options.no_host_dns) except BadHostError as e: raise ScriptError(e) host_name = host_name.lower() logger.debug("will use host_name: %s\n", host_name) if not options.domain_name: domain_name = read_domain_name(host_name[host_name.find(".")+1:], not installer.interactive) logger.debug("read domain_name: %s\n", domain_name) try: validate_domain_name(domain_name) except ValueError as e: raise ScriptError("Invalid domain name: %s" % unicode(e)) else: domain_name = options.domain_name domain_name = domain_name.lower() if not options.realm_name: realm_name = read_realm_name(domain_name, not installer.interactive) logger.debug("read realm_name: %s\n", realm_name) try: validate_domain_name(realm_name, entity="realm") except ValueError as e: raise ScriptError("Invalid realm name: {}".format(unicode(e))) else: realm_name = options.realm_name.upper() if not options.subject_base: options.subject_base = installutils.default_subject_base(realm_name) if not options.ca_subject: options.ca_subject = \ installutils.default_ca_subject_dn(options.subject_base) if options.http_cert_files: if options.http_pin is None: options.http_pin = installutils.read_password( "Enter Apache Server private key unlock", confirm=False, validate=False, retry=False) if options.http_pin is None: raise ScriptError( "Apache Server private key unlock password required") http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12( cert_files=options.http_cert_files, key_password=options.http_pin, key_nickname=options.http_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) http_pkcs12_info = (http_pkcs12_file.name, http_pin) if options.dirsrv_cert_files: if options.dirsrv_pin is None: options.dirsrv_pin = read_password( "Enter Directory Server private key unlock", confirm=False, validate=False, retry=False) if options.dirsrv_pin is None: raise ScriptError( "Directory Server private key unlock password required") dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12( cert_files=options.dirsrv_cert_files, key_password=options.dirsrv_pin, key_nickname=options.dirsrv_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) if options.pkinit_cert_files: if options.pkinit_pin is None: options.pkinit_pin = read_password( "Enter Kerberos KDC private key unlock", confirm=False, validate=False, retry=False) if options.pkinit_pin is None: raise ScriptError( "Kerberos KDC private key unlock password required") pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12( cert_files=options.pkinit_cert_files, key_password=options.pkinit_pin, key_nickname=options.pkinit_cert_name, ca_cert_files=options.ca_cert_files, realm_name=realm_name) pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin) if (options.http_cert_files and options.dirsrv_cert_files and http_ca_cert != dirsrv_ca_cert): raise ScriptError( "Apache Server SSL certificate and Directory Server SSL " "certificate are not signed by the same CA certificate") if (options.http_cert_files and options.pkinit_cert_files and http_ca_cert != pkinit_ca_cert): raise ScriptError( "Apache Server SSL certificate and PKINIT KDC " "certificate are not signed by the same CA certificate") if not options.dm_password: dm_password = read_dm_password() if dm_password is None: raise ScriptError("Directory Manager password required") else: dm_password = options.dm_password if not options.master_password: master_password = ipa_generate_password() else: master_password = options.master_password if not options.admin_password: admin_password = read_admin_password() if admin_password is None: raise ScriptError("IPA admin password required") else: admin_password = options.admin_password # Configuration for ipalib, we will bootstrap and finalize later, after # we are sure we have the configuration file ready. cfg = dict( context='installer', confdir=paths.ETC_IPA, in_server=True, # make sure host name specified by user is used instead of default host=host_name, ) if setup_ca: # we have an IPA-integrated CA cfg['ca_host'] = host_name # Create the management framework config file and finalize api target_fname = paths.IPA_DEFAULT_CONF ipaconf = IPAChangeConf("IPA Server Install") ipaconf.setOptionAssignment(" = ") ipaconf.setSectionNameDelimiters(("[", "]")) xmlrpc_uri = 'https://{0}/ipa/xml'.format( ipautil.format_netloc(host_name)) ldapi_uri = ipaldap.realm_to_ldapi_uri(realm_name) # [global] section gopts = [ ipaconf.setOption('host', host_name), ipaconf.setOption('basedn', ipautil.realm_to_suffix(realm_name)), ipaconf.setOption('realm', realm_name), ipaconf.setOption('domain', domain_name), ipaconf.setOption('xmlrpc_uri', xmlrpc_uri), ipaconf.setOption('ldap_uri', ldapi_uri), ipaconf.setOption('mode', 'production') ] if setup_ca: gopts.extend([ ipaconf.setOption('enable_ra', 'True'), ipaconf.setOption('ra_plugin', 'dogtag'), ipaconf.setOption('dogtag_version', '10') ]) else: gopts.extend([ ipaconf.setOption('enable_ra', 'False'), ipaconf.setOption('ra_plugin', 'None') ]) opts = [ ipaconf.setSection('global', gopts), {'name': 'empty', 'type': 'empty'} ] ipaconf.newConf(target_fname, opts) # Must be readable for everyone os.chmod(target_fname, 0o644) api.bootstrap(**cfg) api.finalize() if setup_ca: ca.install_check(False, None, options) if options.setup_kra: kra.install_check(api, None, options) if options.setup_dns: dns.install_check(False, api, False, options, host_name) ip_addresses = dns.ip_addresses else: ip_addresses = get_server_ip_address(host_name, not installer.interactive, False, options.ip_addresses) # check addresses here, dns module is doing own check no_matching_interface_for_ip_address_warning(ip_addresses) instance_name = "-".join(realm_name.split(".")) dirsrv = services.knownservices.dirsrv if (options.external_cert_files and dirsrv.is_installed(instance_name) and not dirsrv.is_running(instance_name)): logger.debug('Starting Directory Server') services.knownservices.dirsrv.start(instance_name) if options.setup_adtrust: adtrust.install_check(False, options, api) # installer needs to update hosts file when DNS subsystem will be # installed or custom addresses are used if options.ip_addresses or options.setup_dns: installer._update_hosts_file = True print() print("The IPA Master Server will be configured with:") print("Hostname: %s" % host_name) print("IP address(es): %s" % ", ".join(str(ip) for ip in ip_addresses)) print("Domain name: %s" % domain_name) print("Realm name: %s" % realm_name) print() if setup_ca: ca.print_ca_configuration(options) print() if options.setup_dns: print("BIND DNS server will be configured to serve IPA domain with:") print("Forwarders: %s" % ( "No forwarders" if not options.forwarders else ", ".join([str(ip) for ip in options.forwarders]) )) print('Forward policy: %s' % options.forward_policy) print("Reverse zone(s): %s" % ( "No reverse zone" if options.no_reverse or not dns.reverse_zones else ", ".join(str(rz) for rz in dns.reverse_zones) )) print() if not options.setup_adtrust: # If domain name and realm does not match, IPA server will not be able # to establish trust with Active Directory. Print big fat warning. realm_not_matching_domain = (domain_name.upper() != realm_name) if realm_not_matching_domain: print("WARNING: Realm name does not match the domain name.\n" "You will not be able to establish trusts with Active " "Directory unless\nthe realm name of the IPA server matches " "its domain name.\n\n") if installer.interactive and not user_input( "Continue to configure the system with these values?", False): raise ScriptError("Installation aborted") options.realm_name = realm_name options.domain_name = domain_name options.dm_password = dm_password options.master_password = master_password options.admin_password = admin_password options._host_name_overridden = bool(options.host_name) options.host_name = host_name options.ip_addresses = ip_addresses installer._fstore = fstore installer._sstore = sstore installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file installer._http_pkcs12_file = http_pkcs12_file installer._pkinit_pkcs12_file = pkinit_pkcs12_file installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info installer._http_pkcs12_info = http_pkcs12_info installer._pkinit_pkcs12_info = pkinit_pkcs12_info installer._external_cert_file = external_cert_file installer._external_ca_file = external_ca_file installer._ca_cert = http_ca_cert
config = create_replica_config(dirman_password, filename, options) installer._top_dir = config.top_dir config.setup_ca = options.setup_ca config.setup_kra = options.setup_kra # Create the management framework config file # Note: We must do this before bootstraping and finalizing ipalib.api old_umask = os.umask(0o22) # must be readable for httpd try: fd = open(paths.IPA_DEFAULT_CONF, "w") fd.write("[global]\n") fd.write("host=%s\n" % config.host_name) fd.write("basedn=%s\n" % str(ipautil.realm_to_suffix(config.realm_name))) fd.write("realm=%s\n" % config.realm_name) fd.write("domain=%s\n" % config.domain_name) fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % ipautil.format_netloc(config.host_name)) fd.write( "ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % installutils.realm_to_serverid(config.realm_name) ) if ipautil.file_exists(config.dir + "/cacert.p12"): fd.write("enable_ra=True\n") fd.write("ra_plugin=dogtag\n") fd.write("dogtag_version=%s\n" % dogtag.install_constants.DOGTAG_VERSION) else: fd.write("enable_ra=False\n") fd.write("ra_plugin=none\n") fd.write("mode=production\n") fd.close() finally: os.umask(old_umask)