From b733178bac980fba0af5dda9ff1218ca7e2c2676 Mon Sep 17 00:00:00 2001 From: Andreas Olsson Date: Fri, 27 Dec 2019 16:02:25 +0100 Subject: [PATCH] nsupdate: Use provided TSIG key for all queries (#63174) In addition to signing update queries also use the TSIG key to sign lookup queries. By doing that we allow a hidden master to not only to be looked down network wise, but also TSIG wise. A bonus benefit of threating update queries and lookup queries more the same is that will allow for all queries to be refactored into a shared helper method. Currently we have a bit too much duplicated code within the module. --- .../63174-nsupdate-tsig-all-the-queries.yaml | 2 + lib/ansible/modules/net_tools/nsupdate.py | 41 ++++++++++++------- 2 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 changelogs/fragments/63174-nsupdate-tsig-all-the-queries.yaml diff --git a/changelogs/fragments/63174-nsupdate-tsig-all-the-queries.yaml b/changelogs/fragments/63174-nsupdate-tsig-all-the-queries.yaml new file mode 100644 index 0000000000..0935ce9c14 --- /dev/null +++ b/changelogs/fragments/63174-nsupdate-tsig-all-the-queries.yaml @@ -0,0 +1,2 @@ +minor_changes: + - nsupdate - Use provided TSIG key to not only sign update queries but also lookup queries diff --git a/lib/ansible/modules/net_tools/nsupdate.py b/lib/ansible/modules/net_tools/nsupdate.py index 59f29aa293..9c33a082d5 100644 --- a/lib/ansible/modules/net_tools/nsupdate.py +++ b/lib/ansible/modules/net_tools/nsupdate.py @@ -200,21 +200,6 @@ class RecordManager(object): def __init__(self, module): self.module = module - if module.params['zone'] is None: - if module.params['record'][-1] != '.': - self.module.fail_json(msg='record must be absolute when omitting zone parameter') - self.zone = self.lookup_zone() - else: - self.zone = module.params['zone'] - - if self.zone[-1] != '.': - self.zone += '.' - - if module.params['record'][-1] != '.': - self.fqdn = module.params['record'] + '.' + self.zone - else: - self.fqdn = module.params['record'] - if module.params['key_name']: try: self.keyring = dns.tsigkeyring.from_text({ @@ -232,6 +217,21 @@ class RecordManager(object): else: self.algorithm = module.params['key_algorithm'] + if module.params['zone'] is None: + if module.params['record'][-1] != '.': + self.module.fail_json(msg='record must be absolute when omitting zone parameter') + self.zone = self.lookup_zone() + else: + self.zone = module.params['zone'] + + if self.zone[-1] != '.': + self.zone += '.' + + if module.params['record'][-1] != '.': + self.fqdn = module.params['record'] + '.' + self.zone + else: + self.fqdn = module.params['record'] + if self.module.params['type'].lower() == 'txt' and self.module.params['value'] is not None: self.value = list(map(self.txt_helper, self.module.params['value'])) else: @@ -248,11 +248,15 @@ class RecordManager(object): name = dns.name.from_text(self.module.params['record']) while True: query = dns.message.make_query(name, dns.rdatatype.SOA) + if self.keyring: + query.use_tsig(keyring=self.keyring, algorithm=self.algorithm) try: if self.module.params['protocol'] == 'tcp': lookup = dns.query.tcp(query, self.module.params['server'], timeout=10, port=self.module.params['port']) else: lookup = dns.query.udp(query, self.module.params['server'], timeout=10, port=self.module.params['port']) + except (dns.tsig.PeerBadKey, dns.tsig.PeerBadSignature) as e: + self.module.fail_json(msg='TSIG update error (%s): %s' % (e.__class__.__name__, to_native(e))) except (socket_error, dns.exception.Timeout) as e: self.module.fail_json(msg='DNS server error: (%s): %s' % (e.__class__.__name__, to_native(e))) if lookup.rcode() in [dns.rcode.SERVFAIL, dns.rcode.REFUSED]: @@ -400,15 +404,22 @@ class RecordManager(object): def ttl_changed(self): query = dns.message.make_query(self.fqdn, self.module.params['type']) + if self.keyring: + query.use_tsig(keyring=self.keyring, algorithm=self.algorithm) try: if self.module.params['protocol'] == 'tcp': lookup = dns.query.tcp(query, self.module.params['server'], timeout=10, port=self.module.params['port']) else: lookup = dns.query.udp(query, self.module.params['server'], timeout=10, port=self.module.params['port']) + except (dns.tsig.PeerBadKey, dns.tsig.PeerBadSignature) as e: + self.module.fail_json(msg='TSIG update error (%s): %s' % (e.__class__.__name__, to_native(e))) except (socket_error, dns.exception.Timeout) as e: self.module.fail_json(msg='DNS server error: (%s): %s' % (e.__class__.__name__, to_native(e))) + if lookup.rcode() != dns.rcode.NOERROR: + self.module.fail_json(msg='Failed to lookup TTL of existing matching record.') + current_ttl = lookup.answer[0].ttl return current_ttl != self.module.params['ttl']