Browse Source

added init script to init zones for DHCP

tags/v2.0.0
Robin THONI 2 years ago
parent
commit
320feff735
2 changed files with 136 additions and 0 deletions
  1. 134
    0
      init.py
  2. 2
    0
      requirements.txt

+ 134
- 0
init.py View File

@@ -0,0 +1,134 @@
1
+#! /usr/bin/env python3
2
+
3
+import argparse
4
+import docker
5
+import sys
6
+import re
7
+
8
+def get_zones(container):
9
+    out = container.exec_run(['pdnsutil', 'list-all-zones'])
10
+    if out is not None:
11
+        out = out.decode('UTF-8') # bytres to string
12
+        zones = out.split('\n') # convert to list, one zone per line
13
+        zones = list(filter(None, zones)) # remove any empty lines
14
+        zones = zones[0:len(zones) - 1] # remove last line 'All zonecount: xx'
15
+        return zones
16
+    return None
17
+
18
+def add_zone(container, zone):
19
+    out = container.exec_run(['pdnsutil', 'create-zone', zone])
20
+    if out is not None:
21
+        out = out.decode('UTF-8')
22
+        return out == 'Creating empty zone \'%s\'\n' % (zone) # might to strict, but as we can not get return code
23
+    return False
24
+
25
+def get_tsig_keys(container):
26
+    out = container.exec_run(['pdnsutil', 'list-tsig-keys'])
27
+    if out is not None:
28
+        out = out.decode('UTF-8') # bytres to string
29
+        keys = out.split('\n') # convert to list, one key per line
30
+        keys = list(filter(None, keys)) # remove any empty lines
31
+        keys = {"%s|%s" % (key[0], key[1]): key for key in [key.split(' ') for key in keys]}
32
+        return keys
33
+    return None
34
+
35
+def add_tsig_key(container,  key_name, key_algo):
36
+    out = container.exec_run(['pdnsutil', 'generate-tsig-key', key_name, key_algo])
37
+    if out is not None:
38
+        out = out.decode('UTF-8')
39
+        match = re.search('Create new TSIG key %s %s (.+)' % (re.escape(key_name), re.escape(key_algo)), out)
40
+        if match:
41
+            key = match.group(1)
42
+            return key
43
+        else:
44
+            return None
45
+    return None
46
+
47
+def add_tsig_key_to_zone(container, zone, key_name):
48
+    out = container.exec_run(['pdnsutil', 'set-meta', zone, 'TSIG-ALLOW-DNSUPDATE', key_name])
49
+    if out is not None:
50
+        out = out.decode('UTF-8')
51
+        return out == 'Enabled TSIG key %s for %s\n' % (key_name, zone) # might to strict, but as we can not get return code
52
+    return False
53
+
54
+def main():
55
+    parser = argparse.ArgumentParser(description='Init Powerdns server')
56
+    parser.add_argument('--dhcp-zone', dest='dhcp_zone', default=None, help='DHCP zone to create (eg: dhcp.city-a.example.com)')
57
+    parser.add_argument('--site-zone', dest='site_zone', default=None, help='Site zone to create (eg: city-a.example.com)')
58
+    parser.add_argument('--rev-zone', dest='rev_zone', default=None, help='Reverse zone to create (eg: 100.15.10), arpa suffix will be added automatically')
59
+    parser.add_argument('--tsig-key-name', dest='tsig_key_name', default='dhcpupdate', help='TSIG key name to add (eg: dnsupdate)')
60
+    parser.add_argument('--tsig-key-algo', dest='tsig_key_algo', default='hmac-md5', help='TSIG key algorithm to use (eg: hmac-md5)')
61
+    parser.add_argument('--container-pdns', dest='container_pdns', default='pdns-pdns', help='Name of pdns auth docker container (eg: pdns-pdns)')
62
+
63
+    args = parser.parse_args()
64
+
65
+    if args.dhcp_zone is None and args.site_zone is None:
66
+        print('At least one of dhcp-zone or site-zone is required')
67
+        return 64
68
+
69
+    if args.rev_zone is not None and not args.rev_zone.endswith('.in-addr.arpa'):
70
+        args.rev_zone = args.rev_zone + '.in-addr.arpa'
71
+
72
+    print('Getting docker client instance...')
73
+    try:
74
+        client = docker.DockerClient(version='auto')
75
+        client.ping()
76
+    except Exception as e:
77
+        print('Failed to ping docker server: %s' % (e))
78
+        return 1
79
+
80
+    print('Getting docker container %s...' % (args.container_pdns))
81
+    try:
82
+        container = client.containers.get(args.container_pdns)
83
+    except Exception as e:
84
+        print('Can not find container %s' % (e))
85
+        return 2
86
+
87
+    if container.status != 'running':
88
+        print('Container is not running: %s' % (container.status))
89
+        return 3
90
+
91
+    print('Checking existing zones...')
92
+    zones = get_zones(container)
93
+    if zones is None:
94
+        print('Failes to get existing zones: Unknown error')
95
+        return 4
96
+
97
+    print('Checking existing TSIG keys...')
98
+    keys = get_tsig_keys(container)
99
+    if keys is None:
100
+        print('Failes to get existing TSIG keys: Unknown error')
101
+        return 5
102
+
103
+    if '%s.|%s.' % (args.tsig_key_name, args.tsig_key_algo) in keys:
104
+        print('Not adding TSIG key %s %s: already exists' % (args.tsig_key_name, args.tsig_key_algo))
105
+        tsig_key_secret = keys['%s.|%s.' % (args.tsig_key_name, args.tsig_key_algo)][2]
106
+    else:
107
+        print('Adding TSIG key %s %s...' % (args.tsig_key_name, args.tsig_key_algo))
108
+        tsig_key_secret = add_tsig_key(container, args.tsig_key_name, args.tsig_key_algo)
109
+        if tsig_key_secret is None:
110
+            print('Failed to add TSIG key: Unknown error')
111
+            return 6
112
+
113
+
114
+    for zone in [args.dhcp_zone, args.site_zone, args.rev_zone]:
115
+        if zone is not None:
116
+            if zone in zones:
117
+                print('Not adding zone %s: already exists' % (zone))
118
+            else:
119
+                print('Adding zone...')
120
+                if not add_zone(container, zone):
121
+                    print('Failed to add zone: Unknown error')
122
+                    return 7
123
+            print('Adding TSIG %s to zone %s...' % (args.tsig_key_name, zone))
124
+            if not add_tsig_key_to_zone(container, zone, args.tsig_key_name):
125
+                print('Failed to add TSIG key to zone: Unknown error')
126
+
127
+    print('DHCP_TSIG_KEY_NAME=%s' % (args.tsig_key_name))
128
+    print('DHCP_TSIG_KEY_ALGO=%s' % (args.tsig_key_algo))
129
+    print('DHCP_TSIG_KEY_SECRET=%s' % (tsig_key_secret))
130
+
131
+    return 0
132
+
133
+if __name__ == '__main__':
134
+    sys.exit(main())

+ 2
- 0
requirements.txt View File

@@ -0,0 +1,2 @@
1
+argparse
2
+docker

Loading…
Cancel
Save