binder/binder/helpers.py

133 lines
5.5 KiB
Python

import keyutils
import re
import dns.query
import dns.reversename
import dns.update
import keyutils
re_IPADDRESS = re.compile(r"\d+.\d+.\d+.\d+")
class BinderException(Exception):
pass
def list_zone_records(dns_server, zone_name):
"""Take a DNS server and a zone name,
and return an array of its records."""
# Need to move most of this logic into a helper method.
try:
zone = dns.zone.from_xfr(dns.query.xfr(dns_server, zone_name))
except dns.exception.FormError:
# There was an error querying the server for the specific zone.
# Example: a zone that does not exist on the server.
return { 'errors' : 'Encountered a FormError when querying %s on %s' % (zone_name, dns_server) }
except socket.gaierror, err:
# TODO: Need to better handle errors here.
return { 'errors' : "Problems querying DNS server %s: %s" % (dns_server, err) }
names = zone.nodes.keys()
names.sort()
record_array = []
for current_name in names:
current_record = zone[current_name].to_text(current_name)
for split_record in current_record.split("\n"): # Split the records on the newline
record_array.append({'rr_name' : split_record.split(" ")[0],
'rr_ttl' : split_record.split(" ")[1],
'rr_class' : split_record.split(" ")[2],
'rr_type' : split_record.split(" ")[3],
'rr_data' : split_record.split(" ")[4]})
return record_array
def add_forward_record(dns_server, zone_name, record_name, record_type, record_data, ttl, keyring):
"""Take in data from FormAddRecord and a keyring object,
return a response from the DNS server about adding the record."""
dns_update = dns.update.Update(zone_name, keyring = keyring)
dns_update.replace(record_name, ttl, record_type, record_data)
try:
response = dns.query.tcp(dns_update, dns_server)
except dns.tsig.BadPeerKey:
raise BinderException("There was a problem adding your forward record due to a TSIG key issue.")
return response
def add_reverse_record(dns_server, zone_name, record_name, record_data, ttl, keyring):
""" Given passed arguments, add/update a reverse PTR record."""
reverse_ip_fqdn = str(dns.reversename.from_address(record_data))
reverse_ip = re.search(r"([0-9]+).(.*).$", reverse_ip_fqdn).group(1)
reverse_domain = re.search(r"([0-9]+).(.*).$", reverse_ip_fqdn).group(2)
dns_update = dns.update.Update(reverse_domain, keyring = keyring)
dns_update.replace(reverse_ip, ttl, "PTR", "%s.%s." % (record_name, zone_name))
output = dns.query.tcp(dns_update, dns_server)
return output
def add_record(form_data):
"""Add a DNS record with data from a FormAddRecord dict.
If a reverse PTR record is requested, this will be added too."""
if form_data["key_name"]:
keyring = keyutils.create_keyring(form_data["key_name"])
else:
keyring = None
response = []
response.append({ "type" : "Forward Record: %s.%s" % (str(form_data["record_name"]),
str(form_data["zone_name"])),
"output" : add_forward_record(str(form_data["dns_server"]),
str(form_data["zone_name"]),
str(form_data["record_name"]),
str(form_data["record_type"]),
str(form_data["record_data"]),
form_data["ttl"],
keyring)})
if form_data["create_reverse"]:
response.append({ "type" : "Reverse Record: %s" % form_data["record_data"],
"output" : add_reverse_record(str(form_data["dns_server"]),
str(form_data["zone_name"]),
str(form_data["record_name"]),
str(form_data["record_data"]),
form_data["ttl"],
keyring)})
return response
def add_cname_record(dns_server, zone_name, originating_record, cname, ttl, key_name):
"""Add a Cname record."""
if key_name is None:
keyring = keyutils.create_keyring(key_name)
else:
keyring = None
update = dns.update.Update(zone_name, keyring = keyring)
update.replace(cname, int(ttl), 'CNAME', originating_record + ".")
response = dns.query.tcp(update, dns_server)
return response
def delete_record(form_data, rr_items):
"""Delete a list of DNS records passed as strings in rr_items."""
if form_data["key_name"]:
keyring = keyutils.create_keyring(form_data["key_name"])
else:
keyring = None
dns_server = form_data["dns_server"]
delete_response = []
for current_rr_item in rr_items:
re_record = re.search(r"(\w+)\.(.*)$", current_rr_item)
record = re_record.group(1)
domain = re_record.group(2)
dns_update = dns.update.Update(domain, keyring = keyring)
dns_update.delete(record)
output = dns.query.tcp(dns_update, dns_server)
delete_response.append({ "rr_item" : current_rr_item, "output" : output })
return delete_response