a925df312449dbb5de894741bd8d173f3ce00049
[stack/cam.git] / cam / main.py
1 #!/usr/bin/python
2
3 import logging
4 import optparse
5 import os
6 import sys
7 import time
8 from cam import config
9
10
11 USAGE = '''cam [<OPTIONS>] <COMMAND> [<ARG>...]
12 CAM v2.0 - (c)2012 by <ale@incal.net> 
13 A Certification Authority manager for complex situations.
14
15 Known commands:
16
17   init [<RSA_CRT> [<DSA_CRT>]]
18     Initialize the environment and create a new CA certificate
19     (you can also import your own existing certificates)
20
21   gen <TAG>...
22     Create (or re-create) the certificates corresponding
23     to TAG
24
25   gencrl
26     Update the CRL
27
28   list
29     List all known certificates
30
31   fp [<TAG>...]
32     Print SHA1/MD5 fingerprints of certificates
33
34   files <TAG>
35     Dump all the certificate-related files of this TAG
36
37   check 
38     Should be run weekly from a cron job to warn you if some
39     certificates are about to expire (controlled by the 'warning_days'
40     parameter in the 'global' section of the configuration)
41
42 The configuration file consists of a ini-style file, with one 'ca'
43 section that specifies global CA parameters, and more sections for
44 each tag with certificate-specific information. See the examples for
45 more details on how to write your own configuration.
46 '''
47
48
49 def find_cert(certs, name):
50     for c in certs:
51         if c.name == name:
52             return c
53     raise Exception('Certificate "%s" not found' % name)
54
55
56 def main():
57     parser = optparse.OptionParser(usage=USAGE)
58     parser.add_option('-d', '--debug', dest='debug', help='Be verbose',
59                       action='store_true')
60     parser.add_option('-c', '--config', dest='config', help='Config file')
61     opts, args = parser.parse_args()
62     if not opts.config:
63         parser.error('Must specify --config')
64     if len(args) < 1:
65         parser.error('Must specify a command')
66
67     logging.basicConfig()
68     logging.getLogger().setLevel(opts.debug and logging.DEBUG or logging.INFO)
69
70     global_config, ca, certs = config.read_config(opts.config)
71
72     cmd, args = args[0], args[1:]
73
74     try:
75         if cmd == 'init':
76             ca.create()
77         elif cmd == 'gen':
78             if len(args) != 1:
79                 parser.error('Wrong number of arguments')
80             ca.generate(find_cert(certs, args[0]))
81         elif cmd == 'gencrl':
82             ca.gencrl()
83         elif cmd == 'files':
84             if len(args) != 1:
85                 parser.error('Wrong number of arguments')
86             c = find_cert(certs, args[0])
87             print c.public_key_file
88             print c.private_key_file
89         elif cmd == 'list':
90             now = time.time()
91             for cert in sorted(certs, key=lambda x: x.name):
92                 expiry = cert.get_expiration_date()
93                 state = 'OK'
94                 expiry_str = ''
95                 if not expiry:
96                     state = 'MISSING'
97                 else:
98                     if expiry < now:
99                         state = 'EXPIRED'
100                     expiry_str = time.strftime('%Y/%m/%d', time.gmtime(expiry))
101                 print cert.name, cert.cn, state, expiry_str
102         elif cmd == 'fp' or cmd == 'fingerprint':
103             if len(args) > 0:
104                 certs = [find_cert(certs, x) for x in args]
105             for cert in certs:
106                 print cert.name, cert.cn
107                 print '  SHA1:', cert.get_fingerprint('sha1')
108                 print '  MD5:', cert.get_fingerprint('md5')
109         elif cmd == 'check':
110             now = time.time()
111             warning_time = 86400 * int(global_config.get('warning_days', 15))
112             for cert in certs:
113                 exp = cert.get_expiration_date()
114                 if exp and (exp - now) < warning_time:
115                     print '%s (%s) is about to expire.' % (cert.name, cert.cn)
116         else:
117             parser.error('unknown command "%s"' % cmd)
118     finally:
119         ca.close()
120
121
122 def main_wrapper():
123     try:
124         main()
125         return 0
126     except Exception, e:
127         logging.exception('uncaught exception')
128         return 1
129
130
131 if __name__ == '__main__':
132     sys.exit(main_wrapper())