mirror of
https://github.com/cwinfo/powerdns-admin.git
synced 2024-11-09 23:20:27 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
5a1a4b0161
@ -1,5 +1,6 @@
|
|||||||
# PowerDNS-Admin
|
# PowerDNS-Admin
|
||||||
PowerDNS Web-GUI - Built by Flask
|
PowerDNS Web-GUI - Built by Flask
|
||||||
|
[![Build Status](https://travis-ci.org/thomasDOTde/PowerDNS-Admin.svg?branch=master)](https://travis-ci.org/thomasDOTde/PowerDNS-Admin)
|
||||||
|
|
||||||
#### Features:
|
#### Features:
|
||||||
- Multiple domain management
|
- Multiple domain management
|
||||||
@ -76,6 +77,14 @@ Web application configuration is stored in `config.py` file. Let's clone it from
|
|||||||
(flask)$ vim config.py
|
(flask)$ vim config.py
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can configure group based security by tweaking the below parameters in `config.py`. Groups membership comes from LDAP.
|
||||||
|
Setting `LDAP_GROUP_SECURITY` to True enables group-based security. With this enabled only members of the two groups listed below are allowed to login. Members of `LDAP_ADMIN_GROUP` will get the Administrator role and members of `LDAP_USER_GROUP` will get the User role. Sample config below:
|
||||||
|
```
|
||||||
|
LDAP_GROUP_SECURITY = True
|
||||||
|
LDAP_ADMIN_GROUP = 'CN=PowerDNS-Admin Admin,OU=Custom,DC=ivan,DC=local'
|
||||||
|
LDAP_USER_GROUP = 'CN=PowerDNS-Admin User,OU=Custom,DC=ivan,DC=local'
|
||||||
|
```
|
||||||
|
|
||||||
Create database after having proper configs
|
Create database after having proper configs
|
||||||
```
|
```
|
||||||
(flask)% ./create_db.py
|
(flask)% ./create_db.py
|
||||||
|
@ -20,12 +20,21 @@ from lib import utils
|
|||||||
from lib.log import logger
|
from lib.log import logger
|
||||||
logging = logger('MODEL', app.config['LOG_LEVEL'], app.config['LOG_FILE']).config()
|
logging = logger('MODEL', app.config['LOG_LEVEL'], app.config['LOG_FILE']).config()
|
||||||
|
|
||||||
|
LDAP_URI = app.config['LDAP_URI']
|
||||||
|
LDAP_USERNAME = app.config['LDAP_USERNAME']
|
||||||
|
LDAP_PASSWORD = app.config['LDAP_PASSWORD']
|
||||||
|
LDAP_SEARCH_BASE = app.config['LDAP_SEARCH_BASE']
|
||||||
|
LDAP_TYPE = app.config['LDAP_TYPE']
|
||||||
if 'LDAP_TYPE' in app.config.keys():
|
if 'LDAP_TYPE' in app.config.keys():
|
||||||
LDAP_URI = app.config['LDAP_URI']
|
LDAP_URI = app.config['LDAP_URI']
|
||||||
LDAP_USERNAME = app.config['LDAP_USERNAME']
|
LDAP_USERNAME = app.config['LDAP_USERNAME']
|
||||||
LDAP_PASSWORD = app.config['LDAP_PASSWORD']
|
LDAP_PASSWORD = app.config['LDAP_PASSWORD']
|
||||||
LDAP_SEARCH_BASE = app.config['LDAP_SEARCH_BASE']
|
LDAP_SEARCH_BASE = app.config['LDAP_SEARCH_BASE']
|
||||||
LDAP_TYPE = app.config['LDAP_TYPE']
|
LDAP_TYPE = app.config['LDAP_TYPE']
|
||||||
|
LDAP_GROUP_SECURITY = app.config['LDAP_GROUP_SECURITY']
|
||||||
|
if LDAP_GROUP_SECURITY == True:
|
||||||
|
LDAP_ADMIN_GROUP = app.config['LDAP_ADMIN_GROUP']
|
||||||
|
LDAP_USER_GROUP = app.config['LDAP_USER_GROUP']
|
||||||
LDAP_FILTER = app.config['LDAP_FILTER']
|
LDAP_FILTER = app.config['LDAP_FILTER']
|
||||||
LDAP_USERNAMEFIELD = app.config['LDAP_USERNAMEFIELD']
|
LDAP_USERNAMEFIELD = app.config['LDAP_USERNAMEFIELD']
|
||||||
else:
|
else:
|
||||||
@ -216,27 +225,69 @@ class User(db.Model):
|
|||||||
# create user if not exist in the db
|
# create user if not exist in the db
|
||||||
if not User.query.filter(User.username == self.username).first():
|
if not User.query.filter(User.username == self.username).first():
|
||||||
try:
|
try:
|
||||||
# try to get user's firstname & lastname from LDAP
|
ldap_username = result[0][0][0]
|
||||||
# this might be changed in the future
|
l.simple_bind_s(ldap_username, self.password)
|
||||||
self.firstname = result[0][0][1]['givenName'][0]
|
if LDAP_GROUP_SECURITY:
|
||||||
self.lastname = result[0][0][1]['sn'][0]
|
try:
|
||||||
self.email = result[0][0][1]['mail'][0]
|
if LDAP_TYPE == 'ldap':
|
||||||
except Exception:
|
uid = result[0][0][1]['uid'][0]
|
||||||
self.firstname = self.username
|
groupSearchFilter = "(&(objectClass=posixGroup)(memberUid=%s))" % uid
|
||||||
self.lastname = ''
|
else:
|
||||||
|
groupSearchFilter = "(&(objectcategory=group)(member=%s))" % ldap_username
|
||||||
|
groups = self.ldap_search(groupSearchFilter, LDAP_SEARCH_BASE)
|
||||||
|
allowedlogin = False
|
||||||
|
isadmin = False
|
||||||
|
for group in groups:
|
||||||
|
logging.debug(group)
|
||||||
|
if (group[0][0] == LDAP_ADMIN_GROUP):
|
||||||
|
allowedlogin = True
|
||||||
|
isadmin = True
|
||||||
|
logging.info('User %s is part of the "%s" group that allows admin access to PowerDNS-Admin' % (self.username,LDAP_ADMIN_GROUP))
|
||||||
|
if (group[0][0] == LDAP_USER_GROUP):
|
||||||
|
allowedlogin = True
|
||||||
|
logging.info('User %s is part of the "%s" group that allows user access to PowerDNS-Admin' % (self.username,LDAP_USER_GROUP))
|
||||||
|
if allowedlogin == False:
|
||||||
|
logging.error('User %s is not part of the "%s" or "%s" groups that allow access to PowerDNS-Admin' % (self.username,LDAP_ADMIN_GROUP,LDAP_USER_GROUP))
|
||||||
|
return False
|
||||||
|
except:
|
||||||
|
logging.error('LDAP group lookup for user "%s" has failed' % self.username)
|
||||||
|
logging.info('User "%s" logged in successfully' % self.username)
|
||||||
|
|
||||||
# first register user will be in Administrator role
|
# create user if not exist in the db
|
||||||
self.role_id = Role.query.filter_by(name='User').first().id
|
if User.query.filter(User.username == self.username).first() == None:
|
||||||
if User.query.count() == 0:
|
try:
|
||||||
self.role_id = Role.query.filter_by(name='Administrator').first().id
|
# try to get user's firstname & lastname from LDAP
|
||||||
|
# this might be changed in the future
|
||||||
|
self.firstname = result[0][0][1]['givenName'][0]
|
||||||
|
self.lastname = result[0][0][1]['sn'][0]
|
||||||
|
except:
|
||||||
|
self.firstname = self.username
|
||||||
|
self.lastname = ''
|
||||||
|
|
||||||
self.create_user()
|
# first registered user will be in Administrator role or if part of LDAP Admin group
|
||||||
logging.info('Created user "%s" in the DB' % self.username)
|
if (User.query.count() == 0):
|
||||||
|
self.role_id = Role.query.filter_by(name='Administrator').first().id
|
||||||
|
else:
|
||||||
|
self.role_id = Role.query.filter_by(name='User').first().id
|
||||||
|
|
||||||
return True
|
#
|
||||||
|
if LDAP_GROUP_SECURITY:
|
||||||
|
if isadmin == True:
|
||||||
|
self.role_id = Role.query.filter_by(name='Administrator').first().id
|
||||||
|
|
||||||
logging.error('Unsupported authentication method')
|
self.create_user()
|
||||||
return False
|
logging.info('Created user "%s" in the DB' % self.username)
|
||||||
|
else:
|
||||||
|
# user already exists in database, set their admin status based on group membership (if enabled)
|
||||||
|
if LDAP_GROUP_SECURITY:
|
||||||
|
self.set_admin(isadmin)
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
logging.error('User "%s" input a wrong password' % self.username)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
logging.error('Unsupported authentication method')
|
||||||
|
return False
|
||||||
|
|
||||||
def create_user(self):
|
def create_user(self):
|
||||||
"""
|
"""
|
||||||
|
@ -265,7 +265,37 @@
|
|||||||
$(document.body).on("focus", "#current_edit_record_data", function (e) {
|
$(document.body).on("focus", "#current_edit_record_data", function (e) {
|
||||||
var record_type = $(this).parents("tr").find('#record_type').val();
|
var record_type = $(this).parents("tr").find('#record_type').val();
|
||||||
var record_data = $(this);
|
var record_data = $(this);
|
||||||
if (record_type == "MX") {
|
if (record_type == "CAA") {
|
||||||
|
var modal = $("#modal_custom_record");
|
||||||
|
if (record_data.val() == "") {
|
||||||
|
var form = " <label for=\"caa_flag\">CAA Flag</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_flag\" id=\"caa_flag\" placeholder=\"0\"> \
|
||||||
|
<label for=\"caa_tag\">CAA Tag</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_tag\" id=\"caa_tag\" placeholder=\"issue\"> \
|
||||||
|
<label for=\"caa_value\">CAA Value</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_value\" id=\"caa_value\" placeholder=\"eg. letsencrypt.org\"> \
|
||||||
|
";
|
||||||
|
} else {
|
||||||
|
var parts = record_data.val().split(" ");
|
||||||
|
var form = " <label for=\"caa_flag\">CAA Flag</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_flag\" id=\"caa_flag\" placeholder=\"0\" value=\"" + parts[0] + "\"> \
|
||||||
|
<label for=\"caa_tag\">CAA Tag</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_tag\" id=\"caa_tag\" placeholder=\"issue\" value=\"" + parts[1] + "\"> \
|
||||||
|
<label for=\"caa_value\">CAA Value</label> \
|
||||||
|
<input type=\"text\" class=\"form-control\" name=\"caa_value\" id=\"caa_value\" placeholder=\"eg. letsencrypt.org\" value=\"" + parts[2] + "\"> \
|
||||||
|
";
|
||||||
|
}
|
||||||
|
modal.find('.modal-body p').html(form);
|
||||||
|
modal.find('#button_save').click(function() {
|
||||||
|
caa_flag = modal.find('#caa_flag').val();
|
||||||
|
caa_tag = modal.find('#caa_tag').val();
|
||||||
|
caa_value = modal.find('#caa_value').val();
|
||||||
|
data = caa_flag + " " + caa_tag + " " + '"' + caa_value + '"';
|
||||||
|
record_data.val(data);
|
||||||
|
modal.modal('hide');
|
||||||
|
})
|
||||||
|
modal.modal('show');
|
||||||
|
} else if (record_type == "MX") {
|
||||||
var modal = $("#modal_custom_record");
|
var modal = $("#modal_custom_record");
|
||||||
if (record_data.val() == "") {
|
if (record_data.val() == "") {
|
||||||
var form = " <label for=\"mx_priority\">MX Priority</label> \
|
var form = " <label for=\"mx_priority\">MX Priority</label> \
|
||||||
|
@ -900,12 +900,12 @@ def dyndns_update():
|
|||||||
domain = None
|
domain = None
|
||||||
domain_segments = hostname.split('.')
|
domain_segments = hostname.split('.')
|
||||||
for index in range(len(domain_segments)):
|
for index in range(len(domain_segments)):
|
||||||
domain_segments.pop(0)
|
|
||||||
full_domain = '.'.join(domain_segments)
|
full_domain = '.'.join(domain_segments)
|
||||||
potential_domain = Domain.query.filter(Domain.name == full_domain).first()
|
potential_domain = Domain.query.filter(Domain.name == full_domain).first()
|
||||||
if potential_domain in domains:
|
if potential_domain in domains:
|
||||||
domain = potential_domain
|
domain = potential_domain
|
||||||
break
|
break
|
||||||
|
domain_segments.pop(0)
|
||||||
|
|
||||||
if not domain:
|
if not domain:
|
||||||
history = History(msg="DynDNS update: attempted update of %s but it does not exist for this user" % hostname, created_by=current_user.username)
|
history = History(msg="DynDNS update: attempted update of %s but it does not exist for this user" % hostname, created_by=current_user.username)
|
||||||
|
@ -41,6 +41,9 @@ LDAP_URI = 'ldaps://your-ldap-server:636'
|
|||||||
LDAP_USERNAME = 'cn=dnsuser,ou=users,ou=services,dc=duykhanh,dc=me'
|
LDAP_USERNAME = 'cn=dnsuser,ou=users,ou=services,dc=duykhanh,dc=me'
|
||||||
LDAP_PASSWORD = 'dnsuser'
|
LDAP_PASSWORD = 'dnsuser'
|
||||||
LDAP_SEARCH_BASE = 'ou=System Admins,ou=People,dc=duykhanh,dc=me'
|
LDAP_SEARCH_BASE = 'ou=System Admins,ou=People,dc=duykhanh,dc=me'
|
||||||
|
LDAP_GROUP_SECURITY = False
|
||||||
|
LDAP_ADMIN_GROUP = 'CN=PowerDNS-Admin Admin,OU=Custom,DC=ivan,DC=local'
|
||||||
|
LDAP_USER_GROUP = 'CN=PowerDNS-Admin User,OU=Custom,DC=ivan,DC=local'
|
||||||
# Additional options only if LDAP_TYPE=ldap
|
# Additional options only if LDAP_TYPE=ldap
|
||||||
LDAP_USERNAMEFIELD = 'uid'
|
LDAP_USERNAMEFIELD = 'uid'
|
||||||
LDAP_FILTER = '(objectClass=inetorgperson)'
|
LDAP_FILTER = '(objectClass=inetorgperson)'
|
||||||
@ -100,7 +103,7 @@ PDNS_API_KEY = 'you never know'
|
|||||||
PDNS_VERSION = '3.4.7'
|
PDNS_VERSION = '3.4.7'
|
||||||
|
|
||||||
# RECORDS ALLOWED TO EDIT
|
# RECORDS ALLOWED TO EDIT
|
||||||
RECORDS_ALLOW_EDIT = ['A', 'AAAA', 'CNAME', 'SPF', 'PTR', 'MX', 'TXT']
|
RECORDS_ALLOW_EDIT = ['A', 'AAAA', 'CAA', 'CNAME', 'MX', 'PTR', 'SPF', 'SRV', 'TXT']
|
||||||
|
|
||||||
# EXPERIMENTAL FEATURES
|
# EXPERIMENTAL FEATURES
|
||||||
PRETTY_IPV6_PTR = False
|
PRETTY_IPV6_PTR = False
|
||||||
|
Loading…
Reference in New Issue
Block a user