| 1 | #!/usr/bin/env python |
|---|
| 2 | |
|---|
| 3 | import sys, os |
|---|
| 4 | import subprocess, tempfile |
|---|
| 5 | import os.path |
|---|
| 6 | import re |
|---|
| 7 | |
|---|
| 8 | from M2Crypto import X509 |
|---|
| 9 | |
|---|
| 10 | from string import join |
|---|
| 11 | from federation.util import abac_pem_type, abac_split_cert, file_expanding_opts |
|---|
| 12 | |
|---|
| 13 | class Parser(file_expanding_opts): |
|---|
| 14 | def __init__(self): |
|---|
| 15 | file_expanding_opts.__init__(self, usage='%prog [options]') |
|---|
| 16 | self.add_option('--out', dest='out', help='destination file', |
|---|
| 17 | action='callback', callback=self.expand_file, type='str', |
|---|
| 18 | default='./cert.pem') |
|---|
| 19 | self.add_option('--debug', dest='debug', action='store_true', |
|---|
| 20 | default=False, help='Just print command') |
|---|
| 21 | self.add_option('--cert', dest='cert', |
|---|
| 22 | help='Cretificate to copy subject from') |
|---|
| 23 | self.add_option('--nokey', dest='include_key', |
|---|
| 24 | action='store_false', default=True, |
|---|
| 25 | help='Do not include the key in the generated ID') |
|---|
| 26 | self.add_option('--cn', dest='cn', default=None, |
|---|
| 27 | help='Set the CN directly') |
|---|
| 28 | self.add_option('--openssl', dest='openssl', |
|---|
| 29 | help='Path to openssl command', default='/usr/bin/openssl') |
|---|
| 30 | |
|---|
| 31 | parser = Parser() |
|---|
| 32 | opts, args = parser.parse_args() |
|---|
| 33 | delete_key = False |
|---|
| 34 | |
|---|
| 35 | if args: |
|---|
| 36 | key = args[0] |
|---|
| 37 | else: |
|---|
| 38 | sys.exit('Expecting a key as a non-optioned argument') |
|---|
| 39 | |
|---|
| 40 | ktype = abac_pem_type(key) |
|---|
| 41 | if ktype == 'both': |
|---|
| 42 | key, cert = abac_split_cert(key) |
|---|
| 43 | os.unlink(cert) |
|---|
| 44 | delete_key = True |
|---|
| 45 | elif ktype != 'key': |
|---|
| 46 | sys.exit('Cannot use %s as identity. It is a %s ' % (key, ktype) + |
|---|
| 47 | 'and we were expecting a key') |
|---|
| 48 | |
|---|
| 49 | |
|---|
| 50 | try: |
|---|
| 51 | if opts.cn is not None: |
|---|
| 52 | subj = '/CN=' + opts.cn |
|---|
| 53 | if len(subj) > 64: subj = subj[0:63] |
|---|
| 54 | else: |
|---|
| 55 | c = X509.load_cert(opts.cert) |
|---|
| 56 | subj = c.get_subject().as_text() |
|---|
| 57 | if subj.startswith('/'): i = 1 |
|---|
| 58 | else: i = 0 |
|---|
| 59 | subj = '/' + re.sub('/', '\/', subj[i:]) |
|---|
| 60 | |
|---|
| 61 | tf, tn = tempfile.mkstemp(suffix=".pem") |
|---|
| 62 | cmd = [opts.openssl, 'req', '-new', '-nodes', '-subj', |
|---|
| 63 | subj, '-x509', '-days', '3650', |
|---|
| 64 | '-key', key, '-out', tn] |
|---|
| 65 | if opts.debug: |
|---|
| 66 | print join(cmd) |
|---|
| 67 | sys.exit(0) |
|---|
| 68 | else: |
|---|
| 69 | rv = subprocess.call(cmd) |
|---|
| 70 | if rv == 0: |
|---|
| 71 | try: |
|---|
| 72 | of = os.fdopen(os.open(opts.out, |
|---|
| 73 | os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0600), 'w') |
|---|
| 74 | if opts.include_key: sources = (tn, key) |
|---|
| 75 | else:sources = (tn,) |
|---|
| 76 | |
|---|
| 77 | for inf in sources: |
|---|
| 78 | f = open(inf, 'r') |
|---|
| 79 | for line in f: |
|---|
| 80 | print >>of, line, |
|---|
| 81 | f.close() |
|---|
| 82 | of.close() |
|---|
| 83 | except EnvironmentError, e: |
|---|
| 84 | sys.exit("Cannot open %s: %s" % (efilename, e.strerror)) |
|---|
| 85 | else: |
|---|
| 86 | sys.exit("%s failed: %d" % (opts.openssl, rv)) |
|---|
| 87 | finally: |
|---|
| 88 | if delete_key and key: os.unlink(key) |
|---|