|
Packit Service |
ee01e6 |
#!/usr/bin/python
|
|
Packit Service |
0a38ef |
# -*- coding: utf-8 -*-
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
# Authors:
|
|
Packit Service |
0a38ef |
# Rafael Guterres Jeffman <rjeffman@redhat.com>
|
|
Packit Service |
0a38ef |
#
|
|
Packit Service |
0a38ef |
# Copyright (C) 2019 Red Hat
|
|
Packit Service |
0a38ef |
# see file 'COPYING' for use and warranty information
|
|
Packit Service |
0a38ef |
#
|
|
Packit Service |
0a38ef |
# This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
0a38ef |
# it under the terms of the GNU General Public License as published by
|
|
Packit Service |
0a38ef |
# the Free Software Foundation, either version 3 of the License, or
|
|
Packit Service |
0a38ef |
# (at your option) any later version.
|
|
Packit Service |
0a38ef |
#
|
|
Packit Service |
0a38ef |
# This program is distributed in the hope that it will be useful,
|
|
Packit Service |
0a38ef |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
0a38ef |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
0a38ef |
# GNU General Public License for more details.
|
|
Packit Service |
0a38ef |
#
|
|
Packit Service |
0a38ef |
# You should have received a copy of the GNU General Public License
|
|
Packit Service |
0a38ef |
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
ANSIBLE_METADATA = {
|
|
Packit Service |
0a38ef |
"metadata_version": "1.0",
|
|
Packit Service |
0a38ef |
"supported_by": "community",
|
|
Packit Service |
0a38ef |
"status": ["preview"],
|
|
Packit Service |
0a38ef |
}
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
DOCUMENTATION = """
|
|
Packit Service |
0a38ef |
---
|
|
Packit Service |
0a38ef |
module: ipadnsconfig
|
|
Packit Service |
0a38ef |
short description: Manage FreeIPA dnsconfig
|
|
Packit Service |
0a38ef |
description: Manage FreeIPA dnsconfig
|
|
Packit Service |
0a38ef |
options:
|
|
Packit Service |
0a38ef |
ipaadmin_principal:
|
|
Packit Service |
0a38ef |
description: The admin principal
|
|
Packit Service |
0a38ef |
default: admin
|
|
Packit Service |
0a38ef |
ipaadmin_password:
|
|
Packit Service |
0a38ef |
description: The admin password
|
|
Packit Service |
0a38ef |
required: false
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
forwarders:
|
|
Packit Service |
0a38ef |
description: The list of global DNS forwarders.
|
|
Packit Service |
0a38ef |
required: false
|
|
Packit Service |
0a38ef |
options:
|
|
Packit Service |
0a38ef |
ip_address:
|
|
Packit Service |
0a38ef |
description: The forwarder nameserver IP address list (IPv4 and IPv6).
|
|
Packit Service |
0a38ef |
required: true
|
|
Packit Service |
0a38ef |
port:
|
|
Packit Service |
0a38ef |
description: The port to forward requests to.
|
|
Packit Service |
0a38ef |
required: false
|
|
Packit Service |
0a38ef |
forward_policy:
|
|
Packit Service |
0a38ef |
description:
|
|
Packit Service |
0a38ef |
Global forwarding policy. Set to "none" to disable any configured
|
|
Packit Service |
0a38ef |
global forwarders.
|
|
Packit Service |
0a38ef |
required: false
|
|
Packit Service |
0a38ef |
choices: ['only', 'first', 'none']
|
|
Packit Service |
0a38ef |
allow_sync_ptr:
|
|
Packit Service |
0a38ef |
description:
|
|
Packit Service |
0a38ef |
Allow synchronization of forward (A, AAAA) and reverse (PTR) records.
|
|
Packit Service |
0a38ef |
required: false
|
|
Packit Service |
0a38ef |
type: bool
|
|
Packit Service |
0a38ef |
state:
|
|
Packit Service |
0a38ef |
description: State to ensure
|
|
Packit Service |
0a38ef |
default: present
|
|
Packit Service |
0a38ef |
choices: ["present", "absent"]
|
|
Packit Service |
0a38ef |
"""
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
EXAMPLES = """
|
|
Packit Service |
0a38ef |
# Ensure global DNS forward configuration, allowing PTR record synchronization.
|
|
Packit Service |
0a38ef |
- ipadnsconfig:
|
|
Packit Service |
0a38ef |
forwarders:
|
|
Packit Service |
0a38ef |
- ip_address: 8.8.4.4
|
|
Packit Service |
0a38ef |
- ip_address: 2001:4860:4860::8888
|
|
Packit Service |
0a38ef |
port: 53
|
|
Packit Service |
0a38ef |
forward_policy: only
|
|
Packit Service |
0a38ef |
allow_sync_ptr: yes
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
# Ensure forwarder is absent.
|
|
Packit Service |
0a38ef |
- ipadnsconfig:
|
|
Packit Service |
0a38ef |
forwarders:
|
|
Packit Service |
0a38ef |
- ip_address: 2001:4860:4860::8888
|
|
Packit Service |
0a38ef |
port: 53
|
|
Packit Service |
0a38ef |
state: absent
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
# Disable PTR record synchronization.
|
|
Packit Service |
0a38ef |
- ipadnsconfig:
|
|
Packit Service |
0a38ef |
allow_sync_ptr: no
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
# Disable global forwarders.
|
|
Packit Service |
0a38ef |
- ipadnsconfig:
|
|
Packit Service |
0a38ef |
forward_policy: none
|
|
Packit Service |
0a38ef |
"""
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
RETURN = """
|
|
Packit Service |
0a38ef |
"""
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
from ansible.module_utils.basic import AnsibleModule
|
|
Packit Service |
0a38ef |
from ansible.module_utils.ansible_freeipa_module import temp_kinit, \
|
|
Packit Service |
0a38ef |
temp_kdestroy, valid_creds, api_connect, \
|
|
Packit Service |
0a38ef |
api_command_no_name, compare_args_ipa, module_params_get, \
|
|
Packit Service |
0a38ef |
is_ipv4_addr, is_ipv6_addr
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
def find_dnsconfig(module):
|
|
Packit Service |
0a38ef |
_args = {
|
|
Packit Service |
0a38ef |
"all": True,
|
|
Packit Service |
0a38ef |
}
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
_result = api_command_no_name(module, "dnsconfig_show", _args)
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
if "result" in _result:
|
|
Packit Service |
0a38ef |
if _result["result"].get('idnsforwarders', None) is None:
|
|
Packit Service |
0a38ef |
_result["result"]['idnsforwarders'] = ['']
|
|
Packit Service |
0a38ef |
return _result["result"]
|
|
Packit Service |
0a38ef |
else:
|
|
Packit Service |
0a38ef |
module.fail_json(msg="Could not retrieve current DNS configuration.")
|
|
Packit Service |
0a38ef |
return None
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
def gen_args(module, state, dnsconfig, forwarders, forward_policy,
|
|
Packit Service |
0a38ef |
allow_sync_ptr):
|
|
Packit Service |
0a38ef |
_args = {}
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
if forwarders:
|
|
Packit Service |
0a38ef |
_forwarders = []
|
|
Packit Service |
0a38ef |
for forwarder in forwarders:
|
|
Packit Service |
0a38ef |
ip_address = forwarder.get('ip_address')
|
|
Packit Service |
0a38ef |
port = forwarder.get('port')
|
|
Packit Service |
0a38ef |
if not (is_ipv4_addr(ip_address) or is_ipv6_addr(ip_address)):
|
|
Packit Service |
0a38ef |
module.fail_json(
|
|
Packit Service |
0a38ef |
msg="Invalid IP for DNS forwarder: %s" % ip_address)
|
|
Packit Service |
0a38ef |
if port is None:
|
|
Packit Service |
0a38ef |
_forwarders.append(ip_address)
|
|
Packit Service |
0a38ef |
else:
|
|
Packit Service |
0a38ef |
_forwarders.append('%s port %d' % (ip_address, port))
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
global_forwarders = dnsconfig.get('idnsforwarders', [])
|
|
Packit Service |
0a38ef |
if state == 'absent':
|
|
Packit Service |
0a38ef |
_args['idnsforwarders'] = [
|
|
Packit Service |
0a38ef |
fwd for fwd in global_forwarders if fwd not in _forwarders]
|
|
Packit Service |
0a38ef |
# When all forwarders should be excluded, use an empty string ('').
|
|
Packit Service |
0a38ef |
if not _args['idnsforwarders']:
|
|
Packit Service |
0a38ef |
_args['idnsforwarders'] = ['']
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
elif state == 'present':
|
|
Packit Service |
0a38ef |
_args['idnsforwarders'] = [
|
|
Packit Service |
0a38ef |
fwd for fwd in _forwarders if fwd not in global_forwarders]
|
|
Packit Service |
0a38ef |
# If no forwarders should be added, remove argument.
|
|
Packit Service |
0a38ef |
if not _args['idnsforwarders']:
|
|
Packit Service |
0a38ef |
del _args['idnsforwarders']
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
else:
|
|
Packit Service |
0a38ef |
# shouldn't happen, but let's be paranoid.
|
|
Packit Service |
0a38ef |
module.fail_json(msg="Invalid state: %s" % state)
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
if forward_policy is not None:
|
|
Packit Service |
0a38ef |
_args['idnsforwardpolicy'] = forward_policy
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
if allow_sync_ptr is not None:
|
|
Packit Service |
0a38ef |
_args['idnsallowsyncptr'] = 'TRUE' if allow_sync_ptr else 'FALSE'
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
return _args
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
def main():
|
|
Packit Service |
0a38ef |
forwarder_spec = dict(
|
|
Packit Service |
0a38ef |
ip_address=dict(type=str, required=True),
|
|
Packit Service |
0a38ef |
port=dict(type=int, required=False, default=None)
|
|
Packit Service |
0a38ef |
)
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
ansible_module = AnsibleModule(
|
|
Packit Service |
0a38ef |
argument_spec=dict(
|
|
Packit Service |
0a38ef |
# general
|
|
Packit Service |
0a38ef |
ipaadmin_principal=dict(type='str', default='admin'),
|
|
Packit Service |
0a38ef |
ipaadmin_password=dict(type='str', no_log=True),
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
# dnsconfig
|
|
Packit Service |
0a38ef |
forwarders=dict(type='list', default=None, required=False,
|
|
Packit Service |
0a38ef |
options=dict(**forwarder_spec)),
|
|
Packit Service |
0a38ef |
forward_policy=dict(type='str', required=False, default=None,
|
|
Packit Service |
0a38ef |
choices=['only', 'first', 'none']),
|
|
Packit Service |
0a38ef |
allow_sync_ptr=dict(type='bool', required=False, default=None),
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
# general
|
|
Packit Service |
0a38ef |
state=dict(type="str", default="present",
|
|
Packit Service |
0a38ef |
choices=["present", "absent"]),
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
)
|
|
Packit Service |
0a38ef |
)
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
ansible_module._ansible_debug = True
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
# general
|
|
Packit Service |
0a38ef |
ipaadmin_principal = module_params_get(ansible_module,
|
|
Packit Service |
0a38ef |
"ipaadmin_principal")
|
|
Packit Service |
0a38ef |
ipaadmin_password = module_params_get(ansible_module,
|
|
Packit Service |
0a38ef |
"ipaadmin_password")
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
forwarders = module_params_get(ansible_module, 'forwarders') or []
|
|
Packit Service |
0a38ef |
forward_policy = module_params_get(ansible_module, 'forward_policy')
|
|
Packit Service |
0a38ef |
allow_sync_ptr = module_params_get(ansible_module, 'allow_sync_ptr')
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
state = module_params_get(ansible_module, 'state')
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
# Check parameters.
|
|
Packit Service |
0a38ef |
invalid = []
|
|
Packit Service |
0a38ef |
if state == 'absent':
|
|
Packit Service |
0a38ef |
invalid = ['forward_policy', 'allow_sync_ptr']
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
for x in invalid:
|
|
Packit Service |
0a38ef |
if vars()[x] is not None:
|
|
Packit Service |
0a38ef |
ansible_module.fail_json(
|
|
Packit Service |
0a38ef |
msg="Argument '%s' can not be used with state '%s'" %
|
|
Packit Service |
0a38ef |
(x, state))
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
# Init
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
changed = False
|
|
Packit Service |
0a38ef |
ccache_dir = None
|
|
Packit Service |
0a38ef |
ccache_name = None
|
|
Packit Service |
0a38ef |
try:
|
|
Packit Service |
0a38ef |
if not valid_creds(ansible_module, ipaadmin_principal):
|
|
Packit Service |
0a38ef |
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
|
|
Packit Service |
0a38ef |
ipaadmin_password)
|
|
Packit Service |
0a38ef |
api_connect()
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
res_find = find_dnsconfig(ansible_module)
|
|
Packit Service |
0a38ef |
args = gen_args(ansible_module, state, res_find, forwarders,
|
|
Packit Service |
0a38ef |
forward_policy, allow_sync_ptr)
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
# Execute command only if configuration changes.
|
|
Packit Service |
0a38ef |
if not compare_args_ipa(ansible_module, args, res_find):
|
|
Packit Service |
0a38ef |
try:
|
|
Packit Service |
0a38ef |
api_command_no_name(ansible_module, 'dnsconfig_mod', args)
|
|
Packit Service |
0a38ef |
# If command did not fail, something changed.
|
|
Packit Service |
0a38ef |
changed = True
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
except Exception as e:
|
|
Packit Service |
0a38ef |
msg = str(e)
|
|
Packit Service |
0a38ef |
ansible_module.fail_json(msg="dnsconfig_mod: %s" % msg)
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
except Exception as e:
|
|
Packit Service |
0a38ef |
ansible_module.fail_json(msg=str(e))
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
finally:
|
|
Packit Service |
0a38ef |
temp_kdestroy(ccache_dir, ccache_name)
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
# Done
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
ansible_module.exit_json(changed=changed)
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
|
|
Packit Service |
0a38ef |
if __name__ == "__main__":
|
|
Packit Service |
0a38ef |
main()
|