blob: dcdd6f08fd7746ce7609e11c172b2304969bcde8 [file] [log] [blame]
Michael Johnson0a0f9b32019-01-02 16:58:21 -08001# Copyright 2018 Rackspace US Inc. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import datetime
16
17from cryptography.hazmat.backends import default_backend
18from cryptography.hazmat.primitives.asymmetric import rsa
19from cryptography.hazmat.primitives import hashes
20from cryptography import x509
21from cryptography.x509.oid import NameOID
22import OpenSSL
23
24
25def generate_ca_cert_and_key():
26 """Creates a CA cert and key for testing.
27
28 :returns: The cryptography CA cert and CA key objects.
29 """
30
31 ca_key = rsa.generate_private_key(
32 public_exponent=65537, key_size=2048, backend=default_backend())
33
34 subject = issuer = x509.Name([
35 x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
36 x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Denial"),
37 x509.NameAttribute(NameOID.LOCALITY_NAME, u"Corvallis"),
38 x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"OpenStack"),
39 x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"Octavia"),
40 x509.NameAttribute(NameOID.COMMON_NAME, u"ca_cert.example.com"),
41 ])
42
43 ca_cert = x509.CertificateBuilder().subject_name(
44 subject
45 ).issuer_name(
46 issuer
47 ).public_key(
48 ca_key.public_key()
49 ).serial_number(
50 x509.random_serial_number()
51 ).not_valid_before(
52 datetime.datetime.utcnow()
53 ).not_valid_after(
54 datetime.datetime.utcnow() + datetime.timedelta(days=10)
55 ).add_extension(
56 x509.SubjectAlternativeName([x509.DNSName(u"ca_cert.example.com")]),
57 critical=False,
58 ).add_extension(
59 x509.BasicConstraints(ca=True, path_length=None),
60 critical=True,
61 ).sign(ca_key, hashes.SHA256(), default_backend())
62
63 return ca_cert, ca_key
64
65
66def generate_server_cert_and_key(ca_cert, ca_key, server_uuid):
67 """Creates a server cert and key for testing.
68
69 :param ca_cert: A cryptography CA certificate (x509) object.
70 :param ca_key: A cryptography CA key (x509) object.
71 :param server_uuid: A UUID identifying the server.
72 :returns: The cryptography server cert and key objects.
73 """
74
75 server_key = rsa.generate_private_key(
76 public_exponent=65537, key_size=2048, backend=default_backend())
77
78 subject = x509.Name([
79 x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
80 x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Denial"),
81 x509.NameAttribute(NameOID.LOCALITY_NAME, u"Corvallis"),
82 x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"OpenStack"),
83 x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"Octavia"),
84 x509.NameAttribute(NameOID.COMMON_NAME, u"{}.example.com".format(
85 server_uuid)),
86 ])
87
88 server_cert = x509.CertificateBuilder().subject_name(
89 subject
90 ).issuer_name(
91 ca_cert.subject
92 ).public_key(
93 server_key.public_key()
94 ).serial_number(
95 x509.random_serial_number()
96 ).not_valid_before(
97 datetime.datetime.utcnow()
98 ).not_valid_after(
99 datetime.datetime.utcnow() + datetime.timedelta(days=10)
100 ).add_extension(
101 x509.SubjectAlternativeName(
102 [x509.DNSName(u"{}.example.com".format(server_uuid))]),
103 critical=False,
104 ).add_extension(
105 x509.BasicConstraints(ca=False, path_length=None),
106 critical=True,
107 ).sign(ca_key, hashes.SHA256(), default_backend())
108
109 return server_cert, server_key
110
111
112def generate_pkcs12_bundle(server_cert, server_key):
113 """Creates a pkcs12 formated bundle.
114
115 Note: This uses pyOpenSSL as the cryptography package does not yet
116 support creating pkcs12 bundles. The currently un-released
117 2.5 version of cryptography supports reading pkcs12, but not
118 creation. This method should be updated to only use
119 cryptography once it supports creating pkcs12 bundles.
120
121 :param server_cert: A cryptography certificate (x509) object.
122 :param server_key: A cryptography key (x509) object.
123 :returns: A pkcs12 bundle.
124 """
125 # TODO(johnsom) Replace with cryptography once it supports creating pkcs12
126 pkcs12 = OpenSSL.crypto.PKCS12()
127 pkcs12.set_privatekey(
128 OpenSSL.crypto.PKey.from_cryptography_key(server_key))
129 pkcs12.set_certificate(OpenSSL.crypto.X509.from_cryptography(server_cert))
130 return pkcs12.export()