binder/binder/views.py

264 lines
12 KiB
Python

# Binder Views
import subprocess
# 3rd Party
import dns.query
from django.contrib import messages
from django.shortcuts import get_object_or_404, redirect, render
# App Imports
from binder import forms, helpers, models
from binder import exceptions
def home_index(request):
"""List the main index page for Binder."""
return render(request, "index.html")
def view_server_list(request):
"""List the DNS servers configured in the database."""
server_list = models.BindServer.objects.all().order_by("hostname")
server_info = []
for current in server_list:
server_info.append({"host_name": current,
"ip_address": helpers.ip_info(current.hostname),
"server_type": current.server_type})
return render(request, "bcommon/list_servers.html",
{"server_info": server_info})
def view_server_zones(request, dns_server):
"""Display the list of DNS zones a particular DNS host provides."""
zone_array = {}
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
try:
zone_array = this_server.list_zones()
except exceptions.ZoneException as exc:
messages.error(request, "Unable to list server zones. Error: %s" % exc)
except subprocess.CalledProcessError as err:
messages.error(request, "Error in retrieving zones: %s." % str(err.output))
return render(request, "bcommon/list_server_zones.html",
{"dns_server": this_server,
"zone_array": zone_array})
def view_zone_records(request, dns_server, zone_name):
"""Display the list of records for a particular zone."""
zone_array = {}
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
try:
zone_array = this_server.list_zone_records(zone_name)
except exceptions.TransferException as exc:
messages.error(request, "TransferException: %s." % exc)
return render(request, "bcommon/list_zone.html",
{"zone_name": zone_name,
"dns_server": this_server})
except exceptions.KeyringException:
messages.error(request, "Unable to get zone list. A problem was encountered "
"decrypting your TSIG key. Ensure the key is correctly "
"specified in the Binder Database.")
return render(request, "bcommon/list_zone.html",
{ "dns_server": this_server,
"zone_name" :zone_name })
except dns.query.TransferError as err:
messages.error(request, "TransferError: %s." % err)
return render(request, "bcommon/list_zone.html",
{"zone_name": zone_name,
"dns_server": this_server})
return render(request, "bcommon/list_zone.html",
{"zone_array": zone_array,
"dns_server": this_server,
"zone_name": zone_name,
# NOTE: A hack because NSD doesn't support dynamic updates
# so merely display the zone.
"dynamic_dns_available": this_server.server_type in ['BIND']})
def view_add_record(request, dns_server, zone_name):
"""View to add an RR record to DNS zone."""
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
if request.method == 'POST':
if "in-addr.arpa" in zone_name or "ip6.arpa" in zone_name:
form = forms.FormAddReverseRecord(request.POST)
else:
form = forms.FormAddForwardRecord(request.POST)
if form.is_valid():
form_cleaned = form.cleaned_data
try:
helpers.add_record(form_cleaned["dns_server"],
str(form_cleaned["zone_name"]),
str(form_cleaned["record_name"]),
str(form_cleaned["record_type"]),
str(form_cleaned["record_data"]),
form_cleaned["ttl"],
form_cleaned["key_name"],
form_cleaned["create_reverse"])
except (exceptions.KeyringException,
exceptions.RecordException) as exc:
messages.error(request, "Adding %s.%s failed: %s" %
(form_cleaned["record_name"], zone_name, exc))
else:
messages.success(request, "%s.%s was added successfully." %
(form_cleaned["record_name"], zone_name))
return redirect('zone_list',
dns_server=dns_server,
zone_name=zone_name)
else:
messages.error(request, "Form data was invalid. Check all inputs.")
else:
# TODO: do this key_id logic on all forms for default key.
key_id = models.BindServer.objects.get(
hostname=dns_server).default_transfer_key.id
form = forms.FormAddForwardRecord(initial={
'zone_name': zone_name,
'key_name': key_id
})
return render(request, "bcommon/add_record_form.html",
{"dns_server": this_server,
"form": form})
def view_edit_record(request, dns_server, zone_name, record_name=None,
record_type=None, record_data=None, record_ttl=None):
"""View to edit an RR record to DNS zone."""
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
if request.method == 'POST':
if "in-addr.arpa" in zone_name or "ip6.arpa" in zone_name:
form = forms.FormAddReverseRecord(request.POST)
else:
form = forms.FormAddForwardRecord(request.POST)
if form.is_valid():
form_cleaned = form.cleaned_data
try:
helpers.add_record(form_cleaned["dns_server"],
str(form_cleaned["zone_name"]),
str(form_cleaned["record_name"]),
str(form_cleaned["record_type"]),
str(form_cleaned["record_data"]),
form_cleaned["ttl"],
form_cleaned["key_name"],
form_cleaned["create_reverse"])
except (exceptions.KeyringException,
exceptions.RecordException) as exc:
messages.error(request, "Modifying %s.%s failed: %s" %
(form_cleaned["record_name"], zone_name, exc))
else:
messages.success(request, "%s.%s was modified successfully." %
(form_cleaned["record_name"], zone_name))
return redirect('zone_list',
dns_server=dns_server,
zone_name=zone_name)
else:
messages.error(request, "Form data was invalid. Check all inputs.")
else:
key_id = models.BindServer.objects.get(
hostname=dns_server).default_transfer_key.id
form = forms.FormAddForwardRecord(initial={'zone_name': zone_name,
'record_name': record_name,
'record_data': record_data,
'ttl': record_ttl,
'record_type': record_type,
'key_name': key_id
})
return render(request, "bcommon/add_record_form.html",
{"dns_server": this_server,
"form": form})
def view_add_cname_record(request, dns_server, zone_name, record_name):
"""View to allow to add CNAME records."""
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
if request.method == 'POST':
form = forms.FormAddCnameRecord(request.POST)
if form.is_valid():
form_cleaned = form.cleaned_data
try:
helpers.add_cname_record(form_cleaned["dns_server"],
str(form_cleaned["zone_name"]),
str(form_cleaned["cname"]),
'%s.%s' % (str(form_cleaned["originating_record"]),
str(form_cleaned["zone_name"])),
form_cleaned["ttl"],
form_cleaned["key_name"])
except (exceptions.KeyringException,
exceptions.RecordException) as exc:
messages.error(request, "Adding %s.%s failed: %s" %
(form_cleaned["cname"], zone_name, exc))
else:
messages.success(request, "%s.%s was added successfully." %
(form_cleaned["cname"], zone_name))
return redirect('zone_list',
dns_server=dns_server,
zone_name=zone_name)
else:
key_id = models.BindServer.objects.get(
hostname=dns_server).default_transfer_key.id
form = forms.FormAddCnameRecord(initial={
'originating_record': record_name,
'zone_name': zone_name,
'key_name': key_id})
return render(request, "bcommon/add_cname_record_form.html",
{"dns_server": this_server,
"form": form})
def view_delete_record(request, dns_server, zone_name):
"""View to handle the deletion of records."""
dns_server = models.BindServer.objects.get(hostname=dns_server)
rr_list = request.POST.getlist("rr_list")
if len(rr_list) == 0:
messages.error(request, "Select at least one record for deletion.")
return redirect('zone_list',
dns_server=dns_server,
zone_name=zone_name)
if request.method == 'POST':
form = forms.FormDeleteRecord(request.POST)
if form.is_valid():
form_cleaned = form.cleaned_data
rr_list = form_cleaned["rr_list"]
try:
response = helpers.delete_record(form_cleaned["dns_server"],
rr_list,
form_cleaned["key_name"])
except exceptions.KeyringException as exc:
for record in rr_list:
messages.error(request, "Deleting %s.%s failed: %s" %
(record, zone_name, exc))
else:
for record in response:
if record['success'] == True:
messages.success(request, "%s.%s was removed successfully." %
(record['record'], zone_name))
else:
messages.error(request, "Deleting %s.%s failed: %s" %
(record['record'], zone_name, record['description']))
return redirect('zone_list',
dns_server=dns_server,
zone_name=zone_name)
else:
key_id = models.BindServer.objects.get(
hostname=dns_server).default_transfer_key.id
form = forms.FormDeleteRecord(initial={
'zone_name': zone_name,
'key_name': key_id
})
return render(request, "bcommon/delete_record.html",
{"dns_server": dns_server,
"zone_name": zone_name,
"rr_list": rr_list,
"form": form})