Read LDAP config from DB instead of file. Adjustment in site titles

This commit is contained in:
Khanh Ngo 2018-08-18 22:42:18 +07:00
parent 4b9349c83e
commit ada6f844ff
No known key found for this signature in database
GPG Key ID: B9AE3BAF6D5A7B22
24 changed files with 123 additions and 175 deletions

View File

@ -23,19 +23,6 @@ from app.lib import utils
logging = logger.getLogger(__name__) logging = logger.getLogger(__name__)
if 'LDAP_TYPE' in app.config.keys():
LDAP_URI = app.config['LDAP_URI']
LDAP_SEARCH_BASE = app.config['LDAP_SEARCH_BASE']
LDAP_TYPE = app.config['LDAP_TYPE']
LDAP_FILTER = app.config['LDAP_FILTER']
LDAP_USERNAMEFIELD = app.config['LDAP_USERNAMEFIELD']
LDAP_GROUP_SECURITY = app.config.get('LDAP_GROUP_SECURITY')
if LDAP_GROUP_SECURITY == True:
LDAP_ADMIN_GROUP = app.config['LDAP_ADMIN_GROUP']
LDAP_USER_GROUP = app.config['LDAP_USER_GROUP']
else:
LDAP_TYPE = False
if 'PRETTY_IPV6_PTR' in app.config.keys(): if 'PRETTY_IPV6_PTR' in app.config.keys():
import dns.inet import dns.inet
@ -147,7 +134,7 @@ class User(db.Model):
def ldap_init_conn(self): def ldap_init_conn(self):
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
conn = ldap.initialize(LDAP_URI) conn = ldap.initialize(Setting().get('ldap_uri'))
conn.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF) conn.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF)
conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3) conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
conn.set_option(ldap.OPT_X_TLS,ldap.OPT_X_TLS_DEMAND) conn.set_option(ldap.OPT_X_TLS,ldap.OPT_X_TLS_DEMAND)
@ -162,7 +149,7 @@ class User(db.Model):
try: try:
conn = self.ldap_init_conn() conn = self.ldap_init_conn()
conn.simple_bind_s(app.config['LDAP_ADMIN_USERNAME'], app.config['LDAP_ADMIN_PASSWORD']) conn.simple_bind_s(Setting().get('ldap_admin_username'), Setting().get('ldap_admin_password'))
ldap_result_id = conn.search(baseDN, searchScope, searchFilter, retrieveAttributes) ldap_result_id = conn.search(baseDN, searchScope, searchFilter, retrieveAttributes)
result_set = [] result_set = []
@ -177,6 +164,8 @@ class User(db.Model):
except ldap.LDAPError as e: except ldap.LDAPError as e:
logging.error(e) logging.error(e)
logging.debug('baseDN: {0}'.format(baseDN))
logging.debug(traceback.format_exc())
raise raise
def ldap_auth(self, ldap_username, password): def ldap_auth(self, ldap_username, password):
@ -207,34 +196,38 @@ class User(db.Model):
if method == 'LDAP': if method == 'LDAP':
isadmin = False isadmin = False
if not LDAP_TYPE: LDAP_TYPE = Setting().get('ldap_type')
logging.error('LDAP authentication is disabled') LDAP_BASE_DN = Setting().get('ldap_base_dn')
return False LDAP_FILTER_BASIC = Setting().get('ldap_filter_basic')
LDAP_FILTER_USERNAME = Setting().get('ldap_filter_username')
LDAP_ADMIN_GROUP = Setting().get('ldap_admin_group')
LDAP_USER_GROUP = Setting().get('ldap_user_group')
LDAP_GROUP_SECURITY_ENABLED = Setting().get('ldap_sg_enabled')
if LDAP_TYPE == 'ldap': if LDAP_TYPE == 'ldap':
searchFilter = "(&({0}={1}){2})".format(LDAP_USERNAMEFIELD, self.username, LDAP_FILTER) searchFilter = "(&({0}={1}){2})".format(LDAP_FILTER_USERNAME, self.username, LDAP_FILTER_BASIC)
logging.debug('Ldap searchFilter "{0}"'.format(searchFilter)) logging.debug('Ldap searchFilter "{0}"'.format(searchFilter))
elif LDAP_TYPE == 'ad': elif LDAP_TYPE == 'ad':
searchFilter = "(&(objectcategory=person)({0}={1}){2})".format(LDAP_USERNAMEFIELD, self.username, LDAP_FILTER) searchFilter = "(&(objectcategory=person)({0}={1}){2})".format(LDAP_FILTER_USERNAME, self.username, LDAP_FILTER_BASIC)
ldap_result = self.ldap_search(searchFilter, LDAP_SEARCH_BASE) ldap_result = self.ldap_search(searchFilter, LDAP_BASE_DN)
if not ldap_result: if not ldap_result:
logging.warning('LDAP User "{0}" does not exist. Authentication request from {1}'.format(self.username, src_ip)) logging.warning('LDAP User "{0}" does not exist. Authentication request from {1}'.format(self.username, src_ip))
return False return False
else: else:
try: try:
ldap_username = ldap.filter.escape_filter_chars(ldap_result[0][0][0]) ldap_username = ldap.filter.escape_filter_chars(ldap_result[0][0][0])
# check if LDAP_SECURITY_GROUP is enabled # check if LDAP_GROUP_SECURITY_ENABLED is True
# user can be assigned to ADMIN or USER role. # user can be assigned to ADMIN or USER role.
if LDAP_GROUP_SECURITY: if LDAP_GROUP_SECURITY_ENABLED:
try: try:
if (self.ldap_search(searchFilter, LDAP_ADMIN_GROUP)): if (self.ldap_search(searchFilter, LDAP_ADMIN_GROUP)):
isadmin = True isadmin = True
logging.info('User {0} is part of the "{1}" group that allows admin access to PowerDNS-Admin'.format(self.username,LDAP_ADMIN_GROUP)) logging.info('User {0} is part of the "{1}" group that allows admin access to PowerDNS-Admin'.format(self.username, LDAP_ADMIN_GROUP))
elif (self.ldap_search(searchFilter, LDAP_USER_GROUP)): elif (self.ldap_search(searchFilter, LDAP_USER_GROUP)):
logging.info('User {0} is part of the "{1}" group that allows user access to PowerDNS-Admin'.format(self.username,LDAP_USER_GROUP)) logging.info('User {0} is part of the "{1}" group that allows user access to PowerDNS-Admin'.format(self.username, LDAP_USER_GROUP))
else: else:
logging.error('User {0} is not part of the "{1}" or "{2}" groups that allow access to PowerDNS-Admin'.format(self.username,LDAP_ADMIN_GROUP,LDAP_USER_GROUP)) logging.error('User {0} is not part of the "{1}" or "{2}" groups that allow access to PowerDNS-Admin'.format(self.username, LDAP_ADMIN_GROUP, LDAP_USER_GROUP))
return False return False
except Exception as e: except Exception as e:
logging.error('LDAP group lookup for user "{0}" has failed. Authentication request from {1}'.format(self.username, src_ip)) logging.error('LDAP group lookup for user "{0}" has failed. Authentication request from {1}'.format(self.username, src_ip))
@ -256,13 +249,12 @@ class User(db.Model):
self.firstname = self.username self.firstname = self.username
self.lastname = '' self.lastname = ''
try: try:
# try to get user's firstname & lastname from LDAP # try to get user's firstname, lastname and email address from LDAP attributes
# this might be changed in the future
self.firstname = ldap_result[0][0][1]['givenName'][0].decode("utf-8") self.firstname = ldap_result[0][0][1]['givenName'][0].decode("utf-8")
self.lastname = ldap_result[0][0][1]['sn'][0].decode("utf-8") self.lastname = ldap_result[0][0][1]['sn'][0].decode("utf-8")
self.email = ldap_result[0][0][1]['mail'][0].decode("utf-8") self.email = ldap_result[0][0][1]['mail'][0].decode("utf-8")
except Exception as e: except Exception as e:
logging.info("Reading ldap data threw an exception {0}".format(e)) logging.warning("Reading ldap data threw an exception {0}".format(e))
logging.debug(traceback.format_exc()) logging.debug(traceback.format_exc())
# first register user will be in Administrator role # first register user will be in Administrator role
@ -271,7 +263,7 @@ class User(db.Model):
self.role_id = Role.query.filter_by(name='Administrator').first().id self.role_id = Role.query.filter_by(name='Administrator').first().id
# user will be in Administrator role if part of LDAP Admin group # user will be in Administrator role if part of LDAP Admin group
if LDAP_GROUP_SECURITY: if LDAP_GROUP_SECURITY_ENABLED:
if isadmin == True: if isadmin == True:
self.role_id = Role.query.filter_by(name='Administrator').first().id self.role_id = Role.query.filter_by(name='Administrator').first().id
@ -279,7 +271,7 @@ class User(db.Model):
logging.info('Created user "{0}" in the DB'.format(self.username)) logging.info('Created user "{0}" in the DB'.format(self.username))
# user already exists in database, set their admin status based on group membership (if enabled) # user already exists in database, set their admin status based on group membership (if enabled)
if LDAP_GROUP_SECURITY: if LDAP_GROUP_SECURITY_ENABLED:
self.set_admin(isadmin) self.set_admin(isadmin)
self.update_profile() self.update_profile()
return True return True
@ -951,7 +943,7 @@ class Domain(db.Model):
domain_obj = Domain.query.filter(Domain.name == domain_name).first() domain_obj = Domain.query.filter(Domain.name == domain_name).first()
domain_auto_ptr = DomainSetting.query.filter(DomainSetting.domain == domain_obj).filter(DomainSetting.setting == 'auto_ptr').first() domain_auto_ptr = DomainSetting.query.filter(DomainSetting.domain == domain_obj).filter(DomainSetting.setting == 'auto_ptr').first()
domain_auto_ptr = strtobool(domain_auto_ptr.value) if domain_auto_ptr else False domain_auto_ptr = strtobool(domain_auto_ptr.value) if domain_auto_ptr else False
system_auto_ptr = strtobool(Setting().get('auto_ptr')) system_auto_ptr = Setting().get('auto_ptr')
self.name = domain_name self.name = domain_name
domain_id = self.get_id_by_name(domain_reverse_name) domain_id = self.get_id_by_name(domain_reverse_name)
if None == domain_id and \ if None == domain_id and \
@ -1504,8 +1496,8 @@ class Record(object):
}) })
postdata_for_new = {"rrsets": final_records} postdata_for_new = {"rrsets": final_records}
logging.info(postdata_for_new) logging.debug(postdata_for_new)
logging.info(postdata_for_delete) logging.debug(postdata_for_delete)
logging.info(urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain))) logging.info(urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)))
try: try:
headers = {} headers = {}
@ -1523,7 +1515,8 @@ class Record(object):
logging.info('Record was applied successfully.') logging.info('Record was applied successfully.')
return {'status': 'ok', 'msg': 'Record was applied successfully'} return {'status': 'ok', 'msg': 'Record was applied successfully'}
except Exception as e: except Exception as e:
logging.error("Cannot apply record changes to domain {0}. DETAIL: {1}".format(e, domain)) logging.error("Cannot apply record changes to domain {0}. Error: {1}".format(domain, e))
logging.debug(traceback.format_exc())
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'} return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
def auto_ptr(self, domain, new_records, deleted_records): def auto_ptr(self, domain, new_records, deleted_records):
@ -1534,7 +1527,7 @@ class Record(object):
domain_auto_ptr = DomainSetting.query.filter(DomainSetting.domain == domain_obj).filter(DomainSetting.setting == 'auto_ptr').first() domain_auto_ptr = DomainSetting.query.filter(DomainSetting.domain == domain_obj).filter(DomainSetting.setting == 'auto_ptr').first()
domain_auto_ptr = strtobool(domain_auto_ptr.value) if domain_auto_ptr else False domain_auto_ptr = strtobool(domain_auto_ptr.value) if domain_auto_ptr else False
system_auto_ptr = strtobool(Setting().get('auto_ptr')) system_auto_ptr = Setting().get('auto_ptr')
if system_auto_ptr or domain_auto_ptr: if system_auto_ptr or domain_auto_ptr:
try: try:
@ -1785,6 +1778,7 @@ class Setting(db.Model):
'default_domain_table_size': 10, 'default_domain_table_size': 10,
'auto_ptr': False, 'auto_ptr': False,
'allow_quick_edit': True, 'allow_quick_edit': True,
'site_name': 'PowerDNS-Admin',
'pdns_api_url': '', 'pdns_api_url': '',
'pdns_api_key': '', 'pdns_api_key': '',
'pdns_version': '4.1.1', 'pdns_version': '4.1.1',
@ -1793,6 +1787,7 @@ class Setting(db.Model):
'ldap_enabled': False, 'ldap_enabled': False,
'ldap_type': 'ldap', 'ldap_type': 'ldap',
'ldap_uri': '', 'ldap_uri': '',
'ldap_base_dn': '',
'ldap_admin_username': '', 'ldap_admin_username': '',
'ldap_admin_password': '', 'ldap_admin_password': '',
'ldap_filter_basic': '', 'ldap_filter_basic': '',

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_console" %} {% set active_page = "admin_console" %}
{% block title %}<title>DNS Control Panel - Admin Console</title>{% endblock %} {% block title %}<title>Admin Console - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_accounts" %} {% set active_page = "admin_accounts" %}
{% block title %}<title>DNS Control Panel - Edit Account</title>{% endblock %} {% block title %}<title>Edit Account - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_users" %} {% set active_page = "admin_users" %}
{% block title %}<title>DNS Control Panel - Edit User</title>{% endblock %} {% block title %}<title>Edit Use - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_history" %} {% set active_page = "admin_history" %}
{% block title %} {% block title %}
<title>DNS Control Panel - History</title> <title>History - {{ SITE_NAME }}</title>
{% endblock %} {% block dashboard_stat %} {% endblock %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->
<section class="content-header"> <section class="content-header">

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_accounts" %} {% set active_page = "admin_accounts" %}
{% block title %} {% block title %}
<title>DNS Control Panel - Account Management</title> <title>Account Management - {{ SITE_NAME }}</title>
{% endblock %} {% block dashboard_stat %} {% endblock %} {% block dashboard_stat %}
<section class="content-header"> <section class="content-header">
<h1> <h1>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_users" %} {% set active_page = "admin_users" %}
{% block title %} {% block title %}
<title>DNS Control Panel - User Management</title> <title>User Management - {{ SITE_NAME }}</title>
{% endblock %} {% block dashboard_stat %} {% endblock %} {% block dashboard_stat %}
<section class="content-header"> <section class="content-header">
<h1> <h1>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_settings" %} {% set active_page = "admin_settings" %}
{% block title %} {% block title %}
<title>DNS Control Panel - Authentication Settings</title> <title>Authentication Settings - {{ SITE_NAME }}</title>
{% endblock %} {% block dashboard_stat %} {% endblock %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->
<section class="content-header"> <section class="content-header">
@ -79,13 +79,17 @@
<label for="ldap_uri">LDAP URI</label> <label for="ldap_uri">LDAP URI</label>
<input type="text" class="form-control" name="ldap_uri" id="ldap_uri" placeholder="e.g. ldaps://your-ldap-server:636" value="{{ SETTING.get('ldap_uri') }}"> <input type="text" class="form-control" name="ldap_uri" id="ldap_uri" placeholder="e.g. ldaps://your-ldap-server:636" value="{{ SETTING.get('ldap_uri') }}">
</div> </div>
<div class="form-group">
<label for="ldap_base_dn">LDAP Base DN</label>
<input type="text" class="form-control" name="ldap_base_dn" id="ldap_base_dn" placeholder="e.g. dc=mydomain,dc=com" value="{{ SETTING.get('ldap_base_dn') }}">
</div>
<div class="form-group"> <div class="form-group">
<label for="ldap_admin_username">LDAP admin username</label> <label for="ldap_admin_username">LDAP admin username</label>
<input type="text" class="form-control" name="ldap_admin_username" id="ldap_admin_username" placeholder="e.g. cn=admin,dc=mydomain,dc=com" value="{{ SETTING.get('ldap_admin_username') }}"> <input type="text" class="form-control" name="ldap_admin_username" id="ldap_admin_username" placeholder="e.g. cn=admin,dc=mydomain,dc=com" value="{{ SETTING.get('ldap_admin_username') }}">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="ldap_admin_password">LDAP admin password</label> <label for="ldap_admin_password">LDAP admin password</label>
<input type="passowrd" class="form-control" name="ldap_admin_password" id="ldap_admin_password" placeholder="LDAP Admin password" value="{{ SETTING.get('ldap_admin_password') }}"> <input type="password" class="form-control" name="ldap_admin_password" id="ldap_admin_password" placeholder="LDAP Admin password" value="{{ SETTING.get('ldap_admin_password') }}">
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_settings" %} {% set active_page = "admin_settings" %}
{% block title %} {% block title %}
<title>DNS Control Panel - Basic Settings</title> <title>Basic Settings - {{ SITE_NAME }}</title>
{% endblock %} {% block dashboard_stat %} {% endblock %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->
<section class="content-header"> <section class="content-header">

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_settings" %} {% set active_page = "admin_settings" %}
{% block title %} {% block title %}
<title>DNS Control Panel - PDNS Settings</title> <title>PDNS Settings - {{ SITE_NAME }}</title>
{% endblock %} {% block dashboard_stat %} {% endblock %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->
<section class="content-header"> <section class="content-header">

View File

@ -4,7 +4,7 @@
{% block head %} {% block head %}
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
{% block title %}<title>DNS Control Panel</title>{% endblock %} {% block title %}<title>{{ SITE_NAME }}</title>{% endblock %}
<!-- Get Google Fonts we like --> <!-- Get Google Fonts we like -->
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic"> <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto+Mono:400,300,700"> <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto+Mono:400,300,700">

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "dashboard" %} {% set active_page = "dashboard" %}
{% block title %}<title>DNS Control Panel - HOME</title>{% endblock %} {% block title %}<title>Dashboard - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->

View File

@ -1,5 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}<title>{{ domain.name }} - DNS Control Panel</title>{% endblock %} {% block title %}<title>{{ domain.name }} - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<section class="content-header"> <section class="content-header">

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "new_domain" %} {% set active_page = "new_domain" %}
{% block title %}<title>DNS Control Panel - Add Domain</title>{% endblock %} {% block title %}<title>Add Domain - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->

View File

@ -1,5 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}<title>DNS Control Panel - Domain Management</title>{% endblock %} {% block title %}<title>Domain Management - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
{% if status %} {% if status %}

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>DNS Control Panel - Log In</title> <title>Log In - {{ SITE_NAME }}</title>
<!-- Tell the browser to be responsive to screen width --> <!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
{% assets "css_login" -%} {% assets "css_login" -%}
@ -20,7 +20,7 @@
<body class="hold-transition login-page"> <body class="hold-transition login-page">
<div class="login-box"> <div class="login-box">
<div class="login-logo"> <div class="login-logo">
<a href="{{ url_for('index') }}">Sign In {{ login_title }}</a> <a href="{{ url_for('index') }}"><b>PowerDNS</b>-Admin</a>
</div> </div>
<!-- /.login-logo --> <!-- /.login-logo -->
<div class="login-box-body"> <div class="login-box-body">
@ -51,7 +51,7 @@
<div class="form-group"> <div class="form-group">
<input type="otptoken" class="form-control" placeholder="OTP Token" name="otptoken"> <input type="otptoken" class="form-control" placeholder="OTP Token" name="otptoken">
</div> </div>
{% if ldap_enabled and basic_enabled %} {% if SETTING.get('ldap_enabled') and SETTING.get('local_db_enabled') %}
<div class="form-group"> <div class="form-group">
<select class="form-control" name="auth_method"> <select class="form-control" name="auth_method">
<option value="LOCAL">LOCAL Authentication</option> <option value="LOCAL">LOCAL Authentication</option>
@ -62,11 +62,11 @@
{% endif %} {% endif %}
</select> </select>
</div> </div>
{% elif ldap_enabled and not basic_enabled %} {% elif SETTING.get('ldap_enabled') and not SETTING.get('local_db_enabled') %}
<div class="form-group"> <div class="form-group">
<input type="hidden" name="auth_method" value="LDAP"> <input type="hidden" name="auth_method" value="LDAP">
</div> </div>
{% elif basic_enabled and not ldap_enabled %} {% elif SETTING.get('local_db_enabled') and not SETTING.get('ldap_enabled') %}
<div class="form-group"> <div class="form-group">
<input type="hidden" name="auth_method" value="LOCAL"> <input type="hidden" name="auth_method" value="LOCAL">
</div> </div>
@ -91,25 +91,33 @@
<!-- /.col --> <!-- /.col -->
</div> </div>
</form> </form>
{% if google_enabled %} {% if SETTING.get('google_oauth_enabled') or SETTING.get('github_oauth_enabled') %}
<a href="{{ url_for('google_login') }}">Google oauth login</a> <div class="social-auth-links text-center">
<p>- OR -</p>
{% if SETTING.get('github_oauth_enabled') %}
<a href="{{ url_for('github_login') }}" class="btn btn-block btn-social btn-github btn-flat"><i class="fa fa-github"></i> Sign in using
Github</a>
{% endif %}
{% if SETTING.get('google_oauth_enabled') %}
<a href="{{ url_for('google_login') }}" class="btn btn-block btn-social btn-google btn-flat"><i class="fa fa-google-plus"></i> Sign in using
Google</a>
{% endif %}
</div>
{% endif %} {% endif %}
{% if saml_enabled %} {% if saml_enabled %}
<br>
<a href="{{ url_for('saml_login') }}">SAML login</a> <a href="{{ url_for('saml_login') }}">SAML login</a>
{% endif %} {% endif %}
{% if github_enabled %}
<br> {% if SETTING.get('signup_enabled') %}
<a href="{{ url_for('github_login') }}">Github oauth login</a>
{% endif %}
{% if signup_enabled %}
<br> <br>
<a href="{{ url_for('register') }}" class="text-center">Create an account </a> <a href="{{ url_for('register') }}" class="text-center">Create an account </a>
{% endif %} {% endif %}
</div> </div>
<!-- /.login-box-body --> <!-- /.login-box-body -->
<div class="login-box-footer"> <div class="login-box-footer">
<center><p>2018 &copy; Khanh Ngo</p></center> <center><p>Powered by <a href="https://github.com/ngoduykhanh/PowerDNS-Admin">PowerDNS-Admin</a></p></center>
</div> </div>
</div> </div>
<!-- /.login-box --> <!-- /.login-box -->

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>DNS Control Panel - Register</title> <title>Register - {{ SITE_NAME }}</title>
<!-- Tell the browser to be responsive to screen width --> <!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
{% assets "css_login" -%} {% assets "css_login" -%}
@ -77,7 +77,7 @@
</div> </div>
<!-- /.form-box --> <!-- /.form-box -->
<div class="login-box-footer"> <div class="login-box-footer">
<center><p>2018 &copy; Khanh Ngo</p></center> <center><p>Powered by <a href="https://github.com/ngoduykhanh/PowerDNS-Admin">PowerDNS-Admin</a></p></center>
</div> </div>
</div> </div>
<!-- /.login-box --> <!-- /.login-box -->

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_domain_template" %} {% set active_page = "admin_domain_template" %}
{% block title %}<title>DNS Control Panel - Templates</title>{% endblock %} {% block title %}<title>Templates - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_domain_template" %} {% set active_page = "admin_domain_template" %}
{% block title %}<title>DNS Control Panel - Create Template</title>{% endblock %} {% block title %}<title>Create Template - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->

View File

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% set active_page = "admin_domain_template" %} {% set active_page = "admin_domain_template" %}
{% block title %}<title>DNS Control Panel - Edit Template</title>{% endblock %} {% block title %}<title>Edit Template - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<section class="content-header"> <section class="content-header">

View File

@ -1,5 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}<title>DNS Control Panel - My Profile</title>{% endblock %} {% block title %}<title>My Profile - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->
<section class="content-header"> <section class="content-header">

View File

@ -43,6 +43,11 @@ else:
NEW_SCHEMA = False NEW_SCHEMA = False
@app.context_processor
def inject_sitename():
setting = Setting().get('site_name')
return dict(SITE_NAME=setting)
@app.context_processor @app.context_processor
def inject_setting(): def inject_setting():
setting = Setting() setting = Setting()
@ -134,8 +139,7 @@ def error(code, msg=None):
@app.route('/register', methods=['GET']) @app.route('/register', methods=['GET'])
def register(): def register():
SIGNUP_ENABLED = app.config['SIGNUP_ENABLED'] if Setting().get('signup_enabled'):
if SIGNUP_ENABLED:
return render_template('register.html') return render_template('register.html')
else: else:
return render_template('errors/404.html'), 404 return render_template('errors/404.html'), 404
@ -268,11 +272,6 @@ def saml_authorized():
@login_manager.unauthorized_handler @login_manager.unauthorized_handler
def login(): def login():
LOGIN_TITLE = app.config['LOGIN_TITLE'] if 'LOGIN_TITLE' in app.config.keys() else '' LOGIN_TITLE = app.config['LOGIN_TITLE'] if 'LOGIN_TITLE' in app.config.keys() else ''
BASIC_ENABLED = app.config['BASIC_ENABLED']
SIGNUP_ENABLED = app.config['SIGNUP_ENABLED']
LDAP_ENABLED = app.config.get('LDAP_ENABLED')
GITHUB_ENABLE = app.config.get('GITHUB_OAUTH_ENABLE')
GOOGLE_ENABLE = app.config.get('GOOGLE_OAUTH_ENABLE')
SAML_ENABLED = app.config.get('SAML_ENABLED') SAML_ENABLED = app.config.get('SAML_ENABLED')
if g.user is not None and current_user.is_authenticated: if g.user is not None and current_user.is_authenticated:
@ -323,13 +322,7 @@ def login():
return redirect(url_for('index')) return redirect(url_for('index'))
if request.method == 'GET': if request.method == 'GET':
return render_template('login.html', github_enabled=GITHUB_ENABLE, return render_template('login.html', saml_enabled=SAML_ENABLED)
google_enabled=GOOGLE_ENABLE,
saml_enabled=SAML_ENABLED,
ldap_enabled=LDAP_ENABLED,
login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
# process login # process login
username = request.form['username'] username = request.form['username']
@ -357,46 +350,18 @@ def login():
try: try:
auth = user.is_validate(method=auth_method, src_ip=request.remote_addr) auth = user.is_validate(method=auth_method, src_ip=request.remote_addr)
if auth == False: if auth == False:
return render_template('login.html', error='Invalid credentials', return render_template('login.html', saml_enabled=SAML_ENABLED, error='Invalid credentials')
github_enabled=GITHUB_ENABLE,
google_enabled=GOOGLE_ENABLE,
saml_enabled=SAML_ENABLED,
ldap_enabled=LDAP_ENABLED,
login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
except Exception as e: except Exception as e:
return render_template('login.html', error=e, return render_template('login.html', saml_enabled=SAML_ENABLED, error=e)
github_enabled=GITHUB_ENABLE,
google_enabled=GOOGLE_ENABLE,
saml_enabled=SAML_ENABLED,
ldap_enabled=LDAP_ENABLED,
login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
# check if user enabled OPT authentication # check if user enabled OPT authentication
if user.otp_secret: if user.otp_secret:
if otp_token and otp_token.isdigit(): if otp_token and otp_token.isdigit():
good_token = user.verify_totp(otp_token) good_token = user.verify_totp(otp_token)
if not good_token: if not good_token:
return render_template('login.html', error='Invalid credentials', return render_template('login.html', saml_enabled=SAML_ENABLED, error='Invalid credentials')
github_enabled=GITHUB_ENABLE,
google_enabled=GOOGLE_ENABLE,
saml_enabled=SAML_ENABLED,
ldap_enabled=LDAP_ENABLED,
login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
else: else:
return render_template('login.html', error='Token required', return render_template('login.html', saml_enabled=SAML_ENABLED, error='Token required')
github_enabled=GITHUB_ENABLE,
google_enabled=GOOGLE_ENABLE,
saml_enabled=SAML_ENABLED,
ldap_enabled=LDAP_ENABLED,
login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
login_user(user, remember = remember_me) login_user(user, remember = remember_me)
return redirect(request.args.get('next') or url_for('index')) return redirect(request.args.get('next') or url_for('index'))
@ -416,14 +381,7 @@ def login():
try: try:
result = user.create_local_user() result = user.create_local_user()
if result == True: if result == True:
return render_template('login.html', username=username, password=password, return render_template('login.html', saml_enabled=SAML_ENABLED, username=username, password=password)
github_enabled=GITHUB_ENABLE,
google_enabled=GOOGLE_ENABLE,
saml_enabled=SAML_ENABLED,
ldap_enabled=LDAP_ENABLED,
login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
else: else:
return render_template('register.html', error=result['msg']) return render_template('register.html', error=result['msg'])
except Exception as e: except Exception as e:
@ -1416,6 +1374,7 @@ def admin_setting_authentication():
Setting().set('ldap_enabled', True if request.form.get('ldap_enabled') else False) Setting().set('ldap_enabled', True if request.form.get('ldap_enabled') else False)
Setting().set('ldap_type', request.form.get('ldap_type')) Setting().set('ldap_type', request.form.get('ldap_type'))
Setting().set('ldap_uri', request.form.get('ldap_uri')) Setting().set('ldap_uri', request.form.get('ldap_uri'))
Setting().set('ldap_base_dn', request.form.get('ldap_base_dn'))
Setting().set('ldap_admin_username', request.form.get('ldap_admin_username')) Setting().set('ldap_admin_username', request.form.get('ldap_admin_username'))
Setting().set('ldap_admin_password', request.form.get('ldap_admin_password')) Setting().set('ldap_admin_password', request.form.get('ldap_admin_password'))
Setting().set('ldap_filter_basic', request.form.get('ldap_filter_basic')) Setting().set('ldap_filter_basic', request.form.get('ldap_filter_basic'))

View File

@ -6,7 +6,6 @@ WTF_CSRF_ENABLED = True
SECRET_KEY = 'We are the world' SECRET_KEY = 'We are the world'
BIND_ADDRESS = '127.0.0.1' BIND_ADDRESS = '127.0.0.1'
PORT = 9191 PORT = 9191
LOGIN_TITLE = "PDNS"
# TIMEOUT - for large zones # TIMEOUT - for large zones
TIMEOUT = 10 TIMEOUT = 10
@ -35,22 +34,6 @@ SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'pdns.db')
SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository') SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository')
SQLALCHEMY_TRACK_MODIFICATIONS = True SQLALCHEMY_TRACK_MODIFICATIONS = True
# LDAP CONFIG
LDAP_ENABLED = False
LDAP_TYPE = 'ldap'
LDAP_URI = 'ldaps://your-ldap-server:636'
LDAP_ADMIN_USERNAME = 'cn=admin,dc=mydomain,dc=com'
LDAP_ADMIN_PASSWORD = 'password'
LDAP_SEARCH_BASE = 'dc=mydomain,dc=com'
# Additional options only if LDAP_TYPE=ldap
LDAP_USERNAMEFIELD = 'uid'
LDAP_FILTER = '(objectClass=inetorgperson)'
# enable LDAP_GROUP_SECURITY to allow Admin and User roles based on LDAP groups
LDAP_GROUP_SECURITY = False # True or False
LDAP_ADMIN_GROUP = 'cn=sysops,dc=mydomain,dc=com'
LDAP_USER_GROUP = 'cn=user,dc=mydomain,dc=com'
## AD CONFIG ## AD CONFIG
#LDAP_TYPE = 'ad' #LDAP_TYPE = 'ad'
@ -158,9 +141,6 @@ SAML_LOGOUT = False
#for example redirect to google.com after successful saml logout #for example redirect to google.com after successful saml logout
#SAML_LOGOUT_URL = 'https://google.com' #SAML_LOGOUT_URL = 'https://google.com'
#Default Auth
BASIC_ENABLED = True
SIGNUP_ENABLED = True
# POWERDNS CONFIG # POWERDNS CONFIG
PDNS_STATS_URL = 'http://172.16.214.131:8081/' PDNS_STATS_URL = 'http://172.16.214.131:8081/'

View File

@ -32,36 +32,38 @@ def update_data():
# add more new settings # add more new settings
op.bulk_insert(setting_table, op.bulk_insert(setting_table,
[ [
{'id': 8, 'name': 'pdns_api_url', 'value': '', 'view': 'pdns'}, {'id': 8, 'name': 'site_name', 'value': 'PowerDNS-Admin', 'view': 'basic'},
{'id': 9, 'name': 'pdns_api_key', 'value': '', 'view': 'pdns'}, {'id': 9, 'name': 'pdns_api_url', 'value': '', 'view': 'pdns'},
{'id': 10, 'name': 'pdns_version', 'value': '4.1.1', 'view': 'pdns'}, {'id': 10, 'name': 'pdns_api_key', 'value': '', 'view': 'pdns'},
{'id': 11, 'name': 'local_db_enabled', 'value': 'True', 'view': 'authentication'}, {'id': 11, 'name': 'pdns_version', 'value': '4.1.1', 'view': 'pdns'},
{'id': 12, 'name': 'signup_enabled', 'value': 'True', 'view': 'authentication'}, {'id': 12, 'name': 'local_db_enabled', 'value': 'True', 'view': 'authentication'},
{'id': 13, 'name': 'ldap_enabled', 'value': 'False', 'view': 'authentication'}, {'id': 13, 'name': 'signup_enabled', 'value': 'True', 'view': 'authentication'},
{'id': 14, 'name': 'ldap_type', 'value': 'ldap', 'view': 'authentication'}, {'id': 14, 'name': 'ldap_enabled', 'value': 'False', 'view': 'authentication'},
{'id': 15, 'name': 'ldap_uri', 'value': '', 'view': 'authentication'}, {'id': 15, 'name': 'ldap_type', 'value': 'ldap', 'view': 'authentication'},
{'id': 16, 'name': 'ldap_admin_username', 'value': '', 'view': 'authentication'}, {'id': 16, 'name': 'ldap_uri', 'value': '', 'view': 'authentication'},
{'id': 17, 'name': 'ldap_admin_password', 'value': '', 'view': 'authentication'}, {'id': 17, 'name': 'ldap_base_dn', 'value': '', 'view': 'authentication'},
{'id': 18, 'name': 'ldap_filter_basic', 'value': '', 'view': 'authentication'}, {'id': 18, 'name': 'ldap_admin_username', 'value': '', 'view': 'authentication'},
{'id': 19, 'name': 'ldap_filter_username', 'value': '', 'view': 'authentication'}, {'id': 19, 'name': 'ldap_admin_password', 'value': '', 'view': 'authentication'},
{'id': 20, 'name': 'ldap_sg_enabled', 'value': 'False', 'view': 'authentication'}, {'id': 20, 'name': 'ldap_filter_basic', 'value': '', 'view': 'authentication'},
{'id': 21, 'name': 'ldap_admin_group', 'value': '', 'view': 'authentication'}, {'id': 21, 'name': 'ldap_filter_username', 'value': '', 'view': 'authentication'},
{'id': 22, 'name': 'ldap_user_group', 'value': '', 'view': 'authentication'}, {'id': 22, 'name': 'ldap_sg_enabled', 'value': 'False', 'view': 'authentication'},
{'id': 23, 'name': 'github_oauth_enabled', 'value': 'False', 'view': 'authentication'}, {'id': 23, 'name': 'ldap_admin_group', 'value': '', 'view': 'authentication'},
{'id': 24, 'name': 'github_oauth_key', 'value': '', 'view': 'authentication'}, {'id': 24, 'name': 'ldap_user_group', 'value': '', 'view': 'authentication'},
{'id': 25, 'name': 'github_oauth_secret', 'value': '', 'view': 'authentication'}, {'id': 25, 'name': 'github_oauth_enabled', 'value': 'False', 'view': 'authentication'},
{'id': 26, 'name': 'github_oauth_scope', 'value': 'email', 'view': 'authentication'}, {'id': 26, 'name': 'github_oauth_key', 'value': '', 'view': 'authentication'},
{'id': 27, 'name': 'github_oauth_api_url', 'value': 'https://api.github.com/user', 'view': 'authentication'}, {'id': 27, 'name': 'github_oauth_secret', 'value': '', 'view': 'authentication'},
{'id': 28, 'name': 'github_oauth_token_url', 'value': 'https://github.com/login/oauth/access_token', 'view': 'authentication'}, {'id': 28, 'name': 'github_oauth_scope', 'value': 'email', 'view': 'authentication'},
{'id': 29, 'name': 'github_oauth_authorize_url', 'value': 'https://github.com/login/oauth/authorize', 'view': 'authentication'}, {'id': 29, 'name': 'github_oauth_api_url', 'value': 'https://api.github.com/user', 'view': 'authentication'},
{'id': 30, 'name': 'google_oauth_enabled', 'value': 'False', 'view': 'authentication'}, {'id': 30, 'name': 'github_oauth_token_url', 'value': 'https://github.com/login/oauth/access_token', 'view': 'authentication'},
{'id': 31, 'name': 'google_oauth_client_id', 'value': '', 'view': 'authentication'}, {'id': 31, 'name': 'github_oauth_authorize_url', 'value': 'https://github.com/login/oauth/authorize', 'view': 'authentication'},
{'id': 32, 'name': 'google_oauth_client_secret', 'value': '', 'view': 'authentication'}, {'id': 32, 'name': 'google_oauth_enabled', 'value': 'False', 'view': 'authentication'},
{'id': 33, 'name': 'google_redirect_uri', 'value': '/user/authorized', 'view': 'authentication'}, {'id': 33, 'name': 'google_oauth_client_id', 'value': '', 'view': 'authentication'},
{'id': 34, 'name': 'google_token_url', 'value': 'https://accounts.google.com/o/oauth2/token', 'view': 'authentication'}, {'id': 34, 'name': 'google_oauth_client_secret', 'value': '', 'view': 'authentication'},
{'id': 35, 'name': 'google_token_params', 'value': "{'scope': 'email profile'}", 'view': 'authentication'}, {'id': 35, 'name': 'google_redirect_uri', 'value': '/user/authorized', 'view': 'authentication'},
{'id': 36, 'name': 'google_authorize_url', 'value': 'https://accounts.google.com/o/oauth2/auth', 'view': 'authentication'}, {'id': 36, 'name': 'google_token_url', 'value': 'https://accounts.google.com/o/oauth2/token', 'view': 'authentication'},
{'id': 37, 'name': 'google_base_url', 'value': 'https://www.googleapis.com/oauth2/v1/', 'view': 'authentication'}, {'id': 37, 'name': 'google_token_params', 'value': "{'scope': 'email profile'}", 'view': 'authentication'},
{'id': 38, 'name': 'google_authorize_url', 'value': 'https://accounts.google.com/o/oauth2/auth', 'view': 'authentication'},
{'id': 39, 'name': 'google_base_url', 'value': 'https://www.googleapis.com/oauth2/v1/', 'view': 'authentication'},
] ]
) )