Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

refine DNS-checking and add automated tests #372

Merged
merged 11 commits into from
Jul 16, 2024
Merged

refine DNS-checking and add automated tests #372

merged 11 commits into from
Jul 16, 2024

Conversation

hpk42
Copy link
Contributor

@hpk42 hpk42 commented Jul 15, 2024

supersedes #355

There are now phases of DNS checks:

  • initial DNS entries that must be present for "cmdeploy run"

  • required DNS entries for operating within the chatmail server network

  • recommended DNS settings for interoperability and security hardening

"cmdeploy dns" will return 0 as exitcode (all ok) if all required DNS settings are correct but will print warnings for any missing recommended one

We might want to shift the SPF record from recommended into required.

hpk42 added 6 commits July 13, 2024 19:20
- don't try to guess IP addresses but insist on A and AAAA records
- try to allow ipv4 or ipv6 only zones
- move chatmail.zone generation to jinja so we can have conditionals
Copy link
Contributor

@missytake missytake left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

Comment on lines 77 to +101
def check_zonefile(zonefile):
diff = []
"""Check expected zone file entries."""
required = True
required_diff = []
recommended_diff = []

for zf_line in zonefile.splitlines():
if "; Recommended" in zf_line:
required = False
continue
if not zf_line.strip() or zf_line.startswith(";"):
continue
print(f"dns-checking {zf_line!r}")
zf_domain, zf_typ, zf_value = zf_line.split(maxsplit=2)
zf_domain = zf_domain.rstrip(".")
zf_value = zf_value.strip()
query_values = query_dns(zf_typ, zf_domain)
if zf_value in query_values:
continue
query_value = query_dns(zf_typ, zf_domain)
if zf_value != query_value:
assert zf_typ in ("A", "AAAA", "CNAME", "CAA", "SRV", "MX", "TXT"), zf_line
if required:
required_diff.append(zf_line)
else:
recommended_diff.append(zf_line)

return required_diff, recommended_diff
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, this is beautiful. I still think with horror of my previous spaghetti code

Comment on lines +85 to +90
def test_check_zonefile_all_ok(self, cm_data, mockdns_base):
zonefile = cm_data.get("zftest.zone")
parse_zonefile_into_dict(zonefile, mockdns_base)
required_diff, recommended_diff = remote_funcs.check_zonefile(zonefile)
assert not required_diff and not recommended_diff

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this PR, setting recommended DNS records on with a zonefile is sliding out of the part which is tested by CI, as cmdeploy dns doesn't fail for them anymore. This is probably not a huge problem, but we should notice it consciously.

In the past, the CI set all DNS records on ns.testrun.org, and then ran cmdeploy dns to verify them, and return had to be zero (with three tries). Now I wonder if we would notice if one of the recommended DNS records isn't set as expected anymore, as CI could still be green. Note that there can be complications while setting DNS records, e.g. formatting of DKIM records. OTOH, most of them happen in web interfaces, which are not tested anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point. Let's maybe do this is a separate PR -- an option "--all" that gives return code 1 if any dns record does not match.

@hpk42 hpk42 merged commit d3c29b2 into main Jul 16, 2024
5 checks passed
@hpk42 hpk42 deleted the hpk/refine-dns branch July 16, 2024 08:34
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants