mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Allow to setup the CA when promoting a replica
This patch makes --setup-ca work to set upa clone CA while creating a new replica. The standalone ipa-ca-install script is not converted yet though. Signed-off-by: Simo Sorce <simo@redhat.com> Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
parent
102651b10a
commit
2606f5aecd
@ -11,5 +11,10 @@ default: ipaReplTopoConfRoot: o=ipaca
|
||||
default: cn: ipaca
|
||||
|
||||
# Update CA replication settings
|
||||
dn: cn=o\3Dipaca,cn=mapping tree,cn=config
|
||||
add: aci: (targetattr=*)(version 3.0;acl "permission:Add Replication Agreements";allow (add) groupdn = "ldap:///cn=Add Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";)
|
||||
add: aci: (targetattr=*)(targetfilter="(|(objectclass=nsds5Replica)(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement)(objectClass=nsMappingTree))")(version 3.0; acl "permission:Modify Replication Agreements"; allow (read, write, search) groupdn = "ldap:///cn=Modify Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";)
|
||||
add: aci: (targetattr=*)(targetfilter="(|(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement))")(version 3.0;acl "permission:Remove Replication Agreements";allow (delete) groupdn = "ldap:///cn=Remove Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";)
|
||||
|
||||
dn: cn=replica,cn=o\3Dipaca,cn=mapping tree,cn=config
|
||||
onlyifexist: nsds5replicabinddngroup: cn=replication managers,cn=sysaccounts,cn=etc,$SUFFIX
|
||||
|
@ -32,16 +32,21 @@ def install_check(standalone, replica_config, options):
|
||||
if standalone and api.env.ra_plugin == 'selfsign':
|
||||
sys.exit('A selfsign CA can not be added')
|
||||
|
||||
if not ipautil.file_exists(replica_config.dir + "/cacert.p12"):
|
||||
if ((not options.promote
|
||||
and not ipautil.file_exists(replica_config.dir + "/cacert.p12"))):
|
||||
print('CA cannot be installed in CA-less setup.')
|
||||
sys.exit(1)
|
||||
|
||||
if standalone and not options.skip_conncheck:
|
||||
principal = options.principal
|
||||
if principal is None:
|
||||
principal = "admin"
|
||||
replica_conn_check(
|
||||
replica_config.master_host_name, host_name, realm_name, True,
|
||||
replica_config.ca_ds_port, options.admin_password)
|
||||
replica_config.ca_ds_port, options.admin_password,
|
||||
principal=principal)
|
||||
|
||||
if options.skip_schema_check:
|
||||
if options.skip_schema_check or options.promote:
|
||||
root_logger.info("Skipping CA DS schema check")
|
||||
else:
|
||||
cainstance.replica_ca_install_check(replica_config)
|
||||
|
@ -64,6 +64,7 @@ from ipaserver.install import certs
|
||||
from ipaserver.install import dsinstance
|
||||
from ipaserver.install import installutils
|
||||
from ipaserver.install import ldapupdate
|
||||
from ipaserver.install import replication
|
||||
from ipaserver.install import service
|
||||
from ipaserver.install.dogtaginstance import (
|
||||
DEFAULT_DSPORT, PKI_USER, export_kra_agent_pem, DogtagInstance)
|
||||
@ -99,6 +100,13 @@ ConfigFile = /usr/share/pki/ca/conf/database.ldif
|
||||
"""
|
||||
|
||||
|
||||
ADMIN_GROUPS = [
|
||||
'Enterprise CA Administrators',
|
||||
'Enterprise KRA Administrators',
|
||||
'Security Domain Administrators'
|
||||
]
|
||||
|
||||
|
||||
def check_port():
|
||||
"""
|
||||
Check that dogtag port (8443) is available.
|
||||
@ -419,6 +427,7 @@ class CAInstance(DogtagInstance):
|
||||
self.ra_cert = None
|
||||
self.requestId = None
|
||||
self.log = log_mgr.get_logger(self)
|
||||
self.no_db_setup = False
|
||||
|
||||
def configure_instance(self, host_name, dm_password,
|
||||
admin_password, ds_port=DEFAULT_DSPORT,
|
||||
@ -440,6 +449,7 @@ class CAInstance(DogtagInstance):
|
||||
"""
|
||||
self.fqdn = host_name
|
||||
self.dm_password = dm_password
|
||||
self.admin_user = "admin"
|
||||
self.admin_password = admin_password
|
||||
self.ds_port = ds_port
|
||||
self.pkcs12_info = pkcs12_info
|
||||
@ -546,8 +556,8 @@ class CAInstance(DogtagInstance):
|
||||
config.set("CA", "pki_client_pkcs12_password", self.admin_password)
|
||||
|
||||
# Administrator
|
||||
config.set("CA", "pki_admin_name", "admin")
|
||||
config.set("CA", "pki_admin_uid", "admin")
|
||||
config.set("CA", "pki_admin_name", self.admin_user)
|
||||
config.set("CA", "pki_admin_uid", self.admin_user)
|
||||
config.set("CA", "pki_admin_email", "root@localhost")
|
||||
config.set("CA", "pki_admin_password", self.admin_password)
|
||||
config.set("CA", "pki_admin_nickname", "ipa-ca-agent")
|
||||
@ -584,6 +594,12 @@ class CAInstance(DogtagInstance):
|
||||
config.set("CA", "pki_ca_signing_key_algorithm", self.ca_signing_algorithm)
|
||||
|
||||
if self.clone:
|
||||
|
||||
if self.no_db_setup:
|
||||
config.set("CA", "pki_ds_create_new_db", "False")
|
||||
config.set("CA", "pki_clone_setup_replication", "False")
|
||||
config.set("CA", "pki_clone_reindex_data", "True")
|
||||
|
||||
cafile = self.pkcs12_info[0]
|
||||
shutil.copy(cafile, paths.TMP_CA_P12)
|
||||
pent = pwd.getpwnam(PKI_USER)
|
||||
@ -592,7 +608,7 @@ class CAInstance(DogtagInstance):
|
||||
# Security domain registration
|
||||
config.set("CA", "pki_security_domain_hostname", self.master_host)
|
||||
config.set("CA", "pki_security_domain_https_port", "443")
|
||||
config.set("CA", "pki_security_domain_user", "admin")
|
||||
config.set("CA", "pki_security_domain_user", self.admin_user)
|
||||
config.set("CA", "pki_security_domain_password", self.admin_password)
|
||||
|
||||
# Clone
|
||||
@ -701,7 +717,7 @@ class CAInstance(DogtagInstance):
|
||||
"-client_certdb_pwd", self.admin_password,
|
||||
"-preop_pin" , preop_pin,
|
||||
"-domain_name", self.security_domain_name,
|
||||
"-admin_user", "admin",
|
||||
"-admin_user", self.admin_user,
|
||||
"-admin_email", "root@localhost",
|
||||
"-admin_password", self.admin_password,
|
||||
"-agent_name", "ipa-ca-agent",
|
||||
@ -769,7 +785,7 @@ class CAInstance(DogtagInstance):
|
||||
args.append("-sd_admin_port")
|
||||
args.append("443")
|
||||
args.append("-sd_admin_name")
|
||||
args.append("admin")
|
||||
args.append(self.admin_user)
|
||||
args.append("-sd_admin_password")
|
||||
args.append(self.admin_password)
|
||||
args.append("-clone_master_port")
|
||||
@ -1482,6 +1498,211 @@ class CAInstance(DogtagInstance):
|
||||
dogtag.configured_constants().CS_CFG_PATH,
|
||||
dogtag_constants)
|
||||
|
||||
def __create_ds_db(self):
|
||||
'''
|
||||
Create PKI database. Is needed when pkispawn option
|
||||
pki_ds_create_new_db is set to False
|
||||
'''
|
||||
|
||||
if not self.admin_conn:
|
||||
self.ldap_connect()
|
||||
|
||||
backend = 'ipaca'
|
||||
suffix = DN(('o', 'ipaca'))
|
||||
|
||||
# replication
|
||||
dn = DN(('cn', str(suffix)), ('cn', 'mapping tree'), ('cn', 'config'))
|
||||
entry = self.admin_conn.make_entry(
|
||||
dn,
|
||||
objectclass=["top", "extensibleObject", "nsMappingTree"],
|
||||
cn=[suffix],
|
||||
)
|
||||
entry['nsslapd-state'] = ['Backend']
|
||||
entry['nsslapd-backend'] = [backend]
|
||||
self.admin_conn.add_entry(entry)
|
||||
|
||||
# database
|
||||
dn = DN(('cn', 'ipaca'), ('cn', 'ldbm database'), ('cn', 'plugins'),
|
||||
('cn', 'config'))
|
||||
entry = self.admin_conn.make_entry(
|
||||
dn,
|
||||
objectclass=["top", "extensibleObject", "nsBackendInstance"],
|
||||
cn=[backend],
|
||||
)
|
||||
entry['nsslapd-suffix'] = [suffix]
|
||||
self.admin_conn.add_entry(entry)
|
||||
|
||||
def __setup_replication(self):
|
||||
|
||||
repl = replication.CAReplicationManager(self.realm, self.fqdn)
|
||||
repl.setup_cs_replication(self.master_host)
|
||||
|
||||
# Activate Topology for o=ipaca segments
|
||||
self.__update_topology()
|
||||
|
||||
def __add_admin_to_group(self, group):
|
||||
dn = DN(('cn', group), ('ou', 'groups'), ('o', 'ipaca'))
|
||||
entry = self.admin_conn.get_entry(dn)
|
||||
members = entry.get('uniqueMember', [])
|
||||
members.append(self.admin_dn)
|
||||
mod = [(ldap.MOD_REPLACE, 'uniqueMember', members)]
|
||||
try:
|
||||
self.admin_conn.modify_s(dn, mod)
|
||||
except ldap.TYPE_OR_VALUE_EXISTS:
|
||||
# already there
|
||||
pass
|
||||
|
||||
def __setup_admin(self):
|
||||
self.admin_user = "admin-%s" % self.fqdn
|
||||
self.admin_password = binascii.hexlify(os.urandom(16))
|
||||
|
||||
if not self.admin_conn:
|
||||
self.ldap_connect()
|
||||
|
||||
self.admin_dn = DN(('uid', self.admin_user),
|
||||
('ou', 'people'), ('o', 'ipaca'))
|
||||
|
||||
# remove user if left-over exists
|
||||
try:
|
||||
entry = self.admin_conn.delete_entry(self.admin_dn)
|
||||
except errors.NotFound:
|
||||
pass
|
||||
|
||||
# add user
|
||||
entry = self.admin_conn.make_entry(
|
||||
self.admin_dn,
|
||||
objectclass=["top", "person", "organizationalPerson",
|
||||
"inetOrgPerson", "cmsuser"],
|
||||
uid=[self.admin_user],
|
||||
cn=[self.admin_user],
|
||||
sn=[self.admin_user],
|
||||
usertype=['adminType'],
|
||||
mail=['root@localhost'],
|
||||
userPassword=[self.admin_password],
|
||||
userstate=['1']
|
||||
)
|
||||
self.admin_conn.add_entry(entry)
|
||||
|
||||
for group in ADMIN_GROUPS:
|
||||
self.__add_admin_to_group(group)
|
||||
|
||||
# Now wait until the other server gets replicated this data
|
||||
master_conn = ipaldap.IPAdmin(self.master_host,
|
||||
port=replication.DEFAULT_PORT,
|
||||
protocol='ldap')
|
||||
master_conn.do_sasl_gssapi_bind()
|
||||
replication.wait_for_entry(master_conn, entry)
|
||||
del master_conn
|
||||
|
||||
def __remove_admin_from_group(self, group):
|
||||
dn = DN(('cn', group), ('ou', 'groups'), ('o', 'ipaca'))
|
||||
entry = self.admin_conn.get_entry(dn)
|
||||
mod = [(ldap.MOD_DELETE, 'uniqueMember', self.admin_dn)]
|
||||
try:
|
||||
self.admin_conn.modify_s(dn, mod)
|
||||
except ldap.NO_SUCH_ATTRIBUTE:
|
||||
# already removed
|
||||
pass
|
||||
|
||||
def __teardown_admin(self):
|
||||
|
||||
if not self.admin_conn:
|
||||
self.ldap_connect()
|
||||
|
||||
for group in ADMIN_GROUPS:
|
||||
self.__remove_admin_from_group(group)
|
||||
self.admin_conn.delete_entry(self.admin_dn)
|
||||
|
||||
def __restart_ds_instance(self):
|
||||
self.ldap_disconnect()
|
||||
services.knownservices.dirsrv.restart()
|
||||
|
||||
def __client_auth_to_db(self):
|
||||
self.enable_client_auth_to_db(self.dogtag_constants.CS_CFG_PATH)
|
||||
|
||||
def __restart_http_instance(self):
|
||||
# We need to restart apache as we drop a new config file in there
|
||||
services.knownservices.httpd.restart(capture_output=True)
|
||||
|
||||
def __enable_instance(self):
|
||||
basedn = ipautil.realm_to_suffix(self.realm)
|
||||
self.ldap_enable('CA', self.fqdn, None, basedn, ['caRenewalMaster'])
|
||||
|
||||
def configure_replica(self, master_host, subject_base=None,
|
||||
ca_cert_bundle=None, ca_signing_algorithm=None,
|
||||
ca_type=None):
|
||||
"""Creates a replica CA, creating a local DS backend and using
|
||||
the topology plugin to manage replication.
|
||||
Requires domain_level >=1 and custodia on the master.
|
||||
"""
|
||||
self.ds_port = DEFAULT_DSPORT
|
||||
self.master_host = master_host
|
||||
self.master_replication_port = DEFAULT_DSPORT
|
||||
if subject_base is None:
|
||||
self.subject_base = DN(('O', self.realm))
|
||||
else:
|
||||
self.subject_base = subject_base
|
||||
if ca_signing_algorithm is None:
|
||||
self.ca_signing_algorithm = 'SHA256withRSA'
|
||||
else:
|
||||
self.ca_signing_algorithm = ca_signing_algorithm
|
||||
if ca_type is not None:
|
||||
self.ca_type = ca_type
|
||||
else:
|
||||
self.ca_type = 'generic'
|
||||
|
||||
self.pkcs12_info = ca_cert_bundle
|
||||
self.no_db_setup = True
|
||||
self.clone = True
|
||||
|
||||
# TODO: deal with "Externally signed CA setups"
|
||||
|
||||
# Set up steps
|
||||
self.step("creating certificate server user", create_ca_user)
|
||||
|
||||
# Setup Database
|
||||
self.step("creating certificate server db", self.__create_ds_db)
|
||||
self.step("setting up initial replication", self.__setup_replication)
|
||||
|
||||
self.step("creating installation admin user", self.__setup_admin)
|
||||
|
||||
# Setup instance
|
||||
self.step("setting up certificate server", self.__spawn_instance)
|
||||
self.step("stopping instance to update CS.cfg", self.stop_instance)
|
||||
self.step("backing up CS.cfg", self.backup_config)
|
||||
self.step("disabling nonces", self.__disable_nonce)
|
||||
self.step("set up CRL publishing", self.__enable_crl_publish)
|
||||
self.step("enable PKIX certificate path discovery and validation",
|
||||
self.enable_pkix)
|
||||
self.step("set up client auth to db", self.__client_auth_to_db)
|
||||
self.step("destroying installation admin user", self.__teardown_admin)
|
||||
self.step("starting instance", self.start_instance)
|
||||
|
||||
self.step("importing CA chain to RA certificate database",
|
||||
self.__import_ca_chain)
|
||||
self.step("fixing RA database permissions", self.fix_ra_perms)
|
||||
self.step("setting up signing cert profile", self.__setup_sign_profile)
|
||||
self.step("setting audit signing renewal to 2 years",
|
||||
self.set_audit_renewal)
|
||||
|
||||
self.step("configure certmonger for renewals",
|
||||
self.configure_certmonger_renewal)
|
||||
self.step("configure certificate renewals",
|
||||
self.configure_renewal)
|
||||
self.step("configure RA certificate renewal",
|
||||
self.configure_agent_renewal)
|
||||
self.step("configure Server-Cert certificate renewal",
|
||||
self.track_servercert)
|
||||
self.step("Configure HTTP to proxy connections",
|
||||
self.http_proxy)
|
||||
self.step("Restart HTTP server to pick up changes",
|
||||
self.__restart_http_instance)
|
||||
|
||||
self.step("enabling CA instance", self.__enable_instance)
|
||||
|
||||
self.start_creation(runtime=210)
|
||||
|
||||
|
||||
def replica_ca_install_check(config):
|
||||
if not config.setup_ca:
|
||||
return
|
||||
|
@ -138,7 +138,6 @@ class DogtagInstance(service.Service):
|
||||
|
||||
self.dogtag_constants = dogtag_constants
|
||||
self.realm = realm
|
||||
self.dm_password = None
|
||||
self.admin_password = None
|
||||
self.fqdn = host_name
|
||||
self.pkcs12_info = None
|
||||
|
@ -40,6 +40,7 @@ WIN_USER_CONTAINER = DN(('cn', 'Users'))
|
||||
# the default container used by IPA for user entries
|
||||
IPA_USER_CONTAINER = DN(('cn', 'users'), ('cn', 'accounts'))
|
||||
PORT = 636
|
||||
DEFAULT_PORT = 389
|
||||
TIMEOUT = 120
|
||||
REPL_MAN_DN = DN(('cn', 'replication manager'), ('cn', 'config'))
|
||||
DNA_DN = DN(('cn', 'Posix IDs'), ('cn', 'Distributed Numeric Assignment Plugin'), ('cn', 'plugins'), ('cn', 'config'))
|
||||
@ -190,6 +191,8 @@ class ReplicationManager(object):
|
||||
self.starttls = starttls
|
||||
self.suffix = ipautil.realm_to_suffix(realm)
|
||||
self.need_memberof_fixup = False
|
||||
self.db_suffix = self.suffix
|
||||
self.agreement_name_format = "meTo%s"
|
||||
|
||||
# The caller is allowed to pass in an existing IPAdmin connection.
|
||||
# Open a new one if not provided
|
||||
@ -303,7 +306,7 @@ class ReplicationManager(object):
|
||||
agreement_types_filters = []
|
||||
if IPA_REPLICA in agreement_types:
|
||||
agreement_types_filters.append('(&(objectclass=nsds5ReplicationAgreement)(nsDS5ReplicaRoot=%s))'
|
||||
% self.suffix)
|
||||
% self.db_suffix)
|
||||
if WINSYNC in agreement_types:
|
||||
agreement_types_filters.append('(objectclass=nsDSWindowsReplicationAgreement)')
|
||||
if len(agreement_types_filters) > 1:
|
||||
@ -415,7 +418,8 @@ class ReplicationManager(object):
|
||||
return "2"
|
||||
|
||||
def replica_dn(self):
|
||||
return DN(('cn','replica'),('cn',self.suffix),('cn','mapping tree'),('cn','config'))
|
||||
return DN(('cn', 'replica'), ('cn', self.db_suffix),
|
||||
('cn', 'mapping tree'), ('cn', 'config'))
|
||||
|
||||
def replica_config(self, conn, replica_id, replica_binddn):
|
||||
assert isinstance(replica_binddn, DN)
|
||||
@ -446,7 +450,7 @@ class ReplicationManager(object):
|
||||
dn,
|
||||
objectclass=["top", "nsds5replica", "extensibleobject"],
|
||||
cn=["replica"],
|
||||
nsds5replicaroot=[str(self.suffix)],
|
||||
nsds5replicaroot=[str(self.db_suffix)],
|
||||
nsds5replicaid=[str(replica_id)],
|
||||
nsds5replicatype=[replica_type],
|
||||
nsds5flags=["1"],
|
||||
@ -496,7 +500,7 @@ class ReplicationManager(object):
|
||||
'objectclass': [
|
||||
'top', 'extensibleObject', 'nsBackendInstance'],
|
||||
'cn': [cn],
|
||||
'nsslapd-suffix': [str(self.suffix)],
|
||||
'nsslapd-suffix': [str(self.db_suffix)],
|
||||
'nsfarmserverurl': urls,
|
||||
'nsmultiplexorbinddn': [self.repl_man_dn],
|
||||
'nsmultiplexorcredentials': [self.repl_man_passwd],
|
||||
@ -517,22 +521,23 @@ class ReplicationManager(object):
|
||||
|
||||
def setup_chaining_farm(self, conn):
|
||||
try:
|
||||
conn.modify_s(self.suffix, [(ldap.MOD_ADD, 'aci',
|
||||
conn.modify_s(self.db_suffix, [(ldap.MOD_ADD, 'aci',
|
||||
[ "(targetattr = \"*\")(version 3.0; acl \"Proxied authorization for database links\"; allow (proxy) userdn = \"ldap:///%s\";)" % self.repl_man_dn ])])
|
||||
except ldap.TYPE_OR_VALUE_EXISTS:
|
||||
root_logger.debug("proxy aci already exists in suffix %s on %s" % (self.suffix, conn.host))
|
||||
root_logger.debug("proxy aci already exists in suffix %s on %s"
|
||||
% (self.db_suffix, conn.host))
|
||||
|
||||
def get_mapping_tree_entry(self):
|
||||
try:
|
||||
entries = self.conn.get_entries(
|
||||
DN(('cn', 'mapping tree'), ('cn', 'config')),
|
||||
ldap.SCOPE_ONELEVEL,
|
||||
"(cn=\"%s\")" % (self.suffix))
|
||||
"(cn=\"%s\")" % (self.db_suffix))
|
||||
# TODO: Check we got only one entry
|
||||
return entries[0]
|
||||
except errors.NotFound:
|
||||
root_logger.debug(
|
||||
"failed to find mapping tree entry for %s", self.suffix)
|
||||
"failed to find mapping tree entry for %s", self.db_suffix)
|
||||
raise
|
||||
|
||||
|
||||
@ -554,7 +559,8 @@ class ReplicationManager(object):
|
||||
try:
|
||||
self.conn.modify_s(dn, mod)
|
||||
except ldap.TYPE_OR_VALUE_EXISTS:
|
||||
root_logger.debug("chainOnUpdate already enabled for %s" % self.suffix)
|
||||
root_logger.debug("chainOnUpdate already enabled for %s"
|
||||
% self.db_suffix)
|
||||
|
||||
def setup_chain_on_update(self, other_conn):
|
||||
chainbe = self.setup_chaining_backend(other_conn)
|
||||
@ -623,7 +629,7 @@ class ReplicationManager(object):
|
||||
master is not used for IPA agreements but for dogtag it will
|
||||
tell which side we want.
|
||||
"""
|
||||
cn = "meTo%s" % (hostname)
|
||||
cn = self.agreement_name_format % (hostname)
|
||||
dn = DN(('cn', cn), self.replica_dn())
|
||||
|
||||
return (cn, dn)
|
||||
@ -656,7 +662,7 @@ class ReplicationManager(object):
|
||||
nsds5replicahost=[b_hostname],
|
||||
nsds5replicaport=[str(port)],
|
||||
nsds5replicatimeout=[str(TIMEOUT)],
|
||||
nsds5replicaroot=[str(self.suffix)],
|
||||
nsds5replicaroot=[str(self.db_suffix)],
|
||||
description=["me to %s" % b_hostname],
|
||||
)
|
||||
if master is None:
|
||||
@ -841,10 +847,12 @@ class ReplicationManager(object):
|
||||
return self.conn.delete_entry(dn)
|
||||
|
||||
def delete_referral(self, hostname):
|
||||
dn = DN(('cn', self.suffix), ('cn', 'mapping tree'), ('cn', 'config'))
|
||||
dn = DN(('cn', self.db_suffix),
|
||||
('cn', 'mapping tree'), ('cn', 'config'))
|
||||
# TODO: should we detect proto/port somehow ?
|
||||
mod = [(ldap.MOD_DELETE, 'nsslapd-referral',
|
||||
'ldap://%s/%s' % (ipautil.format_netloc(hostname, 389), self.suffix))]
|
||||
'ldap://%s/%s' % (ipautil.format_netloc(hostname, 389),
|
||||
self.db_suffix))]
|
||||
|
||||
try:
|
||||
self.conn.modify_s(dn, mod)
|
||||
@ -1709,8 +1717,8 @@ class CSReplicationManager(ReplicationManager):
|
||||
|
||||
def __init__(self, realm, hostname, dirman_passwd, port):
|
||||
super(CSReplicationManager, self).__init__(
|
||||
realm, hostname, dirman_passwd, port, starttls=True)
|
||||
self.suffix = DN(('o', 'ipaca'))
|
||||
realm, hostname, dirman_passwd, port)
|
||||
self.db_suffix = DN(('o', 'ipaca'))
|
||||
self.hostnames = [] # set before calling or agreement_dn() will fail
|
||||
|
||||
def agreement_dn(self, hostname, master=None):
|
||||
@ -1755,24 +1763,27 @@ class CSReplicationManager(ReplicationManager):
|
||||
raise errors.NotFound(reason='No agreement found for %s' % hostname)
|
||||
|
||||
def delete_referral(self, hostname, port):
|
||||
dn = DN(('cn', self.suffix), ('cn', 'mapping tree'), ('cn', 'config'))
|
||||
dn = DN(('cn', self.db_suffix),
|
||||
('cn', 'mapping tree'), ('cn', 'config'))
|
||||
entry = self.conn.get_entry(dn)
|
||||
try:
|
||||
# TODO: should we detect proto somehow ?
|
||||
entry['nsslapd-referral'].remove('ldap://%s/%s' %
|
||||
(ipautil.format_netloc(hostname, port), self.suffix))
|
||||
entry['nsslapd-referral'].remove(
|
||||
'ldap://%s/%s' %
|
||||
(ipautil.format_netloc(hostname, port), self.db_suffix))
|
||||
self.conn.update_entry(entry)
|
||||
except Exception as e:
|
||||
root_logger.debug("Failed to remove referral value: %s" % e)
|
||||
|
||||
def has_ipaca(self):
|
||||
try:
|
||||
entry = self.conn.get_entry(self.suffix)
|
||||
entry = self.conn.get_entry(self.db_suffix)
|
||||
except errors.NotFound:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def get_cs_replication_manager(realm, host, dirman_passwd):
|
||||
"""Get a CSReplicationManager for a remote host
|
||||
|
||||
@ -1801,3 +1812,42 @@ def get_cs_replication_manager(realm, host, dirman_passwd):
|
||||
root_logger.debug('PKI tree not found on %s:%s' % (host, port))
|
||||
|
||||
raise errors.NotFound(reason='Cannot reach PKI DS at %s on ports %s' % (host, ports))
|
||||
|
||||
|
||||
class CAReplicationManager(ReplicationManager):
|
||||
"""ReplicationManager specific to CA agreements for domain level 1 and
|
||||
above servers.
|
||||
"""
|
||||
|
||||
def __init__(self, realm, hostname):
|
||||
# Always connect to self over ldapi
|
||||
conn = ipaldap.IPAdmin(hostname, ldapi=True, realm=realm)
|
||||
conn.do_external_bind('root')
|
||||
super(CAReplicationManager, self).__init__(
|
||||
realm, hostname, None, port=DEFAULT_PORT, conn=conn)
|
||||
self.db_suffix = DN(('o', 'ipaca'))
|
||||
self.agreement_name_format = "caTo%s"
|
||||
|
||||
def setup_cs_replication(self, r_hostname):
|
||||
"""
|
||||
Assumes a promote replica with working GSSAPI for replication
|
||||
and unified DS instance.
|
||||
"""
|
||||
r_conn = ipaldap.IPAdmin(r_hostname, port=389, protocol='ldap')
|
||||
r_conn.do_sasl_gssapi_bind()
|
||||
|
||||
# Setup the first half
|
||||
l_id = self._get_replica_id(self.conn, r_conn)
|
||||
self.basic_replication_setup(self.conn, l_id, self.repl_man_dn, None)
|
||||
|
||||
# Now setup the other half
|
||||
r_id = self._get_replica_id(r_conn, r_conn)
|
||||
self.basic_replication_setup(r_conn, r_id, self.repl_man_dn, None)
|
||||
|
||||
self.setup_agreement(r_conn, self.conn.host, isgssapi=True)
|
||||
self.setup_agreement(self.conn, r_hostname, isgssapi=True)
|
||||
|
||||
# Finally start replication
|
||||
ret = self.start_replication(r_conn, master=False)
|
||||
if ret != 0:
|
||||
raise RuntimeError("Failed to start replication")
|
||||
|
@ -771,9 +771,9 @@ def install(installer):
|
||||
def promote_check(installer):
|
||||
options = installer
|
||||
|
||||
installer._top_dir = tempfile.mkdtemp("ipa")
|
||||
|
||||
# FIXME: to implement yet
|
||||
if options.setup_ca:
|
||||
raise NotImplementedError
|
||||
if options.setup_kra:
|
||||
raise NotImplementedError
|
||||
|
||||
@ -814,8 +814,10 @@ def promote_check(installer):
|
||||
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.setup_ca = options.setup_ca
|
||||
config.setup_kra = options.setup_kra
|
||||
config.dir = installer._top_dir
|
||||
|
||||
installutils.verify_fqdn(config.host_name, options.no_host_dns)
|
||||
installutils.verify_fqdn(config.master_host_name, options.no_host_dns)
|
||||
@ -1117,14 +1119,6 @@ def promote(installer):
|
||||
config.realm_name)
|
||||
custodia.create_replica(config.master_host_name)
|
||||
|
||||
if config.setup_ca:
|
||||
options.realm_name = config.realm_name
|
||||
options.domain_name = config.domain_name
|
||||
options.host_name = config.host_name
|
||||
options.dm_password = config.dirman_password
|
||||
|
||||
ca.install(False, config, options)
|
||||
|
||||
krb = install_krb(config,
|
||||
setup_pkinit=not options.no_pkinit,
|
||||
promote=True)
|
||||
@ -1133,37 +1127,33 @@ def promote(installer):
|
||||
auto_redirect=not options.no_ui_redirect,
|
||||
promote=True)
|
||||
|
||||
otpd = otpdinstance.OtpdInstance()
|
||||
otpd.create_instance('OTPD', config.host_name, config.dirman_password,
|
||||
ipautil.realm_to_suffix(config.realm_name))
|
||||
|
||||
CA = cainstance.CAInstance(
|
||||
config.realm_name, certs.NSS_DIR,
|
||||
dogtag_constants=dogtag_constants)
|
||||
CA.dm_password = config.dirman_password
|
||||
CA.configure_certmonger_renewal()
|
||||
CA.fix_ra_perms()
|
||||
|
||||
# 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(api, config, options)
|
||||
else:
|
||||
service.print_msg("Restarting the directory server")
|
||||
ds.restart()
|
||||
|
||||
service.print_msg("Restarting the KDC")
|
||||
krb.restart()
|
||||
otpd = otpdinstance.OtpdInstance()
|
||||
otpd.create_instance('OTPD', config.host_name, config.dirman_password,
|
||||
ipautil.realm_to_suffix(config.realm_name))
|
||||
|
||||
if config.setup_ca:
|
||||
dogtag_service = services.knownservices[dogtag_constants.SERVICE_NAME]
|
||||
dogtag_service.restart(dogtag_constants.PKI_INSTANCE_NAME)
|
||||
options.realm_name = config.realm_name
|
||||
options.domain_name = config.domain_name
|
||||
options.host_name = config.host_name
|
||||
options.dm_password = config.dirman_password
|
||||
ca_data = (os.path.join(config.dir, 'cacert.p12'),
|
||||
config.dirman_password)
|
||||
custodia.get_ca_keys(config.ca_host_name, ca_data[0], ca_data[1])
|
||||
|
||||
# Restart httpd to pick up the new IPA configuration
|
||||
service.print_msg("Restarting the web server")
|
||||
http.restart()
|
||||
ca = cainstance.CAInstance(config.realm_name, certs.NSS_DIR,
|
||||
dogtag_constants=dogtag.install_constants,
|
||||
host_name=config.host_name,
|
||||
dm_password=config.dirman_password)
|
||||
ca.configure_replica(config.ca_host_name,
|
||||
subject_base=config.subject_base,
|
||||
ca_cert_bundle=ca_data)
|
||||
|
||||
if options.setup_kra:
|
||||
kra.install(api, config, options)
|
||||
|
||||
ds.replica_populate()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user