Skip to content
Snippets Groups Projects
Commit d6c65387 authored by Andrei Danciuc's avatar Andrei Danciuc
Browse files

Merge branch 'master' into 'master'

Fixed MR conflicts

See merge request eclipse/xfsc/train/dns-zone-manager!16
parents 7f9bdb09 333903b4
No related branches found
No related tags found
No related merge requests found
/zones.db
/test
/tests
/secrets
*.pyc
**/.DS_Store
*.drawio.bkp
.github/
./.vscode
.vscode
./config.conf
.idea/
logger.log
\ No newline at end of file
FROM python:3.11
WORKDIR /usr/lib/zonemgr
COPY . /usr/lib/zonemgr
# Install ZM dependencies
RUN pip3 install -e .
# Install dependencies for setup. NSD python bindings (not available in pip)
RUN apt-get update && \
apt-get install -y nsd && \
apt-get install -y python3-ldns && \
apt-get install -y cron && \
apt-get install -y systemd
RUN update-rc.d nsd defaults && \
service nsd start
ENV SQLALCHEMY_WARN_20=0
ENV SQLALCHEMY_SILENCE_UBER_WARNING=1
ENV PYTHONPATH="${PYTHONPATH}:/usr/lib/python3/dist-packages/"
ENV PORT_ENV=16001
EXPOSE "${PORT_ENV:-16001}"
EXPOSE 53 53/udp
CMD ./script.sh $PORT_ENV
# DNS ZoneManager for GXFS
Work in progress.
The DNS Zone Management is the component responsible for managing the DNS zone file and used for
anchoring the trust framework DID information into the zone file. It is also responsible for resigning
the zone file based on DNSSEC for every new update in the zone file.
The zone manager service was designed to serve the TSPA only.
It manages a zone file by:
TO DOs
- clean code
- ~~remove prints that are not part of the configuration (make them logs)~~
- ~~refactor exceptions and key errors~~
- update documentation
- ~~add initial API documentation as swagger file~~
- update references for LIGHTest (to Eclipse)
- update documentation after dockerization
- Deployment related tasks:
- dockerization
- configuration via config file
- Creating an intermediate database for NS, A, PTR and URI records
- Providing auth mechanism to protect endpoints
- Exposing secure endpoints for managing PTR records (associated with trust frameworks) and URI records (associated with trust lists)
- Updating records and resigning zone file
- Using DNSSEC to provide and additional security layer to the DNS service
The implementation was done based on [LIGHTest zone manager](https://github.com/H2020LIGHTest/ZoneManager).
### Requirements
- OS: Unix based
- Docker v24.0.7
- Domain setup see #Reference (see [config file](config.conf))
- Web server (e.g. nginx)
### Disclaimer
# Setup
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. This
software is the output of a research project. It was developed as
proof-of-concept to explore, test & verify various components created in
the LIGHTest project. It can thus be used to show the concepts of
LIGHTest, and as a reference implementation.
1. Define the environment setup.
# LIGHTest
In the config.conf file define the primary and secondary servers including DNS names and IP addresses.
The primary server will host and run the zone manager service as well as the zone file.
Lightweight Infrastructure for Global Heterogeneous Trust management in
support of an open Ecosystem of Stakeholders and Trust schemes. For more
information please visit the LIGHTest website: https://www.lightest.eu/
2. Build and run Docker container
Build the Docker image
Detailed documentation of LIGHTest and its software components can be
found in the [LIGHTest Deliverables](https://www.lightest.eu/downloads/pub_deliverables/index.html).
`docker build -t zonemanager .`
# ZoneManager
3. Run the container
This is the LIGHTest Zone Manager, a simple REST server that maintains and
signs the DNS zones used by the LIGHTest framework for publishing trust
data.
The zone manager will use the port 16001, make sure you map the correct host port and configure
your proxy to direct traffic accordingly.
It is written in Python 2 using Falcon, gunicorn, LDNS, and SQL Alchemy.
See `requirements.txt` for the exact version we’ve used.
`docker run -p 16001:16001 zonemanager`
Zone Manager consists of a Python 2 module, `zonedb`, and a executable
script, `zonemanager.py` that uses the module to provide the server.
At start up, see the console logs, an API KEY will be generated. For example:
## Installation
Generating a ZM API KEY for communication with TSPA, please note it down:
===================================================================
2Vbj1VwrgrLE9aKQjQUMhexiZ51dxSPW
===================================================================
ZoneManager can almost be installed from the repository using pip.
Unfortunately, LDNS’ Python bindings are not available via pypi.org, so
you will have to install them separately.
If you are on a Debian-ish system:
```
apt-get install apt-get install python-falcon python-gunicorn python-sqlalchemy
```
Now you can install Zone Manager:
```
pip2 install git+http://github.com/H2020LIGHTest/ZoneManager
```
On non-Debian systems, you might need to install dependencies separately.
## Usage
While primarily a web service, Zone Manager comes with a number of
maintenance commands. For each command, it requires the URI to a database
given via the `--database` (or `-d`, for short) option. This needs to be
given before the actual command. The URI is in SQL Alchemy format which
isn’t entirely intuitive. For SQLite, if you provide an absolute file
name, you need to start with four (!) slashes, e.g.,
name, you need to start with four (!) slashes, e.g.,
`sqlite:////var/lib/zonemgr/zones.db`.
Before we can start, we need to initialize the database:
```
zonemanager.py -d sqlite:////var/lib/zonemgr/zones.db init
```
Next we need to add an environment. This tells Zone Manager where it finds
the instance of NSD to talk to and where to store the configuration for
it:
```
zonemanager.py -d sqlite:////var/lib/zonemgr/zones.db add-environment \
--environment default \
--nsd-name ns1.lightest.example.com \
--nsd-reload /var/lib/zonemgr/reload-nsd.sh \
--nsd-conf /var/lib/zonemgr/nsd.zones.conf \
--key-file /var/lib/zonemgr/private_key.tmp
```
There’s five arguments to this. First, we need to give the new environment
so we can refer to it later. This happens via the `--environment` option.
Next, we need to provide the host name of the name server that is run by
our NSD instance via the `--nsd-name` option. This name will appear in the
SOA record of the zones we created.
Whenever Zone Manager updated its zones, it needs to inform NSD to reload
them. This happens via the script provided via the `--nsd-reload` option.
A simple version of that script that assumes that you have installed and
correctly setup the `nsd-control` program is included in the repository.
Zone Manager will create one NSD config file that needs to be included
in your ‘real’ NSD config. The location of this file is provided via the
`--nsd-conf` option.
Finally, we need to have the path to a file where we temporarily store the
private key for signing the zones. This is because of a peculiarity of the
LDNS Python bindings.
Next, we need to add a zone to be controlled by Zone Manager:
```
zonemanager.py -d sqlite:////var/lib/zonemgr/zones.db add-zone \
--environment default \
--apex lightest.example.com \
--pattern lightest
```
We need to provide the name of the argument we created earlier, the apex
of the zone, i.e., the domain name of the top of the domain, and a
pattern. NSD uses patterns to provide configuration for multiple zones.
This needs to be configured in your ‘real’ NSD config. Here, we assume
that you created a pattern named `lightest`.
A correctly configured zone needs a bunch of records. Zone Manager only
creates the SOA record by itself. You will have to manually add at least
the NS records:
This is necessary to make the calls to the endpoints (see [docs](/docs)).
For example, you can check the service status via:
```
zonemanager.py -d sqlite:////var/lib/zonemgr/zones.db add-record \
--environment default \
--apex lightest.example.com \
--ttl 86400 \
lightest.example.com NS \
ns1.lightest.example.com \
ns2.lightest.example.com
curl -X GET \
-H "Authorization: Bearer 2Vbj1VwrgrLE9aKQjQUMhexiZ51dxSPW" \
-H "Content-Type: application/json" \
http://localhost:16001/status
```
Here we add two NS records. The last two arguments are the record data for
two records with the same name and type. These record data arguments are
in master file format. If that requires spaces, you need to quote them.
This way, you can add multiple records at once.
# Reference
We also need at least A records for our name servers:
## System overview
```
zonemanager.py -d sqlite:////var/lib/zonemgr/zones.db add-record \
--environment default --apex lightest.example.com --ttl 86400 \
ns1.lightest.example.com A 192.0.2.1
zonemanager.py -d sqlite:////var/lib/zonemgr/zones.db add-record \
--environment default --apex lightest.example.com --ttl 86400 \
ns2.lightest.example.com A 192.0.2.2
```
![System overview](docs/system overview.png)
Finally we need to set up authentication for our clients. This happens via
simple bearer tokens that are exchanged out of band. Currently, you can
only create new tokens like so:
The zone manager is meant to have the TSPA as its only client. The TSPA can perform CRUD operations
in relation to Trust Frameworks and Trust Lists. The Zone Manager takes every operation request and
updates the zone file accordingly. It takes care of adding and deleting records to the zone file and
its required signig.
```
zonemanager.py -d sqlite:////var/lib/zonemgr/zones.db create-token \
--environment default \
user-alpha \
lightest.example.com
```
This needs the name of the environment, a name of the token – this is only
for your own bookkeeping – and the (apex of the) zone this token is
allowing access to. The token will be printed on the terminal so you can
copy it and give it to your user.
A simple description of the flow:
At startup, the Zone Manager sets up the DNS server (NSD or KNOT) and creates a data base with the base
SOA, NS and A type resource records wich are then formatted, signed and used to create a zone file.
A Trust Framework creation request can then be initialized by the TSPA. When this happens, the Zone
Manager converts the Trust Framework's URL into a PTR record, stores in the data base and anchors it
in the DNS system by updating the zone file accordingly.
In the case of creation of Trust List DID, the process is similar with only difference being that the
DID are stored as URI type records in the database as well as in the zone file.
Now you can start the server:
This is repeated every time a CRUD operation in relation to Trust Framework URLs and Trust List DIDs.
```
zonemanager.py -d sqlite:////var/lib/zonemgr/zones.db server 127.0.0.1:8080
```
The current Zone Manager implementation includes a simple UI that allows the administrator to visualize
the zone data. See the [user interface folder](ui)
This will run the server on localhost’s port 8080. Since Zone Manager
doesn’t do any TLS, you will need to run it behind nginx or Apache.
# Deployment notes
# Licence
### Zone file persistance
- Apache License 2.0 (see [LICENSE](./LICENSE))
- © LIGHTest Consortium
- Apache License 2.0 (see [LICENSE](./LICENSE))
- © LIGHTest Consortium
Please note that when the docker container is run, a new zone file gets created. This will be stored inside
the container in the path defined by the environment variable VAR_PATH in the [setup script](script.sh) file
run by docker when the image is built. This zone file is not persisted in the host machine. If you want to provide
persistency for this file please do so by defining volumes in the [Dockerfile](Dockerfile).
TF_DOMAIN_NAME=testtrain.trust-scheme.de
TF_DOMAIN_IP=52.19.94.74
PRIMARY_SERVER_NDS=ns1.testtrain.trust-scheme.de
PRIMARY_SERVER_IP=52.19.94.74
SECONDARY_SERVER_1_NDS=n2.testtrain.trust-scheme.de
SECONDARY_SERVER_1_IP=52.17.60.21
SECONDARY_SERVER_2_NDS=ns3.testtrain.trust-scheme.de
SECONDARY_SERVER_2_IP=1.2.3.4
\ No newline at end of file
# TO BE UPDATED
# Installation of Demonstration Environment
This memo documents the installation of the Zone Manager for the LIGHTest
demonstration environment.
## Resources
The environment uses three Digital Ocean droplets (other cloud providers
are available) named as follows:
* lightest-primary
* lightest-secondary-sfo
* lightest-secondary-sgp
The lightest-primary droplet will be running the Zone Manager itself
providing the HTTPS API. It also runs NSD as the primary name server for
the zones served by the environment. The other two droplets will run NSD
as the secondary name servers for those zones.
As of writing this document, the droplets had the following addresses:
Droplet | IPv4 address | IPv6 address
------------------------|-----------------|---------------
lightest-primary | 167.71.42.146 | 2a03:b0c0:3:e0::bb:5001
lightest-secondary-sfo | 167.71.127.223 | 2604:a880:2:d1::24:f001
lightest-secondary-sgp | 206.189.82.24 | 2400:6180:0:d1::8e1:3001
We’ll use these addresses in the code snippets below.
All droplets were created using Debian 10.0 (buster) images.
## All Droplets
```
apt-get update
apt-get dist-upgrade
apt-get install nsd
```
## lightest-primary
### Install and Configure Zone Manager
(Because you need to `git clone` from the IAIK Gitlab instance, you need
to SSH into the machine with -A to pass on your credentials.)
We are installing the zone manager itself into `/usr/lib/zonemgr`. It’s
database and NSD configuration will be in `/var/lib/zonemgr/`.
```
apt-get install git gunicorn python-sqlalchemy python-falcon python-ldns \
sqlite3
git clone git@github.com:H2020LIGHTest/ZoneManager.git /usr/lib/zonemgr
adduser --system --home /var/lib/zonemgr zonemgr
cp /usr/lib/zonemgr/etc/zonemgr.service /etc/systemd/system
```
Create the database and an environment called `lightest`:
```
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
init
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
add-environment \
--environment lightest \
--nsd-name ns0.lightest.nlnetlabs.nl \
--nsd-conf /var/lib/zonemgr/nsd.zones.conf \
--nsd-reload /usr/lib/zonemgr/reload-nsd.sh \
--key-file /var/lib/zonemgr/private_key.tmp
```
Add the zone we are going to use, `lightest.nlnetlabs.nl`:
```
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
add-zone \
--environment lightest \
--apex lightest.nlnetlabs.nl \
--pattern lightest
```
The command will print the DS record for the zone. You will need that
record to configure delegation in the parent zone, in this case
`nlnetlabs.nl`.
Make everything owned by the `zonemgr` user it can access things later.
```
chown -R zonemgr: /var/lib/zonemgr
```
Add some necessary records to the zone:
```
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
add-record \
--environment lightest \
--apex lightest.nlnetlabs.nl \
lightest.nlnetlabs.nl NS \
ns0.lightest.nlnetlabs.nl \
ns1.lightest.nlnetlabs.nl \
ns2.lightest.nlnetlabs.nl
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
add-record \
--environment lightest \
--apex lightest.nlnetlabs.nl \
lightest.nlnetlabs.nl A 167.71.42.146
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
add-record \
--environment lightest \
--apex lightest.nlnetlabs.nl \
lightest.nlnetlabs.nl AAAA 2a03:b0c0:3:e0::bb:5001
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
add-record \
--environment lightest \
--apex lightest.nlnetlabs.nl \
ns0.lightest.nlnetlabs.nl A 167.71.42.146
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
add-record \
--environment lightest \
--apex lightest.nlnetlabs.nl \
ns0.lightest.nlnetlabs.nl AAAA 2a03:b0c0:3:e0::bb:5001
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
add-record \
--environment lightest \
--apex lightest.nlnetlabs.nl \
ns1.lightest.nlnetlabs.nl A 167.71.127.223
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
add-record \
--environment lightest \
--apex lightest.nlnetlabs.nl \
ns1.lightest.nlnetlabs.nl AAAA 2604:a880:2:d1::24:f001
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
add-record \
--environment lightest \
--apex lightest.nlnetlabs.nl \
ns2.lightest.nlnetlabs.nl A 206.189.82.24
/usr/lib/zonemgr/zonemanager.py \
--database sqlite:////var/lib/zonemgr/zones.db \
add-record \
--environment lightest \
--apex lightest.nlnetlabs.nl \
ns2.lightest.nlnetlabs.nl AAAA 2400:6180:0:d1::8e1:3001
```
Install the DNSSEC resigning cronjob:
```
crontab -u zonemgr /usr/lib/zonemgr/etc/crontab
```
Enable and start the service:
```
systemctl enable zonemgr
systemctl start zonemgr
```
### Install and Configure NSD
Configure NSD to pick up our zones:
```
cat > /etc/nsd/nsd.conf.d/server.conf <<EOF
server:
ip-address: 0.0.0.0
ip-address: ::0
verbosity: 3
pidfile: "/var/run/nsd/nsd.pid"
EOF
cat > /etc/nsd/nsd.conf.d/zonemgr.conf <<EOF
pattern:
name: lightest
notify: 167.71.127.223 NOKEY
notify: 206.189.82.24 NOKEY
provide-xfr: 167.71.127.223 NOKEY
provide-xfr: 206.189.82.24 NOKEY
include: /var/lib/zonemgr/nsd.zones.conf
EOF
cat > /etc/nsd/nsd.conf.d/remote.conf << EOF
remote-control:
control-enable: yes
control-interface: 127.0.0.1
control-port: 8952
server-key-file: "/etc/nsd/nsd_server.key"
server-cert-file: "/etc/nsd/nsd_server.pem"
control-key-file: "/etc/nsd/nsd_control.key"
control-cert-file: "/etc/nsd/nsd_control.pem"
EOF
```
Enable all the services:
```
systemctl enable nsd
systemctl start nsd
```
### Install Nginx and Acmetool
Get the packages:
```
apt-get install nginx acmetool
```
Start nginx.
```
systemctl enable nginx
systemctl start nginx
```
Bootstrap acmetool. Run
```
acmetool quickstart
```
and then select ’Let’s Encrypt (live)’ and ‘WEBROOT’. Enter
`/var/www/html/.well-known/acme-challenge` is the webroot path (NB: This
is _not_ the default presented). Accept the terms, insert an email address
if you want to and agree to the cronjob to be installed.
Request a certificate:
```
acmetool want lightest.nlnetlabs.nl
```
Now finalize Nginx configuration:
```
cat > /etc/nginx/sites-available/lightest.nlnetlabs.nl <<EOF
server {
listen 80;
listen [::]:80;
server_name lightest.nlnetlabs.nl;
root /var/name/html;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name lightest.nlnetlabs.nl;
ssl_certificate /var/lib/acme/live/lightest.nlnetlabs.nl/fullchain;
ssl_certificate_key /var/lib/acme/live/lightest.nlnetlabs.nl/privkey;
root /var/www/html;
location / {
proxy_pass http://127.0.0.1:8008$request_uri;
}
}
EOF
ln -s ../sites-available/lightest.nlnetlabs.nl /etc/nginx/sites-enabled/lightest.nlnetlabs.nl
```
Reload nginx:
```
systemctl reload nginx
```
## lightest-secondary-sfo and lightest-secondary-sgp
The two secondary servers are identical. They only need NSD to be
configured to serve as a secondary name server for our zones.
```
mkdir -p /var/lib/nsd/secondary
chown nsd: /var/lib/nsd/secondary
cat > /etc/nsd/nsd.conf.d/server.conf <<EOF
server:
ip-address: 0.0.0.0
ip-address: ::0
verbosity: 3
pidfile: "/var/run/nsd/nsd.pid"
EOF
cat > /etc/nsd/nsd.conf.d/secondary.conf <<EOF
pattern:
name: lightest
allow-notify: 167.71.42.146 NOKEY
request-xfr: 167.71.42.146 NOKEY
zone:
name: "lightest.nlnetlabs.nl"
zonefile: "/var/lib/nsd/secondary/lightest.nlnetlabs.nl"
include-pattern: lightest
EOF
cat > /etc/nsd/nsd.conf.d/remote.conf << EOF
remote-control:
control-enable: yes
control-interface: 127.0.0.1
control-port: 8952
server-key-file: "/etc/nsd/nsd_server.key"
server-cert-file: "/etc/nsd/nsd_server.pem"
control-key-file: "/etc/nsd/nsd_control.key"
control-cert-file: "/etc/nsd/nsd_control.pem"
EOF
systemctl enable nsd
systemctl start nsd
```
docs/system overview.png

47.9 KiB

#! /bin/bash
#
# A simple script to load the database.
ZMGR=./zonemanager.py
WORKDIR=test
ADDR=127.0.0.1:8088
BASE=http://$ADDR
api() {
curl -X $1 -H "Authorization: Bearer $TOKEN" http://$ADDR$2
}
vapi() {
curl -v -X $1 -H "Authorization: Bearer $TOKEN" http://$ADDR$2
}
api_put() {
curl -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-X PUT \
--data-raw "$2" \
http://$ADDR$1
}
mkdir -p $WORKDIR
$ZMGR init -f
$ZMGR add-environment -e default -n ns.lightest.nlnetlabs.nl. \
-r "echo foo" \
-c $WORKDIR/nsd.zones.conf -k $WORKDIR/private_key.tmp
$ZMGR add-zone -e default -a lightest.nlnetlabs.nl.
$ZMGR add-record -e default -a lightest.nlnetlabs.nl. \
lightest.nlnetlabs.nl. A 127.0.0.1 127.0.0.2
TOKEN=`$ZMGR create-token -e default default lightest.nlnetlabs.nl.`
coproc $ZMGR server -e default
sleep 1
api GET /status
api_put /names/scheme..lightest.nlnetlabs.nl./trust-list \
'{"url":"http://lightest.nletlabs.nl/","certificate":[{"data":"1234567890123456789012345678901234567890123456789012345678901234"}]}'
while true ; do
api_put /names/scheme.lightest.nlnetlabs.nl./trust-list \
'{"url":"http://lightest.nletlabs.nl/","certificate":[{"data":"1234567890123456789012345678901234567890123456789012345678901234"}]}'
done
echo PUT /names/scheme.lightest.nlnetlabs.nl./trust-list broken
api_put /names/scheme.lightest.nlnetlabs.nl./trust-list \
'{"url":"http://lightest.nletlabs.nl/","certificate":[{"data":""}]}'
echo GET /names/scheme.lightest.nlnetlabs.nl./trust-list
api GET /names/scheme.lightest.nlnetlabs.nl./trust-list
echo
api DELETE /names/scheme.lightest.nlnetlabs.nl./trust-list
api_put /names/scheme.lightest.nlnetlabs.nl./trust-list \
'{"url":"http://lightest.nletlabs.nl/","certificate":[{"data":"1234567890123456789012345678901234567890123456789012345678901234"}]}'
$ZMGR resign
api_put /names/trustservice.lightest.nlnetlabs.nl./schemes \
'{"schemes": [ "some.scheme.com", "sööome.other.scheme.com" ] }'
api_put /names/trustservice.lightest.nlnetlabs.nl./schemes \
'{"schemes": [ "some.scheme.com", "some.other.scheme.com" ] }'
api GET /names/trustservice.lightest.nlnetlabs.nl./schemes
api DELETE /names/trustservice.lightest.nlnetlabs.nl./schemes
api DELETE /names/trustservice.lightest.nlnetlabs.nl./schemes
api GET /names/trustservice.lightest.nlnetlabs.nl./schemes
api_put /names/trustservice.lightest.nlnetlabs.nl./schemes \
'{"schemes": [ "some.scheme.com", "some.other.scheme.com" ] }'
kill $COPROC_PID
sleep 1
# Setup script. It will take the configuration file and will initialize an intermediate sql DB,
# fill it with initial records for the creation of zone file. It also configures and sets the nsd
# server up and starts the Zone Manager server.
#
# Must be called as ./script.sh $PORT
# The Zone Manager server will start at $PORT number.
printf "====>>> STARTING ZONE MANAGER SERVICE SETUP \n"
printf "Setting up NSD (defualt configuration)... \n"
# Condifure NSD server
cat > /tmp/server.conf <<EOF
server:
ip-address: 0.0.0.0
ip-address: ::0
verbosity: 3
pidfile: "/var/run/nsd/nsd.pid"
#port: 5353
EOF
mv /tmp/server.conf /etc/nsd/nsd.conf.d/server.conf
cat > /tmp/remote.conf << EOF
remote-control:
control-enable: yes
control-interface: 0.0.0.0
control-port: 8952
server-key-file: "/etc/nsd/nsd_server.key"
server-cert-file: "/etc/nsd/nsd_server.pem"
control-key-file: "/etc/nsd/nsd_control.key"
control-cert-file: "/etc/nsd/nsd_control.pem"
EOF
mv /tmp/remote.conf /etc/nsd/nsd.conf.d/remote.conf
service nsd start
printf "\n"
service nsd status
printf "\nGetting DNS configuration variables from config file... \n"
# Get configuration variables from the config file
CONFIG_FILE="config.conf"
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
printf " Config file found. Trust framework domain name to set: %s\n" "$TF_DOMAIN_NAME"
else
printf " ERROR: Configuration file \"$CONFIG_FILE\" does not exist. \n"
exit 1
fi
ZM_PATH="/usr/lib/zonemgr/" # path for source code.
VAR_PATH="/var/lib/zonemgr/" # path for variables including DB, zonefile and DNS config file
ZMGR=$ZM_PATH"zonemanager.py"
SQLITE_DB="sqlite:///"$VAR_PATH"zones.db"
export SQLALCHEMY_WARN_20=1
# set permissions, add user and copy the ZM service to system folder
chmod 777 -R "$ZM_PATH"
adduser --system --home "$VAR_PATH" zonemgr
printf "Initializing intermediate DB and adding records to it and to the zone file... \n"
SQLALCHEMY_SILENCE_UBER_WARNING=1
# initialize DB
python3 "$ZM_PATH"zonemanager.py --database "$SQLITE_DB" init -f
# add default environment
python3 "$ZMGR" \
--database $SQLITE_DB \
add-environment \
--environment network \
--nsd-name "$PRIMARY_SERVER_NDS" \
--nsd-conf "$VAR_PATH"nsd.zones.conf \
--nsd-reload "$ZM_PATH"reload-nsd.sh \
--key-file "$VAR_PATH"private_key.tmp
# add default zone with given trust framework domain
python3 "$ZMGR" \
--database $SQLITE_DB \
add-zone \
--environment network \
--apex "$TF_DOMAIN_NAME" \
--pattern network
chown -R zonemgr: /var/lib/zonemgr
# add required NS records and related IP addresses
python3 "$ZMGR" \
--database $SQLITE_DB \
add-record \
--environment network \
--apex "$TF_DOMAIN_NAME" \
"$TF_DOMAIN_NAME" NS \
"$PRIMARY_SERVER_NDS" \
"$SECONDARY_SERVER_1_NDS"
python3 "$ZMGR" \
--database $SQLITE_DB \
add-record \
--environment network \
--apex "$TF_DOMAIN_NAME" \
"$TF_DOMAIN_NAME" A "$TF_DOMAIN_IP"
python3 "$ZMGR" \
--database $SQLITE_DB \
add-record \
--environment network \
--apex "$TF_DOMAIN_NAME" \
"$PRIMARY_SERVER_NDS" A "$PRIMARY_SERVER_IP"
python3 "$ZMGR" \
--database $SQLITE_DB \
add-record \
--environment network \
--apex "$TF_DOMAIN_NAME" \
"$SECONDARY_SERVER_1_NDS" A "$SECONDARY_SERVER_1_IP"
python3 "$ZMGR" \
--database $SQLITE_DB \
add-record \
--environment network \
--apex "$TF_DOMAIN_NAME" \
"$SECONDARY_SERVER_2_NDS" A "$SECONDARY_SERVER_2_IP"
printf "\nAdding cron job for resigning... \n"
# Install the DNSSEC resigning cronjob:
crontab -u zonemgr "$ZM_PATH"etc/crontab
printf "\nConfiguring NSD for ZM... \n"
cat > /tmp/zonemgr.conf <<EOF
pattern:
name: network
notify: $SECONDARY_SERVER_1_IP NOKEY
#notify: $SECONDARY_SERVER_2_IP NOKEY
provide-xfr: $SECONDARY_SERVER_1_IP NOKEY
#provide-xfr: $SECONDARY_SERVER_2_IP NOKEY
include: /var/lib/zonemgr/nsd.zones.conf
EOF
mv /tmp/zonemgr.conf /etc/nsd/nsd.conf.d/zonemgr.conf
printf "\nEnabling and starting nsd server... \n"
service nsd start
printf "\n"
service nsd status
# Generate and print a token (API KEY) that the TSPA must use to call ZM endpoints
printf "\nGenerating a ZM API KEY for communication with TSPA, please note it down: \n"
printf "=================================================================== \n"
python3 "$ZMGR" -d $SQLITE_DB create-token \
--environment network\
network \
"$TF_DOMAIN_NAME"
printf "=================================================================== \n"
printf "\nStarting the Zone Manager service in port %s" "$1...\n"
$ZMGR --database $SQLITE_DB server -e network 0.0.0.0:$1
\ No newline at end of file
......@@ -3,10 +3,14 @@ import logging
import falcon
import gunicorn.app.base
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.util import deprecations
from zonedb.models import Zone, AuthToken, SchemeClaim, TrustList, TrustListCert
from zonedb.master import refresh_zonefile, reload_master
from datetime import datetime
import subprocess
deprecations.SILENCE_UBER_WARNING = 1
deprecations.SQLALCHEMY_WARN_20 = 0
def auth_zone(req):
if not req.auth:
......@@ -60,13 +64,25 @@ def decode_certs(cert_list):
class Status(object):
def on_get(self, req, resp):
zone = auth_zone(req)
databaseStatus = "OK" # checked via auth_zone(req)
system_status = "OK"
doc = {
"environment": req.context.environment.name,
"zone": zone.apex,
"status": "OK",
"Zone": zone.apex,
"status" : system_status,
"dependencies" : {
"Zone_Manager_server_status": "OK",
"Database_status":databaseStatus,
"NSD_server_status":"OK"
}
}
resp.body = json.dumps(doc, ensure_ascii=False)
status = subprocess.run(["service", "nsd", "status"], capture_output=True, text=True)
if status.returncode == 0: # nsd is running
doc["dependencies"]["NSD_server_status"] = "OK"
else:
doc["status"] = "Dependency unavailable"
doc["dependencies"]["NSD_server_status"] = "NSD server is not running"
resp.body = json.dumps(doc, ensure_ascii=False)
class TrustListResource(object):
def __init__(self, list_type):
......@@ -105,7 +121,6 @@ class TrustListResource(object):
raise falcon.HTTPBadRequest("400 Bad Request", "Request must contain a valid did")
self.delete(req, zone, scheme_name)
trust_list = TrustList(zone=zone, name=scheme_name, list_type=self.list_type, did=did)
trust_list = TrustList(zone=zone, name=scheme_name, list_type=self.list_type, did=did)
try:
trust_list.rr()
except:
......@@ -219,6 +234,7 @@ class SchemeClaimResource(object):
class ViewZone(object):
def on_get(self, req, resp):
zone = auth_zone(req)
zones = req.context.session.query(Zone).all()
all_zones = []
for zone in zones:
......@@ -262,9 +278,6 @@ class ApiApplication(gunicorn.app.base.BaseApplication):
api.add_route("/status", Status())
api.add_route("/names/{scheme_name}/trust-list", TrustListResource("scheme"))
api.add_route(
"/names/{scheme_name}/translation", TrustListResource("translation")
)
api.add_route("/names/{scheme_name}/schemes", SchemeClaimResource())
api.add_route("/view-zone", ViewZone())
......
......@@ -5,6 +5,7 @@ import subprocess
import ldns
from zonedb.models import Environment
def refresh_master(session):
"""Recreates all master data for the zone data in the database."""
for env in session.query(Environment):
......@@ -33,12 +34,13 @@ def refresh_environment(session, environment):
def refresh_zonefile(session, environment, zone):
out = ldns.ldns_zone()
soa = ldns.ldns_rr.new_frm_str(str(
record=str(
"%s %i IN SOA %s %s %i %i %i %i %i" % (
zone.apex, zone.soa_ttl, zone.mname, zone.rname, time(),
zone.refresh, zone.retry, zone.expire, zone.minimum
)
))
)
soa = ldns.ldns_rr.new_frm_str(record)
out.set_soa(soa)
rrs = []
for record in zone.records:
......@@ -103,5 +105,4 @@ def get_ds(session, environment, zone):
if res:
res += '\n'
res += str(ds)
return res
return res
\ No newline at end of file
from base64 import urlsafe_b64encode, b16encode, b16decode
from os import path, urandom
from base64 import b16decode
from os import path
from secrets import token_urlsafe
import logging
from ldns import ldns_key, ldns_rr, LDNS_SIGN_ECDSAP256SHA256
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column
from sqlalchemy import Boolean, ForeignKey, Integer, String, Text
from sqlalchemy.orm import relationship
import logging
Base = declarative_base()
......@@ -34,7 +34,7 @@ class Environment(Base):
# NSD configuration
#
nsd_name = Column(String,
doc="""Hostname of the name server.""")
doc="Hostname of the name server.")
nsd_conf = Column(String,
doc="""Path to the NSD configuration to be created.
......@@ -122,7 +122,6 @@ class Zone(Base):
"""Returns whether the zone contains a certain domain name.
It doesn't consider delegations.
"""
# topDomain=".".join(self.apex.split(".")[-2:])
return name.endswith(self.apex)
Environment.zones = relationship("Zone", order_by=Zone.id,
......@@ -191,7 +190,9 @@ class AuthToken(Base):
@classmethod
def create(cls, name, zone):
return AuthToken(
name=name, token=urlsafe_b64encode(urandom(24)), zone=zone
name=name,
token=token_urlsafe(24),
zone=zone,
)
class TrustList(Base):
......@@ -310,6 +311,6 @@ def rr_from_str(rr_str):
try:
return ldns_rr.new_frm_str(rr_str)
except Exception as exc:
print("%s: %s" % (exc, rr_str))
logging.debug(f"Exception creating resource record from string '{rr_str}'. '{exc}'")
raise exc
#! /usr/bin/env python3
#! /usr/bin/env python3
import argparse
from os import path
import logging
from datetime import datetime
from sqlalchemy import create_engine
from sqlalchemy.util import deprecations
from sqlalchemy.orm import sessionmaker
from zonedb.api import ApiApplication
from zonedb.models import AuthToken, Base, Environment, Record, Zone
......@@ -13,6 +13,8 @@ from zonedb import master
logging.basicConfig(filename='/usr/lib/zonemgr/logger.log', encoding='utf-8', level=logging.DEBUG)
deprecations.SILENCE_UBER_WARNING = 1
deprecations.SQLALCHEMY_WARN_20 = 0
def get_config():
"""Produces the configuration."""
......@@ -203,7 +205,7 @@ class Server:
sub.add_argument("--environment", "-e", action="store", required=True,
help="name of the environment to use")
sub.add_argument("bind", action="store", default="127.0.0.1:8088",
sub.add_argument("bind", action="store", default="0.0.0.0:16001",
nargs="?",
help="address:port to bind to")
......@@ -211,9 +213,12 @@ class Server:
@classmethod
def run(cls, config):
config.environment = config.session.query(Environment) \
.filter_by(name=config.environment).one()
ApiApplication(config).run()
try:
config.environment = config.session.query(Environment) \
.filter_by(name=config.environment).one()
ApiApplication(config).run()
except Exception as exc:
logging.debug("Error starting server. %s", str(exc))
if __name__ == "__main__":
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment