From 87fb6e3e69f3cb4c0eff11635dda507662a61a7e Mon Sep 17 00:00:00 2001 From: ale Date: Sat, 27 Sep 2014 10:49:06 +0100 Subject: [PATCH] split commands into their own functions; improve logging and error reporting --- cam/main.py | 167 +++++++++++++++++++++++++++++++++------------------- setup.py | 8 +-- 2 files changed, 110 insertions(+), 65 deletions(-) diff --git a/cam/main.py b/cam/main.py index a925df3..22b9758 100755 --- a/cam/main.py +++ b/cam/main.py @@ -9,14 +9,14 @@ from cam import config USAGE = '''cam [] [...] -CAM v2.0 - (c)2012 by -A Certification Authority manager for complex situations. +CAM v%(version)s - (c)2012-2014 by +Minimal X509 Certification Authority management tool. Known commands: - init [ []] + init [] Initialize the environment and create a new CA certificate - (you can also import your own existing certificates) + (you can also import an existing certificate) gen ... Create (or re-create) the certificates corresponding @@ -31,7 +31,7 @@ Known commands: fp [...] Print SHA1/MD5 fingerprints of certificates - files + files ... Dump all the certificate-related files of this TAG check @@ -39,11 +39,14 @@ Known commands: certificates are about to expire (controlled by the 'warning_days' parameter in the 'global' section of the configuration) -The configuration file consists of a ini-style file, with one 'ca' +The configuration file consists of a ini-style file, with a 'ca' section that specifies global CA parameters, and more sections for -each tag with certificate-specific information. See the examples for -more details on how to write your own configuration. -''' +each tag with certificate-specific information. See the documentation +for more details on how to write your own configuration. + +Run `cam --help' to get a list of available command-line options. + +''' % {'version': '2.1'} def find_cert(certs, name): @@ -53,76 +56,118 @@ def find_cert(certs, name): raise Exception('Certificate "%s" not found' % name) +def cmd_init(global_config, ca, certs, args): + ca.create() + + +def cmd_gen(global_config, ca, certs, args): + if len(args) < 1: + print 'Nothing to do.' + for tag in args: + ca.generate(find_cert(certs, tag)) + + +def cmd_gencrl(global_config, ca, certs, args): + ca.gencrl() + + +def cmd_files(global_config, ca, certs, args): + if len(args) < 1: + print 'Nothing to do.' + for tag in args: + c = find_cert(certs, tag) + print c.public_key_file + print c.private_key_file + + +def cmd_list(global_config, ca, certs, args): + now = time.time() + for cert in sorted(certs, key=lambda x: x.name): + expiry = cert.get_expiration_date() + state = 'OK' + expiry_str = '' + if not expiry: + state = 'MISSING' + else: + if expiry < now: + state = 'EXPIRED' + expiry_str = time.strftime('%Y/%m/%d', time.gmtime(expiry)) + print cert.name, cert.cn, state, expiry_str + + +def cmd_fingerprint(global_config, ca, certs, args): + if len(args) > 0: + certs = [find_cert(certs, x) for x in args] + for cert in certs: + print cert.name, cert.cn + print ' SHA1:', cert.get_fingerprint('sha1') + print ' MD5:', cert.get_fingerprint('md5') + + +def cmd_check(global_config, ca, certs, args): + now = time.time() + warning_time = 86400 * int(global_config.get('warning_days', 15)) + retval = 0 + for cert in certs: + exp = cert.get_expiration_date() + if exp and (exp - now) < warning_time: + print '%s (%s) is about to expire.' % (cert.name, cert.cn) + retval = 1 + return retval + + +cmd_table = { + 'init': cmd_init, + 'gen': cmd_gen, + 'gencrl': cmd_gencrl, + 'files': cmd_files, + 'list': cmd_list, + 'fp': cmd_fingerprint, + 'fingerprint': cmd_fingerprint, + 'check': cmd_check, +} + + def main(): parser = optparse.OptionParser(usage=USAGE) parser.add_option('-d', '--debug', dest='debug', help='Be verbose', action='store_true') parser.add_option('-c', '--config', dest='config', help='Config file') opts, args = parser.parse_args() + + if len(args) > 0 and args[0] == 'help': + parser.print_help() + return 0 if not opts.config: parser.error('Must specify --config') if len(args) < 1: parser.error('Must specify a command') - logging.basicConfig() - logging.getLogger().setLevel(opts.debug and logging.DEBUG or logging.INFO) - - global_config, ca, certs = config.read_config(opts.config) - - cmd, args = args[0], args[1:] + logging.basicConfig( + format='cam: %(levelname)s: %(message)s', + level=logging.DEBUG if opts.debug else logging.INFO) try: - if cmd == 'init': - ca.create() - elif cmd == 'gen': - if len(args) != 1: - parser.error('Wrong number of arguments') - ca.generate(find_cert(certs, args[0])) - elif cmd == 'gencrl': - ca.gencrl() - elif cmd == 'files': - if len(args) != 1: - parser.error('Wrong number of arguments') - c = find_cert(certs, args[0]) - print c.public_key_file - print c.private_key_file - elif cmd == 'list': - now = time.time() - for cert in sorted(certs, key=lambda x: x.name): - expiry = cert.get_expiration_date() - state = 'OK' - expiry_str = '' - if not expiry: - state = 'MISSING' - else: - if expiry < now: - state = 'EXPIRED' - expiry_str = time.strftime('%Y/%m/%d', time.gmtime(expiry)) - print cert.name, cert.cn, state, expiry_str - elif cmd == 'fp' or cmd == 'fingerprint': - if len(args) > 0: - certs = [find_cert(certs, x) for x in args] - for cert in certs: - print cert.name, cert.cn - print ' SHA1:', cert.get_fingerprint('sha1') - print ' MD5:', cert.get_fingerprint('md5') - elif cmd == 'check': - now = time.time() - warning_time = 86400 * int(global_config.get('warning_days', 15)) - for cert in certs: - exp = cert.get_expiration_date() - if exp and (exp - now) < warning_time: - print '%s (%s) is about to expire.' % (cert.name, cert.cn) + global_config, ca, certs = config.read_config(opts.config) + try: + cmd, args = args[0], args[1:] + if cmd not in cmd_table: + parser.error('unknown command "%s"' % cmd) + cmdfn = cmd_table[cmd] + return cmdfn(global_config, ca, certs, args) + finally: + ca.close() + except Exception as e: + if opts.debug: + logging.exception(e) else: - parser.error('unknown command "%s"' % cmd) - finally: - ca.close() + logging.error(e) + return 1 def main_wrapper(): try: - main() - return 0 + return main() except Exception, e: logging.exception('uncaught exception') return 1 diff --git a/setup.py b/setup.py index 775e525..07f8658 100644 --- a/setup.py +++ b/setup.py @@ -4,11 +4,11 @@ from setuptools import setup, find_packages setup( name="cam", - version="2.0", - description="X509 Certification Authority management", + version="2.1", + description="Minimal X509 Certification Authority management", author="ale", author_email="ale@incal.net", - url="http://code.autistici.org/p/cam", + url="https://git.autistici.org/ai/cam", install_requires=[], setup_requires=[], zip_safe=False, @@ -20,5 +20,5 @@ setup( "cam = cam.main:main", ], }, - ) +) -- 2.20.1