140 lines
4.1 KiB
Python
140 lines
4.1 KiB
Python
#!/usr/bin/python
|
|
#
|
|
# Copyright 2023 Red Hat, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
from ipaddress import ip_address, IPv4Address
|
|
|
|
|
|
def _parse_host_entry(entry):
|
|
if len(entry.split()) >= 2:
|
|
value = entry.split()[0]
|
|
try:
|
|
ip = ip_address(value)
|
|
record_type = 'A' if (type(ip) is IPv4Address) else 'AAAA'
|
|
except ValueError:
|
|
return "", "", "Invalid", ""
|
|
|
|
host = entry.split()[1]
|
|
host_split = host.split('.', 1)
|
|
if (len(host_split) == 2):
|
|
name = host_split[0]
|
|
zone = host_split[1]
|
|
return value, name, record_type, zone
|
|
return "", "", "Invalid", ""
|
|
|
|
|
|
def _get_reverse_entry(name, zone, ip_str):
|
|
# this should follow ipa heuristics to get the reverse domain
|
|
|
|
ip = ip_address(ip_str)
|
|
prefix = 1 if (type(ip) is IPv4Address) else 16
|
|
|
|
zone_name = '.'.join(ip.reverse_pointer.split('.')[prefix:])
|
|
record_name = '.'.join(ip.reverse_pointer.split('.', prefix)[:-1])
|
|
record_value = '.'.join((name, zone)) + '.'
|
|
|
|
record = {"record_name": record_name,
|
|
"zone_name": zone_name,
|
|
"record_type": "PTR",
|
|
"record_value": record_value}
|
|
return zone_name, record
|
|
|
|
|
|
def _clean_hosts_entries(hosts_entries, cdomain):
|
|
entries = list()
|
|
for host_entry in hosts_entries:
|
|
value, name, record_type, zone = _parse_host_entry(host_entry)
|
|
|
|
if record_type == "Invalid":
|
|
continue
|
|
|
|
if not zone.endswith(cdomain):
|
|
continue
|
|
|
|
entries.append(host_entry)
|
|
return entries
|
|
|
|
|
|
def _parse_hosts_entries(hosts_entries_in, cdomain):
|
|
"""Extract parameters to add dns entries from hosts_data
|
|
|
|
---
|
|
:param hosts_data: is a list of strings, with each string being a line
|
|
in the /etc/hosts file.
|
|
|
|
:returns: two lists. a list of dicts containing the parameters needed for
|
|
ansible-freeipa dnsrecord to add, and a list of dicts containing
|
|
dnszones to add.
|
|
"""
|
|
zones = set()
|
|
records = list()
|
|
|
|
hosts_entries = _clean_hosts_entries(hosts_entries_in, cdomain)
|
|
|
|
# get forward entries
|
|
for host_entry in hosts_entries:
|
|
value, name, record_type, zone = _parse_host_entry(host_entry)
|
|
|
|
# add forward zone
|
|
if zone not in zones:
|
|
zones.add(zone)
|
|
|
|
# add forward record
|
|
record = {"record_name": name,
|
|
"zone_name": zone,
|
|
"record_type": record_type,
|
|
"record_value": value}
|
|
|
|
records.append(record)
|
|
|
|
# NOTE(alee) Create a set of reverse DNS records to be added. We need
|
|
# to process entries in the reverse order, because there may be duplicate
|
|
# entries and we only want the latest entry.
|
|
|
|
visited_ips = set()
|
|
for host_entry in reversed(hosts_entries):
|
|
value, name, record_type, zone = _parse_host_entry(host_entry)
|
|
|
|
if value in visited_ips:
|
|
continue
|
|
|
|
visited_ips.add(value)
|
|
zone, record = _get_reverse_entry(name, zone, value)
|
|
|
|
# add reverse zone
|
|
if zone not in zones:
|
|
zones.add(zone)
|
|
|
|
# add reverse record
|
|
records.append(record)
|
|
|
|
return [list(zones), records]
|
|
|
|
|
|
def get_dns_zones(hosts_entries, cdomain):
|
|
return _parse_hosts_entries(hosts_entries, cdomain)[0]
|
|
|
|
|
|
def get_dns_entries(hosts_entries, cdomain):
|
|
return _parse_hosts_entries(hosts_entries, cdomain)[1]
|
|
|
|
|
|
class FilterModule(object):
|
|
def filters(self):
|
|
return {
|
|
'get_dns_entries': get_dns_entries,
|
|
'get_dns_zones': get_dns_zones
|
|
}
|