~nskaggs/juju-ci-tools/add-assess-terms

1491.2.4 by Christopher Lee
Move certificate methods into own file.
1
from OpenSSL import crypto
2
import os
3
from textwrap import dedent
4
5
6
def create_certificate(target_dir, ip_address):
7
    """Generate a cert and key file incl. IP SAN for `ip_address`
8
9
    Creates a cert.pem and key.pem file signed with a known ca cert.
10
    The generated cert will contain a IP SAN (subject alternative name) that
11
    includes the ip address of the server. This is required for log-forwarding.
12
13
    :return: tuple containing generated cert, key filepath pair
14
15
    """
16
    ip_address = 'IP:{}'.format(ip_address)
17
18
    key = crypto.PKey()
19
    key.generate_key(crypto.TYPE_RSA, 2048)
20
21
    csr_contents = generate_csr(target_dir, key, ip_address)
22
    req = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr_contents)
23
24
    ca_cert = crypto.load_certificate(
1491.2.9 by Christopher Lee
Change certificate details to not be a getter function.
25
        crypto.FILETYPE_PEM, ca_pem_contents)
1491.2.4 by Christopher Lee
Move certificate methods into own file.
26
    ca_key = crypto.load_privatekey(
1491.2.9 by Christopher Lee
Change certificate details to not be a getter function.
27
        crypto.FILETYPE_PEM, ca_key_pem_contents)
1491.2.4 by Christopher Lee
Move certificate methods into own file.
28
29
    cert = crypto.X509()
30
    cert.set_version(0x2)
31
    cert.set_subject(req.get_subject())
32
    cert.set_serial_number(1)
33
    cert.gmtime_adj_notBefore(0)
34
    cert.gmtime_adj_notAfter(24 * 60 * 60)
35
    cert.set_issuer(ca_cert.get_subject())
36
    cert.set_pubkey(req.get_pubkey())
37
    cert.add_extensions([
38
        crypto.X509Extension('subjectAltName', False, ip_address),
39
        crypto.X509Extension(
40
            'extendedKeyUsage', False, 'clientAuth, serverAuth'),
41
        crypto.X509Extension(
42
            'keyUsage', True, 'keyEncipherment'),
43
    ])
44
    cert.sign(ca_key, "sha256")
45
46
    cert_filepath = os.path.join(target_dir, 'cert.pem')
47
    with open(cert_filepath, 'wt') as f:
48
        f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
49
50
    key_filepath = os.path.join(target_dir, 'key.pem')
51
    with open(key_filepath, 'wt') as f:
52
        f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key))
53
54
    return (cert_filepath, key_filepath)
55
56
57
def generate_csr(target_dir, key, ip_address):
58
    req = crypto.X509Req()
59
    req.set_version(0x2)
60
    req.get_subject().CN = "anyServer"
61
    # Add the IP SAN
62
    req.add_extensions([
63
        crypto.X509Extension("subjectAltName", False, ip_address)
64
    ])
65
    req.set_pubkey(key)
66
    req.sign(key, "sha256")
67
68
    return crypto.dump_certificate_request(crypto.FILETYPE_PEM, req)
69
70
1491.2.9 by Christopher Lee
Change certificate details to not be a getter function.
71
ca_pem_contents = dedent("""\
1491.2.4 by Christopher Lee
Move certificate methods into own file.
72
    -----BEGIN CERTIFICATE-----
73
    MIIEFTCCAn2gAwIBAgIBBzANBgkqhkiG9w0BAQsFADAjMRIwEAYDVQQDEwlhbnlT
74
    ZXJ2ZXIxDTALBgNVBAoTBGp1anUwHhcNMTYwNzExMDQyOTM1WhcNMjYwNzA5MDQy
75
    OTM1WjAjMRIwEAYDVQQDEwlhbnlTZXJ2ZXIxDTALBgNVBAoTBGp1anUwggGiMA0G
76
    CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCn6OxY33yAirABoE4UaZJBOnQORIzC
77
    125R71E2TG5gSHjHKA70L0C3dgyWhW9wcyhUbXBuz8Oep2J7kHvzuUPw2AWXI+Y2
78
    c0afWVqfj5kuyUpGhXsqylyf7NDPFs8hwGA6ZCFS3oUAvX8awsVucklxGeZNXZNK
79
    ZFilXKaX1Z3soORmKFZzVfDRqDuofZ2E0tmPh9C5gQ8qswjdBnTrj+0rCnvNekO0
80
    aND6AlkBHU+87pvcax0uUF6PYkXxPikKk1ftCQSII5oB5ksAtRpcZsYl5hT3U/t1
81
    DOA7c35RuIx7ogkcXP9jZ6J2tkmX+GMtUF29KEEnVCht32VDX+C3yS6lbfQB4oDt
82
    Yp3wXRY/LXTW7XTUrhoXB4nkYbw59gis5Cr7zDtUpiWFVYgy/kbxalljSM4N3w2i
83
    dtfxJHYjTfK98124qbCBb4A4ZNBJE2jy//lSIcIMXJv1LXQtTqR4rO1j6TBurohF
84
    NmUYpy3Zv7gn2CkfX6QfNFIj8elKT6dd+RUCAwEAAaNUMFIwDwYDVR0TAQH/BAUw
85
    AwEB/zAPBgNVHREECDAGhwQKwoylMA8GA1UdDwEB/wQFAwMHBAAwHQYDVR0OBBYE
86
    FP+v8GAqHiUCIygXbwWzbUhl/22DMA0GCSqGSIb3DQEBCwUAA4IBgQBVYKeT1O2M
87
    U3OPOy0IwqcA1/64rS1GlRmiw+papmjsy3aru03r8igahnbFd7wQawHaCScXbI/n
88
    OAPT4PDGXn6b71t4uHwWaM8wde159RO3G32N/VfhV6LPRUQunmAZh5QcJK6wWpYu
89
    B1f0dPkU+Q1AfX12oTOX/ld2/o7jaVswHoHoW6K2WQmwzlRQ953J+RJ7jXfrYDKl
90
    OAp3Hb69wAN4Ayc1s92iYUwV5q8UaHQoskHOLWJu964yFBHL8SLe6TLD+Jjv05Mc
91
    Ca7NKq/n25VTDNNaXl5MCNZ048m/GGHfktxxCddaF2grhC5HTUetwkq026PE0Wcq
92
    P+cDrIq6uTA25QqyBYistSa/7z2o0NBi56ySRqxlP2J2TPFZyOb+ZiA4EgYY5no5
93
    u2E+WuKZLVWl7eaQYOHgfYzFf3CvalSBwIjNynRwD/2Ebk7K29GPrIugb3V2+Vwh
94
    rltUXOHUkFGjEHIhr8zixfCxh5OzPJMnJwCZZRYzMO0/0Gw7ll9DmH0=
95
    -----END CERTIFICATE-----
96
    """)
97
98
1491.2.9 by Christopher Lee
Change certificate details to not be a getter function.
99
ca_key_pem_contents = dedent("""\
1491.2.4 by Christopher Lee
Move certificate methods into own file.
100
    -----BEGIN RSA PRIVATE KEY-----
101
    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
138
    -----END RSA PRIVATE KEY-----
139
    """)