Commit 87fb6e3e authored by ale's avatar ale

split commands into their own functions; improve logging and error reporting

parent d82b2c9a
...@@ -9,14 +9,14 @@ from cam import config ...@@ -9,14 +9,14 @@ from cam import config
USAGE = '''cam [<OPTIONS>] <COMMAND> [<ARG>...] USAGE = '''cam [<OPTIONS>] <COMMAND> [<ARG>...]
CAM v2.0 - (c)2012 by <ale@incal.net> CAM v%(version)s - (c)2012-2014 by <ale@incal.net>
A Certification Authority manager for complex situations. Minimal X509 Certification Authority management tool.
Known commands: Known commands:
init [<RSA_CRT> [<DSA_CRT>]] init [<RSA_CRT>]
Initialize the environment and create a new CA certificate 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 <TAG>... gen <TAG>...
Create (or re-create) the certificates corresponding Create (or re-create) the certificates corresponding
...@@ -31,7 +31,7 @@ Known commands: ...@@ -31,7 +31,7 @@ Known commands:
fp [<TAG>...] fp [<TAG>...]
Print SHA1/MD5 fingerprints of certificates Print SHA1/MD5 fingerprints of certificates
files <TAG> files <TAG>...
Dump all the certificate-related files of this TAG Dump all the certificate-related files of this TAG
check check
...@@ -39,11 +39,14 @@ Known commands: ...@@ -39,11 +39,14 @@ Known commands:
certificates are about to expire (controlled by the 'warning_days' certificates are about to expire (controlled by the 'warning_days'
parameter in the 'global' section of the configuration) 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 section that specifies global CA parameters, and more sections for
each tag with certificate-specific information. See the examples for each tag with certificate-specific information. See the documentation
more details on how to write your own configuration. 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): def find_cert(certs, name):
...@@ -53,76 +56,118 @@ def find_cert(certs, name): ...@@ -53,76 +56,118 @@ def find_cert(certs, name):
raise Exception('Certificate "%s" not found' % 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(): def main():
parser = optparse.OptionParser(usage=USAGE) parser = optparse.OptionParser(usage=USAGE)
parser.add_option('-d', '--debug', dest='debug', help='Be verbose', parser.add_option('-d', '--debug', dest='debug', help='Be verbose',
action='store_true') action='store_true')
parser.add_option('-c', '--config', dest='config', help='Config file') parser.add_option('-c', '--config', dest='config', help='Config file')
opts, args = parser.parse_args() opts, args = parser.parse_args()
if len(args) > 0 and args[0] == 'help':
parser.print_help()
return 0
if not opts.config: if not opts.config:
parser.error('Must specify --config') parser.error('Must specify --config')
if len(args) < 1: if len(args) < 1:
parser.error('Must specify a command') parser.error('Must specify a command')
logging.basicConfig() logging.basicConfig(
logging.getLogger().setLevel(opts.debug and logging.DEBUG or logging.INFO) format='cam: %(levelname)s: %(message)s',
level=logging.DEBUG if opts.debug else logging.INFO)
global_config, ca, certs = config.read_config(opts.config)
cmd, args = args[0], args[1:]
try: try:
if cmd == 'init': global_config, ca, certs = config.read_config(opts.config)
ca.create() try:
elif cmd == 'gen': cmd, args = args[0], args[1:]
if len(args) != 1: if cmd not in cmd_table:
parser.error('Wrong number of arguments') parser.error('unknown command "%s"' % cmd)
ca.generate(find_cert(certs, args[0])) cmdfn = cmd_table[cmd]
elif cmd == 'gencrl': return cmdfn(global_config, ca, certs, args)
ca.gencrl() finally:
elif cmd == 'files': ca.close()
if len(args) != 1: except Exception as e:
parser.error('Wrong number of arguments') if opts.debug:
c = find_cert(certs, args[0]) logging.exception(e)
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)
else: else:
parser.error('unknown command "%s"' % cmd) logging.error(e)
finally: return 1
ca.close()
def main_wrapper(): def main_wrapper():
try: try:
main() return main()
return 0
except Exception, e: except Exception, e:
logging.exception('uncaught exception') logging.exception('uncaught exception')
return 1 return 1
......
...@@ -4,11 +4,11 @@ from setuptools import setup, find_packages ...@@ -4,11 +4,11 @@ from setuptools import setup, find_packages
setup( setup(
name="cam", name="cam",
version="2.0", version="2.1",
description="X509 Certification Authority management", description="Minimal X509 Certification Authority management",
author="ale", author="ale",
author_email="ale@incal.net", author_email="ale@incal.net",
url="http://code.autistici.org/p/cam", url="https://git.autistici.org/ai/cam",
install_requires=[], install_requires=[],
setup_requires=[], setup_requires=[],
zip_safe=False, zip_safe=False,
...@@ -20,5 +20,5 @@ setup( ...@@ -20,5 +20,5 @@ setup(
"cam = cam.main:main", "cam = cam.main:main",
], ],
}, },
) )
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment