Skip to content

Commit

Permalink
Wipe the ipa-ca DNS record when updating system records
Browse files Browse the repository at this point in the history
If a server with a CA has been marked as hidden and
contains the last A or AAAA address then that address
would remain in the ipa-ca entry.

This is because update-dns-system-records did not delete
values, it just re-computed them. So if no A or AAAA
records were found then the existing value was left.

Fixes: https://pagure.io/freeipa/issue/9195

Signed-off-by: Rob Crittenden <rcritten@redhat.com>
  • Loading branch information
rcritten committed Jul 18, 2022
1 parent b7243ed commit 461cb38
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 1 deletion.
11 changes: 10 additions & 1 deletion ipaserver/dns_data_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from time import sleep, time

from ipalib import errors
from ipalib.constants import IPA_CA_RECORD
from ipalib.dns import record_name_format
from ipapython.dnsutil import DNSName
from ipaserver.install import installutils
Expand Down Expand Up @@ -183,7 +184,7 @@ def __add_uri_records(

def __add_ca_records_from_hostname(self, zone_obj, hostname):
assert isinstance(hostname, DNSName) and hostname.is_absolute()
r_name = DNSName('ipa-ca') + self.domain_abs
r_name = DNSName(IPA_CA_RECORD) + self.domain_abs
rrsets = None
end_time = time() + CA_RECORDS_DNS_TIMEOUT
while True:
Expand Down Expand Up @@ -443,6 +444,14 @@ def update_base_records(self):
)
)

# Remove the ipa-ca record(s). They will be reconstructed in
# get_base_records().
r_name = DNSName('ipa-ca') + self.domain_abs
try:
self.api_instance.Command.dnsrecord_del(
self.domain_abs, r_name, del_all=True)
except errors.NotFound:
pass
base_zone = self.get_base_records()
for record_name, node in base_zone.items():
set_cname_template = record_name in names_requiring_cname_templates
Expand Down
80 changes: 80 additions & 0 deletions ipatests/test_integration/test_dns_locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ def _gen_expected_a_rrset(rname, servers, ttl=86400):
dns.rdatatype.A, servers)


def _gen_expected_aaaa_rrset(rname, servers, ttl=86400):
return dns.rrset.from_text_list(rname, ttl, dns.rdataclass.IN,
dns.rdatatype.AAAA, servers)


def _get_relative_weights(text):
"""Takes location-show output and returns a list of percentages"""
return re.findall(r"\d+.\d%", text)
Expand Down Expand Up @@ -186,6 +191,25 @@ def _test_A_rec_against_server(self, server_ip, domain, expected_servers,
"with IP: '{}' for name '{}' (expected:\n{}\ngot:\n{})".
format(server_ip, name_abs, expected, query))

def _test_AAAA_rec_against_server(self, server_ip, domain,
expected_servers,
rec_list=IPA_CA_A_REC):
for rname in rec_list:
name_abs = rname.derelativize(domain)
expected = _gen_expected_aaaa_rrset(name_abs, expected_servers)
try:
query = resolve_records_from_server(
name_abs, 'AAAA', server_ip)
except dns.resolver.NoAnswer as e:
if len(expected_servers) == 0:
return True
raise(e)

assert expected == query, (
"Expected and received DNS data do not match on server "
"with IP: '{}' for name '{}' (expected:\n{}\ngot:\n{})".
format(server_ip, name_abs, expected, query))

def _test_SRV_rec_against_server(self, server_ip, domain, expected_servers,
rec_list=IPA_DEFAULT_MASTER_SRV_REC):
for rname, port in rec_list:
Expand Down Expand Up @@ -537,6 +561,62 @@ def test_ipa_ca_records(self):
for ip in (self.master.ip, self.replicas[0].ip, self.replicas[1].ip):
self._test_A_rec_against_server(ip, self.domain, expected_servers)

def test_hidden_ipa_ca_records(self):
"""Test ipa-ca dns records with a hidden server with a CA
If a server has the last A/AAAA record make sure it is
removed when hidden.
"""

FAKE_IPV6_ADDRESS = '2620:ffff:ffff:ffff:ffff:ffff:ffff:ffff'
self.delete_update_system_records(rnames=IPA_CA_A_REC)

# CI is still using IPv4. Add a single IPv6 record for testing.
self.master.run_command([
'ipa', 'dnsrecord-add', str(self.domain),
self.replicas[1].hostname + '.',
'--aaaa-rec', FAKE_IPV6_ADDRESS])

# This should add the new IP to the ipa-ca name.
self.master.run_command(['ipa', 'dns-update-system-records'])
time.sleep(5)

expected_ipv4_servers = (self.master.ip, self.replicas[1].ip)
expected_ipv6_servers = (FAKE_IPV6_ADDRESS,)

self._test_A_rec_against_server(self.master.ip, self.domain,
expected_ipv4_servers)
self._test_AAAA_rec_against_server(self.master.ip, self.domain,
expected_ipv6_servers)

# Now hide a server
self.master.run_command([
'ipa', 'server-state',
self.replicas[1].hostname, '--state=hidden'])

expected_ipv4_servers = (self.master.ip,)
expected_ipv6_servers = tuple()

self._test_A_rec_against_server(self.master.ip, self.domain,
expected_ipv4_servers)
self._test_AAAA_rec_against_server(self.master.ip, self.domain,
expected_ipv6_servers)
self.master.run_command([
'ipa', 'server-state',
self.replicas[1].hostname, '--state=enabled'])

expected_ipv4_servers = (self.master.ip, self.replicas[1].ip)
expected_ipv6_servers = (FAKE_IPV6_ADDRESS,)

self._test_A_rec_against_server(self.master.ip, self.domain,
expected_ipv4_servers)
self._test_AAAA_rec_against_server(self.master.ip, self.domain,
expected_ipv6_servers)

self.master.run_command([
'ipa', 'dnsrecord-del', str(self.domain),
self.replicas[1].hostname,
'--aaaa-rec', FAKE_IPV6_ADDRESS])

def test_adtrust_system_records(self):
""" Test ADTrust dns records with firstly installing a trust then
Expand Down

0 comments on commit 461cb38

Please sign in to comment.