mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Use A/AAAA records instead of CNAME records in ipa-ca.
https://fedorahosted.org/freeipa/ticket/3547
This commit is contained in:
committed by
Martin Kosek
parent
ddeb1cea55
commit
f684c6d6f8
@@ -26,4 +26,4 @@ _kpasswd._udp IN SRV 0 100 464 $HOST
|
|||||||
$OPTIONAL_NTP
|
$OPTIONAL_NTP
|
||||||
|
|
||||||
; CNAME for IPA CA replicas (used for CRL, OCSP)
|
; CNAME for IPA CA replicas (used for CRL, OCSP)
|
||||||
$IPA_CA_CNAME IN CNAME $HOST
|
$IPA_CA_RECORD
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ def install_dns_records(config, options):
|
|||||||
try:
|
try:
|
||||||
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
|
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
|
||||||
bind_pw=config.dirman_password)
|
bind_pw=config.dirman_password)
|
||||||
bind.add_ipa_ca_cname(config.host_name, config.domain_name)
|
bind.add_ipa_ca_dns_records(config.host_name, config.domain_name)
|
||||||
finally:
|
finally:
|
||||||
if api.Backend.ldap2.isconnected():
|
if api.Backend.ldap2.isconnected():
|
||||||
api.Backend.ldap2.disconnect()
|
api.Backend.ldap2.disconnect()
|
||||||
|
|||||||
@@ -718,6 +718,7 @@ def del_master(realm, hostname, options):
|
|||||||
api.Backend.ldap2.connect(ccache=ccache)
|
api.Backend.ldap2.connect(ccache=ccache)
|
||||||
bind = bindinstance.BindInstance()
|
bind = bindinstance.BindInstance()
|
||||||
bind.remove_master_dns_records(hostname, realm, realm.lower())
|
bind.remove_master_dns_records(hostname, realm, realm.lower())
|
||||||
|
bind.remove_ipa_ca_dns_records(hostname, realm.lower())
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print "Failed to cleanup %s DNS entries: %s" % (hostname, e)
|
print "Failed to cleanup %s DNS entries: %s" % (hostname, e)
|
||||||
print "You may need to manually remove them from the tree"
|
print "You may need to manually remove them from the tree"
|
||||||
|
|||||||
@@ -727,31 +727,35 @@ def migrate_crl_publish_dir(ca):
|
|||||||
'request pki-ca restart')
|
'request pki-ca restart')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def add_server_cname_records():
|
def add_ca_dns_records():
|
||||||
root_logger.info('[Add missing server CNAME records]')
|
root_logger.info('[Add missing CA DNS records]')
|
||||||
|
|
||||||
if not sysupgrade.get_upgrade_state('dns', 'ipa_ca_cname'):
|
if sysupgrade.get_upgrade_state('dns', 'ipa_ca_records'):
|
||||||
try:
|
root_logger.info('IPA CA DNS records already processed')
|
||||||
api.Backend.ldap2.connect(autobind=True)
|
return
|
||||||
except ipalib.errors.PublicError, e:
|
|
||||||
root_logger.error("Cannot connect to LDAP to add DNS records: %s", e)
|
|
||||||
else:
|
|
||||||
ret = api.Command['dns_is_enabled']()
|
|
||||||
if not ret['result']:
|
|
||||||
root_logger.info('DNS is not configured')
|
|
||||||
sysupgrade.set_upgrade_state('dns', 'ipa_ca_cname', True)
|
|
||||||
return
|
|
||||||
|
|
||||||
bind = bindinstance.BindInstance()
|
try:
|
||||||
# DNS is enabled, so let bindinstance find out if CA is enabled
|
api.Backend.ldap2.connect(autobind=True)
|
||||||
# and let it add the CNAME in that case
|
except ipalib.errors.PublicError, e:
|
||||||
bind.add_ipa_ca_cname(api.env.host, api.env.domain, ca_configured=None)
|
root_logger.error("Cannot connect to LDAP to add DNS records: %s", e)
|
||||||
sysupgrade.set_upgrade_state('dns', 'ipa_ca_cname', True)
|
return
|
||||||
finally:
|
|
||||||
if api.Backend.ldap2.isconnected():
|
ret = api.Command['dns_is_enabled']()
|
||||||
api.Backend.ldap2.disconnect()
|
if not ret['result']:
|
||||||
else:
|
root_logger.info('DNS is not configured')
|
||||||
root_logger.info('IPA CA CNAME already processed')
|
sysupgrade.set_upgrade_state('dns', 'ipa_ca_records', True)
|
||||||
|
return
|
||||||
|
|
||||||
|
bind = bindinstance.BindInstance()
|
||||||
|
|
||||||
|
bind.convert_ipa_ca_cnames(api.env.domain)
|
||||||
|
|
||||||
|
# DNS is enabled, so let bindinstance find out if CA is enabled
|
||||||
|
# and let it add the record in that case
|
||||||
|
bind.add_ipa_ca_dns_records(api.env.host, api.env.domain,
|
||||||
|
ca_configured=None)
|
||||||
|
|
||||||
|
sysupgrade.set_upgrade_state('dns', 'ipa_ca_records', True)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
@@ -845,7 +849,7 @@ def main():
|
|||||||
|
|
||||||
cleanup_kdc(fstore)
|
cleanup_kdc(fstore)
|
||||||
setup_firefox_extension(fstore)
|
setup_firefox_extension(fstore)
|
||||||
add_server_cname_records()
|
add_ca_dns_records()
|
||||||
changed_psearch = named_enable_psearch()
|
changed_psearch = named_enable_psearch()
|
||||||
changed_autoincrement = named_enable_serial_autoincrement()
|
changed_autoincrement = named_enable_serial_autoincrement()
|
||||||
changed_gssapi_conf = named_update_gssapi_configuration()
|
changed_gssapi_conf = named_update_gssapi_configuration()
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import installutils
|
|||||||
import service
|
import service
|
||||||
from ipaserver.plugins import ldap2
|
from ipaserver.plugins import ldap2
|
||||||
from ipaserver.install.dsinstance import realm_to_serverid
|
from ipaserver.install.dsinstance import realm_to_serverid
|
||||||
from ipaserver.install.cainstance import IPA_CA_CNAME
|
from ipaserver.install.cainstance import IPA_CA_RECORD
|
||||||
from ipapython import sysrestore, ipautil, ipaldap
|
from ipapython import sysrestore, ipautil, ipaldap
|
||||||
from ipapython.ipa_log_manager import *
|
from ipapython.ipa_log_manager import *
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
@@ -357,6 +357,13 @@ def del_rr(zone, name, type, rdata):
|
|||||||
except (errors.NotFound, errors.AttrValueNotFound, errors.EmptyModlist):
|
except (errors.NotFound, errors.AttrValueNotFound, errors.EmptyModlist):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def del_fwd_rr(zone, host, ip_address):
|
||||||
|
addr = netaddr.IPAddress(ip_address)
|
||||||
|
if addr.version == 4:
|
||||||
|
del_rr(zone, host, "A", ip_address)
|
||||||
|
elif addr.version == 6:
|
||||||
|
del_rr(zone, host, "AAAA", ip_address)
|
||||||
|
|
||||||
def get_rr(zone, name, type):
|
def get_rr(zone, name, type):
|
||||||
rectype = '%srecord' % unicode(type.lower())
|
rectype = '%srecord' % unicode(type.lower())
|
||||||
ret = api.Command.dnsrecord_find(unicode(zone), unicode(name))
|
ret = api.Command.dnsrecord_find(unicode(zone), unicode(name))
|
||||||
@@ -367,6 +374,9 @@ def get_rr(zone, name, type):
|
|||||||
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def get_fwd_rr(zone, host):
|
||||||
|
return [x for t in ("A", "AAAA") for x in get_rr(zone, host, t)]
|
||||||
|
|
||||||
def zonemgr_callback(option, opt_str, value, parser):
|
def zonemgr_callback(option, opt_str, value, parser):
|
||||||
"""
|
"""
|
||||||
Properly validate and convert --zonemgr Option to IA5String
|
Properly validate and convert --zonemgr Option to IA5String
|
||||||
@@ -523,7 +533,7 @@ class BindInstance(service.Service):
|
|||||||
if self.reverse_zone is not None:
|
if self.reverse_zone is not None:
|
||||||
self.step("setting up reverse zone", self.__setup_reverse_zone)
|
self.step("setting up reverse zone", self.__setup_reverse_zone)
|
||||||
self.step("setting up our own record", self.__add_self)
|
self.step("setting up our own record", self.__add_self)
|
||||||
self.step("setting up CA CNAME record", self.__add_ipa_ca_cname)
|
self.step("setting up CA record", self.__add_ipa_ca_record)
|
||||||
|
|
||||||
self.step("setting up kerberos principal", self.__setup_principal)
|
self.step("setting up kerberos principal", self.__setup_principal)
|
||||||
self.step("setting up named.conf", self.__setup_named_conf)
|
self.step("setting up named.conf", self.__setup_named_conf)
|
||||||
@@ -568,6 +578,15 @@ class BindInstance(service.Service):
|
|||||||
else:
|
else:
|
||||||
optional_ntp = ""
|
optional_ntp = ""
|
||||||
|
|
||||||
|
addr = netaddr.IPAddress(self.ip_address)
|
||||||
|
if addr.version in (4, 6):
|
||||||
|
ipa_ca = "%s\t\t\tIN %s\t\t\t%s\n" % (
|
||||||
|
IPA_CA_RECORD,
|
||||||
|
"A" if addr.version == 4 else "AAAA",
|
||||||
|
self.ip_address)
|
||||||
|
else:
|
||||||
|
ipa_ca = ""
|
||||||
|
|
||||||
boolean_var = {}
|
boolean_var = {}
|
||||||
for var in ('persistent_search', 'serial_autoincrement'):
|
for var in ('persistent_search', 'serial_autoincrement'):
|
||||||
boolean_var[var] = "yes" if getattr(self, var, False) else "no"
|
boolean_var[var] = "yes" if getattr(self, var, False) else "no"
|
||||||
@@ -583,7 +602,7 @@ class BindInstance(service.Service):
|
|||||||
OPTIONAL_NTP=optional_ntp,
|
OPTIONAL_NTP=optional_ntp,
|
||||||
ZONEMGR=self.zonemgr,
|
ZONEMGR=self.zonemgr,
|
||||||
ZONE_REFRESH=self.zone_refresh,
|
ZONE_REFRESH=self.zone_refresh,
|
||||||
IPA_CA_CNAME=IPA_CA_CNAME,
|
IPA_CA_RECORD=ipa_ca,
|
||||||
PERSISTENT_SEARCH=boolean_var['persistent_search'],
|
PERSISTENT_SEARCH=boolean_var['persistent_search'],
|
||||||
SERIAL_AUTOINCREMENT=boolean_var['serial_autoincrement'],)
|
SERIAL_AUTOINCREMENT=boolean_var['serial_autoincrement'],)
|
||||||
|
|
||||||
@@ -610,27 +629,35 @@ class BindInstance(service.Service):
|
|||||||
def __add_self_ns(self):
|
def __add_self_ns(self):
|
||||||
add_ns_rr(self.domain, api.env.host, self.dns_backup, force=True)
|
add_ns_rr(self.domain, api.env.host, self.dns_backup, force=True)
|
||||||
|
|
||||||
def __add_ipa_ca_cname(self):
|
def _add_ipa_ca_dns_records(self, domain_name, fqdn, addrs, ca_configured):
|
||||||
if self.ca_configured is False:
|
if ca_configured is False:
|
||||||
root_logger.debug("CA is not configured, skip this step")
|
root_logger.debug("CA is not configured")
|
||||||
return
|
return
|
||||||
elif self.ca_configured is None:
|
elif ca_configured is None:
|
||||||
# we do not know if CA is configured for this host and we can
|
# we do not know if CA is configured for this host and we can
|
||||||
# add the CA CNAME record. So we need to find out
|
# add the CA record. So we need to find out
|
||||||
root_logger.debug("Check if CA is enabled for this host")
|
root_logger.debug("Check if CA is enabled for this host")
|
||||||
base_dn = DN(('cn', api.env.host), ('cn', 'masters'), ('cn', 'ipa'),
|
base_dn = DN(('cn', fqdn), ('cn', 'masters'), ('cn', 'ipa'),
|
||||||
('cn', 'etc'), api.env.basedn)
|
('cn', 'etc'), api.env.basedn)
|
||||||
ldap_filter = '(&(objectClass=ipaConfigObject)(cn=CA))'
|
ldap_filter = '(&(objectClass=ipaConfigObject)(cn=CA))'
|
||||||
try:
|
try:
|
||||||
api.Backend.ldap2.find_entries(filter=ldap_filter, base_dn=base_dn)
|
api.Backend.ldap2.find_entries(filter=ldap_filter, base_dn=base_dn)
|
||||||
except ipalib.errors.NotFound:
|
except ipalib.errors.NotFound:
|
||||||
# CA is not configured
|
|
||||||
root_logger.debug("CA is not configured")
|
root_logger.debug("CA is not configured")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
root_logger.debug("CA is configured for this host, continue")
|
root_logger.debug("CA is configured for this host")
|
||||||
|
|
||||||
add_rr(self.domain, IPA_CA_CNAME, "CNAME", self.host_in_rr)
|
try:
|
||||||
|
for addr in addrs:
|
||||||
|
add_fwd_rr(domain_name, IPA_CA_RECORD, addr)
|
||||||
|
except errors.ValidationError:
|
||||||
|
# there is a CNAME record in ipa-ca, we can't add A/AAAA records
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __add_ipa_ca_record(self):
|
||||||
|
self._add_ipa_ca_dns_records(self.domain, self.fqdn, [self.ip_address],
|
||||||
|
self.ca_configured)
|
||||||
|
|
||||||
def __add_self(self):
|
def __add_self(self):
|
||||||
zone = self.domain
|
zone = self.domain
|
||||||
@@ -743,14 +770,62 @@ class BindInstance(service.Service):
|
|||||||
self.ca_configured = ca_configured
|
self.ca_configured = ca_configured
|
||||||
|
|
||||||
self.__add_self()
|
self.__add_self()
|
||||||
self.__add_ipa_ca_cname()
|
self.__add_ipa_ca_record()
|
||||||
|
|
||||||
def add_ipa_ca_cname(self, fqdn, domain_name, ca_configured=True):
|
def add_ipa_ca_dns_records(self, fqdn, domain_name, ca_configured=True):
|
||||||
self.host = fqdn.split(".")[0]
|
host, zone = fqdn.split(".", 1)
|
||||||
self.fqdn = fqdn
|
if dns_zone_exists(zone):
|
||||||
self.domain = domain_name
|
addrs = get_fwd_rr(zone, host)
|
||||||
self.ca_configured = ca_configured
|
else:
|
||||||
self.__add_ipa_ca_cname()
|
addrs = installutils.resolve_host(fqdn)
|
||||||
|
|
||||||
|
self._add_ipa_ca_dns_records(domain_name, fqdn, addrs, ca_configured)
|
||||||
|
|
||||||
|
def convert_ipa_ca_cnames(self, domain_name):
|
||||||
|
# get ipa-ca CNAMEs
|
||||||
|
cnames = get_rr(domain_name, IPA_CA_RECORD, "CNAME")
|
||||||
|
if not cnames:
|
||||||
|
return
|
||||||
|
|
||||||
|
root_logger.info('Converting IPA CA CNAME records to A/AAAA records')
|
||||||
|
|
||||||
|
# create CNAME to FQDN mapping
|
||||||
|
cname_fqdn = {}
|
||||||
|
for cname in cnames:
|
||||||
|
if cname.endswith('.'):
|
||||||
|
fqdn = cname[:-1]
|
||||||
|
else:
|
||||||
|
fqdn = '%s.%s' % (cname, domain_name)
|
||||||
|
cname_fqdn[cname] = fqdn
|
||||||
|
|
||||||
|
# get FQDNs of all IPA masters
|
||||||
|
ldap = api.Backend.ldap2
|
||||||
|
try:
|
||||||
|
entries = ldap.get_entries(
|
||||||
|
DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'),
|
||||||
|
api.env.basedn),
|
||||||
|
ldap.SCOPE_ONELEVEL, None, ['cn'])
|
||||||
|
masters = set(e['cn'][0] for e in entries)
|
||||||
|
except errors.NotFound:
|
||||||
|
masters = set()
|
||||||
|
|
||||||
|
# check if all CNAMEs point to IPA masters
|
||||||
|
for cname in cnames:
|
||||||
|
fqdn = cname_fqdn[cname]
|
||||||
|
if fqdn not in masters:
|
||||||
|
root_logger.warning(
|
||||||
|
"Cannot convert IPA CA CNAME records to A/AAAA records, "
|
||||||
|
"please convert them manually if necessary")
|
||||||
|
return
|
||||||
|
|
||||||
|
# delete all CNAMEs
|
||||||
|
for cname in cnames:
|
||||||
|
del_rr(domain_name, IPA_CA_RECORD, "CNAME", cname)
|
||||||
|
|
||||||
|
# add A/AAAA records
|
||||||
|
for cname in cnames:
|
||||||
|
fqdn = cname_fqdn[cname]
|
||||||
|
self.add_ipa_ca_dns_records(fqdn, domain_name, None)
|
||||||
|
|
||||||
def remove_master_dns_records(self, fqdn, realm_name, domain_name):
|
def remove_master_dns_records(self, fqdn, realm_name, domain_name):
|
||||||
host = fqdn.split(".")[0]
|
host = fqdn.split(".")[0]
|
||||||
@@ -769,16 +844,15 @@ class BindInstance(service.Service):
|
|||||||
("_kpasswd._tcp", "SRV", "0 100 464 %s" % self.host_in_rr),
|
("_kpasswd._tcp", "SRV", "0 100 464 %s" % self.host_in_rr),
|
||||||
("_kpasswd._udp", "SRV", "0 100 464 %s" % self.host_in_rr),
|
("_kpasswd._udp", "SRV", "0 100 464 %s" % self.host_in_rr),
|
||||||
("_ntp._udp", "SRV", "0 100 123 %s" % self.host_in_rr),
|
("_ntp._udp", "SRV", "0 100 123 %s" % self.host_in_rr),
|
||||||
(IPA_CA_CNAME, "CNAME", self.host_in_rr),
|
|
||||||
("@", "NS", fqdn+"."),
|
("@", "NS", fqdn+"."),
|
||||||
)
|
)
|
||||||
|
|
||||||
for (record, type, rdata) in resource_records:
|
for (record, type, rdata) in resource_records:
|
||||||
del_rr(zone, record, type, rdata)
|
del_rr(zone, record, type, rdata)
|
||||||
|
|
||||||
areclist = [("A", x) for x in get_rr(zone, host, "A")] + [("AAAA", x) for x in get_rr(zone, host, "AAAA")]
|
areclist = get_fwd_rr(zone, host)
|
||||||
for (type, rdata) in areclist:
|
for rdata in areclist:
|
||||||
del_rr(zone, host, type, rdata)
|
del_fwd_rr(zone, host, rdata)
|
||||||
|
|
||||||
rzone = find_reverse_zone(rdata)
|
rzone = find_reverse_zone(rdata)
|
||||||
if rzone is not None:
|
if rzone is not None:
|
||||||
@@ -787,6 +861,16 @@ class BindInstance(service.Service):
|
|||||||
# remove also master NS record from the reverse zone
|
# remove also master NS record from the reverse zone
|
||||||
del_rr(rzone, "@", "NS", fqdn+".")
|
del_rr(rzone, "@", "NS", fqdn+".")
|
||||||
|
|
||||||
|
def remove_ipa_ca_dns_records(self, fqdn, domain_name):
|
||||||
|
host, zone = fqdn.split(".", 1)
|
||||||
|
if dns_zone_exists(zone):
|
||||||
|
addrs = get_fwd_rr(zone, host)
|
||||||
|
else:
|
||||||
|
addrs = installutils.resolve_host(fqdn)
|
||||||
|
|
||||||
|
for addr in addrs:
|
||||||
|
del_fwd_rr(domain_name, IPA_CA_RECORD, addr)
|
||||||
|
|
||||||
def check_global_configuration(self):
|
def check_global_configuration(self):
|
||||||
"""
|
"""
|
||||||
Check global DNS configuration in LDAP server and inform user when it
|
Check global DNS configuration in LDAP server and inform user when it
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ PKI_DS_USER = dogtag.install_constants.DS_USER
|
|||||||
|
|
||||||
# When IPA is installed with DNS support, this CNAME should hold all IPA
|
# When IPA is installed with DNS support, this CNAME should hold all IPA
|
||||||
# replicas with CA configured
|
# replicas with CA configured
|
||||||
IPA_CA_CNAME = "ipa-ca"
|
IPA_CA_RECORD = "ipa-ca"
|
||||||
|
|
||||||
# We need to reset the template because the CA uses the regular boot
|
# We need to reset the template because the CA uses the regular boot
|
||||||
# information
|
# information
|
||||||
@@ -1271,7 +1271,7 @@ class CAInstance(service.Service):
|
|||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
# OCSP extension
|
# OCSP extension
|
||||||
ocsp_url = 'http://%s.%s/ca/ocsp' % (IPA_CA_CNAME, ipautil.format_netloc(domain))
|
ocsp_url = 'http://%s.%s/ca/ocsp' % (IPA_CA_RECORD, ipautil.format_netloc(domain))
|
||||||
|
|
||||||
ocsp_location_0 = installutils.get_directive(
|
ocsp_location_0 = installutils.get_directive(
|
||||||
self.dogtag_constants.IPA_SERVICE_PROFILE,
|
self.dogtag_constants.IPA_SERVICE_PROFILE,
|
||||||
@@ -1298,7 +1298,7 @@ class CAInstance(service.Service):
|
|||||||
|
|
||||||
|
|
||||||
# CRL extension
|
# CRL extension
|
||||||
crl_url = 'http://%s.%s/ipa/crl/MasterCRL.bin'% (IPA_CA_CNAME, ipautil.format_netloc(domain))
|
crl_url = 'http://%s.%s/ipa/crl/MasterCRL.bin'% (IPA_CA_RECORD, ipautil.format_netloc(domain))
|
||||||
|
|
||||||
crl_point_0 = installutils.get_directive(
|
crl_point_0 = installutils.get_directive(
|
||||||
self.dogtag_constants.IPA_SERVICE_PROFILE,
|
self.dogtag_constants.IPA_SERVICE_PROFILE,
|
||||||
|
|||||||
Reference in New Issue
Block a user