mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
plugins/modules/cloudflare_dns: Add CAA record support (#7399)
* plugins/modules/cloudflare_dns: Add CAA record support * PEP8 compliance * Specify version_added Co-authored-by: Felix Fontein <felix@fontein.de> * Update changelogs/fragments/7399-cloudflare_dns-add-CAA-record-support.yml Co-authored-by: Felix Fontein <felix@fontein.de> * Fix typo Co-authored-by: Felix Fontein <felix@fontein.de> * Remove unrelated change * Specify version_added Co-authored-by: Felix Fontein <felix@fontein.de> --------- Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
parent
e829a7384f
commit
8c7778735d
2 changed files with 67 additions and 6 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- cloudflare_dns - add CAA record support (https://github.com/ansible-collections/community.general/pull/7399).
|
|
@ -59,6 +59,20 @@ options:
|
||||||
- Required for O(type=TLSA) when O(state=present).
|
- Required for O(type=TLSA) when O(state=present).
|
||||||
type: int
|
type: int
|
||||||
choices: [ 0, 1, 2, 3 ]
|
choices: [ 0, 1, 2, 3 ]
|
||||||
|
flag:
|
||||||
|
description:
|
||||||
|
- Issuer Critical Flag.
|
||||||
|
- Required for O(type=CAA) when O(state=present).
|
||||||
|
type: int
|
||||||
|
choices: [ 0, 1 ]
|
||||||
|
version_added: 8.0.0
|
||||||
|
tag:
|
||||||
|
description:
|
||||||
|
- CAA issue restriction.
|
||||||
|
- Required for O(type=CAA) when O(state=present).
|
||||||
|
type: str
|
||||||
|
choices: [ issue, issuewild, iodef ]
|
||||||
|
version_added: 8.0.0
|
||||||
hash_type:
|
hash_type:
|
||||||
description:
|
description:
|
||||||
- Hash type number.
|
- Hash type number.
|
||||||
|
@ -139,7 +153,7 @@ options:
|
||||||
- The type of DNS record to create. Required if O(state=present).
|
- The type of DNS record to create. Required if O(state=present).
|
||||||
- O(type=DS), O(type=SSHFP), and O(type=TLSA) were added in Ansible 2.7.
|
- O(type=DS), O(type=SSHFP), and O(type=TLSA) were added in Ansible 2.7.
|
||||||
type: str
|
type: str
|
||||||
choices: [ A, AAAA, CNAME, DS, MX, NS, SPF, SRV, SSHFP, TLSA, TXT ]
|
choices: [ A, AAAA, CNAME, DS, MX, NS, SPF, SRV, SSHFP, TLSA, CAA, TXT ]
|
||||||
value:
|
value:
|
||||||
description:
|
description:
|
||||||
- The record value.
|
- The record value.
|
||||||
|
@ -262,6 +276,15 @@ EXAMPLES = r'''
|
||||||
hash_type: 1
|
hash_type: 1
|
||||||
value: 6b76d034492b493e15a7376fccd08e63befdad0edab8e442562f532338364bf3
|
value: 6b76d034492b493e15a7376fccd08e63befdad0edab8e442562f532338364bf3
|
||||||
|
|
||||||
|
- name: Create a CAA record subdomain.example.com
|
||||||
|
community.general.cloudflare_dns:
|
||||||
|
zone: example.com
|
||||||
|
record: subdomain
|
||||||
|
type: CAA
|
||||||
|
flag: 0
|
||||||
|
tag: issue
|
||||||
|
value: ca.example.com
|
||||||
|
|
||||||
- name: Create a DS record for subdomain.example.com
|
- name: Create a DS record for subdomain.example.com
|
||||||
community.general.cloudflare_dns:
|
community.general.cloudflare_dns:
|
||||||
zone: example.com
|
zone: example.com
|
||||||
|
@ -291,7 +314,7 @@ record:
|
||||||
sample: "2016-03-25T19:09:42.516553Z"
|
sample: "2016-03-25T19:09:42.516553Z"
|
||||||
data:
|
data:
|
||||||
description: Additional record data.
|
description: Additional record data.
|
||||||
returned: success, if type is SRV, DS, SSHFP or TLSA
|
returned: success, if type is SRV, DS, SSHFP TLSA or CAA
|
||||||
type: dict
|
type: dict
|
||||||
sample: {
|
sample: {
|
||||||
name: "jabber",
|
name: "jabber",
|
||||||
|
@ -391,6 +414,8 @@ class CloudflareAPI(object):
|
||||||
self.algorithm = module.params['algorithm']
|
self.algorithm = module.params['algorithm']
|
||||||
self.cert_usage = module.params['cert_usage']
|
self.cert_usage = module.params['cert_usage']
|
||||||
self.hash_type = module.params['hash_type']
|
self.hash_type = module.params['hash_type']
|
||||||
|
self.flag = module.params['flag']
|
||||||
|
self.tag = module.params['tag']
|
||||||
self.key_tag = module.params['key_tag']
|
self.key_tag = module.params['key_tag']
|
||||||
self.port = module.params['port']
|
self.port = module.params['port']
|
||||||
self.priority = module.params['priority']
|
self.priority = module.params['priority']
|
||||||
|
@ -595,7 +620,7 @@ class CloudflareAPI(object):
|
||||||
def delete_dns_records(self, **kwargs):
|
def delete_dns_records(self, **kwargs):
|
||||||
params = {}
|
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', 'key_tag']:
|
'algorithm', 'cert_usage', 'hash_type', 'selector', 'key_tag', 'flag', 'tag']:
|
||||||
if param in kwargs:
|
if param in kwargs:
|
||||||
params[param] = kwargs[param]
|
params[param] = kwargs[param]
|
||||||
else:
|
else:
|
||||||
|
@ -640,7 +665,7 @@ class CloudflareAPI(object):
|
||||||
def ensure_dns_record(self, **kwargs):
|
def ensure_dns_record(self, **kwargs):
|
||||||
params = {}
|
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', 'key_tag']:
|
'algorithm', 'cert_usage', 'hash_type', 'selector', 'key_tag', 'flag', 'tag']:
|
||||||
if param in kwargs:
|
if param in kwargs:
|
||||||
params[param] = kwargs[param]
|
params[param] = kwargs[param]
|
||||||
else:
|
else:
|
||||||
|
@ -757,12 +782,36 @@ class CloudflareAPI(object):
|
||||||
}
|
}
|
||||||
search_value = str(params['cert_usage']) + '\t' + str(params['selector']) + '\t' + str(params['hash_type']) + '\t' + params['value']
|
search_value = str(params['cert_usage']) + '\t' + str(params['selector']) + '\t' + str(params['hash_type']) + '\t' + params['value']
|
||||||
|
|
||||||
|
if params['type'] == 'CAA':
|
||||||
|
for attr in [params['flag'], params['tag'], params['value']]:
|
||||||
|
if (attr is None) or (attr == ''):
|
||||||
|
self.module.fail_json(msg="You must provide flag, tag and a value to create this record type")
|
||||||
|
caa_data = {
|
||||||
|
"flags": params['flag'],
|
||||||
|
"tag": params['tag'],
|
||||||
|
"value": params['value'],
|
||||||
|
}
|
||||||
|
new_record = {
|
||||||
|
"type": params['type'],
|
||||||
|
"name": params['record'],
|
||||||
|
'data': caa_data,
|
||||||
|
"ttl": params['ttl'],
|
||||||
|
}
|
||||||
|
search_value = None
|
||||||
|
|
||||||
zone_id = self._get_zone_id(params['zone'])
|
zone_id = self._get_zone_id(params['zone'])
|
||||||
records = self.get_dns_records(params['zone'], params['type'], search_record, search_value)
|
records = self.get_dns_records(params['zone'], params['type'], search_record, search_value)
|
||||||
# in theory this should be impossible as cloudflare does not allow
|
# in theory this should be impossible as cloudflare does not allow
|
||||||
# the creation of duplicate records but lets cover it anyways
|
# the creation of duplicate records but lets cover it anyways
|
||||||
if len(records) > 1:
|
if len(records) > 1:
|
||||||
self.module.fail_json(msg="More than one record already exists for the given attributes. That should be impossible, please open an issue!")
|
# As Cloudflare API cannot filter record containing quotes
|
||||||
|
# CAA records must be compared locally
|
||||||
|
if params['type'] == 'CAA':
|
||||||
|
for rr in records:
|
||||||
|
if rr['data']['flags'] == caa_data['flags'] and rr['data']['tag'] == caa_data['tag'] and rr['data']['value'] == caa_data['value']:
|
||||||
|
return rr, self.changed
|
||||||
|
else:
|
||||||
|
self.module.fail_json(msg="More than one record already exists for the given attributes. That should be impossible, please open an issue!")
|
||||||
# record already exists, check if it must be updated
|
# record already exists, check if it must be updated
|
||||||
if len(records) == 1:
|
if len(records) == 1:
|
||||||
cur_record = records[0]
|
cur_record = records[0]
|
||||||
|
@ -811,6 +860,8 @@ def main():
|
||||||
hash_type=dict(type='int', choices=[1, 2]),
|
hash_type=dict(type='int', choices=[1, 2]),
|
||||||
key_tag=dict(type='int', no_log=False),
|
key_tag=dict(type='int', no_log=False),
|
||||||
port=dict(type='int'),
|
port=dict(type='int'),
|
||||||
|
flag=dict(type='int', choices=[0, 1]),
|
||||||
|
tag=dict(type='str', choices=['issue', 'issuewild', 'iodef']),
|
||||||
priority=dict(type='int', default=1),
|
priority=dict(type='int', default=1),
|
||||||
proto=dict(type='str'),
|
proto=dict(type='str'),
|
||||||
proxied=dict(type='bool', default=False),
|
proxied=dict(type='bool', default=False),
|
||||||
|
@ -821,7 +872,7 @@ def main():
|
||||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
state=dict(type='str', default='present', choices=['absent', 'present']),
|
||||||
timeout=dict(type='int', default=30),
|
timeout=dict(type='int', default=30),
|
||||||
ttl=dict(type='int', default=1),
|
ttl=dict(type='int', default=1),
|
||||||
type=dict(type='str', choices=['A', 'AAAA', 'CNAME', 'DS', 'MX', 'NS', 'SPF', 'SRV', 'SSHFP', 'TLSA', 'TXT']),
|
type=dict(type='str', choices=['A', 'AAAA', 'CNAME', 'DS', 'MX', 'NS', 'SPF', 'SRV', 'SSHFP', 'TLSA', 'CAA', 'TXT']),
|
||||||
value=dict(type='str', aliases=['content']),
|
value=dict(type='str', aliases=['content']),
|
||||||
weight=dict(type='int', default=1),
|
weight=dict(type='int', default=1),
|
||||||
zone=dict(type='str', required=True, aliases=['domain']),
|
zone=dict(type='str', required=True, aliases=['domain']),
|
||||||
|
@ -832,6 +883,7 @@ def main():
|
||||||
('state', 'absent', ['record']),
|
('state', 'absent', ['record']),
|
||||||
('type', 'SRV', ['proto', 'service']),
|
('type', 'SRV', ['proto', 'service']),
|
||||||
('type', 'TLSA', ['proto', 'port']),
|
('type', 'TLSA', ['proto', 'port']),
|
||||||
|
('type', 'CAA', ['flag', 'tag']),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -858,6 +910,13 @@ def main():
|
||||||
and (module.params['value'] is None or module.params['value'] == ''))):
|
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.")
|
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.")
|
||||||
|
|
||||||
|
if module.params['type'] == 'CAA':
|
||||||
|
if not ((module.params['flag'] is not None and module.params['tag'] is not None
|
||||||
|
and not (module.params['value'] is None or module.params['value'] == ''))
|
||||||
|
or (module.params['flag'] is None and module.params['tag'] is None
|
||||||
|
and (module.params['value'] is None or module.params['value'] == ''))):
|
||||||
|
module.fail_json(msg="For CAA records the params flag, tag and value all need to be defined, or not at all.")
|
||||||
|
|
||||||
if module.params['type'] == 'DS':
|
if module.params['type'] == 'DS':
|
||||||
if not ((module.params['key_tag'] is not None and module.params['algorithm'] is not None and module.params['hash_type'] is not None
|
if not ((module.params['key_tag'] is not None and 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'] == ''))
|
and not (module.params['value'] is None or module.params['value'] == ''))
|
||||||
|
|
Loading…
Reference in a new issue