PowerDNS-Admin

PowerDNS-Admin is a web-based administration interface for PowerDNS.

Unlike other older front-end applications for PowerDNS, who often write directly to the PowerDNS database, it uses the PowerDNS application programming interface introduced in PowerDNS 3.x and 4.x.

Prerequisites

  • A working PowerDNS installation;
  • MariaDB database server for storage of zone meta-data, users and their roles;
  • Git to get the source code;
  • Python language development environment;
  • Development libraries for MariaDB, SASL, LDAP and SSL
  • uWSGI Python application web-server;
  • Nginx web-server as a reverse proxy to the web application;

A random password for the database user (16 characters recommended):

$ pwgen -cns 16 1

A random Flask secret app key (24 characters recommended):

$ pwgen -cns 24 1

Database

Independently of PowerDNS storing its data in a MariaDB database, PowerDNS- Admin uses its own database to store users, access rights and various other information about the managed domains (zones).

To create the database used by the PowerDNS-Admin application start an interactive session with root privileges on your database server:

$ mysql -u root -p
Enter password: ********

While using your MariaDB root password to login.

mysql> CREATE DATABASE powerdnsadmin;
mysql> GRANT ALL PRIVILEGES ON powerdnsadmin.* TO 'powerdnsadmin'@'localhost'
                IDENTIFIED BY '********';
mysql> FLUSH PRIVILEGES;
mysql> quit

While using the random database user password created earlier.

Installation

Software Libraries

Install required software packages:

$ sudo apt-get install libsasl2-dev libldap2-dev libmariadbclient-dev

Source Code

Note

As of now (October 2016) PowerDNS-Admin does only run with Python 2.x, although support for Python 3 is planned.

Download the source code of the project from GitHub and set the web-server user as its owner:

$ cd /usr/local/lib
$ sudo git clone https://github.com/ngoduykhanh/PowerDNS-Admin.git
$ sudo chown -R www-data:www-data PowerDNS-Admin

We work as the web-server user from here on:

$ sudo -u www-data -Hs

Create a new virtual Python environment called flask and activate it:

$ cd /usr/local/lib/PowerDNS-Admin
$ virtualenv --python=python2.7 flask
$ source ./flask/bin/activate

You should now see that your are working in a virtual environment by looking at your system command prompt:

(flask) $

Install required Python packages:

(flask) $ pip install -r requirements.txt
(flask) $ pip install mysql

Configuration

Copy the configuration example and edit it:

(flask) $ cp config_template.py config.py

/usr/local/lib/PowerDNS-Admin/config.py:

Basic Settings

  • Enable CSRF (Cross-Site Request Forgery) protection for the HTML forms. Default is True.
  • Set a secret key to sign the users browser cookies for user session protection.
  • The address and port where the applications web-interface listens for incoming requests.
# BASIC APP CONFIG
WTF_CSRF_ENABLED = True
SECRET_KEY = 'We are the world'
BIND_ADDRESS = '127.0.0.1'
PORT = 9393
LOGIN_TITLE = "PDNS"

Database Connection

# DATABASE CONFIG
#You'll need MySQL-python
SQLA_DB_USER = 'powerdnsadmin'
SQLA_DB_PASSWORD = 'powerdnsadminpassword'
SQLA_DB_HOST = 'mysqlhostorip'
SQLA_DB_NAME = 'powerdnsadmin'

While using the random database user password created earlier.

Disable LDAP Connection

Since we don’t have or use LDAP, we disable it by commenting out the relevant entries.

#LDAP_URI = 'ldaps://your-ldap-server:636'
#LDAP_USERNAME = 'cn=dnsuser,ou=users,ou=services,dc=duykhanh,dc=me'
#LDAP_PASSWORD = 'dnsuser'
#LDAP_SEARCH_BASE = 'ou=System Admins,ou=People,dc=duykhanh,dc=me'
## Additional options only if LDAP_TYPE=ldap
#LDAP_USERNAMEFIELD = 'uid'
#LDAP_FILTER = '(objectClass=inetorgperson)'

## AD CONFIG

PowerDNS API Server Connection

This is how the web application connects to the API interface of the PowerDNS server.

Settings should match with your REST-API server configuration of PowerDNS.

# POWERDNS CONFIG
PDNS_STATS_URL = 'http://172.16.214.131:8081/'
PDNS_API_KEY = 'you never know'
PDNS_VERSION = '3.4.7'

DNS Record Types

The allowed DNS types. The defaults (‘A’, ‘AAAA’, ‘CNAME’, ‘SPF’, ‘PTR’, ‘MX’, ‘TXT’) are very minimal.

A list of all the types of DNS records which PowerDNS supports is available in the PowerDNS server documentation.

We recommend the following, which are used throughout other chapters in this guide:

  • A (mapping hostnames to IPv4 addresses)
  • AAAA (mapping hostnames to IPv6 addresses)
  • CERT (to store SSL/TLS certificates in DNS)
  • CNAME (alias of a hostname)
  • MX (mail exchange servers)
  • NAPTR (reverse mapping of phone numbers to VoIP addresses)
  • NS (the name-servers responsible for a domain)
  • OPENPGPKEY (store PGP keys in DNS)
  • PTR (reverse mapping of IP addresses to host names)
  • SPF (Sender Policy Framework against mail spam)
  • SSHFP (to store SSH public key fingerprints in DNS)
  • SRV (mapping service connections in domains)
  • TLSA (SSL/TLS certificates that a service is allowed to present to clients)
  • TXT (store text in DNS)

The following might be used in our domains too, but should not be allowed to be edited by users, as they are managed elsewhere.

  • CDNSKEY (DNSSEC related)
  • CDS (DNSSEC related)
  • DNSKEY (DNSSEC related, managed by pdnsutil)
  • KEY (DNSSEC related)
  • NSEC, NSEC3, NSEC3PARAM (DNSSEC related, managed by pdnsutil)
  • RRSIG (DNSSEC related, managed by pdnsutil)
  • SOA (Start Of Authority, defines a domain in DNS)
  • TKEY, TSIG (keys to sign and authenticate communications between authorized DNS servers and clients)
# RECORDS ALLOWED TO EDIT
RECORDS_ALLOW_EDIT = ['A', 'AAAA', 'CNAME', 'SPF', 'PTR', 'MX', 'TXT']

Initialize Database

Let it create the database records:

(flask) $ ./create_db.py

First Run

Let it start for a first time to create the administrative user:

(flask) $ ./start.py

Point your browser to http://192.0.2.41:9393 to create your first user account, which automatically will have administrative privileges.

Log-out with your browser and stop the server by pressing CTRL-C in you session.

uWSGI Configuration

Create a uWSGI app configuration in the /etc/uwsgi/apps-available/powerdns-admin.ini with the following contents:

; PowerDNS-Admin
[uwsgi]
plugins = python27

;uid=www-data
;gid=www-data

chdir = /usr/local/lib/PowerDNS-Admin/
pythonpath = /usr/local/lib/PowerDNS-Admin/
virtualenv = /usr/local/lib/PowerDNS-Admin/flask

mount = /pdns=run.py
manage-script-name = true
callable = app

vacuum = true
harakiri = 20
post-buffering = 8192

;socket = /run/uwsgi/app/%n/%n.socket
;chown-socket = www-data

;pidfile = /run/uwsgi/app/%n/%n.pid

;daemonize = /var/log/uwsgi/app/%n.log

enable-threads =

The lines commented out, are already defined in the system-wide defaults.

Create a symlink to activate:

$ cd /etc/uwsgi/
$ sudo ln -s apps-available/powerdns-admin.ini apps-enabled/

Start the uwsgi service:

$ sudo service uwsgi start powerdns-admin

Nginx Configuration

Create the file /etc/nginx/webapps/powerdns-admin.conf as follows:

#
# PowerDNS-Admin
# a web-based user interface to PowerDNS API server
#

location /dns {
    try_files $uri @powerdns-admin;
}

location @powerdns-admin {
   include uwsgi_params;
   uwsgi_pass unix:/run/uwsgi/app/powerdns-admin/powerdns-admin.socket;
}

location /dns/static/ {
   alias /usr/local/lib/PowerDNS-Admin/app/static/;
}

Include the file in the appropriate Nginx server definition:

# PowerDNS-Admin
include     webapps/powerdns-admin.conf;

Test the and reload the Nginx configuration:

$ sudo service nginx conftest && sudo service nginx reload