From 6d772874f978295d7e5315bfbd5a65d744d1f744 Mon Sep 17 00:00:00 2001 From: Andreas Olsson Date: Wed, 15 Aug 2018 17:30:33 +0200 Subject: [PATCH] Add SSHFP and TLSA records to cloudflare_dns module (#44011) * Update cloudflare_dns account link * Add SSHFP and TLSA records to cloudflare_dns module These are record types which Cloudflare recently added support for. They both go well together with DNSSEC. Technically it's a bit of a simplification to use the hash_type parameter for TLSA records. Yet, it fits with all the real world usage I have seen, and it keeps the module from sprawling too much. Related to #43803 --- .../modules/net_tools/cloudflare_dns.py | 135 +++++++++- .../roles/test_cloudflare_dns/tasks/main.yml | 2 + .../tasks/sshfp_record.yml | 207 +++++++++++++++ .../test_cloudflare_dns/tasks/tlsa_record.yml | 239 ++++++++++++++++++ 4 files changed, 575 insertions(+), 8 deletions(-) create mode 100644 test/legacy/roles/test_cloudflare_dns/tasks/sshfp_record.yml create mode 100644 test/legacy/roles/test_cloudflare_dns/tasks/tlsa_record.yml diff --git a/lib/ansible/modules/net_tools/cloudflare_dns.py b/lib/ansible/modules/net_tools/cloudflare_dns.py index b4870fb45c5..4449c02f2d5 100644 --- a/lib/ansible/modules/net_tools/cloudflare_dns.py +++ b/lib/ansible/modules/net_tools/cloudflare_dns.py @@ -27,20 +27,38 @@ options: account_api_token: description: - > - Account API token. You can obtain your API key from the bottom of the Cloudflare 'My Account' page, found here: U(https://www.cloudflare.com/a/account) + Account API token. You can obtain your API key from the bottom of the Cloudflare 'My Account' page, found here: U(https://dash.cloudflare.com/) required: true account_email: description: - "Account email." required: true + algorithm: + description: + - Algorithm number. Required for C(type=SSHFP) when C(state=present). + choices: [ 1, 2, 3, 4 ] + type: int + version_added: 2.7 + cert_usage: + description: + - Certificate usage number. Required for C(type=TLSA) when C(state=present). + choices: [ 0, 1, 2, 3 ] + type: int + version_added: 2.7 + hash_type: + description: + - Hash type number. Required for C(type=SSHFP) and C(type=TLSA) when C(state=present). + choices: [ 1, 2 ] + type: int + version_added: 2.7 port: - description: Service port. Required for C(type=SRV) + description: Service port. Required for C(type=SRV) and C(type=TLSA). priority: description: Record priority. Required for C(type=MX) and C(type=SRV) default: "1" proto: description: - - Service protocol. Required for C(type=SRV). + - Service protocol. Required for C(type=SRV) and C(type=TLSA). - Common values are tcp and udp. - Before Ansible 2.6 only tcp and udp were available. proxied: @@ -53,6 +71,12 @@ options: - Record to add. Required if C(state=present). Default is C(@) (e.g. the zone name) default: "@" aliases: [ "name" ] + selector: + description: + - Selector number. Required for C(type=TLSA) when C(state=present). + choices: [ 0, 1 ] + type: int + version_added: 2.7 service: description: Record service. Required for C(type=SRV) solo: @@ -75,7 +99,8 @@ options: type: description: - The type of DNS record to create. Required if C(state=present) - choices: [ 'A', 'AAAA', 'CNAME', 'TXT', 'SRV', 'MX', 'NS', 'SPF' ] + - C(type=SSHFP) and C(type=TLSA) added in Ansible 2.7. + choices: [ 'A', 'AAAA', 'CNAME', 'TXT', 'SRV', 'MX', 'NS', 'SPF', 'SSHFP', 'TLSA' ] value: description: - The record value. Required for C(state=present) @@ -161,6 +186,27 @@ EXAMPLES = ''' weight: 20 type: SRV value: fooserver.my.com + +# create a SSHFP record login.example.com +- cloudflare_dns: + zone: example.com + record: login + type: SSHFP + algorithm: 4 + hash_type: 2 + value: 9dc1d6742696d2f51ca1f1a78b3d16a840f7d111eb9454239e70db31363f33e1 + +# create a TLSA record _25._tcp.mail.example.com +- cloudflare_dns: + zone: example.com + record: mail + port: 25 + proto: tcp + type: TLSA + cert_usage: 3 + selector: 1 + hash_type: 1 + value: 6b76d034492b493e15a7376fccd08e63befdad0edab8e442562f532338364bf3 ''' RETURN = ''' @@ -181,7 +227,7 @@ record: sample: 2016-03-25T19:09:42.516553Z data: description: additional record data - returned: success, if type is SRV + returned: success, if type is SRV, SSHFP or TLSA type: dictionary sample: { name: "jabber", @@ -271,10 +317,14 @@ class CloudflareAPI(object): self.module = module self.account_api_token = module.params['account_api_token'] self.account_email = module.params['account_email'] + self.algorithm = module.params['algorithm'] + self.cert_usage = module.params['cert_usage'] + self.hash_type = module.params['hash_type'] self.port = module.params['port'] self.priority = module.params['priority'] self.proto = module.params['proto'] self.proxied = module.params['proxied'] + self.selector = module.params['selector'] self.record = module.params['record'] self.service = module.params['service'] self.is_solo = module.params['solo'] @@ -298,6 +348,12 @@ class CloudflareAPI(object): if (self.service is not None) and (not self.service.startswith('_')): self.service = '_' + self.service + if (self.type == 'TLSA'): + if (self.proto is not None) and (not self.proto.startswith('_')): + self.proto = '_' + self.proto + if (self.port is not None): + self.port = '_' + str(self.port) + if not self.record.endswith(self.zone): self.record = self.record + '.' + self.zone @@ -447,7 +503,7 @@ class CloudflareAPI(object): def delete_dns_records(self, **kwargs): params = {} - for param in ['port', 'proto', 'service', 'solo', 'type', 'record', 'value', 'weight', 'zone']: + for param in ['port', 'proto', 'service', 'solo', 'type', 'record', 'value', 'weight', 'zone', 'algorithm', 'cert_usage', 'hash_type', 'selector']: if param in kwargs: params[param] = kwargs[param] else: @@ -460,6 +516,13 @@ class CloudflareAPI(object): if not (params['value'] is None or params['value'] == ''): content = str(params['weight']) + '\t' + str(params['port']) + '\t' + params['value'] search_record = params['service'] + '.' + params['proto'] + '.' + params['record'] + elif params['type'] == 'SSHFP': + if not (params['value'] is None or params['value'] == ''): + content = str(params['algorithm']) + '\t' + str(params['hash_type']) + '\t' + params['value'] + elif params['type'] == 'TLSA': + if not (params['value'] is None or params['value'] == ''): + content = str(params['cert_usage']) + '\t' + str(params['selector']) + '\t' + str(params['hash_type']) + '\t' + params['value'] + search_record = params['port'] + '.' + params['proto'] + '.' + params['record'] if params['solo']: search_value = None else: @@ -481,7 +544,8 @@ class CloudflareAPI(object): def ensure_dns_record(self, **kwargs): params = {} - for param in ['port', 'priority', 'proto', 'proxied', 'service', 'ttl', 'type', 'record', 'value', 'weight', 'zone']: + for param in ['port', 'priority', 'proto', 'proxied', 'service', 'ttl', 'type', 'record', 'value', 'weight', 'zone', + 'algorithm', 'cert_usage', 'hash_type', 'selector']: if param in kwargs: params[param] = kwargs[param] else: @@ -543,6 +607,42 @@ class CloudflareAPI(object): search_value = str(params['weight']) + '\t' + str(params['port']) + '\t' + params['value'] search_record = params['service'] + '.' + params['proto'] + '.' + params['record'] + if params['type'] == 'SSHFP': + for attr in [params['algorithm'], params['hash_type'], params['value']]: + if (attr is None) or (attr == ''): + self.module.fail_json(msg="You must provide algorithm, hash_type and a value to create this record type") + sshfp_data = { + "fingerprint": params['value'], + "type": params['hash_type'], + "algorithm": params['algorithm'], + } + new_record = { + "type": params['type'], + "name": params['record'], + 'data': sshfp_data, + "ttl": params['ttl'], + } + search_value = str(params['algorithm']) + '\t' + str(params['hash_type']) + '\t' + params['value'] + + if params['type'] == 'TLSA': + for attr in [params['port'], params['proto'], params['cert_usage'], params['selector'], params['hash_type'], params['value']]: + if (attr is None) or (attr == ''): + self.module.fail_json(msg="You must provide port, proto, cert_usage, selector, hash_type and a value to create this record type") + search_record = params['port'] + '.' + params['proto'] + '.' + params['record'] + tlsa_data = { + "usage": params['cert_usage'], + "selector": params['selector'], + "matching_type": params['hash_type'], + "certificate": params['value'], + } + new_record = { + "type": params['type'], + "name": search_record, + 'data': tlsa_data, + "ttl": params['ttl'], + } + search_value = str(params['cert_usage']) + '\t' + str(params['selector']) + '\t' + str(params['hash_type']) + '\t' + params['value'] + zone_id = self._get_zone_id(params['zone']) records = self.get_dns_records(params['zone'], params['type'], search_record, search_value) # in theory this should be impossible as cloudflare does not allow @@ -586,17 +686,21 @@ def main(): argument_spec=dict( account_api_token=dict(required=True, no_log=True, type='str'), account_email=dict(required=True, type='str'), + algorithm=dict(required=False, default=None, choices=[1, 2, 3, 4], type='int'), + cert_usage=dict(required=False, default=None, choices=[0, 1, 2, 3], type='int'), + hash_type=dict(required=False, default=None, choices=[1, 2], type='int'), port=dict(required=False, default=None, type='int'), priority=dict(required=False, default=1, type='int'), proto=dict(required=False, default=None, type='str'), proxied=dict(required=False, default=False, type='bool'), record=dict(required=False, default='@', aliases=['name'], type='str'), + selector=dict(required=False, default=None, choices=[0, 1], type='int'), service=dict(required=False, default=None, type='str'), solo=dict(required=False, default=None, type='bool'), state=dict(required=False, default='present', choices=['present', 'absent'], type='str'), timeout=dict(required=False, default=30, type='int'), ttl=dict(required=False, default=1, type='int'), - type=dict(required=False, default=None, choices=['A', 'AAAA', 'CNAME', 'TXT', 'SRV', 'MX', 'NS', 'SPF'], type='str'), + type=dict(required=False, default=None, choices=['A', 'AAAA', 'CNAME', 'TXT', 'SRV', 'MX', 'NS', 'SPF', 'SSHFP', 'TLSA'], type='str'), value=dict(required=False, default=None, aliases=['content'], type='str'), weight=dict(required=False, default=1, type='int'), zone=dict(required=True, default=None, aliases=['domain'], type='str'), @@ -606,6 +710,7 @@ def main(): ('state', 'present', ['record', 'type', 'value']), ('state', 'absent', ['record']), ('type', 'SRV', ['proto', 'service']), + ('type', 'TLSA', ['proto', 'port']), ] ), ) @@ -617,6 +722,20 @@ def main(): and (module.params['value'] is None or module.params['value'] == ''))): module.fail_json(msg="For SRV records the params weight, port and value all need to be defined, or not at all.") + if module.params['type'] == 'SSHFP': + if not ((module.params['algorithm'] is not None and module.params['hash_type'] is not None + and not (module.params['value'] is None or module.params['value'] == '')) + or (module.params['algorithm'] is None and module.params['hash_type'] is None + and (module.params['value'] is None or module.params['value'] == ''))): + module.fail_json(msg="For SSHFP records the params algorithm, hash_type and value all need to be defined, or not at all.") + + if module.params['type'] == 'TLSA': + if not ((module.params['cert_usage'] is not None and module.params['selector'] is not None and module.params['hash_type'] is not None + and not (module.params['value'] is None or module.params['value'] == '')) + or (module.params['cert_usage'] is None and module.params['selector'] is None and module.params['hash_type'] is None + and (module.params['value'] is None or module.params['value'] == ''))): + module.fail_json(msg="For TLSA records the params cert_usage, selector, hash_type and value all need to be defined, or not at all.") + changed = False cf_api = CloudflareAPI(module) diff --git a/test/legacy/roles/test_cloudflare_dns/tasks/main.yml b/test/legacy/roles/test_cloudflare_dns/tasks/main.yml index 339a216ea06..cc463b0dfd7 100644 --- a/test/legacy/roles/test_cloudflare_dns/tasks/main.yml +++ b/test/legacy/roles/test_cloudflare_dns/tasks/main.yml @@ -62,3 +62,5 @@ - include: spf_record.yml - include: mx_record.yml - include: srv_record.yml +- include: sshfp_record.yml +- include: tlsa_record.yml diff --git a/test/legacy/roles/test_cloudflare_dns/tasks/sshfp_record.yml b/test/legacy/roles/test_cloudflare_dns/tasks/sshfp_record.yml new file mode 100644 index 00000000000..634e2b85783 --- /dev/null +++ b/test/legacy/roles/test_cloudflare_dns/tasks/sshfp_record.yml @@ -0,0 +1,207 @@ +--- +######## SSHFP record tests ################# + +- name: "Test: SSHFP record creation" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + type: SSHFP + algorithm: 1 + hash_type: 2 + value: feb66965cee89137b4d4a46a15c718c3f15ad408b6d1b528a2ed479a54da762c + ttl: 150 + register: cloudflare_dns + +- name: "Validate: SSHFP record creation" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is changed + - cloudflare_dns.result.record.content == "1\t2\tfeb66965cee89137b4d4a46a15c718c3f15ad408b6d1b528a2ed479a54da762c" + - cloudflare_dns.result.record.ttl == 150 + - cloudflare_dns.result.record.type == "SSHFP" + - cloudflare_dns.result.record.name == "{{ cloudflare_dns_record }}.{{ cloudflare_zone }}" + - cloudflare_dns.result.record.zone_name == "{{ cloudflare_zone }}" + - cloudflare_dns.result.record.data.algorithm == 1 + - cloudflare_dns.result.record.data.type == 2 + - cloudflare_dns.result.record.data.fingerprint == "feb66965cee89137b4d4a46a15c718c3f15ad408b6d1b528a2ed479a54da762c" + +- name: "Test: SSHFP record idempotency" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + type: SSHFP + algorithm: 1 + hash_type: 2 + value: feb66965cee89137b4d4a46a15c718c3f15ad408b6d1b528a2ed479a54da762c + ttl: 150 + register: cloudflare_dns + +- name: "Validate: SSHFP record idempotency" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is not changed + +- name: "Test: SSHFP record update" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + type: SSHFP + algorithm: 1 + hash_type: 2 + value: feb66965cee89137b4d4a46a15c718c3f15ad408b6d1b528a2ed479a54da762c + ttl: 300 + register: cloudflare_dns + +- name: "Validate: SSHFP record update" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is changed + - cloudflare_dns.result.record.ttl == 300 + +- name: "Test: SSHFP record duplicate (create new record)" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + type: SSHFP + algorithm: 1 + hash_type: 2 + value: fd3800532d26b56279524d4d1ed8afbfd9f725113c394bc185e447ba991f368b + ttl: 300 + register: cloudflare_dns + +- name: "Validate: SSHFP record duplicate (create new record)" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is changed + - cloudflare_dns.result.record.content == "1\t2\tfd3800532d26b56279524d4d1ed8afbfd9f725113c394bc185e447ba991f368b" + - cloudflare_dns.result.record.ttl == 300 + - cloudflare_dns.result.record.type == "SSHFP" + - cloudflare_dns.result.record.name == "{{ cloudflare_dns_record }}.{{ cloudflare_zone }}" + - cloudflare_dns.result.record.zone_name == "{{ cloudflare_zone }}" + - cloudflare_dns.result.record.data.algorithm == 1 + - cloudflare_dns.result.record.data.type == 2 + - cloudflare_dns.result.record.data.fingerprint == "fd3800532d26b56279524d4d1ed8afbfd9f725113c394bc185e447ba991f368b" + +- name: "Test: SSHFP record duplicate (old record present)" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + type: SSHFP + algorithm: 1 + hash_type: 2 + value: feb66965cee89137b4d4a46a15c718c3f15ad408b6d1b528a2ed479a54da762c + ttl: 300 + register: cloudflare_dns + +- name: "Validate: SSHFP record duplicate (old record present)" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is not changed + - cloudflare_dns.result.record.content == "1\t2\tfeb66965cee89137b4d4a46a15c718c3f15ad408b6d1b528a2ed479a54da762c" + - cloudflare_dns.result.record.ttl == 300 + - cloudflare_dns.result.record.type == "SSHFP" + - cloudflare_dns.result.record.name == "{{ cloudflare_dns_record }}.{{ cloudflare_zone }}" + - cloudflare_dns.result.record.zone_name == "{{ cloudflare_zone }}" + - cloudflare_dns.result.record.data.algorithm == 1 + - cloudflare_dns.result.record.data.type == 2 + - cloudflare_dns.result.record.data.fingerprint == "feb66965cee89137b4d4a46a15c718c3f15ad408b6d1b528a2ed479a54da762c" + +- name: "Test: SSHFP record duplicate (make new record solo)" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + type: SSHFP + algorithm: 1 + hash_type: 2 + value: fd3800532d26b56279524d4d1ed8afbfd9f725113c394bc185e447ba991f368b + ttl: 300 + solo: true + register: cloudflare_dns + +- name: "Validate: SSHFP record duplicate (make new record solo)" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is changed + - cloudflare_dns.result.record.content == "1\t2\tfd3800532d26b56279524d4d1ed8afbfd9f725113c394bc185e447ba991f368b" + - cloudflare_dns.result.record.ttl == 300 + - cloudflare_dns.result.record.type == "SSHFP" + - cloudflare_dns.result.record.name == "{{ cloudflare_dns_record }}.{{ cloudflare_zone }}" + - cloudflare_dns.result.record.zone_name == "{{ cloudflare_zone }}" + - cloudflare_dns.result.record.data.algorithm == 1 + - cloudflare_dns.result.record.data.type == 2 + - cloudflare_dns.result.record.data.fingerprint == "fd3800532d26b56279524d4d1ed8afbfd9f725113c394bc185e447ba991f368b" + +- name: "Test: SSHFP record duplicate (old record absent)" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + type: SSHFP + algorithm: 1 + hash_type: 2 + value: feb66965cee89137b4d4a46a15c718c3f15ad408b6d1b528a2ed479a54da762c + state: absent + register: cloudflare_dns + +- name: "Validate: SSHFP record duplicate (old record absent)" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is not changed + +- name: "Test: SSHFP record deletion" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + type: SSHFP + algorithm: 1 + hash_type: 2 + value: fd3800532d26b56279524d4d1ed8afbfd9f725113c394bc185e447ba991f368b + state: absent + register: cloudflare_dns + +- name: "Validate: SSHFP record deletion" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is changed + +- name: "Test: SSHFP record deletion succeeded" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + type: SSHFP + algorithm: 1 + hash_type: 2 + value: fd3800532d26b56279524d4d1ed8afbfd9f725113c394bc185e447ba991f368b + state: absent + register: cloudflare_dns + +- name: "Validate: SSHFP record deletion succeeded" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is not changed diff --git a/test/legacy/roles/test_cloudflare_dns/tasks/tlsa_record.yml b/test/legacy/roles/test_cloudflare_dns/tasks/tlsa_record.yml new file mode 100644 index 00000000000..148534a24a8 --- /dev/null +++ b/test/legacy/roles/test_cloudflare_dns/tasks/tlsa_record.yml @@ -0,0 +1,239 @@ +--- +######## TLSA record tests ################# + +- name: "Test: TLSA record creation" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + port: 25 + proto: tcp + type: TLSA + cert_usage: 3 + selector: 1 + hash_type: 1 + value: 09c5d90ef4cf74625de04719c71c85ea99182ab81aaab99795466a8c100ead5f + ttl: 150 + register: cloudflare_dns + +- name: "Validate: TLSA record creation" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is changed + - cloudflare_dns.result.record.content == "3\t1\t1\t09c5d90ef4cf74625de04719c71c85ea99182ab81aaab99795466a8c100ead5f" + - cloudflare_dns.result.record.ttl == 150 + - cloudflare_dns.result.record.type == "TLSA" + - cloudflare_dns.result.record.name == "_25._tcp.{{ cloudflare_dns_record }}.{{ cloudflare_zone }}" + - cloudflare_dns.result.record.zone_name == "{{ cloudflare_zone }}" + - cloudflare_dns.result.record.data.matching_type == 1 + - cloudflare_dns.result.record.data.selector == 1 + - cloudflare_dns.result.record.data.usage == 3 + - cloudflare_dns.result.record.data.certificate == "09c5d90ef4cf74625de04719c71c85ea99182ab81aaab99795466a8c100ead5f" + +- name: "Test: TLSA record idempotency" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + port: 25 + proto: tcp + type: TLSA + cert_usage: 3 + selector: 1 + hash_type: 1 + value: 09c5d90ef4cf74625de04719c71c85ea99182ab81aaab99795466a8c100ead5f + ttl: 150 + register: cloudflare_dns + + +- name: "Validate: TLSA record idempotency" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is not changed + +- name: "Test: TLSA record update" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + port: 25 + proto: tcp + type: TLSA + cert_usage: 3 + selector: 1 + hash_type: 1 + value: 09c5d90ef4cf74625de04719c71c85ea99182ab81aaab99795466a8c100ead5f + ttl: 300 + register: cloudflare_dns + +- name: "Validate: TLSA record update" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is changed + - cloudflare_dns.result.record.ttl == 300 + +- name: "Test: TLSA record duplicate (create new record)" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + port: 25 + proto: tcp + type: TLSA + cert_usage: 3 + selector: 1 + hash_type: 1 + value: 76e283e0cde1d28a85c7b44a26f35260f42e176f4f076e7bdd29895ca76da3d2 + ttl: 300 + register: cloudflare_dns + +- name: "Validate: TLSA record duplicate (create new record)" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is changed + - cloudflare_dns.result.record.content == "3\t1\t1\t76e283e0cde1d28a85c7b44a26f35260f42e176f4f076e7bdd29895ca76da3d2" + - cloudflare_dns.result.record.ttl == 300 + - cloudflare_dns.result.record.type == "TLSA" + - cloudflare_dns.result.record.name == "_25._tcp.{{ cloudflare_dns_record }}.{{ cloudflare_zone }}" + - cloudflare_dns.result.record.zone_name == "{{ cloudflare_zone }}" + - cloudflare_dns.result.record.data.matching_type == 1 + - cloudflare_dns.result.record.data.selector == 1 + - cloudflare_dns.result.record.data.usage == 3 + - cloudflare_dns.result.record.data.certificate == "76e283e0cde1d28a85c7b44a26f35260f42e176f4f076e7bdd29895ca76da3d2" + +- name: "Test: TLSA record duplicate (old record present)" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + port: 25 + proto: tcp + type: TLSA + cert_usage: 3 + selector: 1 + hash_type: 1 + value: 09c5d90ef4cf74625de04719c71c85ea99182ab81aaab99795466a8c100ead5f + ttl: 300 + register: cloudflare_dns + +- name: "Validate: TLSA record duplicate (old record present)" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is not changed + - cloudflare_dns.result.record.content == "3\t1\t1\t09c5d90ef4cf74625de04719c71c85ea99182ab81aaab99795466a8c100ead5f" + - cloudflare_dns.result.record.ttl == 300 + - cloudflare_dns.result.record.type == "TLSA" + - cloudflare_dns.result.record.name == "_25._tcp.{{ cloudflare_dns_record }}.{{ cloudflare_zone }}" + - cloudflare_dns.result.record.zone_name == "{{ cloudflare_zone }}" + - cloudflare_dns.result.record.data.matching_type == 1 + - cloudflare_dns.result.record.data.selector == 1 + - cloudflare_dns.result.record.data.usage == 3 + - cloudflare_dns.result.record.data.certificate == "09c5d90ef4cf74625de04719c71c85ea99182ab81aaab99795466a8c100ead5f" + +- name: "Test: TLSA record duplicate (make new record solo)" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + port: 25 + proto: tcp + type: TLSA + cert_usage: 3 + selector: 1 + hash_type: 1 + value: 76e283e0cde1d28a85c7b44a26f35260f42e176f4f076e7bdd29895ca76da3d2 + ttl: 300 + solo: true + register: cloudflare_dns + +- name: "Validate: TLSA record duplicate (make new record solo)" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is changed + - cloudflare_dns.result.record.content == "3\t1\t1\t76e283e0cde1d28a85c7b44a26f35260f42e176f4f076e7bdd29895ca76da3d2" + - cloudflare_dns.result.record.ttl == 300 + - cloudflare_dns.result.record.type == "TLSA" + - cloudflare_dns.result.record.name == "_25._tcp.{{ cloudflare_dns_record }}.{{ cloudflare_zone }}" + - cloudflare_dns.result.record.zone_name == "{{ cloudflare_zone }}" + - cloudflare_dns.result.record.data.matching_type == 1 + - cloudflare_dns.result.record.data.selector == 1 + - cloudflare_dns.result.record.data.usage == 3 + - cloudflare_dns.result.record.data.certificate == "76e283e0cde1d28a85c7b44a26f35260f42e176f4f076e7bdd29895ca76da3d2" + +- name: "Test: TLSA record duplicate (old record absent)" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + port: 25 + proto: tcp + type: TLSA + cert_usage: 3 + selector: 1 + hash_type: 1 + value: 09c5d90ef4cf74625de04719c71c85ea99182ab81aaab99795466a8c100ead5f + state: absent + register: cloudflare_dns + +- name: "Validate: TLSA record duplicate (old record absent)" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is not changed + +- name: "Test: TLSA record deletion" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + port: 25 + proto: tcp + type: TLSA + cert_usage: 3 + selector: 1 + hash_type: 1 + value: 76e283e0cde1d28a85c7b44a26f35260f42e176f4f076e7bdd29895ca76da3d2 + state: absent + register: cloudflare_dns + +- name: "Validate: TLSA record deletion" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is changed + +- name: "Test: TLSA record deletion succeeded" + cloudflare_dns: + account_email: "{{ cloudflare_email }}" + account_api_token: "{{ cloudflare_api_token }}" + zone: "{{ cloudflare_zone }}" + record: "{{ cloudflare_dns_record }}" + port: 25 + proto: tcp + type: TLSA + cert_usage: 3 + selector: 1 + hash_type: 1 + value: 76e283e0cde1d28a85c7b44a26f35260f42e176f4f076e7bdd29895ca76da3d2 + state: absent + register: cloudflare_dns + +- name: "Validate: TLSA record deletion succeeded" + assert: + that: + - cloudflare_dns is successful + - cloudflare_dns is not changed