~sinzui/juju-ci-tools/juju-core2

« back to all changes in this revision

Viewing changes to certificates.py

  • Committer: Curtis Hovey
  • Date: 2016-11-01 13:58:17 UTC
  • mfrom: (1282.2.418 trunk)
  • Revision ID: curtis@canonical.com-20161101135817-l6uitv08e9fm4l03
Merged trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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(
 
25
        crypto.FILETYPE_PEM, ca_pem_contents)
 
26
    ca_key = crypto.load_privatekey(
 
27
        crypto.FILETYPE_PEM, ca_key_pem_contents)
 
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
 
 
71
ca_pem_contents = dedent("""\
 
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
 
 
99
ca_key_pem_contents = dedent("""\
 
100
    -----BEGIN RSA PRIVATE KEY-----
 
101
    MIIG4wIBAAKCAYEAp+jsWN98gIqwAaBOFGmSQTp0DkSMwtduUe9RNkxuYEh4xygO
 
102
    9C9At3YMloVvcHMoVG1wbs/Dnqdie5B787lD8NgFlyPmNnNGn1lan4+ZLslKRoV7
 
103
    Kspcn+zQzxbPIcBgOmQhUt6FAL1/GsLFbnJJcRnmTV2TSmRYpVyml9Wd7KDkZihW
 
104
    c1Xw0ag7qH2dhNLZj4fQuYEPKrMI3QZ064/tKwp7zXpDtGjQ+gJZAR1PvO6b3Gsd
 
105
    LlBej2JF8T4pCpNX7QkEiCOaAeZLALUaXGbGJeYU91P7dQzgO3N+UbiMe6IJHFz/
 
106
    Y2eidrZJl/hjLVBdvShBJ1Qobd9lQ1/gt8kupW30AeKA7WKd8F0WPy101u101K4a
 
107
    FweJ5GG8OfYIrOQq+8w7VKYlhVWIMv5G8WpZY0jODd8NonbX8SR2I03yvfNduKmw
 
108
    gW+AOGTQSRNo8v/5UiHCDFyb9S10LU6keKztY+kwbq6IRTZlGKct2b+4J9gpH1+k
 
109
    HzRSI/HpSk+nXfkVAgMBAAECggGAJigjVYrr8xYRKz1voOngx5vt9bQUPM7SDiKR
 
110
    VQKHbq/panCq/Uijr01PTQFjsq0otA7upu/l527oTWYnFNq8GsYsdw08apFFsj6O
 
111
    /oWWbPBnRaFdvPqhk+IwDW+EgIoEFCDfBcL1fJaThNRQI2orUF1vXZNvPk+RaXql
 
112
    jQmJStXBMYnnI2ybPjm53O821ZFIyXo2r4Epni1zTS8DcOiTH93RBn/LVPsgyj+w
 
113
    VDWCAlBC8RMSXYz8AB93/3t9vh5/VTE8qRC9j6lqTxNsUYlCsHuB/j6A7XqFU6U7
 
114
    BVkKUHXRKo2nNcKwjsfPlnk/M41JT/N5RIpTbXRiBgZklIcXxxWdYDGD6M7n2YiP
 
115
    dMwmLZIxPRVp7LTQIxrztkqL5Kp/X9DasI6BPCgifxm4spvjMn5X+k5x4E6GABC2
 
116
    lx/cgriOl+nxgsy4372Kpt62srPRu4Vajr6DDH6nR1O0vxqu4ifawoe7YAUzXzvi
 
117
    5kFWNzpnQ9pZ9s8iW0xP4eAuVZydAoHBAMEToj0he4vY5NyH/axf6u9BA/gkXn4D
 
118
    z38uYykYLr5b8BdEpbB0xZ/LgFOq45ZJcEYo0NjPLgiKuvtvZAKXm0Pka4a8D9Cp
 
119
    NhhoIN9iarZxgDkwvPX2VO1oGB8G/C5WlB2Y0P7QW9wxXZjA0KOkSJEdLP9kBvuQ
 
120
    s/eezIYUiM6upvqPqwKtniMYH1Dz3pApId/APUre0Qo52ITJGr6D849BfMqKYb5Z
 
121
    4ifBUeztydZy8goNHIv4yERUVGoHVviWpwKBwQDeoZ+EGqv010U7ioMIhkJnt4CY
 
122
    CrAHOFJye+Th1wRHGGFy/UOe8SwxwZPAbexH/+HgC5IQ9FSx5SIDuaSWmjOd0DUi
 
123
    Lih2+J3T29haP2259gCvy9UtU+MGW6hP+bhdyJl1SmxSetfDAToAA5tBTSjcu4ea
 
124
    8bKZwm7gHwxnXMuuGkkIUNSul1P9FwUEi3ZaefF3LN3P03e0T93n97DWCKA5yL2w
 
125
    tx7Y8o8AGyBaajPj9S8jLvw8bMzaSuXizucL5eMCgcBdX29gfObQtO3JMQMe76wg
 
126
    VKLkyEHiU1lvujE+WHGSoce0mQBAG9jO9I106PnzXkSryWVm1JsAiobuvenxzvvJ
 
127
    k5fkquJDGPIOT51GKsRMwwstnUJk+OINhf/UUX53smsi/RplgMJL9Ju9GdJMsVBe
 
128
    zWtLf0ZZNpuyLtveI+QdgB1Eo2Iig3AsrKfIcIe71AiLut5pbORPO7ZYUSFb7VhG
 
129
    eXcuREoM0k8qxrUmDcFEsoYXEkwx7Ph9AwNn23DV+5UCgcEA2ojWN2ui/czOJdsa
 
130
    MqTvzDWBoj1je0LbE4vwKYvRpCQXjDN1TDC6zACTk2GTfT19MFrLP59G//TGhdeV
 
131
    60tkfXXiojGjAN2ct1jnL/dxMwh6thWkpUDh6dzRA+hCBLUjhdHPMMtqvf2XPGpN
 
132
    3TTrdnkSbJLyWSJVieSQXWnmeXlN1T7a9qKPDDGreEGZpMhssSo2dYnDyBhZ4Bjv
 
133
    2blP5kjZgvzN5/F5U4ZNJNN5KjwD0EqPyJSYJXM943xrqe83AoHAUYcDXY+TEpvQ
 
134
    WSHib0P+0yX4uZblgAqWk6nPKFIS1mw4mCO71vRHbxztA9gmqxhdSU2aDhHBslIg
 
135
    50eGW9aaTaR6M6vsULA4danJso8Fzgiaz3oxOwSkxBdIu1F0Mr6JlI5PEN21vKXX
 
136
    tsiC2JJEasQbEbNLA5X4hX/jXWwPw0JGMW6UR6RaMHevA09579COUFrtEguZfDi6
 
137
    1xP72bo/RzQ1cWLjb5QVkf155q/BpzrWYQJwo/8TEIL33XZcMES5
 
138
    -----END RSA PRIVATE KEY-----
 
139
    """)