summaryrefslogtreecommitdiffstats
path: root/bin/python/isc/keymgr.py.in
diff options
context:
space:
mode:
Diffstat (limited to 'bin/python/isc/keymgr.py.in')
-rw-r--r--bin/python/isc/keymgr.py.in207
1 files changed, 207 insertions, 0 deletions
diff --git a/bin/python/isc/keymgr.py.in b/bin/python/isc/keymgr.py.in
new file mode 100644
index 0000000..67fe4c7
--- /dev/null
+++ b/bin/python/isc/keymgr.py.in
@@ -0,0 +1,207 @@
+# 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 __future__ import print_function
+import os, sys, argparse, glob, re, time, calendar, pprint
+from collections import defaultdict
+
+prog = "dnssec-keymgr"
+
+from isc import dnskey, keydict, keyseries, policy, parsetab, utils
+
+
+############################################################################
+# print a fatal error and exit
+############################################################################
+def fatal(*args, **kwargs):
+ print(*args, **kwargs)
+ sys.exit(1)
+
+
+############################################################################
+# find the location of an external command
+############################################################################
+def set_path(command, default=None):
+ """find the location of a specified command. If a default is supplied,
+ exists and it's an executable, we use it; otherwise we search PATH
+ for an alternative.
+ :param command: command to look for
+ :param default: default value to use
+ :return: PATH with the location of a suitable binary
+ """
+ fpath = default
+ if not fpath or not os.path.isfile(fpath) or not os.access(fpath, os.X_OK):
+ path = os.environ["PATH"]
+ if not path:
+ path = os.path.defpath
+ for directory in path.split(os.pathsep):
+ fpath = directory + os.sep + command
+ if os.path.isfile(fpath) and os.access(fpath, os.X_OK):
+ break
+ fpath = None
+
+ return fpath
+
+
+############################################################################
+# parse arguments
+############################################################################
+def parse_args():
+ """Read command line arguments, returns 'args' object
+ :return: args object properly prepared
+ """
+
+ keygen = set_path(
+ "dnssec-keygen", os.path.join(utils.prefix("sbin"), "dnssec-keygen")
+ )
+ settime = set_path(
+ "dnssec-settime", os.path.join(utils.prefix("sbin"), "dnssec-settime")
+ )
+
+ parser = argparse.ArgumentParser(
+ description=prog + ": schedule "
+ "DNSSEC key rollovers according to a "
+ "pre-defined policy"
+ )
+
+ parser.add_argument(
+ "zone",
+ type=str,
+ nargs="*",
+ default=None,
+ help="Zone(s) to which the policy should be applied "
+ + "(default: all zones in the directory)",
+ )
+ parser.add_argument(
+ "-K", dest="path", type=str, help="Directory containing keys", metavar="dir"
+ )
+ parser.add_argument(
+ "-c", dest="policyfile", type=str, help="Policy definition file", metavar="file"
+ )
+ parser.add_argument(
+ "-g",
+ dest="keygen",
+ default=keygen,
+ type=str,
+ help="Path to 'dnssec-keygen'",
+ metavar="path",
+ )
+ parser.add_argument(
+ "-r",
+ dest="randomdev",
+ type=str,
+ default=None,
+ help="DEPRECATED",
+ metavar="path",
+ )
+ parser.add_argument(
+ "-s",
+ dest="settime",
+ default=settime,
+ type=str,
+ help="Path to 'dnssec-settime'",
+ metavar="path",
+ )
+ parser.add_argument(
+ "-k",
+ dest="no_zsk",
+ action="store_true",
+ default=False,
+ help="Only apply policy to key-signing keys (KSKs)",
+ )
+ parser.add_argument(
+ "-z",
+ dest="no_ksk",
+ action="store_true",
+ default=False,
+ help="Only apply policy to zone-signing keys (ZSKs)",
+ )
+ parser.add_argument(
+ "-f",
+ "--force",
+ dest="force",
+ action="store_true",
+ default=False,
+ help="Force updates to key events " + "even if they are in the past",
+ )
+ parser.add_argument(
+ "-q",
+ "--quiet",
+ dest="quiet",
+ action="store_true",
+ default=False,
+ help="Update keys silently",
+ )
+ parser.add_argument("-v", "--version", action="version", version=utils.version)
+
+ args = parser.parse_args()
+
+ if args.randomdev:
+ fatal("ERROR: -r option has been deprecated.")
+
+ if args.no_zsk and args.no_ksk:
+ fatal("ERROR: -z and -k cannot be used together.")
+
+ if args.keygen is None:
+ fatal("ERROR: dnssec-keygen not found")
+
+ if args.settime is None:
+ fatal("ERROR: dnssec-settime not found")
+
+ # if a policy file was specified, check that it exists.
+ # if not, use the default file, unless it doesn't exist
+ if args.policyfile is not None:
+ if not os.path.exists(args.policyfile):
+ fatal('ERROR: Policy file "%s" not found' % args.policyfile)
+ else:
+ args.policyfile = os.path.join(utils.sysconfdir, "dnssec-policy.conf")
+ if not os.path.exists(args.policyfile):
+ args.policyfile = None
+
+ return args
+
+
+############################################################################
+# main
+############################################################################
+def main():
+ args = parse_args()
+
+ # As we may have specific locations for the binaries, we put that info
+ # into a context object that can be passed around
+ context = {
+ "keygen_path": args.keygen,
+ "settime_path": args.settime,
+ "keys_path": args.path,
+ "randomdev": args.randomdev,
+ }
+
+ try:
+ dp = policy.dnssec_policy(args.policyfile)
+ except Exception as e:
+ fatal("Unable to load DNSSEC policy: " + str(e))
+
+ try:
+ kd = keydict(dp, path=args.path, zones=args.zone)
+ except Exception as e:
+ fatal("Unable to build key dictionary: " + str(e))
+
+ try:
+ ks = keyseries(kd, context=context)
+ except Exception as e:
+ fatal("Unable to build key series: " + str(e))
+
+ try:
+ ks.enforce_policy(
+ dp, ksk=args.no_zsk, zsk=args.no_ksk, force=args.force, quiet=args.quiet
+ )
+ except Exception as e:
+ fatal("Unable to apply policy: " + str(e))