From 4565e93d93d1263b452254c40a4e358c0c163de4 Mon Sep 17 00:00:00 2001 From: Jeffrey Forman Date: Sat, 27 Oct 2012 18:03:45 -0400 Subject: [PATCH] a fairly big rewrite of add/delete record that actually works! --- binder/bcommon/forms.py | 17 ++-- binder/bcommon/helpers.py | 79 +++++++++++------ binder/bcommon/views.py | 42 ++++----- binder/templates/base.htm | 78 ++++++++-------- binder/templates/bcommon/add_record_form.htm | 88 +++++++++++++++++-- .../templates/bcommon/add_record_result.htm | 21 ++--- .../bcommon/delete_record_initial.htm | 1 + binder/urls.py | 27 +++--- 8 files changed, 217 insertions(+), 136 deletions(-) diff --git a/binder/bcommon/forms.py b/binder/bcommon/forms.py index 82516ca..68cf768 100644 --- a/binder/bcommon/forms.py +++ b/binder/bcommon/forms.py @@ -1,6 +1,6 @@ from django import forms -from bcommon.models import BindServer, Key +from bcommon.models import Key RECORD_TYPE_CHOICES = (("A", "A"), ("AAAA", "AAAA"), ("CNAME", "CNAME")) TTL_CHOICES = ((300, "5 minutes"), @@ -10,13 +10,14 @@ TTL_CHOICES = ((300, "5 minutes"), (86400, "1 day")) class FormAddRecord(forms.Form): - dns_server = forms.CharField(max_length=100, label="Hostname of DNS Server", widget=forms.TextInput(attrs={'readonly':'readonly'})) - name = forms.CharField(max_length=100, label="Record Name (FQDN)") - record_type = forms.ChoiceField(choices=RECORD_TYPE_CHOICES, label="Record Type") - ttl = forms.ChoiceField(choices=TTL_CHOICES, label="TTL", initial=86400) - create_reverse = forms.BooleanField(label="Create Reverse Record (PTR)?", required=False) - data = forms.CharField(max_length=256, label="Record Data (IP/Hostname)") - key_name = forms.ModelChoiceField(queryset=Key.objects.all(), empty_label=None, label="TSIG Key", required=False) + dns_server = forms.CharField(max_length=100) + record_name = forms.RegexField(max_length=100, regex="^[a-zA-Z0-9-_]+$", required=False) + record_type = forms.CharField(max_length=10) + zone_name = forms.CharField(max_length=100) + record_data = forms.GenericIPAddressField() + ttl = forms.IntegerField(min_value=1) + create_reverse = forms.BooleanField(required=False) + key_name = forms.ModelChoiceField(queryset=Key.objects.all(), empty_label=None, required=False) class FormAddCnameRecord(forms.Form): diff --git a/binder/bcommon/helpers.py b/binder/bcommon/helpers.py index e43a07b..effeabb 100644 --- a/binder/bcommon/helpers.py +++ b/binder/bcommon/helpers.py @@ -5,8 +5,13 @@ 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.""" @@ -34,39 +39,29 @@ def list_zone_records(dns_server, zone_name): 'rr_data' : split_record.split(" ")[4]}) return record_array -def add_forward_record(form_data, zone_keyring): +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.""" - re_form_data = re.search(r"(\w+).(.*)", form_data["name"]) - hostname = re_form_data.group(1) - domain = re_form_data.group(2) - - dns_update = dns.update.Update(domain, keyring = zone_keyring) - if str(form_data["record_type"]) == "CNAME": - data_suffix = "." - else: - data_suffix = "" - - dns_update.replace(hostname, int(form_data["ttl"]), str(form_data["record_type"]), str(form_data["data"]) + data_suffix) + 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, form_data["dns_server"]) + response = dns.query.tcp(dns_update, dns_server) except dns.tsig.BadPeerKey: - raise Exception("There was a problem adding your forward record due to a TSIG key issue.") + raise BinderException("There was a problem adding your forward record due to a TSIG key issue.") return response -def add_reverse_record(form_data, zone_keyring): - """ Given a FormAddRecord dict and zone_keyring, - add/update a reverse PTR record.""" - reverse_ip_fqdn = str(dns.reversename.from_address(form_data["data"])) +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 = zone_keyring) - dns_update.replace(reverse_ip, int(form_data["ttl"]), "PTR", str(form_data["name"]) + ".") - output = dns.query.tcp(dns_update, form_data["dns_server"]) + 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 @@ -75,23 +70,50 @@ def add_record(form_data): If a reverse PTR record is requested, this will be added too.""" if form_data["key_name"]: - keyring = create_keyring(form_data["key_name"]) + keyring = keyutils.create_keyring(form_data["key_name"]) else: keyring = None - response = {} - forward_response = add_forward_record(form_data, keyring) - response["forward_response"] = forward_response + 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"]: - reverse_response = add_reverse_record(form_data, keyring) - response["reverse_response"] = reverse_response + 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 = 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 ("key_name" in form_data and form_data["key_name"]): + + if form_data["key_name"]: keyring = create_keyring(form_data["key_name"]) else: keyring = None @@ -102,7 +124,6 @@ def delete_record(form_data, 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) diff --git a/binder/bcommon/views.py b/binder/bcommon/views.py index 001b151..1166af1 100644 --- a/binder/bcommon/views.py +++ b/binder/bcommon/views.py @@ -2,7 +2,7 @@ from bcommon.models import BindServer, Key from django.template import Context -from django.shortcuts import render_to_response, redirect +from django.shortcuts import render_to_response, redirect, render from bcommon.helpers import add_record, delete_record, add_cname_record from bcommon.forms import FormAddRecord, FormAddCnameRecord @@ -49,6 +49,7 @@ def view_zone_records(request, dns_server, zone_name): this_server = BindServer.objects.get(hostname=dns_server) zone_array = this_server.list_zone_records(zone_name) except Exception, err: + # TODO: Use a custom exception here. return render_to_response('bcommon/list_zone.htm', { 'errors' : err}, context_instance=RequestContext(request)) @@ -59,41 +60,35 @@ def view_zone_records(request, dns_server, zone_name): 'zone_name' : zone_name}, context_instance=RequestContext(request)) -def view_add_record(request, dns_server, zone): +def view_add_record(request, dns_server, zone_name): """ View to provide form to add a DNS record. """ - form = FormAddRecord(initial={ 'dns_server' : dns_server, - 'zone' : zone }) - return render_to_response('bcommon/add_record_form.htm', - { 'form' : form }, - context_instance=RequestContext(request)) + return render(request, 'bcommon/add_record_form.htm', + { "dns_server" : dns_server, + "zone_name" : zone_name }) def view_add_record_result(request): """ Process the input given to add a DNS record. """ + errors = None if request.method == "GET": - # Return home. You shouldn't be accessing this url via a GET. return redirect('/') form = FormAddRecord(request.POST) if form.is_valid(): cd = form.cleaned_data - else: - form = FormAddRecord(request.POST) - return render_to_response('bcommon/add_record_form.htm', - { 'form' : form }, - context_instance=RequestContext(request)) - - try: - add_record_response = add_record(cd) - except Exception, err: + try: + add_record_response = add_record(cd) + except BinderException, errors: + pass return render_to_response('bcommon/add_record_result.htm', - { "errors" : err }, + { "errors" : errors, + "response" : add_record_response }, context_instance=RequestContext(request)) - return render_to_response('bcommon/add_record_result.htm', - { 'response' : add_record_response, - 'rr_data' : cd }, - context_instance=RequestContext(request)) - + return render(request, 'bcommon/add_record_form.htm', + { "dns_server" : request.POST["dns_server"], + "zone_name" : request.POST["zone_name"], + "form_errors" : form.errors, + "form_data" : request.POST }) def view_add_cname_record(request, dns_server, zone_name, record_name): """ Process given input to add a CNAME pointer.""" @@ -172,7 +167,6 @@ def view_delete_result(request): { "errors" : err }, context_instance=RequestContext(request)) - return render_to_response('bcommon/delete_record_result.htm', { 'delete_result' : delete_result }, context_instance=RequestContext(request)) diff --git a/binder/templates/base.htm b/binder/templates/base.htm index 1d0b6ad..58ad465 100644 --- a/binder/templates/base.htm +++ b/binder/templates/base.htm @@ -9,53 +9,51 @@
-
-{% block navigation %} - -{% endblock navigation %} -
+
+ {% block navigation %} + + {% endblock navigation %} +
-
+
+ + + + - - - + {% block errors %} - -{% block errors %} - -{% if errors %} -
- Errors were encountered: -
- {{ errors }} - {% if error_context %} - {{ error_context }} - {% endif %} -
-{% endif %} - -{% endblock errors %} - -{% block body %} -{% endblock body %} - - -
-
{% block footer %} {% endblock footer %} diff --git a/binder/templates/bcommon/add_record_form.htm b/binder/templates/bcommon/add_record_form.htm index 298a20c..0bb25ff 100644 --- a/binder/templates/bcommon/add_record_form.htm +++ b/binder/templates/bcommon/add_record_form.htm @@ -1,15 +1,91 @@ {% extends "base.htm" %} {% block pageheader %} -Add record in {{ dns_server }} +Add record in {{ zone_name }} {% endblock pageheader %} {% block body %} -
{% csrf_token %} - - {{ form.as_table }} -
- +{% csrf_token %} + Create Foward Record + +
+ +
+ {{dns_server}} + +
+
+ + +
+ +
+
+ .{{zone_name}} +
+ {% if form_errors.record_name %} +
+ Record Name: {{ form_errors.record_name|stringformat:"s"|striptags }} Previous Value: {{ form_data.record_name }} +
+ {% endif %} +
+
+ +
+ +
+ +
+
+ +
+ +
+
+ +
+ {% if form_errors.record_data %} +
+ Record Name: {{ form_errors.record_data|stringformat:"s"|striptags }} Previous Value: {{ form_data.record_data }} +
+ {% endif %} +
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+
+ +
+ {% endblock body %} diff --git a/binder/templates/bcommon/add_record_result.htm b/binder/templates/bcommon/add_record_result.htm index c16a354..ece1aa3 100644 --- a/binder/templates/bcommon/add_record_result.htm +++ b/binder/templates/bcommon/add_record_result.htm @@ -7,24 +7,15 @@ Add Record Result {% block body %} -{% if response.forward_response %} +{% for current_response in response %} - - + + - - + + -{% endif %} - -{% if response.reverse_response %} - - - - - -{% endif %} +{% endfor %}
Record: {{ response.name }}Add ResultRecord:Output
Forward: {{ rr_data.name }}
{{ response.forward_response }}
{{ current_response.type }}
{{ current_response.output }}
Reverse: {{ rr_data.data }}
{{ response.reverse_response }}
- {% endblock body %} diff --git a/binder/templates/bcommon/delete_record_initial.htm b/binder/templates/bcommon/delete_record_initial.htm index 533fb4c..88d4f45 100644 --- a/binder/templates/bcommon/delete_record_initial.htm +++ b/binder/templates/bcommon/delete_record_initial.htm @@ -31,6 +31,7 @@ Delete record(s) in {{ zone_name }} Key