Merge branch 'nsd'
This commit is contained in:
commit
fe09f1f57a
11
Dockerfile
11
Dockerfile
|
@ -1,16 +1,13 @@
|
||||||
FROM python:2.7
|
FROM python:3-alpine
|
||||||
|
|
||||||
MAINTAINER Jeffrey Forman <code@jeffreyforman.net>
|
MAINTAINER Jeffrey Forman <code@jeffreyforman.net>
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
|
||||||
|
|
||||||
RUN apt-get update \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
WORKDIR /code
|
WORKDIR /code
|
||||||
COPY . /code/
|
COPY . /code/
|
||||||
|
|
||||||
RUN pip install -r requirements.txt
|
RUN apk add --no-cache nsd build-base python3-dev libffi-dev openssl-dev libc-dev libxslt-dev \
|
||||||
|
&& pip install --upgrade pip \
|
||||||
|
&& pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,6 @@ bootstrapping.
|
||||||
```
|
```
|
||||||
python manage.py migrate
|
python manage.py migrate
|
||||||
python manage.py createsuperuser
|
python manage.py createsuperuser
|
||||||
...
|
|
||||||
python manage.py dumpdata -o binder/fixtures/initial_data.json
|
python manage.py dumpdata -o binder/fixtures/initial_data.json
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import binascii
|
import binascii
|
||||||
import dns.tsigkeyring
|
import dns.tsigkeyring
|
||||||
from models import BindServer, Key
|
from binder.models import BindServer, Key
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.forms import ModelForm, ValidationError
|
from django.forms import ModelForm, ValidationError
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -8,7 +8,7 @@ from django.core import validators
|
||||||
from django.forms import ValidationError
|
from django.forms import ValidationError
|
||||||
|
|
||||||
# App Imports
|
# App Imports
|
||||||
from models import Key
|
from binder.models import Key
|
||||||
|
|
||||||
|
|
||||||
class CustomUnicodeListField(forms.CharField):
|
class CustomUnicodeListField(forms.CharField):
|
||||||
|
|
|
@ -170,7 +170,7 @@ def ip_info(host_name):
|
||||||
if s_family == 10 and s_type == 1:
|
if s_family == 10 and s_type == 1:
|
||||||
ipv6_count += 1
|
ipv6_count += 1
|
||||||
info.append(["IPv6 (%d)" % ipv6_count, s_sockaddr[0]])
|
info.append(["IPv6 (%d)" % ipv6_count, s_sockaddr[0]])
|
||||||
except socket.gaierror, err:
|
except (socket.gaierror, err):
|
||||||
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
|
||||||
|
|
|
@ -2,22 +2,26 @@ from django.conf import settings
|
||||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
|
||||||
class LoginRequiredMiddleware(object):
|
class LoginRequiredMiddleware:
|
||||||
"""Middleware to redirect to the login page if the user isn't authenticated
|
"""Middleware to redirect to the login page if the user isn't authenticated
|
||||||
|
|
||||||
After successful authentication the user is redirected back to the page he
|
After successful authentication the user is redirected back to the page he
|
||||||
initially wanted to access.
|
initially wanted to access.
|
||||||
"""
|
"""
|
||||||
def process_request(self, request):
|
def __init__(self, get_response):
|
||||||
|
self.get_response = get_response
|
||||||
|
|
||||||
|
def __call__(self, request):
|
||||||
# allow access to the login url
|
# allow access to the login url
|
||||||
|
response = self.get_response(request)
|
||||||
if request.path == settings.LOGIN_URL:
|
if request.path == settings.LOGIN_URL:
|
||||||
return
|
return response
|
||||||
# redirect to the login url if the user isn't authenticated
|
# redirect to the login url if the user isn't authenticated
|
||||||
if not request.user.is_authenticated():
|
if not request.user.is_authenticated:
|
||||||
if request.path not in (settings.LOGIN_URL,
|
if request.path not in (settings.LOGIN_URL,
|
||||||
settings.LOGIN_REDIRECT_URL):
|
settings.LOGIN_REDIRECT_URL):
|
||||||
return HttpResponseRedirect('%s?%s=%s' % (settings.LOGIN_URL,
|
return HttpResponseRedirect('%s?%s=%s' % (settings.LOGIN_URL,
|
||||||
REDIRECT_FIELD_NAME,
|
REDIRECT_FIELD_NAME,
|
||||||
request.path))
|
request.path))
|
||||||
else:
|
|
||||||
return HttpResponseRedirect(settings.LOGIN_URL)
|
return HttpResponseRedirect(settings.LOGIN_URL)
|
||||||
|
return response
|
||||||
|
|
|
@ -48,7 +48,7 @@ class Key(models.Model):
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
f = Fernet(settings.FERNET_KEY)
|
f = Fernet(settings.FERNET_KEY)
|
||||||
crypted_key = f.encrypt(bytes(self.data))
|
crypted_key = f.encrypt(bytes(self.data, encoding="utf8"))
|
||||||
self.data = crypted_key
|
self.data = crypted_key
|
||||||
super(Key, self).save(*args, **kwargs)
|
super(Key, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ class Key(models.Model):
|
||||||
try:
|
try:
|
||||||
key_data = self.decrypt_keydata()
|
key_data = self.decrypt_keydata()
|
||||||
keyring = dns.tsigkeyring.from_text({self.name: key_data})
|
keyring = dns.tsigkeyring.from_text({self.name: key_data})
|
||||||
except binascii.Error, err:
|
except (binascii.Error, err):
|
||||||
raise exceptions.KeyringException("Incorrect key data. Verify key: %s. Reason: %s" % (self.name, err))
|
raise exceptions.KeyringException("Incorrect key data. Verify key: %s. Reason: %s" % (self.name, err))
|
||||||
|
|
||||||
return keyring
|
return keyring
|
||||||
|
@ -99,6 +99,7 @@ class BindServer(models.Model):
|
||||||
default_transfer_key = models.ForeignKey(Key,
|
default_transfer_key = models.ForeignKey(Key,
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
help_text="The default key to use for all actions "
|
help_text="The default key to use for all actions "
|
||||||
"with this DNS server as long as no other key is "
|
"with this DNS server as long as no other key is "
|
||||||
"specified explicitly.")
|
"specified explicitly.")
|
||||||
|
@ -153,7 +154,7 @@ class BindServer(models.Model):
|
||||||
except dns.tsig.PeerBadKey:
|
except dns.tsig.PeerBadKey:
|
||||||
# The incorrect TSIG key was selected for transfers.
|
# The incorrect TSIG key was selected for transfers.
|
||||||
raise exceptions.TransferException("Unable to list zone records because of a TSIG key mismatch.")
|
raise exceptions.TransferException("Unable to list zone records because of a TSIG key mismatch.")
|
||||||
except socket.error, err:
|
except socket.error as err:
|
||||||
# Thrown when the DNS server does not respond for a zone transfer (XFR).
|
# Thrown when the DNS server does not respond for a zone transfer (XFR).
|
||||||
raise exceptions.TransferException("DNS server did not respond for transfer. Reason: %s" % err)
|
raise exceptions.TransferException("DNS server did not respond for transfer. Reason: %s" % err)
|
||||||
except dns.exception.FormError:
|
except dns.exception.FormError:
|
||||||
|
|
|
@ -97,13 +97,14 @@ TEMPLATES = [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = (
|
MIDDLEWARE = (
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
|
||||||
'django.middleware.common.CommonMiddleware',
|
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
'binder.middlewares.LoginRequiredMiddleware',
|
'binder.middlewares.LoginRequiredMiddleware',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,8 @@ class Model_Key_Tests(TestCase):
|
||||||
key_1.save()
|
key_1.save()
|
||||||
decrypt_key = Fernet(settings.FERNET_KEY)
|
decrypt_key = Fernet(settings.FERNET_KEY)
|
||||||
decrypted_tsig_key = decrypt_key.decrypt(bytes(key_1.data))
|
decrypted_tsig_key = decrypt_key.decrypt(bytes(key_1.data))
|
||||||
self.assertEqual(original_tsig_key, decrypted_tsig_key)
|
self.assertEqual(bytes(original_tsig_key, encoding="utf8"),
|
||||||
|
decrypted_tsig_key)
|
||||||
|
|
||||||
@override_settings(FERNET_KEY='yfE1kyYLNlpR-2ybdB-Mvs_k1ZoDMFFVtE_PpWYxVgs=')
|
@override_settings(FERNET_KEY='yfE1kyYLNlpR-2ybdB-Mvs_k1ZoDMFFVtE_PpWYxVgs=')
|
||||||
def test_FernetKeyDecryptionFailure(self):
|
def test_FernetKeyDecryptionFailure(self):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.client import Client
|
from django.test.client import Client
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.core.urlresolvers import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from binder import models
|
from binder import models
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ class PostTests(TestCase):
|
||||||
self.assertContains(response,
|
self.assertContains(response,
|
||||||
'<input type="hidden" id="zone_name" name="zone_name" value="testzone1.test.net" />', html=True)
|
'<input type="hidden" id="zone_name" name="zone_name" value="testzone1.test.net" />', html=True)
|
||||||
self.assertContains(response,
|
self.assertContains(response,
|
||||||
'<input type="hidden" id="rr_list" name="rr_list" value="[u'testrecord1.testzone1.test.net', u'testrecord2.testzone1.test.net']"/>',
|
'<input type="hidden" id="rr_list" name="rr_list" value="['testrecord1.testzone1.test.net', 'testrecord2.testzone1.test.net']"/>',
|
||||||
html=True)
|
html=True)
|
||||||
self.assertContains(response,
|
self.assertContains(response,
|
||||||
'<input type="hidden" id="dns_server" name="dns_server" value="testserver.test.net" />',
|
'<input type="hidden" id="dns_server" name="dns_server" value="testserver.test.net" />',
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
from django.conf.urls import include, url
|
from django.conf.urls import include, url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
import django.contrib.auth.views
|
from django.contrib.auth import login
|
||||||
|
from django.contrib.auth.views import logout_then_login
|
||||||
|
from django.contrib.auth import views as auth_views
|
||||||
import binder.views
|
import binder.views
|
||||||
admin.autodiscover()
|
admin.autodiscover()
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^admin/', include(admin.site.urls)),
|
url(r'^admin/', admin.site.urls),
|
||||||
|
|
||||||
url(r'^accounts/login/$', django.contrib.auth.views.login, name='login'),
|
url(r'^accounts/login/$', auth_views.LoginView.as_view(), name='login'),
|
||||||
url(r'^accounts/logout/$', django.contrib.auth.views.logout_then_login, name='logout'),
|
url(r'^accounts/logout/$', logout_then_login, name='logout'),
|
||||||
|
|
||||||
url(r'^$', binder.views.home_index, name="index"),
|
url(r'^$', binder.views.home_index, name="index"),
|
||||||
url(r'^server_list/$', binder.views.view_server_list, name="server_list"),
|
url(r'^server_list/$', binder.views.view_server_list, name="server_list"),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
docker build -t jforman/binder:latest .
|
docker build -t jforman/binder:latest .
|
||||||
docker run -it --rm -v `pwd`:/code/ -w /code/ jforman/binder:latest /bin/bash
|
docker run -it --rm -v `pwd`:/code/ -w /code/ jforman/binder:latest /bin/ash
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
|
Django
|
||||||
cryptography
|
cryptography
|
||||||
Django>=1.10
|
|
||||||
dnspython>=1.11
|
dnspython>=1.11
|
||||||
pybindxml>=0.7
|
pybindxml>=0.7
|
||||||
lxml
|
lxml
|
||||||
mysqlclient
|
|
||||||
|
|
Loading…
Reference in New Issue