diff options
author | Gregor Kleen <gkleen@yggdrasil.li> | 2022-02-27 16:48:41 +0100 |
---|---|---|
committer | Gregor Kleen <gkleen@yggdrasil.li> | 2022-02-27 16:48:41 +0100 |
commit | c471ec95f8ccf0363cfae09c4479bf8e0907d065 (patch) | |
tree | 455f443e310587a6cec09447148855d204cce31c /overlays/inwx-cdnskey/inwx-cdnskey.py | |
parent | f8cec37ed3fda24dd3e834120b0f6dbcf95e54d2 (diff) | |
download | nixos-c471ec95f8ccf0363cfae09c4479bf8e0907d065.tar nixos-c471ec95f8ccf0363cfae09c4479bf8e0907d065.tar.gz nixos-c471ec95f8ccf0363cfae09c4479bf8e0907d065.tar.bz2 nixos-c471ec95f8ccf0363cfae09c4479bf8e0907d065.tar.xz nixos-c471ec95f8ccf0363cfae09c4479bf8e0907d065.zip |
inwx-cdnskey
Diffstat (limited to 'overlays/inwx-cdnskey/inwx-cdnskey.py')
-rw-r--r-- | overlays/inwx-cdnskey/inwx-cdnskey.py | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/overlays/inwx-cdnskey/inwx-cdnskey.py b/overlays/inwx-cdnskey/inwx-cdnskey.py new file mode 100644 index 00000000..0add24a9 --- /dev/null +++ b/overlays/inwx-cdnskey/inwx-cdnskey.py | |||
@@ -0,0 +1,95 @@ | |||
1 | #!@python@/bin/python | ||
2 | |||
3 | from INWX.Domrobot import ApiClient, ApiType | ||
4 | from xdg import BaseDirectory | ||
5 | import configparser | ||
6 | import sys | ||
7 | import dns.message | ||
8 | import dns.rdataclass | ||
9 | import dns.rdatatype | ||
10 | import dns.query | ||
11 | import dns.zone | ||
12 | import dns.rdtypes.ANY.DNSKEY | ||
13 | import argparse | ||
14 | import ipaddress | ||
15 | import re | ||
16 | import base64 | ||
17 | |||
18 | |||
19 | class ApiConnection: | ||
20 | username = '' | ||
21 | password = '' | ||
22 | shared_secret = None | ||
23 | api_client = None | ||
24 | |||
25 | def __init__(self, **kwargs): | ||
26 | config = configparser.ConfigParser() | ||
27 | config.read(BaseDirectory.load_config_paths('inwx-cdnskey.ini')) | ||
28 | self.username = config.get('INWX', 'username') | ||
29 | self.password = config.get('INWX', 'password') | ||
30 | self.shared_secret = config.get('INWX', 'shared_secret', fallback=None) | ||
31 | self.api_client = ApiClient(api_url=ApiClient.API_LIVE_URL, api_type=ApiType.JSON_RPC, **kwargs) | ||
32 | |||
33 | def __enter__(self): | ||
34 | self.api_client.login(self.username, self.password, shared_secret = self.shared_secret) | ||
35 | return self | ||
36 | |||
37 | def __exit__(self, type, value, traceback): | ||
38 | self.logout() | ||
39 | |||
40 | def login(self, *args, **kwargs): | ||
41 | return ApiConnection.check_api_result(self.api_client.login(*args, **kwargs), msg='API login error') | ||
42 | |||
43 | def logout(self, *args, **kwargs): | ||
44 | return ApiConnection.check_api_result(self.api_client.logout(*args, **kwargs), msg='API logout error', success_code=1500) | ||
45 | |||
46 | def call_api(self, *args, **kwargs): | ||
47 | return ApiConnection.check_api_result(self.api_client.call_api(*args, **kwargs), msg='API error') | ||
48 | |||
49 | @staticmethod | ||
50 | def check_api_result(result, msg='API error', success_code=1000): | ||
51 | if result['code'] != success_code: | ||
52 | raise ApiConnection.format_exception(msg, result) | ||
53 | return result | ||
54 | |||
55 | @staticmethod | ||
56 | def format_exception(msg, result): | ||
57 | return Exception(f"{msg}. Code: {result['code']} Message: {result['msg']}") | ||
58 | |||
59 | |||
60 | |||
61 | def main(): | ||
62 | parser = argparse.ArgumentParser(prog = "inwx-cdnskey") | ||
63 | parser.add_argument('--resolver', metavar='ADDRESS', type=ipaddress.ip_address, default='127.0.0.1') | ||
64 | parser.add_argument('domains', metavar='DOMAIN', nargs='+') | ||
65 | args = parser.parse_args() | ||
66 | |||
67 | with ApiConnection(debug_mode=False) as api_conn: | ||
68 | for domain in args.domains: | ||
69 | active_keys = set() | ||
70 | deleted_keys = set() | ||
71 | api_data = api_conn.call_api('dnssec.listkeys', {'domainName': domain})['resData'] | ||
72 | for dat in api_data: | ||
73 | if dat.get('publicKey') is None: | ||
74 | continue | ||
75 | |||
76 | dnskey_rdat = dns.rdtypes.ANY.DNSKEY.DNSKEY(dns.rdataclass.IN, dns.rdatatype.DNSKEY, int(dat['flagId']), 3, int(dat['algorithmId']), base64.b64decode(dat['publicKey'])) | ||
77 | if dat['status'] == 'DELETED': | ||
78 | deleted_keys.add(dnskey_rdat) | ||
79 | else: | ||
80 | active_keys.add(dnskey_rdat) | ||
81 | |||
82 | dns_keys = set() | ||
83 | qname = dns.name.from_text(domain) | ||
84 | q = dns.message.make_query(qname, dns.rdatatype.CDNSKEY) | ||
85 | r, _ = dns.query.udp_with_fallback(q, str(args.resolver)) | ||
86 | for rdat in r.find_rrset(dns.message.ANSWER, qname, dns.rdataclass.IN, dns.rdatatype.CDNSKEY): | ||
87 | dnskey_rdat = dns.rdtypes.ANY.DNSKEY.DNSKEY(dns.rdataclass.IN, dns.rdatatype.DNSKEY, rdat.flags, rdat.protocol, rdat.algorithm, rdat.key) | ||
88 | dns_keys.add(dnskey_rdat) | ||
89 | |||
90 | print('delete: ', active_keys - dns_keys) | ||
91 | print('add: ', dns_keys - active_keys) | ||
92 | |||
93 | |||
94 | if __name__ == '__main__': | ||
95 | sys.exit(main()) | ||