PowerDNS instead of bind9 #2
35 changed files with 739 additions and 330 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
.secrets.cfg
|
||||
__pycache__
|
||||
|
|
|
@ -67,10 +67,12 @@ pkg_apt = {
|
|||
|
||||
'arping': {},
|
||||
'at': {},
|
||||
'build-essential': {},
|
||||
'bzip2': {},
|
||||
'curl': {},
|
||||
'diffutils': {},
|
||||
'dnsutils': {},
|
||||
'git': {},
|
||||
'grep': {},
|
||||
'gzip': {},
|
||||
'htop': {},
|
||||
|
@ -88,6 +90,7 @@ pkg_apt = {
|
|||
'netcat': {},
|
||||
'nmap': {},
|
||||
'python3': {},
|
||||
'python3-dev': {},
|
||||
'python3-pip': {},
|
||||
'python3-virtualenv': {},
|
||||
'tar': {},
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
% for key in keys:
|
||||
key ${key['name']} {
|
||||
algorithm ${key['algorithm']};
|
||||
secret "${key['secret']}";
|
||||
};
|
||||
% endfor
|
|
@ -1,30 +0,0 @@
|
|||
include "/etc/bind/keys.conf";
|
||||
|
||||
% for zone in sorted(primary_zones):
|
||||
zone "${zone}" IN {
|
||||
type master;
|
||||
file "/var/lib/bind/primary/${zone}";
|
||||
};
|
||||
% endfor
|
||||
|
||||
|
||||
zone "10.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
|
||||
zone "16.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "17.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "18.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "19.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "20.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "21.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "22.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "23.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "24.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "25.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "26.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "27.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "28.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "29.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "30.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
zone "31.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
||||
|
||||
zone "168.192.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
|
|
@ -1,3 +0,0 @@
|
|||
% for o in node.metadata.get('bind', {}).get('options', []):
|
||||
<%include file="options/${o}"/>
|
||||
% endfor
|
|
@ -1,146 +0,0 @@
|
|||
from os import listdir
|
||||
from os.path import isfile, join
|
||||
from datetime import datetime
|
||||
from subprocess import check_output
|
||||
|
||||
ZONE_HEADER = """
|
||||
; _ ____ _ _ _____ _ _ _ _ ____
|
||||
; / \\ / ___| | | |_ _| | | | \\ | |/ ___|
|
||||
; / _ \\| | | |_| | | | | | | | \\| | | _
|
||||
; / ___ \\ |___| _ | | | | |_| | |\\ | |_| |
|
||||
; /_/ \\_\\____|_| |_| |_| \\___/|_| \\_|\\____|
|
||||
;
|
||||
; --> Diese Datei wird von BundleWrap verwaltet! <--
|
||||
|
||||
$TTL 60
|
||||
@ IN SOA ns-1.kunbox.net. hostmaster.kunbox.net. (
|
||||
{serial}
|
||||
3600
|
||||
3600
|
||||
86400
|
||||
300
|
||||
)
|
||||
@ IN NS bind01.gce.kunbox.net.
|
||||
IN NS b.ns14.net.
|
||||
IN NS c.ns14.net.
|
||||
IN NS d.ns14.net.
|
||||
"""
|
||||
|
||||
svc_systemd = {
|
||||
'bind9': {
|
||||
'needs': {
|
||||
'pkg_apt:bind9',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pkg_apt = {
|
||||
'bind9': {},
|
||||
}
|
||||
|
||||
directories = {
|
||||
"/var/lib/bind/primary": {
|
||||
'group': 'bind',
|
||||
'needs': {
|
||||
'pkg_apt:bind9',
|
||||
},
|
||||
'owner': 'bind',
|
||||
'purge': True,
|
||||
},
|
||||
"/var/log/named": {
|
||||
'group': 'bind',
|
||||
'needs': {
|
||||
'pkg_apt:bind9',
|
||||
},
|
||||
'owner': 'bind',
|
||||
},
|
||||
}
|
||||
|
||||
files = {
|
||||
"/etc/bind/keys.conf": {
|
||||
'content_type': 'mako',
|
||||
'group': 'bind',
|
||||
'mode': '0440',
|
||||
'context': {
|
||||
'keys': node.metadata.get('bind', {}).get('keys', []),
|
||||
},
|
||||
'triggers': {
|
||||
'svc_systemd:bind9:reload',
|
||||
},
|
||||
'needs': {
|
||||
'pkg_apt:bind9',
|
||||
},
|
||||
},
|
||||
"/etc/bind/named.conf.options": {
|
||||
'content_type': 'mako',
|
||||
'group': 'bind',
|
||||
'mode': '0440',
|
||||
'triggers': {
|
||||
'svc_systemd:bind9:reload',
|
||||
},
|
||||
'needs': {
|
||||
'pkg_apt:bind9',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if node.metadata.get('bind', {}).get('rndc', ''):
|
||||
files['/etc/bind/rndc.conf'] = {
|
||||
'mode': '0440',
|
||||
'source': 'rndc/{}'.format(node.metadata['bind']['rndc']),
|
||||
'content_type': 'mako',
|
||||
'triggers': {
|
||||
'svc_systemd:bind9:reload',
|
||||
},
|
||||
}
|
||||
|
||||
# this looks for zones either directly at data/bind/zones/ or in a subdirectory if so configured
|
||||
zone_path = join(
|
||||
repo.path,
|
||||
'data', 'bind', 'files', 'zones',
|
||||
node.metadata.get('bind', {}).get('zone_path', ""),
|
||||
)
|
||||
|
||||
primary_zones = set()
|
||||
|
||||
for zone in listdir(zone_path):
|
||||
if not isfile(join(zone_path, zone)) or zone.startswith(".") or zone.startswith("_"):
|
||||
continue
|
||||
|
||||
output = check_output(['git', 'log', '-1', '--pretty=%ci', join(zone_path, zone)]).decode('utf-8').strip()
|
||||
serial = datetime.strptime(output, '%Y-%m-%d %H:%M:%S %z').strftime('%y%m%d%H%M')
|
||||
|
||||
primary_zones.add(zone)
|
||||
|
||||
files["/var/lib/bind/primary/{}".format(zone)] = {
|
||||
'content_type': 'mako',
|
||||
'context': {
|
||||
'header': ZONE_HEADER.format(serial=serial),
|
||||
'metadata_records': node.metadata.get('bind', {}).get('zones_primary', {}).get(zone, {}).get('records', []),
|
||||
},
|
||||
'mode': '0444',
|
||||
'owner': 'bind',
|
||||
'source': 'zones/{}'.format(join(node.metadata.get('bind', {}).get('zone_path', ""), zone)),
|
||||
'triggers': {
|
||||
'svc_systemd:bind9:reload',
|
||||
},
|
||||
'needs': {
|
||||
'pkg_apt:bind9'
|
||||
},
|
||||
}
|
||||
|
||||
primary_zones.union(set(node.metadata.get('bind', {}).get('zones_primary', {}).keys()))
|
||||
|
||||
files['/etc/bind/named.conf.local'] = {
|
||||
'content_type': 'mako',
|
||||
'context': {
|
||||
'primary_zones': list(primary_zones),
|
||||
},
|
||||
'group': 'bind',
|
||||
'triggers': {
|
||||
'svc_systemd:bind9:reload',
|
||||
},
|
||||
'needs': {
|
||||
'pkg_apt:bind9',
|
||||
},
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
from bundlewrap.metadata import atomic
|
||||
|
||||
|
||||
defaults = {
|
||||
'icinga2_api': {
|
||||
'bind': {
|
||||
'services': {
|
||||
'BIND PROCESS': {
|
||||
'command_on_monitored_host': '/usr/lib/nagios/plugins/check_procs -C named -c 1:1',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@metadata_reactor
|
||||
def port_checks(metadata):
|
||||
services = {}
|
||||
|
||||
for interface in metadata.get('bind/listen', set()):
|
||||
services[f'BIND PORT {interface}'] = {
|
||||
'check_command': 'tcp',
|
||||
'vars.tcp_address': metadata.get(f'interfaces/{interface}/ip_addresses')[0],
|
||||
'vars.tcp_port': 53,
|
||||
}
|
||||
|
||||
return {
|
||||
'icinga2_api': {
|
||||
'bind': {
|
||||
'services': services,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@metadata_reactor
|
||||
def generate_dns_entries_for_nodes(metadata):
|
||||
results = set()
|
||||
|
||||
for rnode in repo.nodes:
|
||||
node_name_split = rnode.name.split('.')
|
||||
node_name_split.reverse()
|
||||
dns_name = '.'.join(node_name_split)
|
||||
ip4 = None
|
||||
ip6 = None
|
||||
|
||||
# We only need this for GCE, because machines over there don't
|
||||
# have a public ipv4 address.
|
||||
if rnode.metadata.get('external_ipv4', None):
|
||||
ip4 = rnode.metadata.get('external_ipv4')
|
||||
|
||||
for iface, config in sorted(rnode.metadata.get('interfaces', {}).items()):
|
||||
if not ip4 and 'ipv4' in config:
|
||||
ip4 = sorted(config['ipv4'])[0]
|
||||
|
||||
if not ip6 and 'ipv6' in config:
|
||||
ip6 = sorted(config['ipv6'])[0]
|
||||
|
||||
if ip4:
|
||||
results.add('{} IN A {}'.format(dns_name, ip4))
|
||||
|
||||
if ip6:
|
||||
results.add('{} IN AAAA {}'.format(dns_name, ip6))
|
||||
|
||||
return {
|
||||
'bind': {
|
||||
'zones_primary': {
|
||||
'kunbox.net': {
|
||||
'records': results,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
pkg_apt = {
|
||||
'postgresql-11': {},
|
||||
'postgresql-client-11': {},
|
||||
'postgresql-server-dev-11': {},
|
||||
}
|
||||
|
||||
if node.has_bundle('zfs'):
|
||||
|
|
2
bundles/powerdns/files/bind.conf
Normal file
2
bundles/powerdns/files/bind.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
launch+=bind
|
||||
bind-config=/etc/powerdns/named.conf
|
6
bundles/powerdns/files/named.conf
Normal file
6
bundles/powerdns/files/named.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
% for zone in sorted(zones):
|
||||
zone "${zone}" {
|
||||
file "/var/lib/powerdns/zones/${zone}";
|
||||
type native;
|
||||
};
|
||||
% endfor
|
28
bundles/powerdns/files/pdns.conf
Normal file
28
bundles/powerdns/files/pdns.conf
Normal file
|
@ -0,0 +1,28 @@
|
|||
launch=
|
||||
include-dir=/etc/powerdns/pdns.d
|
||||
|
||||
api=yes
|
||||
api-key=${api_key}
|
||||
webserver=yes
|
||||
|
||||
disable-syslog=yes
|
||||
log-timestamp=no
|
||||
|
||||
max-tcp-connections=500
|
||||
max-tcp-connections-per-client=10
|
||||
|
||||
security-poll-suffix=
|
||||
|
||||
server-id=${my_hostname}
|
||||
|
||||
default-ttl=60
|
||||
|
||||
% if is_secondary:
|
||||
# Primary servers: ${', '.join(sorted(my_primary_servers['nodes']))}
|
||||
slave=yes
|
||||
superslave=yes
|
||||
allow-notify-from=${','.join(sorted(my_primary_servers['ips']))}
|
||||
% else:
|
||||
allow-notify-from=
|
||||
master=yes
|
||||
% endif
|
6
bundles/powerdns/files/pgsql.conf
Normal file
6
bundles/powerdns/files/pgsql.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
launch+=gpgsql
|
||||
gpgsql-host=localhost
|
||||
gpgsql-port=5432
|
||||
gpgsql-dbname=powerdns
|
||||
gpgsql-user=powerdns
|
||||
gpgsql-password=${password}
|
105
bundles/powerdns/files/schema.pgsql.sql
Normal file
105
bundles/powerdns/files/schema.pgsql.sql
Normal file
|
@ -0,0 +1,105 @@
|
|||
-- 4.3 schema, https://doc.powerdns.com/authoritative/backends/generic-postgresql.html
|
||||
|
||||
CREATE TABLE domains (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
master VARCHAR(128) DEFAULT NULL,
|
||||
last_check INT DEFAULT NULL,
|
||||
type VARCHAR(6) NOT NULL,
|
||||
notified_serial BIGINT DEFAULT NULL,
|
||||
account VARCHAR(40) DEFAULT NULL,
|
||||
CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT)))
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX name_index ON domains(name);
|
||||
|
||||
ALTER TABLE domains OWNER TO ${user};
|
||||
|
||||
CREATE TABLE records (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
domain_id INT DEFAULT NULL,
|
||||
name VARCHAR(255) DEFAULT NULL,
|
||||
type VARCHAR(10) DEFAULT NULL,
|
||||
content VARCHAR(65535) DEFAULT NULL,
|
||||
ttl INT DEFAULT NULL,
|
||||
prio INT DEFAULT NULL,
|
||||
change_date INT DEFAULT NULL,
|
||||
disabled BOOL DEFAULT 'f',
|
||||
ordername VARCHAR(255),
|
||||
auth BOOL DEFAULT 't',
|
||||
CONSTRAINT domain_exists
|
||||
FOREIGN KEY(domain_id) REFERENCES domains(id)
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT)))
|
||||
);
|
||||
|
||||
CREATE INDEX rec_name_index ON records(name);
|
||||
CREATE INDEX nametype_index ON records(name,type);
|
||||
CREATE INDEX domain_id ON records(domain_id);
|
||||
CREATE INDEX recordorder ON records (domain_id, ordername text_pattern_ops);
|
||||
|
||||
ALTER TABLE records OWNER TO ${user};
|
||||
|
||||
CREATE TABLE supermasters (
|
||||
ip INET NOT NULL,
|
||||
nameserver VARCHAR(255) NOT NULL,
|
||||
account VARCHAR(40) NOT NULL,
|
||||
PRIMARY KEY(ip, nameserver)
|
||||
);
|
||||
|
||||
ALTER TABLE supermasters OWNER TO ${user};
|
||||
|
||||
CREATE TABLE comments (
|
||||
id SERIAL PRIMARY KEY,
|
||||
domain_id INT NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
type VARCHAR(10) NOT NULL,
|
||||
modified_at INT NOT NULL,
|
||||
account VARCHAR(40) DEFAULT NULL,
|
||||
comment VARCHAR(65535) NOT NULL,
|
||||
CONSTRAINT domain_exists
|
||||
FOREIGN KEY(domain_id) REFERENCES domains(id)
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT)))
|
||||
);
|
||||
|
||||
CREATE INDEX comments_domain_id_idx ON comments (domain_id);
|
||||
CREATE INDEX comments_name_type_idx ON comments (name, type);
|
||||
CREATE INDEX comments_order_idx ON comments (domain_id, modified_at);
|
||||
|
||||
ALTER TABLE comments OWNER TO ${user};
|
||||
|
||||
CREATE TABLE domainmetadata (
|
||||
id SERIAL PRIMARY KEY,
|
||||
domain_id INT REFERENCES domains(id) ON DELETE CASCADE,
|
||||
kind VARCHAR(32),
|
||||
content TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX domainidmetaindex ON domainmetadata(domain_id);
|
||||
|
||||
ALTER TABLE domainmetadata OWNER TO ${user};
|
||||
|
||||
CREATE TABLE cryptokeys (
|
||||
id SERIAL PRIMARY KEY,
|
||||
domain_id INT REFERENCES domains(id) ON DELETE CASCADE,
|
||||
flags INT NOT NULL,
|
||||
active BOOL,
|
||||
content TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX domainidindex ON cryptokeys(domain_id);
|
||||
ALTER TABLE cryptokeys OWNER TO ${user};
|
||||
|
||||
|
||||
CREATE TABLE tsigkeys (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
algorithm VARCHAR(50),
|
||||
secret VARCHAR(255),
|
||||
CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT)))
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);
|
||||
|
||||
ALTER TABLE tsigkeys OWNER TO ${user};
|
163
bundles/powerdns/items.py
Normal file
163
bundles/powerdns/items.py
Normal file
|
@ -0,0 +1,163 @@
|
|||
from datetime import datetime
|
||||
from os import listdir
|
||||
from os.path import isfile, join
|
||||
from subprocess import check_output
|
||||
|
||||
zone_path = join(repo.path, 'data', 'powerdns', 'files', 'bind-zones')
|
||||
|
||||
ZONE_HEADER = """
|
||||
; _ ____ _ _ _____ _ _ _ _ ____
|
||||
; / \\ / ___| | | |_ _| | | | \\ | |/ ___|
|
||||
; / _ \\| | | |_| | | | | | | | \\| | | _
|
||||
; / ___ \\ |___| _ | | | | |_| | |\\ | |_| |
|
||||
; /_/ \\_\\____|_| |_| |_| \\___/|_| \\_|\\____|
|
||||
;
|
||||
; --> Diese Datei wird von BundleWrap verwaltet! <--
|
||||
|
||||
$TTL 60
|
||||
@ IN SOA ns-1.kunbox.net. hostmaster.kunbox.net. (
|
||||
{serial}
|
||||
3600
|
||||
3600
|
||||
86400
|
||||
300
|
||||
)
|
||||
"""
|
||||
for rnode in sorted(repo.nodes_in_group('dns')):
|
||||
ZONE_HEADER += '@ IN NS {}.\n'.format(rnode.metadata.get('powerdns', {}).get('my_hostname', rnode.hostname))
|
||||
|
||||
directories = {
|
||||
'/etc/powerdns/pdns.d': {
|
||||
'purge': True,
|
||||
'needs': {
|
||||
'pkg_apt:pdns-server',
|
||||
'pkg_apt:pdns-backend-bind',
|
||||
'pkg_apt:pdns-backend-pgsql',
|
||||
},
|
||||
'triggers': {
|
||||
'svc_systemd:pdns:restart',
|
||||
},
|
||||
},
|
||||
'/var/lib/powerdns/zones': {
|
||||
'purge': True,
|
||||
'needs': {
|
||||
'pkg_apt:pdns-backend-bind',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
files = {
|
||||
'/etc/powerdns/pdns.conf': {
|
||||
'content_type': 'mako',
|
||||
'context': {
|
||||
'api_key': node.metadata['powerdns']['api_key'],
|
||||
'my_hostname': node.metadata['powerdns'].get('my_hostname', node.name),
|
||||
'is_secondary': node.metadata['powerdns'].get('is_secondary', False),
|
||||
'my_primary_servers': node.metadata['powerdns'].get('my_primary_servers', {}),
|
||||
},
|
||||
'needs': {
|
||||
'pkg_apt:pdns-server',
|
||||
},
|
||||
'triggers': {
|
||||
'svc_systemd:pdns:restart',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
svc_systemd = {
|
||||
'pdns': {
|
||||
'needs': {
|
||||
'directory:',
|
||||
'file:',
|
||||
'pkg_apt:pdns-server',
|
||||
'pkg_apt:pdns-backend-bind',
|
||||
'pkg_apt:pdns-backend-pgsql',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
actions = {
|
||||
'powerdns_reload_zones': {
|
||||
'triggered': True,
|
||||
'command': 'pdns_control rediscover; pdns_control reload',
|
||||
'needs': {
|
||||
'svc_systemd:pdns',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if node.metadata['powerdns'].get('features', {}).get('bind', False):
|
||||
primary_zones = set()
|
||||
for zone in listdir(zone_path):
|
||||
if not isfile(join(zone_path, zone)) or zone.startswith(".") or zone.startswith("_"):
|
||||
continue
|
||||
|
||||
try:
|
||||
output = check_output(['git', 'log', '-1', '--pretty=%ci', join(zone_path, zone)]).decode('utf-8').strip()
|
||||
serial = datetime.strptime(output, '%Y-%m-%d %H:%M:%S %z').strftime('%y%m%d%H%M')
|
||||
except:
|
||||
serial = datetime.now().strftime('%y%m%d0000')
|
||||
|
||||
primary_zones.add(zone)
|
||||
|
||||
files["/var/lib/powerdns/zones/{}".format(zone)] = {
|
||||
'content_type': 'mako',
|
||||
'context': {
|
||||
'header': ZONE_HEADER.format(serial=serial),
|
||||
'metadata_records': node.metadata.get('powerdns', {}).get('bind-zones', {}).get(zone, {}).get('records', []),
|
||||
},
|
||||
'source': 'bind-zones/{}'.format(zone),
|
||||
'triggers': {
|
||||
'action:powerdns_reload_zones',
|
||||
},
|
||||
}
|
||||
|
||||
files['/etc/powerdns/pdns.d/bind.conf'] = {
|
||||
'needs': {
|
||||
'pkg_apt:pdns-backend-bind',
|
||||
},
|
||||
'triggers': {
|
||||
'action:powerdns_reload_zones',
|
||||
},
|
||||
}
|
||||
|
||||
files['/etc/powerdns/named.conf'] = {
|
||||
'content_type': 'mako',
|
||||
'context': {
|
||||
'zones': primary_zones,
|
||||
},
|
||||
'needs': {
|
||||
'pkg_apt:pdns-backend-bind',
|
||||
},
|
||||
'triggers': {
|
||||
'action:powerdns_reload_zones',
|
||||
},
|
||||
}
|
||||
|
||||
if node.metadata['powerdns'].get('features', {}).get('pgsql', False):
|
||||
files['/etc/powerdns/pdns.d/pgsql.conf'] = {
|
||||
'content_type': 'mako',
|
||||
'context': {
|
||||
'password': node.metadata['postgresql']['users']['powerdns']['password'],
|
||||
},
|
||||
'needs': {
|
||||
'pkg_apt:pdns-backend-pgsql',
|
||||
},
|
||||
'triggers': {
|
||||
'action:powerdns_reload_zones',
|
||||
},
|
||||
}
|
||||
|
||||
files['/etc/powerdns/schema.pgsql.sql'] = {}
|
||||
|
||||
actions['powerdns_load_pgsql_schema'] = {
|
||||
'command': node.metadata['postgresql']['users']['powerdns']['password'].format_into('PGPASSWORD={} psql -h 127.0.0.1 -d powerdns -U powerdns -w < /etc/powerdns/schema.pgsql.sql'),
|
||||
'unless': 'sudo -u postgres psql -d powerdns -c "\dt" | grep domains 2>&1 >/dev/null',
|
||||
'needs': {
|
||||
'bundle:postgresql',
|
||||
'file:/etc/powerdns/schema.pgsql.sql',
|
||||
},
|
||||
'needed_by': {
|
||||
'svc_systemd:pdns',
|
||||
},
|
||||
}
|
91
bundles/powerdns/metadata.py
Normal file
91
bundles/powerdns/metadata.py
Normal file
|
@ -0,0 +1,91 @@
|
|||
from bundlewrap.exceptions import NoSuchGroup
|
||||
|
||||
defaults = {
|
||||
'apt': {
|
||||
'packages': {
|
||||
'pdns-server': {},
|
||||
'pdns-tools': {},
|
||||
'pdns-backend-bind': {},
|
||||
'pdns-backend-pgsql': {},
|
||||
},
|
||||
},
|
||||
'powerdns': {
|
||||
'api_key': repo.vault.password_for('{} powerdns api'.format(node.name)),
|
||||
},
|
||||
'postgresql': {
|
||||
'users': {
|
||||
'powerdns': {
|
||||
'password': repo.vault.password_for('{} postgresql powerdns'.format(node.name)),
|
||||
},
|
||||
},
|
||||
'databases': {
|
||||
'powerdns': {
|
||||
'owner': 'powerdns',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@metadata_reactor
|
||||
def get_ips_of_primary_nameservers(metadata):
|
||||
if not metadata.get('powerdns/is_secondary', False):
|
||||
return {}
|
||||
|
||||
ips = set()
|
||||
nodes = set()
|
||||
for rnode in repo.nodes_in_group('dns'):
|
||||
if not rnode.metadata.get('powerdns/is_secondary', False):
|
||||
ips.update({
|
||||
str(ip) for ip in repo.libs.tools.resolve_identifier(repo, rnode.name)
|
||||
})
|
||||
nodes.add(rnode.name)
|
||||
|
||||
return {
|
||||
'powerdns': {
|
||||
'my_primary_servers': {
|
||||
'ips': ips,
|
||||
'nodes': nodes,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@metadata_reactor
|
||||
def generate_dns_entries_for_nodes(metadata):
|
||||
results = set()
|
||||
|
||||
for rnode in repo.nodes:
|
||||
node_name_split = rnode.name.split('.')
|
||||
node_name_split.reverse()
|
||||
dns_name = '.'.join(node_name_split)
|
||||
ip4 = None
|
||||
ip6 = None
|
||||
|
||||
# We only need this for GCE, because machines over there don't
|
||||
# have a public ipv4 address.
|
||||
if rnode.metadata.get('external_ipv4', None):
|
||||
ip4 = rnode.metadata.get('external_ipv4')
|
||||
|
||||
for iface, config in sorted(rnode.metadata.get('interfaces', {}).items()):
|
||||
if not ip4 and 'ipv4' in config:
|
||||
ip4 = sorted(config['ipv4'])[0]
|
||||
|
||||
if not ip6 and 'ipv6' in config:
|
||||
ip6 = sorted(config['ipv6'])[0]
|
||||
|
||||
if ip4:
|
||||
results.add('{} IN A {}'.format(dns_name, ip4))
|
||||
|
||||
if ip6:
|
||||
results.add('{} IN AAAA {}'.format(dns_name, ip6))
|
||||
|
||||
return {
|
||||
'powerdns': {
|
||||
'bind-zones': {
|
||||
'kunbox.net': {
|
||||
'records': results,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
14
bundles/powerdnsadmin/files/config.py
Normal file
14
bundles/powerdnsadmin/files/config.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
SALT = '${repo.vault.decrypt('encrypt$gAAAAABfidFVqVEgWvlXgP-GSQUgVtcTxzoZx2G8VYWHaGKRpgaLDchlTRcKwqgvfG5orNpXt7aDd5i2aehi6cvIlxYNdL87twfVhDLBDho8j-Uz5Vga8-9cEzEZULl5pFCIcRlYUCKyEIOcdXSaLCM3p8pGjrh-O8_g49rbADKmLFoJx2vVTVs=')}'
|
||||
SECRET_KEY = '${repo.vault.password_for('{} powerdnsadmin secret_key'.format(node.name))}'
|
||||
BIND_ADDRESS = '127.0.0.1'
|
||||
PORT = 9191
|
||||
OFFLINE_MODE = True
|
||||
|
||||
SQLA_DB_USER = 'powerdnsadmin'
|
||||
SQLA_DB_PASSWORD = '${node.metadata['postgresql']['users']['powerdnsadmin']['password']}'
|
||||
SQLA_DB_HOST = '127.0.0.1'
|
||||
SQLA_DB_NAME = 'powerdnsadmin'
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
||||
SQLALCHEMY_DATABASE_URI = 'postgresql://' + SQLA_DB_USER + ':' + SQLA_DB_PASSWORD + '@' + SQLA_DB_HOST + '/' + SQLA_DB_NAME
|
||||
|
||||
SAML_ENABLED = False
|
14
bundles/powerdnsadmin/files/powerdnsadmin.service
Normal file
14
bundles/powerdnsadmin/files/powerdnsadmin.service
Normal file
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=PowerDNS-Admin
|
||||
After=network.target postgresql.service
|
||||
|
||||
[Service]
|
||||
User=powerdnsadmin
|
||||
Group=powerdnsadmin
|
||||
Environment=FLASK_CONF=/opt/powerdnsadmin/config.py
|
||||
WorkingDirectory=/opt/powerdnsadmin/src
|
||||
ExecStartPre=-/bin/chown powerdnsadmin:powerdnsadmin /opt/powerdnsadmin/src/powerdnsadmin/static
|
||||
ExecStart=/opt/powerdnsadmin/venv/bin/gunicorn 'powerdnsadmin:create_app()'
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
87
bundles/powerdnsadmin/items.py
Normal file
87
bundles/powerdnsadmin/items.py
Normal file
|
@ -0,0 +1,87 @@
|
|||
assert node.has_bundle('nodejs')
|
||||
assert node.has_bundle('postgresql')
|
||||
|
||||
directories = {
|
||||
'/opt/powerdnsadmin/src': {},
|
||||
}
|
||||
|
||||
git_deploy = {
|
||||
'/opt/powerdnsadmin/src': {
|
||||
'repo': 'https://github.com/ngoduykhanh/PowerDNS-Admin.git',
|
||||
'rev': 'master',
|
||||
'triggers': {
|
||||
'action:powerdnsadmin_install_deps',
|
||||
'action:powerdnsadmin_upgrade_database',
|
||||
'action:powerdnsadmin_compile_assets',
|
||||
'svc_systemd:powerdnsadmin:restart',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
files = {
|
||||
'/opt/powerdnsadmin/config.py': {
|
||||
'content_type': 'mako',
|
||||
},
|
||||
'/etc/systemd/system/powerdnsadmin.service': {
|
||||
'triggers': {
|
||||
'action:systemd-reload',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
actions = {
|
||||
'powerdnsadmin_create_virtualenv': {
|
||||
'command': '/usr/bin/python3 -m virtualenv -p python3 /opt/powerdnsadmin/venv/',
|
||||
'unless': 'test -d /opt/powerdnsadmin/venv/',
|
||||
'needs': {
|
||||
'directory:/opt/powerdnsadmin', # provided by bundle:users
|
||||
},
|
||||
},
|
||||
'powerdnsadmin_install_deps': {
|
||||
'triggered': True,
|
||||
'command': '/opt/powerdnsadmin/venv/bin/pip install -r /opt/powerdnsadmin/src/requirements.txt',
|
||||
'needs': {
|
||||
'action:powerdnsadmin_create_virtualenv',
|
||||
'pkg_apt:',
|
||||
},
|
||||
},
|
||||
'powerdnsadmin_install_deps': {
|
||||
'triggered': True,
|
||||
'command': '/opt/powerdnsadmin/venv/bin/pip install -r /opt/powerdnsadmin/src/requirements.txt',
|
||||
'needs': {
|
||||
'action:powerdnsadmin_create_virtualenv',
|
||||
'pkg_apt:',
|
||||
},
|
||||
},
|
||||
'powerdnsadmin_upgrade_database': {
|
||||
'triggered': True,
|
||||
'command': 'FLASK_CONF=/opt/powerdnsadmin/config.py FLASK_APP=/opt/powerdnsadmin/src/powerdnsadmin/__init__.py /opt/powerdnsadmin/venv/bin/flask db upgrade',
|
||||
# TODO unless
|
||||
'needs': {
|
||||
'action:powerdnsadmin_install_deps',
|
||||
'bundle:postgresql',
|
||||
'pkg_apt:',
|
||||
},
|
||||
},
|
||||
'powerdnsadmin_compile_assets': {
|
||||
'triggered': True,
|
||||
'command': 'cd /opt/powerdnsadmin/src && yarn install --pure-lockfile && FLASK_APP=/opt/powerdnsadmin/src/powerdnsadmin/__init__.py /opt/powerdnsadmin/venv/bin/flask assets build',
|
||||
'needs': {
|
||||
'action:powerdnsadmin_install_deps',
|
||||
'pkg_apt:',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
svc_systemd = {
|
||||
'powerdnsadmin': {
|
||||
'needs': {
|
||||
'file:/opt/powerdnsadmin/config.py',
|
||||
'file:/etc/systemd/system/powerdnsadmin.service',
|
||||
'git_deploy:/opt/powerdnsadmin/src',
|
||||
'action:powerdnsadmin_install_deps',
|
||||
'action:powerdnsadmin_upgrade_database',
|
||||
'action:powerdnsadmin_compile_assets',
|
||||
},
|
||||
},
|
||||
}
|
35
bundles/powerdnsadmin/metadata.py
Normal file
35
bundles/powerdnsadmin/metadata.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
defaults = {
|
||||
'apt': {
|
||||
'packages': {
|
||||
'default-libmysqlclient-dev': {},
|
||||
'libffi-dev': {},
|
||||
'libldap2-dev': {},
|
||||
'libsasl2-dev': {},
|
||||
'libssl-dev': {},
|
||||
'libxml2-dev': {},
|
||||
'libxmlsec1-dev': {},
|
||||
'libxslt1-dev': {},
|
||||
'pkg-config': {},
|
||||
'python3-psycopg2': {},
|
||||
'python3-wheel': {},
|
||||
},
|
||||
},
|
||||
'users': {
|
||||
'powerdnsadmin': {
|
||||
'home': '/opt/powerdnsadmin',
|
||||
},
|
||||
},
|
||||
'postgresql': {
|
||||
'users': {
|
||||
'powerdnsadmin': {
|
||||
'password': repo.vault.password_for('{} postgresql powerdnsadmin'.format(node.name)),
|
||||
},
|
||||
},
|
||||
'databases': {
|
||||
'powerdnsadmin': {
|
||||
'owner': 'powerdnsadmin',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
${header}
|
||||
|
||||
$ORIGIN franzi.business.
|
||||
|
||||
@ IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
IN MX 10 mx0.kunbox.net.
|
||||
IN TXT v=spf1 mx ~all
|
||||
|
||||
* IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
|
||||
grafana IN A 165.232.105.69
|
||||
IN AAAA 2a03:b0c0:1:e0::627:8001
|
||||
|
||||
icinga IN A 165.232.42.173
|
||||
IN AAAA 2a03:b0c0:1:e0::665:8001
|
||||
|
||||
sewfile IN A 116.203.205.248
|
||||
IN AAAA 2a01:4f8:c0c:c71b::1
|
||||
IN TXT v=spf1 a mx ~all
|
||||
|
||||
|
||||
_matrix._tcp IN SRV 10 10 8448 matrix
|
||||
|
||||
2019._domainkey IN TXT v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwkg6UAcu3V98hal1UVf6yB0WT1CKDS0AK83CUlSP8bUwraPxkxK1nkQOUsmjbQs6a3FhdsKprMi32GeUaTVvZg81JIybPk3jNugfNWfSjs2TXPomYu+XD2pmmbR3cZlzC5NGR2nmBFt/P/S2ihPHj35KziiBIwK1TdvOi1M2+upCjK33Icco0ByCm0gJpD2O0cbqcBcUKqd6X440vYhNXH1ygp0e91P0iRnvS9sg6yD0xjD8kD6j/8GfxBY+9bpU3EvDoBgyJSbjw5b6PUVJbKMXzw1NIRNj0SXKs5BakjS8+7u62vR11IPCYRwy+yr0rDT0tNegM7gStIIgoTpOoQIDAQAB
|
||||
_dmarc IN TXT v=DMARC1; p=none; rua=mailto:postmaster@kunsmann.eu; ruf=mailto:postmaster@kunsmann.eu; fo=0:d:s; adkim=r; aspf=r
|
||||
_token._dnswl IN TXT gg3mbwjx9bbuo5osvhq7oz6bc881wcmc
|
|
@ -1,27 +0,0 @@
|
|||
${header}
|
||||
|
||||
$ORIGIN kunbox.net.
|
||||
|
||||
@ IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
|
||||
; Needs to have a working Mail address, otherwise Telekom goes mimimi
|
||||
IN MX 10 mx0
|
||||
IN TXT v=spf1 mx ~all
|
||||
|
||||
; Mail servers
|
||||
mx0 IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
*.mx0 IN CNAME mx0
|
||||
|
||||
% for record in sorted(metadata_records):
|
||||
${record}
|
||||
% endfor
|
||||
|
||||
2019._domainkey IN TXT v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwkg6UAcu3V98hal1UVf6yB0WT1CKDS0AK83CUlSP8bUwraPxkxK1nkQOUsmjbQs6a3FhdsKprMi32GeUaTVvZg81JIybPk3jNugfNWfSjs2TXPomYu+XD2pmmbR3cZlzC5NGR2nmBFt/P/S2ihPHj35KziiBIwK1TdvOi1M2+upCjK33Icco0ByCm0gJpD2O0cbqcBcUKqd6X440vYhNXH1ygp0e91P0iRnvS9sg6yD0xjD8kD6j/8GfxBY+9bpU3EvDoBgyJSbjw5b6PUVJbKMXzw1NIRNj0SXKs5BakjS8+7u62vR11IPCYRwy+yr0rDT0tNegM7gStIIgoTpOoQIDAQAB
|
||||
_dmarc IN TXT v=DMARC1; p=none; rua=mailto:postmaster@kunsmann.eu; ruf=mailto:postmaster@kunsmann.eu; fo=0:d:s; adkim=r; aspf=r
|
||||
_token._dnswl IN TXT 6akc10htbgmg56e072w0w2n0wql4oezu
|
||||
|
||||
f2k1.de._report._dmarc IN TXT v=DMARC1
|
||||
franzi.business._report._dmarc IN TXT v=DMARC1
|
||||
kunsmann.eu._report._dmarc IN TXT v=DMARC1
|
|
@ -1,15 +0,0 @@
|
|||
${header}
|
||||
|
||||
$ORIGIN kunsmann.eu.
|
||||
|
||||
@ IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
IN MX 10 mx0.kunbox.net.
|
||||
IN TXT v=spf1 a mx ~all
|
||||
|
||||
* IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
|
||||
2019._domainkey IN TXT v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwkg6UAcu3V98hal1UVf6yB0WT1CKDS0AK83CUlSP8bUwraPxkxK1nkQOUsmjbQs6a3FhdsKprMi32GeUaTVvZg81JIybPk3jNugfNWfSjs2TXPomYu+XD2pmmbR3cZlzC5NGR2nmBFt/P/S2ihPHj35KziiBIwK1TdvOi1M2+upCjK33Icco0ByCm0gJpD2O0cbqcBcUKqd6X440vYhNXH1ygp0e91P0iRnvS9sg6yD0xjD8kD6j/8GfxBY+9bpU3EvDoBgyJSbjw5b6PUVJbKMXzw1NIRNj0SXKs5BakjS8+7u62vR11IPCYRwy+yr0rDT0tNegM7gStIIgoTpOoQIDAQAB
|
||||
_dmarc IN TXT v=DMARC1; p=none; rua=mailto:postmaster@kunsmann.eu; ruf=mailto:postmaster@kunsmann.eu; fo=0:d:s; adkim=r; aspf=r
|
||||
_token._dnswl IN TXT 5mx0rv9ru8s1zz4tf4xlt48osh09czmg
|
28
data/powerdns/files/bind-zones/franzi.business
Normal file
28
data/powerdns/files/bind-zones/franzi.business
Normal file
|
@ -0,0 +1,28 @@
|
|||
${header}
|
||||
|
||||
$ORIGIN franzi.business.
|
||||
|
||||
@ IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
IN MX 10 mx0.kunbox.net.
|
||||
IN TXT "v=spf1 mx ~all"
|
||||
|
||||
* IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
|
||||
grafana IN A 165.232.105.69
|
||||
IN AAAA 2a03:b0c0:1:e0::627:8001
|
||||
|
||||
icinga IN A 165.232.42.173
|
||||
IN AAAA 2a03:b0c0:1:e0::665:8001
|
||||
|
||||
sewfile IN A 116.203.205.248
|
||||
IN AAAA 2a01:4f8:c0c:c71b::1
|
||||
IN TXT "v=spf1 a mx ~all"
|
||||
|
||||
|
||||
_matrix._tcp IN SRV 10 10 8448 matrix
|
||||
|
||||
2019._domainkey IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwkg6UAcu3V98hal1UVf6yB0WT1CKDS0AK83CUlSP8bUwraPxkxK1nkQOUsmjbQs6a3FhdsKprMi32GeUaTVvZg81JIybPk3jNugfNWfSjs2TXPomYu+XD2pmmbR3cZlzC5NGR2nmBFt/P/S2ihPHj35KziiBIwK1TdvOi1M2+upCjK33Icco0ByCm0gJpD2O0cbqcBcUKqd6X440vYhNXH1ygp0e91P0iRnvS9sg6yD0xjD8kD6j/8GfxBY+9bpU3EvDoBgyJSbjw5b6PUVJbKMXzw1NIRNj0SXKs5BakjS8+7u62vR11IPCYRwy+yr0rDT0tNegM7gStIIgoTpOoQIDAQAB"
|
||||
_dmarc IN TXT "v=DMARC1; p=none; rua=mailto:postmaster@kunsmann.eu; ruf=mailto:postmaster@kunsmann.eu; fo=0:d:s; adkim=r; aspf=r"
|
||||
_token._dnswl IN TXT "gg3mbwjx9bbuo5osvhq7oz6bc881wcmc"
|
30
data/powerdns/files/bind-zones/kunbox.net
Normal file
30
data/powerdns/files/bind-zones/kunbox.net
Normal file
|
@ -0,0 +1,30 @@
|
|||
${header}
|
||||
|
||||
$ORIGIN kunbox.net.
|
||||
|
||||
@ IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
|
||||
; Needs to have a working Mail address, otherwise Telekom goes mimimi
|
||||
IN MX 10 mx0
|
||||
IN TXT "v=spf1 mx ~all"
|
||||
|
||||
; Mail servers
|
||||
mx0 IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
*.mx0 IN CNAME mx0
|
||||
|
||||
; Nameservers
|
||||
ns-1 IN A 34.89.208.78
|
||||
|
||||
% for record in sorted(metadata_records):
|
||||
${record}
|
||||
% endfor
|
||||
|
||||
2019._domainkey IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwkg6UAcu3V98hal1UVf6yB0WT1CKDS0AK83CUlSP8bUwraPxkxK1nkQOUsmjbQs6a3FhdsKprMi32GeUaTVvZg81JIybPk3jNugfNWfSjs2TXPomYu+XD2pmmbR3cZlzC5NGR2nmBFt/P/S2ihPHj35KziiBIwK1TdvOi1M2+upCjK33Icco0ByCm0gJpD2O0cbqcBcUKqd6X440vYhNXH1ygp0e91P0iRnvS9sg6yD0xjD8kD6j/8GfxBY+9bpU3EvDoBgyJSbjw5b6PUVJbKMXzw1NIRNj0SXKs5BakjS8+7u62vR11IPCYRwy+yr0rDT0tNegM7gStIIgoTpOoQIDAQAB"
|
||||
_dmarc IN TXT "v=DMARC1; p=none; rua=mailto:postmaster@kunsmann.eu; ruf=mailto:postmaster@kunsmann.eu; fo=0:d:s; adkim=r; aspf=r"
|
||||
_token._dnswl IN TXT "6akc10htbgmg56e072w0w2n0wql4oezu"
|
||||
|
||||
f2k1.de._report._dmarc IN TXT "v=DMARC1"
|
||||
franzi.business._report._dmarc IN TXT "v=DMARC1"
|
||||
kunsmann.eu._report._dmarc IN TXT "v=DMARC1"
|
15
data/powerdns/files/bind-zones/kunsmann.eu
Normal file
15
data/powerdns/files/bind-zones/kunsmann.eu
Normal file
|
@ -0,0 +1,15 @@
|
|||
${header}
|
||||
|
||||
$ORIGIN kunsmann.eu.
|
||||
|
||||
@ IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
IN MX 10 mx0.kunbox.net.
|
||||
IN TXT "v=spf1 a mx ~all"
|
||||
|
||||
* IN A 94.130.52.224
|
||||
IN AAAA 2a01:4f8:10b:2a5f::2
|
||||
|
||||
2019._domainkey IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwkg6UAcu3V98hal1UVf6yB0WT1CKDS0AK83CUlSP8bUwraPxkxK1nkQOUsmjbQs6a3FhdsKprMi32GeUaTVvZg81JIybPk3jNugfNWfSjs2TXPomYu+XD2pmmbR3cZlzC5NGR2nmBFt/P/S2ihPHj35KziiBIwK1TdvOi1M2+upCjK33Icco0ByCm0gJpD2O0cbqcBcUKqd6X440vYhNXH1ygp0e91P0iRnvS9sg6yD0xjD8kD6j/8GfxBY+9bpU3EvDoBgyJSbjw5b6PUVJbKMXzw1NIRNj0SXKs5BakjS8+7u62vR11IPCYRwy+yr0rDT0tNegM7gStIIgoTpOoQIDAQAB"
|
||||
_dmarc IN TXT "v=DMARC1; p=none; rua=mailto:postmaster@kunsmann.eu; ruf=mailto:postmaster@kunsmann.eu; fo=0:d:s; adkim=r; aspf=r"
|
||||
_token._dnswl IN TXT "5mx0rv9ru8s1zz4tf4xlt48osh09czmg"
|
|
@ -3,7 +3,7 @@ ${header}
|
|||
$ORIGIN trans-agenda.eu.
|
||||
|
||||
@ IN MX 10 mx0.kunbox.net.
|
||||
IN TXT v=spf1 a mx ~all
|
||||
IN TXT "v=spf1 a mx ~all"
|
||||
|
||||
part.of.the IN A 94.130.52.224
|
||||
part.of.the IN AAAA 2a01:4f8:10b:2a5f::2
|
|
@ -7,6 +7,17 @@ groups['webserver'] = {
|
|||
|
||||
groups['dns'] = {
|
||||
'bundles': {
|
||||
'bind',
|
||||
'postgresql',
|
||||
'powerdns',
|
||||
},
|
||||
'metadata': {
|
||||
'powerdns': {
|
||||
'features': {
|
||||
'bind': True,
|
||||
'pgsql': True,
|
||||
},
|
||||
# Overridden in node metadata for primary server
|
||||
'is_secondary': True,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
31
libs/tools.py
Normal file
31
libs/tools.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
from bundlewrap.exceptions import NoSuchGroup, NoSuchNode
|
||||
from ipaddress import ip_address
|
||||
|
||||
def resolve_identifier(repo, identifier):
|
||||
"""
|
||||
Try to resolve an identifier (group or node). Return a set of ip
|
||||
addresses valid for this identifier.
|
||||
"""
|
||||
try:
|
||||
nodes = {repo.get_node(identifier)}
|
||||
except NoSuchNode:
|
||||
try:
|
||||
nodes = repo.nodes_in_group(identifier)
|
||||
except NoSuchGroup:
|
||||
try:
|
||||
return {ip_address(identifier)}
|
||||
except:
|
||||
return set()
|
||||
|
||||
found_ips = set()
|
||||
for node in nodes:
|
||||
for interface, config in node.metadata.get('interfaces', {}).items():
|
||||
for ip in config.get('ipv4', set()):
|
||||
found_ips.add(ip_address(ip))
|
||||
for ip in config.get('ipv4', set()):
|
||||
found_ips.add(ip_address(ip))
|
||||
|
||||
if node.metadata.get('external_ipv4'):
|
||||
found_ips.add(ip_address(node.metadata.get('external_ipv4')))
|
||||
|
||||
return found_ips
|
11
nodes/a.ns14.net.py
Normal file
11
nodes/a.ns14.net.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
# This node is not actually part of this repository, it's a DNS server
|
||||
# managed by AutoDNS. It needs a node file, because we're using that to
|
||||
# auto-generate DNS configs.
|
||||
|
||||
nodes['a.ns14.net'] = {
|
||||
'hostname': 'a.ns14.net',
|
||||
'dummy': True,
|
||||
'groups': {
|
||||
'dns',
|
||||
},
|
||||
}
|
11
nodes/b.ns14.net.py
Normal file
11
nodes/b.ns14.net.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
# This node is not actually part of this repository, it's a DNS server
|
||||
# managed by AutoDNS. It needs a node file, because we're using that to
|
||||
# auto-generate DNS configs.
|
||||
|
||||
nodes['b.ns14.net'] = {
|
||||
'hostname': 'b.ns14.net',
|
||||
'dummy': True,
|
||||
'groups': {
|
||||
'dns',
|
||||
},
|
||||
}
|
11
nodes/c.ns14.net.py
Normal file
11
nodes/c.ns14.net.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
# This node is not actually part of this repository, it's a DNS server
|
||||
# managed by AutoDNS. It needs a node file, because we're using that to
|
||||
# auto-generate DNS configs.
|
||||
|
||||
nodes['c.ns14.net'] = {
|
||||
'hostname': 'c.ns14.net',
|
||||
'dummy': True,
|
||||
'groups': {
|
||||
'dns',
|
||||
},
|
||||
}
|
11
nodes/d.ns14.net.py
Normal file
11
nodes/d.ns14.net.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
# This node is not actually part of this repository, it's a DNS server
|
||||
# managed by AutoDNS. It needs a node file, because we're using that to
|
||||
# auto-generate DNS configs.
|
||||
|
||||
nodes['d.ns14.net'] = {
|
||||
'hostname': 'd.ns14.net',
|
||||
'dummy': True,
|
||||
'groups': {
|
||||
'dns',
|
||||
},
|
||||
}
|
|
@ -1,9 +1,14 @@
|
|||
# ns-3.kunbox.net
|
||||
# ns-1.kunbox.net
|
||||
# Frankfurt, Germany
|
||||
|
||||
nodes['gce.bind01'] = {
|
||||
'bundles': {
|
||||
'nodejs',
|
||||
'powerdnsadmin',
|
||||
},
|
||||
'groups': {
|
||||
'dns',
|
||||
'webserver',
|
||||
},
|
||||
'metadata': {
|
||||
'interfaces': {
|
||||
|
@ -15,6 +20,22 @@ nodes['gce.bind01'] = {
|
|||
},
|
||||
},
|
||||
'external_ipv4': '34.89.208.78',
|
||||
'nginx': {
|
||||
'vhosts': {
|
||||
'ns-1.kunbox.net': {
|
||||
'proxy': {
|
||||
'/': {
|
||||
'target': 'http://127.0.0.1:8000/',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'powerdns': {
|
||||
'is_secondary': False,
|
||||
'secondary_nameservers': 'dns',
|
||||
'my_hostname': 'ns-1.kunbox.net',
|
||||
},
|
||||
'vm': {
|
||||
'cpu': 1,
|
||||
'ram': 1,
|
||||
|
|
Loading…
Reference in a new issue