summaryrefslogtreecommitdiffstats
path: root/contrib/kasp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/kasp')
-rw-r--r--contrib/kasp/README11
-rw-r--r--contrib/kasp/kasp.xml134
-rw-r--r--contrib/kasp/kasp2policy.py209
-rw-r--r--contrib/kasp/policy.good24
4 files changed, 378 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..d94b084
--- /dev/null
+++ b/contrib/kasp/kasp.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- 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..b78a968
--- /dev/null
+++ b/contrib/kasp/kasp2policy.py
@@ -0,0 +1,209 @@
+#!/usr/bin/python
+############################################################################
+# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+############################################################################
+# kasp2policy.py
+# This translates the Keys section of a KASP XML file into a dnssec.policy
+# file that can be used by dnssec-keymgr.
+############################################################################
+
+from xml.etree import cElementTree as ET
+from collections import defaultdict
+from isc import dnskey
+import ply.yacc as yacc
+import ply.lex as lex
+import re
+
+############################################################################
+# Translate KASP duration values into seconds
+############################################################################
+class kasptime:
+ class ktlex:
+ 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'
+
+ def t_NUM(self, t):
+ r'\d+'
+ t.value = int(t.value)
+ return t
+
+ def t_error(self, 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)
+
+ def p_ktime_4(self, p):
+ "ktime : P periods T times"
+ p[0] = p[2] + p[4]
+
+ def p_ktime_3(self, p):
+ "ktime : P T times"
+ p[0] = p[3]
+
+ def p_ktime_2(self, p):
+ "ktime : P periods"
+ p[0] = p[2]
+
+ def p_periods_1(self, p):
+ "periods : period"
+ p[0] = p[1]
+
+ def p_periods_2(self, p):
+ "periods : periods period"
+ p[0] = p[1] + p[2]
+
+ def p_times_1(self, p):
+ "times : time"
+ p[0] = p[1]
+
+ def p_times_2(self, p):
+ "times : times time"
+ p[0] = p[1] + p[2]
+
+ def p_period(self, 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
+
+ def p_time(self, 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])
+
+ def p_error(self, p):
+ print("Syntax error")
+
+############################################################################
+# Load the contents of a KASP XML file as a python dictionary
+############################################################################
+class kasp():
+ @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)
+ d = {t.tag:
+ {k:v[0] if len(v) == 1 else v for k, v in dd.iteritems()}}
+ 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__":
+ from pprint import *
+ import sys
+
+ if len(sys.argv) < 2:
+ print("Usage: kasp2policy <filename>")
+ exit(1)
+
+ try:
+ kinfo = kasp(sys.argv[1])
+ except:
+ print("%s: unable to load KASP file '%s'" % (sys.argv[0], sys.argv[1]))
+ exit(1)
+
+ kt = kasptime()
+ first = True
+
+ for p in kinfo['KASP']['Policy']:
+ if not p['@name'] or not p['Keys']: continue
+ if not first:
+ print("")
+ first = False
+ if p['Description']:
+ d = p['Description'].strip()
+ print("# %s" % re.sub(r"\n\s*", "\n# ", d))
+ print("policy %s {" % p['@name'])
+ ksk = p['Keys']['KSK']
+ zsk = p['Keys']['ZSK']
+ kalg = ksk['Algorithm']
+ zalg = zsk['Algorithm']
+ algnum = kalg['#text'] or zalg['#text']
+ if algnum:
+ print("\talgorithm %s;" % dnskey.algstr(int(algnum)))
+ if p['Keys']['TTL']:
+ print("\tkeyttl %d;" % kt.parse(p['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;
+};