Commit | Line | Data |
---|---|---|
c3c15dc7 KS |
1 | #!/usr/bin/env python3 |
2 | # | |
3 | ||
4 | import argparse | |
5 | import ipaddress | |
6 | import subprocess | |
7 | ||
8 | import dns.message | |
9 | import dns.query | |
10 | import dns.resolver | |
11 | ||
12 | def get_argument_parser(): | |
13 | parser = argparse.ArgumentParser( | |
14 | prog='update_dns_entry.py', | |
15 | description='Generate fixed-address DHCP configuration based for hosts based on DNS entries' | |
16 | ) | |
17 | parser.add_argument( | |
18 | '-s', '--server', default=None, required=True, | |
19 | help='Server for DNS updates' | |
20 | ) | |
21 | parser.add_argument( | |
22 | '-u', '--user', default=None, | |
23 | help='The user to use with samba-tool' | |
24 | ) | |
25 | parser.add_argument( | |
26 | '-z', '--zone', required=True, | |
27 | help='The zone in which to update the entry' | |
28 | ) | |
29 | parser.add_argument( | |
30 | '-n', '--name', required=True, | |
31 | help='DNS entry name' | |
32 | ) | |
33 | parser.add_argument( | |
34 | '-v', '--value', required=True, | |
35 | help='DNS entry value' | |
36 | ) | |
37 | parser.add_argument( | |
38 | '-t', '--type', default='A', | |
39 | help='Entry type' | |
40 | ) | |
41 | return parser | |
42 | ||
43 | ||
44 | def update_dns_entry(server, zone, name, entry_type, value, user=None, with_reverse = True): | |
45 | if entry_type == "A": | |
46 | assert(ipaddress.ip_address(value)) | |
47 | try: | |
48 | server_ip = str(ipaddress.ip_address(server)) | |
49 | except ValueError: | |
50 | server_ip = dns.resolver.resolve(server)[0].to_text() | |
51 | ||
52 | commands = [] | |
53 | # Verify existing entry | |
54 | query = dns.message.make_query('.'.join([name, zone]), entry_type) | |
55 | record = dns.query.udp(query, server_ip); | |
56 | if len(record.answer) == 0: | |
57 | # Create | |
58 | argv = ['samba-tool', 'dns', 'add', server, zone, name, entry_type, value] | |
59 | if user is not None: | |
60 | argv += ['-U', user] | |
61 | commands.append(argv) | |
62 | else: | |
63 | assert(len(record.answer) == 1) | |
64 | # Check validity | |
65 | existing = (record.answer)[0][0].to_text() | |
66 | if existing != value: | |
67 | # Update | |
68 | argv = ['samba-tool', 'dns', 'update', server, zone, name, entry_type, existing, value] | |
69 | if user is not None: | |
70 | argv += ['-U', user] | |
71 | commands.append(argv) | |
72 | ||
73 | # Check reverse | |
74 | if with_reverse and entry_type == 'A': | |
75 | rname, rzone = ipaddress.ip_address(value).reverse_pointer.split('.', 1) | |
76 | rvalue = '.'.join([name, zone]) + '.' | |
77 | rtype = 'PTR' | |
78 | query = dns.message.make_query(ipaddress.ip_address(value).reverse_pointer, rtype) | |
79 | record = dns.query.udp(query, server_ip) | |
80 | if len(record.answer) == 0: | |
81 | argv = ['samba-tool', 'dns', 'add', server, rzone, rname, rtype, rvalue] | |
82 | if user is not None: | |
83 | argv += ['-U', user] | |
84 | commands.append(argv) | |
85 | else: | |
86 | assert(len(record.answer) == 1) | |
87 | existing = (record.answer)[0][0].to_text() | |
88 | if existing != value: | |
89 | argv = ['samba-tool', 'dns', 'update', server, rzone, rname, rtype, existing, rvalue] | |
90 | if user is not None: | |
91 | argv += ['-U', user] | |
92 | commands.append(argv) | |
93 | ||
94 | # Run commands | |
95 | for command in commands: | |
96 | subprocess.run(command, check=True) | |
97 | ||
98 | ||
99 | if __name__ == '__main__': | |
100 | parser = get_argument_parser() | |
101 | args = parser.parse_args() | |
102 | update_dns_entry(args.server, args.zone, args.name, args.type, args.value, user=args.user) |