def test_ipaconf_env(self): ipa_confdir = os.environ.get('IPA_CONFDIR', None) try: with TempHome() as home: defaultconf = home.join('default.conf') with open(defaultconf, 'w') as f: f.write(textwrap.dedent(""" [global] basedn = dc=ipa,dc=test realm = IPA.TEST domain = ipa.test """) ) os.environ['IPA_CONFDIR'] = home.path api = create_api(mode='unit_test') api.bootstrap() api.finalize() assert api.env.confdir == home.path assert api.env.conf_default == defaultconf assert api.env.realm == 'IPA.TEST' assert api.env.domain == 'ipa.test' os.environ['IPA_CONFDIR'] = home.join('invalid') api = create_api(mode='unit_test') with pytest.raises(errors.EnvironmentError): api.bootstrap() finally: if ipa_confdir: os.environ['IPA_CONFDIR'] = ipa_confdir else: os.environ.pop('IPA_CONFDIR')
def test_ipaconf_env(self): ipa_confdir = os.environ.get('IPA_CONFDIR', None) try: with TempHome() as home: defaultconf = home.join('default.conf') with open(defaultconf, 'w') as f: f.write( textwrap.dedent(""" [global] basedn = dc=ipa,dc=test realm = IPA.TEST domain = ipa.test """)) os.environ['IPA_CONFDIR'] = home.path api = create_api(mode='unit_test') api.bootstrap() api.finalize() assert api.env.confdir == home.path assert api.env.conf_default == defaultconf assert api.env.realm == 'IPA.TEST' assert api.env.domain == 'ipa.test' os.environ['IPA_CONFDIR'] = home.join('invalid') api = create_api(mode='unit_test') with pytest.raises(errors.EnvironmentError): api.bootstrap() finally: if ipa_confdir: os.environ['IPA_CONFDIR'] = ipa_confdir else: os.environ.pop('IPA_CONFDIR')
def test_args_valid_option(self): sys.argv = ['/usr/bin/ipa', '-v', 'user-show'] api = create_api(mode='unit_test') (_options, argv) = api.bootstrap_with_global_options(context='unit_test') assert argv == ['user-show'] assert _options.verbose == 1
def test_Backend(self): """ Test using the ldap2 Backend directly (ala ipa-server-install) """ # Create our own api because the one generated for the tests is # a client-only api. Then we register in the commands and objects # we need for the test. myapi = create_api(mode=None) myapi.bootstrap(context='cli', in_server=True, in_tree=True) myapi.register(ldap2) myapi.register(host) myapi.register(service) myapi.register(service_show) myapi.finalize() pwfile = api.env.dot_ipa + os.sep + ".dmpw" if ipautil.file_exists(pwfile): fp = open(pwfile, "r") dm_password = fp.read().rstrip() fp.close() else: raise nose.SkipTest("No directory manager password in %s" % pwfile) myapi.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dm_password) result = myapi.Command['service_show']('ldap/%s@%s' % (api.env.host, api.env.realm,)) entry_attrs = result['result'] cert = entry_attrs.get('usercertificate') cert = cert[0] serial = unicode(x509.get_serial_number(cert, x509.DER)) assert serial is not None
def application(environ, start_response): if environ.get('REQUEST_METHOD', None) != 'POST': return wsgi_redirect(start_response, 'index.html') content_type = environ.get('CONTENT_TYPE', '').lower() if not content_type.startswith('application/x-www-form-urlencoded'): return bad_request(start_response) form_data = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ) if 'username' not in form_data or 'password' not in form_data: return bad_request(start_response) status = '200 Success' response_headers = [] result = 'error' response = b'' # API object only for configuration, finalize() not needed api = create_api(mode=None) api.bootstrap(context='server', confdir=paths.ETC_IPA, in_server=True) try: bind(api.env.ldap_uri, api.env.basedn, form_data['username'].value, form_data['password'].value) except IOError as err: if err.errno == errno.EPERM: result = 'invalid-password' if err.errno == errno.EIO: result = 'migration-error' else: result = 'ok' response_headers.append(('X-IPA-Migrate-Result', result)) start_response(status, response_headers) return [response]
def test_Backend(self): """ Test using the ldap2 Backend directly (ala ipa-server-install) """ # Create our own api because the one generated for the tests is # a client-only api. Then we register in the commands and objects # we need for the test. myapi = create_api(mode=None) myapi.bootstrap(context='cli', in_server=True, in_tree=True) myapi.register(ldap2) myapi.register(host) myapi.register(service) myapi.register(service_show) myapi.finalize() pwfile = api.env.dot_ipa + os.sep + ".dmpw" if ipautil.file_exists(pwfile): fp = open(pwfile, "r") dm_password = fp.read().rstrip() fp.close() else: raise nose.SkipTest("No directory manager password in %s" % pwfile) myapi.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dm_password) result = myapi.Command['service_show']('ldap/%s@%s' % ( api.env.host, api.env.realm, )) entry_attrs = result['result'] cert = entry_attrs.get('usercertificate') cert = cert[0] serial = unicode(x509.get_serial_number(cert, x509.DER)) assert serial is not None
def test_Backend(self): """ Test using the ldap2 Backend directly (ala ipa-server-install) """ # Create our own api because the one generated for the tests is # a client-only api. Then we register in the commands and objects # we need for the test. myapi = create_api(mode=None) myapi.bootstrap(context='cli', in_server=True, confdir=paths.ETC_IPA) myapi.finalize() pwfile = api.env.dot_ipa + os.sep + ".dmpw" if os.path.isfile(pwfile): with open(pwfile, "r") as fp: dm_password = fp.read().rstrip() else: raise unittest.SkipTest( "No directory manager password in %s" % pwfile ) myapi.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dm_password) result = myapi.Command['service_show']('ldap/%s@%s' % (api.env.host, api.env.realm,)) entry_attrs = result['result'] cert = entry_attrs.get('usercertificate')[0] assert cert.serial_number is not None
def test_args_invalid_option(self): sys.argv = ['/usr/bin/ipa', '-verbose', 'user-show'] api = create_api(mode='unit_test') try: api.bootstrap_with_global_options(context='unit_test') except errors.OptionError as e: assert e.msg == 'Unable to parse option rbose'
def test_no_args(self): sys.argv = ['/usr/bin/ipa'] api = create_api(mode='unit_test') (_options, argv) = api.bootstrap_with_global_options(context='unit_test') assert len(argv) == 0 assert _options.env is None assert _options.conf is None assert _options.debug is None assert _options.delegate is None assert _options.verbose is None
def gen_remote_api(master_host_name, etc_ipa): ldapuri = 'ldaps://%s' % ipautil.format_netloc(master_host_name) xmlrpc_uri = 'https://{}/ipa/xml'.format(ipautil.format_netloc(master_host_name)) remote_api = create_api(mode=None) remote_api.bootstrap(in_server=True, context='installer', confdir=etc_ipa, ldap_uri=ldapuri, xmlrpc_uri=xmlrpc_uri) remote_api.finalize() return remote_api
def create_test_api(**kw): """ Returns (api, home) tuple. This function returns a tuple containing an `ipalib.plugable.API` instance and a `TempHome` instance. """ home = TempHome() api = ipalib.create_api(mode='unit_test') api.env.in_tree = True for (key, value) in kw.items(): api.env[key] = value return (api, home)
def mock_api(request): test_api = create_api(mode=None) test_api.bootstrap(in_server=True, ldap_uri=api.env.ldap_uri) test_api.finalize() if not test_api.Backend.ldap2.isconnected(): test_api.Backend.ldap2.connect() def finalize(): test_api.Backend.ldap2.disconnect() request.addfinalizer(finalize) return test_api
def application(environ, start_response): if environ.get("REQUEST_METHOD", None) != "POST": return wsgi_redirect(start_response, "index.html") form_data = cgi.FieldStorage(fp=environ["wsgi.input"], environ=environ) if "username" not in form_data or "password" not in form_data: return wsgi_redirect(start_response, "invalid.html") # API object only for configuration, finalize() not needed api = create_api(mode=None) api.bootstrap(context="server", in_server=True) try: bind(api.env.ldap_uri, api.env.basedn, form_data["username"].value, form_data["password"].value) except IOError as err: if err.errno == errno.EPERM: return wsgi_redirect(start_response, "invalid.html") if err.errno == errno.EIO: return wsgi_redirect(start_response, "error.html") ui_url = get_ui_url(environ) return wsgi_redirect(start_response, ui_url)
def application(environ, start_response): if environ.get('REQUEST_METHOD', None) != 'POST': return wsgi_redirect(start_response, 'index.html') form_data = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ) if 'username' not in form_data or 'password' not in form_data: return wsgi_redirect(start_response, 'invalid.html') # API object only for configuration, finalize() not needed api = create_api(mode=None) api.bootstrap(context='server', confdir=paths.ETC_IPA, in_server=True) try: bind(api.env.ldap_uri, api.env.basedn, form_data['username'].value, form_data['password'].value) except IOError as err: if err.errno == errno.EPERM: return wsgi_redirect(start_response, 'invalid.html') if err.errno == errno.EIO: return wsgi_redirect(start_response, 'error.html') ui_url = get_ui_url(environ) return wsgi_redirect(start_response, ui_url)
def __init__(self, dm_password=_sentinel, sub_dict=None, online=_sentinel, ldapi=_sentinel, api=api): ''' :parameters: dm_password deprecated and no longer used sub_dict substitution dictionary online deprecated and no longer used ldapi deprecated and no longer used api bootstrapped API object (for configuration) 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. ''' if any(arg is not _sentinel for arg in (dm_password, online, ldapi)): warnings.warn( "dm_password, online, and ldapi arguments are deprecated", DeprecationWarning, stacklevel=2 ) self.sub_dict = sub_dict if sub_dict is not None else {} self.conn = None self.modified = False self.ldapuri = ipaldap.realm_to_ldapi_uri(api.env.realm) self.api = create_api(mode=None) self.api.bootstrap( in_server=True, context='updates', confdir=paths.ETC_IPA, ldap_uri=self.ldapuri ) self.api.finalize() self.create_connection() # get ipa-local domain idrange settings domain_range = f"{self.api.env.realm}_id_range" try: result = self.api.Command.idrange_show(domain_range)["result"] except errors.NotFound: idstart = None idmax = None else: idstart = int(result['ipabaseid'][0]) idrange_size = int(result['ipaidrangesize'][0]) idmax = idstart + idrange_size - 1 default_sub = get_sub_dict( realm=api.env.realm, domain=api.env.domain, suffix=api.env.basedn, fqdn=api.env.host, idstart=idstart, idmax=idmax, ) replication_plugin = ( installutils.get_replication_plugin_name(self.conn.get_entry) ) default_sub["REPLICATION_PLUGIN"] = replication_plugin for k, v in default_sub.items(): self.sub_dict.setdefault(k, v)
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 __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 __init__(self, dm_password=_sentinel, sub_dict=None, online=_sentinel, ldapi=_sentinel, api=api): ''' :parameters: dm_password deprecated and no longer used sub_dict substitution dictionary online deprecated and no longer used ldapi deprecated and no longer used api bootstrapped API object (for configuration) 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. ''' if any(arg is not _sentinel for arg in (dm_password, online, ldapi)): warnings.warn( "dm_password, online, and ldapi arguments are deprecated", DeprecationWarning, stacklevel=2 ) self.sub_dict = sub_dict if sub_dict is not None else {} self.conn = None self.modified = False self.ldapuri = ipaldap.realm_to_ldapi_uri(api.env.realm) default_sub = dict( REALM=api.env.realm, DOMAIN=api.env.domain, SUFFIX=api.env.basedn, ESCAPED_SUFFIX=str(api.env.basedn), FQDN=api.env.host, LIBARCH=paths.LIBARCH, TIME=int(time.time()), MIN_DOMAIN_LEVEL=str(constants.MIN_DOMAIN_LEVEL), MAX_DOMAIN_LEVEL=str(constants.MAX_DOMAIN_LEVEL), STRIP_ATTRS=" ".join(constants.REPL_AGMT_STRIP_ATTRS), EXCLUDES="(objectclass=*) $ EXCLUDE %s" % ( " ".join(constants.REPL_AGMT_EXCLUDES) ), TOTAL_EXCLUDES="(objectclass=*) $ EXCLUDE %s" % ( " ".join(constants.REPL_AGMT_TOTAL_EXCLUDES) ), SELINUX_USERMAP_DEFAULT=platformconstants.SELINUX_USERMAP_DEFAULT, SELINUX_USERMAP_ORDER=platformconstants.SELINUX_USERMAP_ORDER, FIPS="#" if tasks.is_fips_enabled() else "", ) for k, v in default_sub.items(): self.sub_dict.setdefault(k, v) self.api = create_api(mode=None) self.api.bootstrap( in_server=True, context='updates', confdir=paths.ETC_IPA, ldap_uri=self.ldapuri ) self.api.finalize()
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 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)
fqdns = result['result']['fqdns'] if detail: # print per host details for fqdn in fqdns: textui.print_plain("Hostname %s" % (fqdn)) details = result['result']['details'][fqdn].items() details.sort(key=lambda x: x[0]) textui.print_keyval(details) else: # print list of hostnames textui.print_plain(" ".join(fqdns)) if __name__ == '__main__': from ipalib import create_api api = create_api() else: from ipalib import api api.register(aii) api.register(aii_find) if __name__ == '__main__': api.finalize() from ipalib import cli textui = cli.textui() args = [unicode('somehost'), unicode('somesubdomain.somedomain')]
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.") # 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=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 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
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):
fqdns = result['result']['fqdns'] if detail: # print per host details for fqdn in fqdns: textui.print_plain("Hostname %s" % (fqdn)) details = result['result']['details'][fqdn].items() details.sort(key=lambda x: x[0]) textui.print_keyval(details) else: # print list of hostnames textui.print_plain(" ".join(fqdns)) if __name__ == '__main__': from ipalib import create_api api = create_api() else: from ipalib import api api.register(aii) api.register(aii_find) if __name__ == '__main__': api.finalize() from ipalib import cli textui = cli.textui() args = [unicode('somehost'), unicode('somesubdomain.somedomain')] options = { 'install': True,
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. ''' 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('.', '-')) 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 self.ldapuri = installutils.realm_to_ldapi_uri(self.realm) if suffix is not None: assert isinstance(suffix, DN) 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"] = api.env.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"] = paths.LIBARCH if not self.sub_dict.get("TIME"): self.sub_dict["TIME"] = int(time.time()) 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', confdir=paths.ETC_IPA, ldap_uri=self.ldapuri) 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 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