summaryrefslogtreecommitdiffstats
path: root/contrib/kasp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 07:24:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 07:24:22 +0000
commit45d6379135504814ab723b57f0eb8be23393a51d (patch)
treed4f2ec4acca824a8446387a758b0ce4238a4dffa /contrib/kasp
parentInitial commit. (diff)
downloadbind9-upstream.tar.xz
bind9-upstream.zip
Adding upstream version 1:9.16.44.upstream/1%9.16.44upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--contrib/kasp/README11
-rw-r--r--contrib/kasp/kasp.xml146
-rw-r--r--contrib/kasp/kasp2policy.py223
-rw-r--r--contrib/kasp/policy.good24
4 files changed, 404 insertions, 0 deletions
diff --git a/contrib/kasp/README b/contrib/kasp/README
new file mode 100644
index 0000000..fb897f1
--- /dev/null
+++ b/contrib/kasp/README
@@ -0,0 +1,11 @@
+This directory is for tools and scripts related to the OpenDNSSEC KASP
+("key and signature policy") format. Currently it only contains
+"kasp2policy.py", a python script for converting KASP key policy
+to the "dnssec.policy" format that is used by dnssec-keymgr.
+
+This depends on PLY (python lex/yacc) and on the "isc.dnskey" module in
+bin/python/isc.
+
+Basic test:
+$ python kasp2policy.py kasp.xml > policy.out
+$ diff policy.out policy.good
diff --git a/contrib/kasp/kasp.xml b/contrib/kasp/kasp.xml
new file mode 100644
index 0000000..a92d096
--- /dev/null
+++ b/contrib/kasp/kasp.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+
+SPDX-License-Identifier: MPL-2.0
+
+This Source Code Form is subject to the terms of the Mozilla Public
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at https://mozilla.org/MPL/2.0/.
+
+See the COPYRIGHT file distributed with this work for additional
+information regarding copyright ownership.
+-->
+
+<!-- Sample KASP file to use for testing kasp2policy.py. -->
+<KASP>
+ <Policy name="Policy1">
+ <Description>A default policy that will
+ amaze you and your friends</Description>
+ <Signatures>
+ <Resign>PT5M</Resign>
+ <Refresh>PT5M</Refresh>
+ <Validity>
+ <Default>PT15M</Default>
+ <Denial>PT15M</Denial>
+ </Validity>
+ <Jitter>PT2M</Jitter>
+ <InceptionOffset>PT1M</InceptionOffset>
+ </Signatures>
+
+ <Denial>
+ <NSEC>
+ </NSEC>
+ </Denial>
+
+ <Keys>
+ <!-- Parameters for both KSK and ZSK -->
+ <TTL>PT1M</TTL>
+ <RetireSafety>PT0S</RetireSafety>
+ <PublishSafety>PT0S</PublishSafety>
+
+ <!-- Parameters for KSK only -->
+ <KSK>
+ <Algorithm length="2048">5</Algorithm>
+ <Lifetime>PT40M</Lifetime>
+ <Repository>softHSM</Repository>
+ <Standby>1</Standby>
+ </KSK>
+
+ <!-- Parameters for ZSK only -->
+ <ZSK>
+ <Algorithm length="2048">5</Algorithm>
+ <Lifetime>PT25M</Lifetime>
+ <Repository>softHSM</Repository>
+ <Standby>1</Standby>
+ </ZSK>
+ </Keys>
+
+ <Zone>
+ <PropagationDelay>PT0S</PropagationDelay>
+ <SOA>
+ <TTL>PT0S</TTL>
+ <Minimum>PT0S</Minimum>
+ <Serial>unixtime</Serial>
+ </SOA>
+ </Zone>
+
+ <Parent>
+ <PropagationDelay>PT8M</PropagationDelay>
+ <DS>
+ <TTL>PT0S</TTL>
+ </DS>
+ <SOA>
+ <TTL>PT0S</TTL>
+ <Minimum>PT0S</Minimum>
+ </SOA>
+ </Parent>
+ </Policy>
+ <Policy name="Policy2">
+ <Description>A default policy that will amaze you and your friends</Description>
+ <Signatures>
+ <Resign>PT7M</Resign>
+ <Refresh>PT7M</Refresh>
+ <Validity>
+ <Default>PT15M</Default>
+ <Denial>PT16M</Denial>
+ </Validity>
+ <Jitter>PT2M</Jitter>
+ <InceptionOffset>PT1M</InceptionOffset>
+ </Signatures>
+
+ <Denial>
+ <NSEC3>
+ <Resalt>P120D</Resalt>
+ <Hash>
+ <Algorithm>1</Algorithm>
+ <Iterations>5</Iterations>
+ <Salt length="8"/>
+ </Hash>
+ </NSEC3>
+ </Denial>
+
+ <Keys>
+ <!-- Parameters for both KSK and ZSK -->
+ <TTL>PT15M</TTL>
+ <RetireSafety>PT0S</RetireSafety>
+ <PublishSafety>PT0S</PublishSafety>
+
+ <!-- Parameters for KSK only -->
+ <KSK>
+ <Algorithm length="2048">7</Algorithm>
+ <Lifetime>PT45M</Lifetime>
+ <Repository>softHSM</Repository>
+ <Standby>1</Standby>
+ </KSK>
+
+ <!-- Parameters for ZSK only -->
+ <ZSK>
+ <Algorithm length="2048">7</Algorithm>
+ <Lifetime>PT25M</Lifetime>
+ <Repository>softHSM</Repository>
+ <Standby>1</Standby>
+ </ZSK>
+ </Keys>
+
+ <Zone>
+ <PropagationDelay>PT0S</PropagationDelay>
+ <SOA>
+ <TTL>PT0S</TTL>
+ <Minimum>PT0S</Minimum>
+ <Serial>unixtime</Serial>
+ </SOA>
+ </Zone>
+
+ <Parent>
+ <PropagationDelay>PT12M</PropagationDelay>
+ <DS>
+ <TTL>PT0S</TTL>
+ </DS>
+ <SOA>
+ <TTL>PT0S</TTL>
+ <Minimum>PT0S</Minimum>
+ </SOA>
+ </Parent>
+ </Policy>
+</KASP>
diff --git a/contrib/kasp/kasp2policy.py b/contrib/kasp/kasp2policy.py
new file mode 100644
index 0000000..a2536a7
--- /dev/null
+++ b/contrib/kasp/kasp2policy.py
@@ -0,0 +1,223 @@
+#!/usr/bin/python
+
+# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+from xml.etree import cElementTree as ET
+from collections import defaultdict
+import re
+from ply import yacc
+from ply import lex
+from isc import dnskey
+
+
+############################################################################
+# Translate KASP duration values into seconds
+############################################################################
+class KaspTime:
+ # pylint: disable=invalid-name
+ class KTLex:
+ # pylint: disable=invalid-name
+
+ tokens = ("P", "T", "Y", "M", "D", "H", "S", "NUM")
+
+ t_P = r"(?i)P"
+ t_T = r"(?i)T"
+ t_Y = r"(?i)Y"
+ t_M = r"(?i)M"
+ t_D = r"(?i)D"
+ t_H = r"(?i)H"
+ t_S = r"(?i)S"
+
+ @staticmethod
+ def t_NUM(t):
+ r"\d+"
+ t.value = int(t.value)
+ return t
+
+ @staticmethod
+ def t_error(t):
+ print("Illegal character '%s'" % t.value[0])
+ t.lexer.skip(1)
+
+ def __init__(self):
+ self.lexer = lex.lex(object=self)
+
+ def __init__(self):
+ self.lexer = self.KTLex()
+ self.tokens = self.lexer.tokens
+ self.parser = yacc.yacc(debug=False, write_tables=False, module=self)
+
+ def parse(self, text):
+ self.lexer.lexer.lineno = 0
+ return self.parser.parse(text)
+
+ @staticmethod
+ def p_ktime_4(p):
+ "ktime : P periods T times"
+ p[0] = p[2] + p[4]
+
+ @staticmethod
+ def p_ktime_3(p):
+ "ktime : P T times"
+ p[0] = p[3]
+
+ @staticmethod
+ def p_ktime_2(p):
+ "ktime : P periods"
+ p[0] = p[2]
+
+ @staticmethod
+ def p_periods_1(p):
+ "periods : period"
+ p[0] = p[1]
+
+ @staticmethod
+ def p_periods_2(p):
+ "periods : periods period"
+ p[0] = p[1] + p[2]
+
+ @staticmethod
+ def p_times_1(p):
+ "times : time"
+ p[0] = p[1]
+
+ @staticmethod
+ def p_times_2(p):
+ "times : times time"
+ p[0] = p[1] + p[2]
+
+ @staticmethod
+ def p_period(p):
+ """period : NUM Y
+ | NUM M
+ | NUM D"""
+ if p[2].lower() == "y":
+ p[0] = int(p[1]) * 31536000
+ elif p[2].lower() == "m":
+ p[0] = int(p[1]) * 2592000
+ elif p[2].lower() == "d":
+ p[0] += int(p[1]) * 86400
+
+ @staticmethod
+ def p_time(p):
+ """time : NUM H
+ | NUM M
+ | NUM S"""
+ if p[2].lower() == "h":
+ p[0] = int(p[1]) * 3600
+ elif p[2].lower() == "m":
+ p[0] = int(p[1]) * 60
+ elif p[2].lower() == "s":
+ p[0] = int(p[1])
+
+ @staticmethod
+ def p_error():
+ print("Syntax error")
+
+
+############################################################################
+# Load the contents of a KASP XML file as a python dictionary
+############################################################################
+class Kasp:
+ # pylint: disable=invalid-name
+
+ @staticmethod
+ def _todict(t):
+ d = {t.tag: {} if t.attrib else None}
+ children = list(t)
+ if children:
+ dd = defaultdict(list)
+ for dc in map(Kasp._todict, children):
+ for k, v in dc.iteritems():
+ dd[k].append(v)
+ k = {k: v[0] if len(v) == 1 else v for k, v in dd.items()}
+ d = {t.tag: k}
+ if t.attrib:
+ d[t.tag].update(("@" + k, v) for k, v in t.attrib.iteritems())
+ if t.text:
+ text = t.text.strip()
+ if children or t.attrib:
+ if text:
+ d[t.tag]["#text"] = text
+ else:
+ d[t.tag] = text
+ return d
+
+ def __init__(self, filename):
+ self._dict = Kasp._todict(ET.parse(filename).getroot())
+
+ def __getitem__(self, key):
+ return self._dict[key]
+
+ def __len__(self):
+ return len(self._dict)
+
+ def __iter__(self):
+ return self._dict.__iter__()
+
+ def __repr__(self):
+ return repr(self._dict)
+
+
+############################################################################
+# Load the contents of a KASP XML file as a python dictionary
+############################################################################
+if __name__ == "__main__":
+ import sys
+
+ if len(sys.argv) < 2:
+ print("Usage: kasp2policy <filename>")
+ sys.exit(1)
+
+ KINFO = Kasp(sys.argv[1])
+ try:
+ KINFO = Kasp(sys.argv[1])
+ except FileNotFoundError:
+ print("%s: unable to load KASP file '%s'" % (sys.argv[0], sys.argv[1]))
+ sys.exit(1)
+
+ KT = KaspTime()
+ FIRST = True
+
+ for policy in KINFO["KASP"]["Policy"]:
+ if not policy["@name"] or not policy["Keys"]:
+ continue
+ if not FIRST:
+ print("")
+ FIRST = False
+ if policy["Description"]:
+ desc = policy["Description"].strip()
+ print("# %s" % re.sub(r"\n\s*", "\n# ", desc))
+ print("policy %s {" % policy["@name"])
+ ksk = policy["Keys"]["KSK"]
+ zsk = policy["Keys"]["ZSK"]
+ kalg = ksk["Algorithm"]
+ zalg = zsk["Algorithm"]
+ algnum = kalg["#text"] or zalg["#text"]
+ if algnum:
+ print("\talgorithm %s;" % dnskey.algstr(int(algnum)))
+ if policy["Keys"]["TTL"]:
+ print("\tkeyttl %d;" % KT.parse(policy["Keys"]["TTL"]))
+ if kalg["@length"]:
+ print("\tkey-size ksk %d;" % int(kalg["@length"]))
+ if zalg["@length"]:
+ print("\tkey-size zsk %d;" % int(zalg["@length"]))
+ if ksk["Lifetime"]:
+ print("\troll-period ksk %d;" % KT.parse(ksk["Lifetime"]))
+ if zsk["Lifetime"]:
+ print("\troll-period zsk %d;" % KT.parse(zsk["Lifetime"]))
+ if ksk["Standby"]:
+ print("\tstandby ksk %d;" % int(ksk["Standby"]))
+ if zsk["Standby"]:
+ print("\tstandby zsk %d;" % int(zsk["Standby"]))
+ print("};")
diff --git a/contrib/kasp/policy.good b/contrib/kasp/policy.good
new file mode 100644
index 0000000..18c6360
--- /dev/null
+++ b/contrib/kasp/policy.good
@@ -0,0 +1,24 @@
+# A default policy that will
+# amaze you and your friends
+policy Policy1 {
+ algorithm RSASHA1;
+ keyttl 60;
+ key-size ksk 2048;
+ key-size zsk 2048;
+ roll-period ksk 2400;
+ roll-period zsk 1500;
+ standby ksk 1;
+ standby zsk 1;
+};
+
+# A default policy that will amaze you and your friends
+policy Policy2 {
+ algorithm NSEC3RSASHA1;
+ keyttl 900;
+ key-size ksk 2048;
+ key-size zsk 2048;
+ roll-period ksk 2700;
+ roll-period zsk 1500;
+ standby ksk 1;
+ standby zsk 1;
+};