source: trunk/locker/sbin/vhostcert @ 2815

Last change on this file since 2815 was 2815, checked in by ezyang, 7 years ago
Add documentation on how to use vhostcert.
  • Property svn:executable set to *
File size: 2.4 KB
Line 
1#!/usr/bin/python
2
3from __future__ import print_function
4
5import base64
6import re
7import sys
8from OpenSSL import crypto
9
10# How to use:
11# 1. Download the "X509, Base64 encoded" cert from the Certificate
12#    Services Manager
13# 2. Run "vhostcert import < foo_mit_edu.cer". Save stdout (a base64
14#    blob)
15# 3. Log in as root to a Scripts server, and run vhostedit foo.mit.edu
16# 4. Add entries:
17#       scriptsVhostCertificate: space-separated base64 blobs from vhostcert import
18#       scriptsVhostCertificateKeyFile: scripts-2048.key
19# 5. On each server:
20#       /etc/httpd/export-scripts-certs
21#       systemctl reload httpd.service
22#
23# TODO: Make this script do the vhostedit automatically.
24
25def debug_chain(chain):
26    for i, c in enumerate(chain):
27        print(i, 's:', c.get_subject(), file=sys.stderr)
28        print(i, 'i:', c.get_issuer(), file=sys.stderr)
29    print(file=sys.stderr)
30
31def pem_to_scripts(data):
32    certs = [
33        crypto.load_certificate(crypto.FILETYPE_PEM, m.group(0))
34        for m in
35        re.finditer(
36            b'-----BEGIN CERTIFICATE-----\r?\n.+?\r?\n-----END CERTIFICATE-----',
37            data, re.DOTALL)
38    ]
39
40    # Put the chain in the right order, and delete any self-signed root
41    leaf, = [c for c in certs if not any(
42        c1.get_issuer() == c.get_subject() for c1 in certs)]
43    chain = [leaf]
44    count = 1
45    while True:
46        issuers = [c for c in certs if chain[-1].get_issuer() == c.get_subject()]
47        if not issuers:
48            break
49        issuer, = issuers
50        assert issuer not in chain
51        count += 1
52        if issuer.get_issuer() == issuer.get_subject():
53            break
54        chain.append(issuer)
55    assert count == len(certs)
56
57    debug_chain(chain)
58
59    return b' '.join(base64.b64encode(
60        crypto.dump_certificate(crypto.FILETYPE_ASN1, c)) for c in chain)
61
62def scripts_to_pem(data):
63    chain = [
64        crypto.load_certificate(crypto.FILETYPE_ASN1, base64.b64decode(d))
65        for d in data.split(b' ')
66    ]
67
68    debug_chain(chain)
69
70    return b''.join(crypto.dump_certificate(crypto.FILETYPE_PEM, c) for c in chain)
71
72def __main__():
73    if sys.argv[1:] == ['import']:
74        print(pem_to_scripts(sys.stdin.read().encode()).decode())
75    elif sys.argv[1:] == ['export']:
76        print(scripts_to_pem(sys.stdin.read().encode()).decode(), end='')
77    else:
78        print('usage: {} {{import|export}}'.format(__file__), file=sys.stderr)
79
80if __name__ == '__main__':
81    sys.exit(__main__())
Note: See TracBrowser for help on using the repository browser.