create feeder function to send dns updates. forward/reverse/cname call send_dns_update.

Collapse keyutils into helper. Create single create_keyring function that decides what to create.
This commit is contained in:
Jeffrey Forman 2012-11-30 07:25:23 -05:00
parent 46a91e2fdf
commit 063d64d6c6
3 changed files with 78 additions and 54 deletions

View File

@ -2,6 +2,7 @@
# 3rd Party # 3rd Party
from django import forms from django import forms
from django.core.exceptions import ValidationError
# App Imports # App Imports
from models import Key from models import Key

View File

@ -1,18 +1,20 @@
### Binder Helpers ### Binder Helpers
# Standard Imports # Standard Imports
from collections import OrderedDict import binascii
import re import re
import socket import socket
import sys
# 3rd Party # 3rd Party
import dns.query import dns.query
import dns.reversename import dns.reversename
import dns.update
import dns.tsig import dns.tsig
import dns.tsigkeyring
import dns.update
# App Imports # App Imports
from binder import exceptions, keyutils, models from binder import exceptions, models
def add_record(dns_server, zone_name, record_name, record_type, record_data, ttl, key_name, create_reverse=False): def add_record(dns_server, zone_name, record_name, record_type, record_data, ttl, key_name, create_reverse=False):
""" Parse passed elements and determine which records to create. """ Parse passed elements and determine which records to create.
@ -25,15 +27,15 @@ def add_record(dns_server, zone_name, record_name, record_type, record_data, ttl
String record_data (IP address) String record_data (IP address)
Int ttl Int ttl
String key_name (from Key model) String key_name (from Key model)
Boolean create_reverse Boolean create_reverse (Whether to create a PTR record, default False)
Return: Return:
Dict containing {description, output} from record creation Dict containing {description, output} from record creation
""" """
response = [] response = []
response.append({ "description" : "Forward Record Added: %s.%s" % (record_name, zone_name), response.append({ "description" : "Forward Record Creation: %s.%s" % (record_name, zone_name),
"output" : update_record(dns_server, "output" : create_update(dns_server,
zone_name, zone_name,
record_name, record_name,
record_type, record_type,
@ -53,8 +55,8 @@ def add_record(dns_server, zone_name, record_name, record_type, record_data, ttl
# for this reverse DNS record parsing. # for this reverse DNS record parsing.
reverse_ip = re.search(r"([0-9]+).(.*)$", reverse_ip_fqdn).group(1) reverse_ip = re.search(r"([0-9]+).(.*)$", reverse_ip_fqdn).group(1)
reverse_domain = re.search(r"([0-9]+).(.*)$", reverse_ip_fqdn).group(2) reverse_domain = re.search(r"([0-9]+).(.*)$", reverse_ip_fqdn).group(2)
response.append({ "description" : "Reverse Record Added: %s" % record_data, response.append({ "description" : "Reverse Record Creation: %s" % record_data,
"output" : update_record(dns_server, "output" : create_update(dns_server,
reverse_domain, reverse_domain,
reverse_ip, reverse_ip,
"PTR", "PTR",
@ -67,7 +69,7 @@ def add_record(dns_server, zone_name, record_name, record_type, record_data, ttl
def add_cname_record(dns_server, zone_name, cname, originating_record, ttl, key_name): def add_cname_record(dns_server, zone_name, cname, originating_record, ttl, key_name):
"""Add a Cname record.""" """Add a Cname record."""
output = update_record(dns_server, output = create_update(dns_server,
zone_name, zone_name,
cname, cname,
"CNAME", "CNAME",
@ -81,12 +83,8 @@ def add_cname_record(dns_server, zone_name, cname, originating_record, ttl, key_
def delete_record(dns_server, rr_list, key_name): def delete_record(dns_server, rr_list, key_name):
"""Delete a list of DNS records passed as strings in rr_items.""" """Delete a list of DNS records passed as strings in rr_items."""
if key_name is None:
keyring = None
else:
try: try:
this_key = models.Key.objects.get(name=key_name) keyring = create_keyring(key_name)
keyring = keyutils.create_keyring(this_key.name, this_key.data)
except exceptions.KeyringException, err: except exceptions.KeyringException, err:
return([{ "description" : "Error in deletion process", return([{ "description" : "Error in deletion process",
"output" : err }]) "output" : err }])
@ -98,28 +96,24 @@ def delete_record(dns_server, rr_list, key_name):
domain = re_record.group(2) domain = re_record.group(2)
dns_update = dns.update.Update(domain, keyring = keyring) dns_update = dns.update.Update(domain, keyring = keyring)
dns_update.delete(record) dns_update.delete(record)
try: output = send_dns_update(dns_update, dns_server, key_name)
output = dns.query.tcp(dns_update, dns_server)
except dns.tsig.PeerBadKey:
output = "The DNS server does not know about the TSIG key: %s" % key_name
delete_response.append({ "description" : "Delete Record: %s" % current_rr, delete_response.append({ "description" : "Delete Record: %s" % current_rr,
"output" : output }) "output" : output })
return delete_response return delete_response
def update_record(dns_server, zone_name, record_name, record_type, record_data, ttl, key_name): def create_update(dns_server, zone_name, record_name, record_type, record_data, ttl, key_name):
""" Update/Create DNS record of name and type with passed data and ttl. """ """ Update/Create DNS record of name and type with passed data and ttl. """
if key_name is None: try:
keyring = None keyring = create_keyring(key_name)
else: except exceptions.KeyringException, err:
this_key = models.Key.objects.get(name=key_name) return(err)
keyring = keyutils.create_keyring(this_key.name, this_key.data)
dns_update = dns.update.Update(zone_name, keyring = keyring) dns_update = dns.update.Update(zone_name, keyring = keyring)
dns_update.replace(record_name, ttl, record_type, record_data) dns_update.replace(record_name, ttl, record_type, record_data)
output = dns.query.tcp(dns_update, dns_server) output = send_dns_update(dns_update, dns_server, key_name)
return output return output
@ -142,3 +136,57 @@ def ip_info(host_name):
info.append(["Error", "Unable to resolve %s: %s" % (host_name, err)]) info.append(["Error", "Unable to resolve %s: %s" % (host_name, err)])
return info return info
def send_dns_update(dns_message, dns_server, key_name):
""" Send DNS message to server and return response.
Args:
Update dns_update
String dns_server
String key_name
Returns:
String output
"""
try:
output = dns.query.tcp(dns_message, dns_server)
except dns.tsig.PeerBadKey:
output = ("DNS server %s is not configured for TSIG key: %s." %
(dns_server, key_name))
except dns.tsig.PeerBadSignature:
output = ("DNS server %s did like the TSIG signature we sent. Check key %s "
"for correctness." % (dns_server, key_name))
return output
def create_keyring(key_name):
"""Return a tsigkeyring object from key name and key data.
Args:
key_name: String representation of Key name object
Return:
None if key_name is none.
keyring object with the key name and TSIG secret.
Raises:
KeyringException: For incorrect key data.
"""
if key_name is None:
return None
# TODO: Unittest here for key_name that does not exist
# Stick this in a try/except and catch models.Key.DoesNotExist
this_key = models.Key.objects.get(name=key_name)
try:
keyring = dns.tsigkeyring.from_text({
this_key.name : this_key.data
})
except binascii.Error, err:
raise exceptions.KeyringException("Incorrect key data. Verify key: %s. Reason: %s" % (key_name, err))
return keyring

View File

@ -1,25 +0,0 @@
import binascii
import dns.tsigkeyring
from binder import exceptions
def create_keyring(key_name, key_data):
"""Return a tsigkeyring object from key name and key data.
Args:
key_name: String representation of key name
key_data: String representation of TSIG key hash
Return:
keyring object with the key name and TSIG secret.
"""
try:
keyring = dns.tsigkeyring.from_text({
key_name : key_data
})
except binascii.Error, err:
raise exceptions.KeyringException("Error creating keyring. Verify correct key data for key: %s. Reason: %s" % (key_name, err))
return keyring