mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-25 08:21:05 -06:00
replica-install: Use different API instance for the remote server
Reviewed-By: Tomas Babej <tbabej@redhat.com>
This commit is contained in:
parent
d7ef7e1ca0
commit
8713c5a695
@ -41,7 +41,7 @@ from ipaserver.install.installutils import (
|
||||
from ipaserver.plugins.ldap2 import ldap2
|
||||
from ipaserver.install import cainstance
|
||||
from ipaserver.install import krainstance
|
||||
from ipalib import api, errors, util, certstore, x509
|
||||
from ipalib import api, create_api, errors, util, certstore, x509
|
||||
from ipalib.constants import CACERT
|
||||
from ipapython import version
|
||||
from ipapython.config import IPAOptionParser
|
||||
@ -287,62 +287,34 @@ def install_bind(config, options):
|
||||
print ""
|
||||
|
||||
|
||||
@contextmanager
|
||||
def temporary_ldap2_connection(host_name, bind_pw, bind_dn=DIRMAN_DN):
|
||||
"""Context in which the ldap2 backend is connected to the given host
|
||||
|
||||
When the context is entered, forcefully change the ldap2's URI and connect
|
||||
with the given password.
|
||||
When it's exited, disconnect and restore ldap2 to previous configuration.
|
||||
|
||||
Needed to use the standard IPA tools on the remote master, before the
|
||||
DS on localhost is installed.
|
||||
"""
|
||||
# TODO: We shouldn't have to resort to such hacks
|
||||
cur_uri = api.Backend.ldap2.ldap_uri
|
||||
# ldap2 is finalized at this point, so use __setattr__ directly
|
||||
object.__setattr__(api.Backend.ldap2, 'ldap_uri',
|
||||
'ldaps://%s' % ipautil.format_netloc(host_name))
|
||||
api.Backend.ldap2.connect(bind_dn=DIRMAN_DN, bind_pw=bind_pw,
|
||||
tls_cacertfile=CACERT)
|
||||
yield
|
||||
|
||||
api.Backend.ldap2.disconnect()
|
||||
#set it back to the default
|
||||
object.__setattr__(api.Backend.ldap2, 'ldap_uri', cur_uri)
|
||||
|
||||
|
||||
def install_dns_records(config, options):
|
||||
def install_dns_records(config, options, remote_api):
|
||||
|
||||
if not bindinstance.dns_container_exists(config.master_host_name,
|
||||
ipautil.realm_to_suffix(config.realm_name),
|
||||
dm_password=config.dirman_password):
|
||||
return
|
||||
|
||||
# We have to force to connect to the remote master because we do this step
|
||||
# before our DS server is installed.
|
||||
with temporary_ldap2_connection(
|
||||
config.master_host_name, config.dirman_password):
|
||||
try:
|
||||
bind = bindinstance.BindInstance(dm_password=config.dirman_password)
|
||||
for ip in config.ips:
|
||||
reverse_zone = bindinstance.find_reverse_zone(ip)
|
||||
try:
|
||||
bind = bindinstance.BindInstance(dm_password=config.dirman_password,
|
||||
api=remote_api)
|
||||
for ip in config.ips:
|
||||
reverse_zone = bindinstance.find_reverse_zone(ip, remote_api)
|
||||
|
||||
bind.add_master_dns_records(config.host_name,
|
||||
str(ip),
|
||||
config.realm_name,
|
||||
config.domain_name,
|
||||
reverse_zone,
|
||||
options.conf_ntp,
|
||||
options.setup_ca)
|
||||
except errors.NotFound, e:
|
||||
root_logger.debug('Replica DNS records could not be added '
|
||||
'on master: %s', str(e))
|
||||
bind.add_master_dns_records(config.host_name,
|
||||
str(ip),
|
||||
config.realm_name,
|
||||
config.domain_name,
|
||||
reverse_zone,
|
||||
options.conf_ntp,
|
||||
options.setup_ca)
|
||||
except errors.NotFound, e:
|
||||
root_logger.debug('Replica DNS records could not be added '
|
||||
'on master: %s', str(e))
|
||||
|
||||
# we should not fail here no matter what
|
||||
except Exception, e:
|
||||
root_logger.info('Replica DNS records could not be added '
|
||||
'on master: %s', str(e))
|
||||
# we should not fail here no matter what
|
||||
except Exception, e:
|
||||
root_logger.info('Replica DNS records could not be added '
|
||||
'on master: %s', str(e))
|
||||
|
||||
|
||||
def check_dirsrv():
|
||||
@ -604,93 +576,96 @@ def main():
|
||||
"ipa-replica-prepare to create a new replica file.")
|
||||
|
||||
ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name)
|
||||
replman = conn = None
|
||||
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 out the password
|
||||
conn = ldap2(shared_instance=False, ldap_uri=ldapuri, base_dn='')
|
||||
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
|
||||
# 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
|
||||
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
|
||||
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()
|
||||
|
||||
if options.skip_schema_check:
|
||||
root_logger.info("Skipping CA DS schema check")
|
||||
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
|
||||
exit(3)
|
||||
cainstance.replica_ca_install_check(config)
|
||||
|
||||
# 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
|
||||
exit(3)
|
||||
# Configure ntpd
|
||||
if options.conf_ntp:
|
||||
ipaclient.ntpconf.force_ntpd(sstore)
|
||||
ntp = ntpinstance.NTPInstance()
|
||||
ntp.create_instance()
|
||||
|
||||
# Install CA cert so that we can do SSL connections with ldap
|
||||
install_ca_cert(conn, api.env.basedn, api.env.realm, cafile)
|
||||
# Configure dirsrv
|
||||
ds = install_replica_ds(config)
|
||||
|
||||
# If remote host has DNS, check forward/reverse resolution
|
||||
with temporary_ldap2_connection(
|
||||
config.master_host_name, config.dirman_password):
|
||||
dns_masters = 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')
|
||||
# Configure the CA if necessary
|
||||
CA = cainstance.install_replica_ca(config)
|
||||
|
||||
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)
|
||||
# Always try to install DNS records
|
||||
install_dns_records(config, options, remote_api)
|
||||
finally:
|
||||
if conn and conn.isconnected():
|
||||
if conn.isconnected():
|
||||
conn.disconnect()
|
||||
if replman and replman.conn:
|
||||
replman.conn.unbind()
|
||||
|
||||
if options.skip_schema_check:
|
||||
root_logger.info("Skipping CA DS schema check")
|
||||
else:
|
||||
cainstance.replica_ca_install_check(config)
|
||||
|
||||
# Configure ntpd
|
||||
if options.conf_ntp:
|
||||
ipaclient.ntpconf.force_ntpd(sstore)
|
||||
ntp = ntpinstance.NTPInstance()
|
||||
ntp.create_instance()
|
||||
|
||||
# Configure dirsrv
|
||||
ds = install_replica_ds(config)
|
||||
|
||||
# Configure the CA if necessary
|
||||
CA = cainstance.install_replica_ca(config)
|
||||
|
||||
# Always try to install DNS records
|
||||
install_dns_records(config, options)
|
||||
|
||||
# We need to ldap_enable the CA now that DS is up and running
|
||||
if CA and config.setup_ca:
|
||||
|
@ -255,7 +255,7 @@ def dns_container_exists(fqdn, suffix, dm_password=None, ldapi=False, realm=None
|
||||
|
||||
return ret
|
||||
|
||||
def dns_zone_exists(name):
|
||||
def dns_zone_exists(name, api=api):
|
||||
try:
|
||||
zone = api.Command.dnszone_show(unicode(name))
|
||||
except ipalib.errors.NotFound:
|
||||
@ -284,12 +284,12 @@ def verify_reverse_zone(zone, ip_address):
|
||||
|
||||
return True
|
||||
|
||||
def find_reverse_zone(ip_address):
|
||||
def find_reverse_zone(ip_address, api=api):
|
||||
ip = netaddr.IPAddress(ip_address)
|
||||
zone = normalize_zone(ip.reverse_dns)
|
||||
|
||||
while len(zone) > 0:
|
||||
if dns_zone_exists(zone):
|
||||
if dns_zone_exists(zone, api):
|
||||
return zone
|
||||
foo, bar, zone = zone.partition('.')
|
||||
|
||||
@ -311,7 +311,7 @@ def read_reverse_zone(default, ip_address):
|
||||
return normalize_zone(zone)
|
||||
|
||||
def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None,
|
||||
update_policy=None, force=False):
|
||||
update_policy=None, force=False, api=api):
|
||||
|
||||
# always normalize zones
|
||||
name = normalize_zone(name)
|
||||
@ -341,7 +341,7 @@ def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None,
|
||||
except (errors.DuplicateEntry, errors.EmptyModlist):
|
||||
pass
|
||||
|
||||
def add_rr(zone, name, type, rdata, dns_backup=None, **kwargs):
|
||||
def add_rr(zone, name, type, rdata, dns_backup=None, api=api, **kwargs):
|
||||
addkw = { '%srecord' % str(type.lower()) : unicode(rdata) }
|
||||
addkw.update(kwargs)
|
||||
try:
|
||||
@ -351,16 +351,16 @@ def add_rr(zone, name, type, rdata, dns_backup=None, **kwargs):
|
||||
if dns_backup:
|
||||
dns_backup.add(zone, type, name, rdata)
|
||||
|
||||
def add_fwd_rr(zone, host, ip_address):
|
||||
def add_fwd_rr(zone, host, ip_address, api=api):
|
||||
addr = netaddr.IPAddress(ip_address)
|
||||
if addr.version == 4:
|
||||
add_rr(zone, host, "A", ip_address)
|
||||
add_rr(zone, host, "A", ip_address, None, api)
|
||||
elif addr.version == 6:
|
||||
add_rr(zone, host, "AAAA", ip_address)
|
||||
add_rr(zone, host, "AAAA", ip_address, None, api)
|
||||
|
||||
def add_ptr_rr(zone, ip_address, fqdn, dns_backup=None):
|
||||
def add_ptr_rr(zone, ip_address, fqdn, dns_backup=None, api=api):
|
||||
name = get_reverse_record_name(zone, ip_address)
|
||||
add_rr(zone, name, "PTR", normalize_zone(fqdn), dns_backup)
|
||||
add_rr(zone, name, "PTR", normalize_zone(fqdn), dns_backup, api)
|
||||
|
||||
def add_ns_rr(zone, hostname, dns_backup=None, force=True):
|
||||
hostname = normalize_zone(hostname)
|
||||
@ -384,7 +384,7 @@ def del_fwd_rr(zone, host, ip_address):
|
||||
def del_ns_rr(zone, name, rdata):
|
||||
del_rr(zone, name, 'NS', rdata)
|
||||
|
||||
def get_rr(zone, name, type):
|
||||
def get_rr(zone, name, type, api=api):
|
||||
rectype = '%srecord' % unicode(type.lower())
|
||||
ret = api.Command.dnsrecord_find(unicode(zone), unicode(name))
|
||||
if ret['count'] > 0:
|
||||
@ -394,8 +394,8 @@ def get_rr(zone, name, type):
|
||||
|
||||
return []
|
||||
|
||||
def get_fwd_rr(zone, host):
|
||||
return [x for t in ("A", "AAAA") for x in get_rr(zone, host, t)]
|
||||
def get_fwd_rr(zone, host, api=api):
|
||||
return [x for t in ("A", "AAAA") for x in get_rr(zone, host, t, api)]
|
||||
|
||||
def zonemgr_callback(option, opt_str, value, parser):
|
||||
"""
|
||||
@ -533,7 +533,7 @@ class DnsBackup(object):
|
||||
|
||||
|
||||
class BindInstance(service.Service):
|
||||
def __init__(self, fstore=None, dm_password=None):
|
||||
def __init__(self, fstore=None, dm_password=None, api=api):
|
||||
service.Service.__init__(self, "named",
|
||||
service_desc="DNS",
|
||||
dm_password=dm_password,
|
||||
@ -550,6 +550,7 @@ class BindInstance(service.Service):
|
||||
self.sub_dict = None
|
||||
self.reverse_zones = []
|
||||
self.dm_password = dm_password
|
||||
self.api = api
|
||||
self.named_regular = services.service('named-regular')
|
||||
|
||||
if fstore:
|
||||
@ -815,9 +816,9 @@ class BindInstance(service.Service):
|
||||
)
|
||||
|
||||
for (rname, rdata) in srv_records:
|
||||
add_rr(self.domain, rname, "SRV", rdata, self.dns_backup)
|
||||
add_rr(self.domain, rname, "SRV", rdata, self.dns_backup, self.api)
|
||||
|
||||
if not dns_zone_exists(zone):
|
||||
if not dns_zone_exists(zone, self.api):
|
||||
# add DNS domain for host first
|
||||
root_logger.debug(
|
||||
"Host domain (%s) is different from DNS domain (%s)!" % (
|
||||
@ -825,15 +826,15 @@ class BindInstance(service.Service):
|
||||
root_logger.debug("Add DNS zone for host first.")
|
||||
|
||||
add_zone(zone, self.zonemgr, dns_backup=self.dns_backup,
|
||||
ns_hostname=self.fqdn, force=True)
|
||||
ns_hostname=self.fqdn, force=True, api=self.api)
|
||||
|
||||
# Add forward and reverse records to self
|
||||
for addr in addrs:
|
||||
add_fwd_rr(zone, host, addr)
|
||||
add_fwd_rr(zone, host, addr, self.api)
|
||||
|
||||
reverse_zone = find_reverse_zone(addr)
|
||||
reverse_zone = find_reverse_zone(addr, self.api)
|
||||
if reverse_zone:
|
||||
add_ptr_rr(reverse_zone, addr, fqdn)
|
||||
add_ptr_rr(reverse_zone, addr, fqdn, None, self.api)
|
||||
|
||||
def __add_self(self):
|
||||
self.__add_master_records(self.fqdn, self.ip_addresses)
|
||||
@ -863,10 +864,10 @@ class BindInstance(service.Service):
|
||||
# add the CA record. So we need to find out
|
||||
root_logger.debug("Check if CA is enabled for this host")
|
||||
base_dn = DN(('cn', fqdn), ('cn', 'masters'), ('cn', 'ipa'),
|
||||
('cn', 'etc'), api.env.basedn)
|
||||
('cn', 'etc'), self.api.env.basedn)
|
||||
ldap_filter = '(&(objectClass=ipaConfigObject)(cn=CA))'
|
||||
try:
|
||||
api.Backend.ldap2.find_entries(filter=ldap_filter, base_dn=base_dn)
|
||||
self.api.Backend.ldap2.find_entries(filter=ldap_filter, base_dn=base_dn)
|
||||
except ipalib.errors.NotFound:
|
||||
root_logger.debug("CA is not configured")
|
||||
return
|
||||
@ -875,7 +876,7 @@ class BindInstance(service.Service):
|
||||
|
||||
try:
|
||||
for addr in addrs:
|
||||
add_fwd_rr(self.domain, IPA_CA_RECORD, addr)
|
||||
add_fwd_rr(self.domain, IPA_CA_RECORD, addr, self.api)
|
||||
except errors.ValidationError:
|
||||
# there is a CNAME record in ipa-ca, we can't add A/AAAA records
|
||||
pass
|
||||
@ -885,7 +886,7 @@ class BindInstance(service.Service):
|
||||
self.ca_configured)
|
||||
|
||||
if self.first_instance:
|
||||
ldap = api.Backend.ldap2
|
||||
ldap = self.api.Backend.ldap2
|
||||
try:
|
||||
entries = ldap.get_entries(
|
||||
DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'),
|
||||
@ -902,8 +903,8 @@ class BindInstance(service.Service):
|
||||
continue
|
||||
|
||||
host, zone = fqdn.split('.', 1)
|
||||
if dns_zone_exists(zone):
|
||||
addrs = get_fwd_rr(zone, host)
|
||||
if dns_zone_exists(zone, self.api):
|
||||
addrs = get_fwd_rr(zone, host, self.api)
|
||||
else:
|
||||
addrs = installutils.resolve_host(fqdn)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user