| # Copyright 2018 Rackspace US Inc. All rights reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| # not use this file except in compliance with the License. You may obtain |
| # a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations |
| # under the License. |
| |
| import datetime |
| |
| from cryptography.hazmat.backends import default_backend |
| from cryptography.hazmat.primitives.asymmetric import rsa |
| from cryptography.hazmat.primitives import hashes |
| from cryptography import x509 |
| from cryptography.x509.oid import NameOID |
| import OpenSSL |
| |
| |
| def generate_ca_cert_and_key(): |
| """Creates a CA cert and key for testing. |
| |
| :returns: The cryptography CA cert and CA key objects. |
| """ |
| |
| ca_key = rsa.generate_private_key( |
| public_exponent=65537, key_size=2048, backend=default_backend()) |
| |
| subject = issuer = x509.Name([ |
| x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), |
| x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Denial"), |
| x509.NameAttribute(NameOID.LOCALITY_NAME, u"Corvallis"), |
| x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"OpenStack"), |
| x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"Octavia"), |
| x509.NameAttribute(NameOID.COMMON_NAME, u"ca_cert.example.com"), |
| ]) |
| |
| ca_cert = x509.CertificateBuilder().subject_name( |
| subject |
| ).issuer_name( |
| issuer |
| ).public_key( |
| ca_key.public_key() |
| ).serial_number( |
| x509.random_serial_number() |
| ).not_valid_before( |
| datetime.datetime.utcnow() |
| ).not_valid_after( |
| datetime.datetime.utcnow() + datetime.timedelta(days=10) |
| ).add_extension( |
| x509.SubjectAlternativeName([x509.DNSName(u"ca_cert.example.com")]), |
| critical=False, |
| ).add_extension( |
| x509.BasicConstraints(ca=True, path_length=None), |
| critical=True, |
| ).sign(ca_key, hashes.SHA256(), default_backend()) |
| |
| return ca_cert, ca_key |
| |
| |
| def generate_server_cert_and_key(ca_cert, ca_key, server_uuid): |
| """Creates a server cert and key for testing. |
| |
| :param ca_cert: A cryptography CA certificate (x509) object. |
| :param ca_key: A cryptography CA key (x509) object. |
| :param server_uuid: A UUID identifying the server. |
| :returns: The cryptography server cert and key objects. |
| """ |
| |
| server_key = rsa.generate_private_key( |
| public_exponent=65537, key_size=2048, backend=default_backend()) |
| |
| subject = x509.Name([ |
| x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"), |
| x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Denial"), |
| x509.NameAttribute(NameOID.LOCALITY_NAME, u"Corvallis"), |
| x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"OpenStack"), |
| x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"Octavia"), |
| x509.NameAttribute(NameOID.COMMON_NAME, u"{}.example.com".format( |
| server_uuid)), |
| ]) |
| |
| server_cert = x509.CertificateBuilder().subject_name( |
| subject |
| ).issuer_name( |
| ca_cert.subject |
| ).public_key( |
| server_key.public_key() |
| ).serial_number( |
| x509.random_serial_number() |
| ).not_valid_before( |
| datetime.datetime.utcnow() |
| ).not_valid_after( |
| datetime.datetime.utcnow() + datetime.timedelta(days=10) |
| ).add_extension( |
| x509.SubjectAlternativeName( |
| [x509.DNSName(u"{}.example.com".format(server_uuid))]), |
| critical=False, |
| ).add_extension( |
| x509.BasicConstraints(ca=False, path_length=None), |
| critical=True, |
| ).sign(ca_key, hashes.SHA256(), default_backend()) |
| |
| return server_cert, server_key |
| |
| |
| def generate_pkcs12_bundle(server_cert, server_key): |
| """Creates a pkcs12 formated bundle. |
| |
| Note: This uses pyOpenSSL as the cryptography package does not yet |
| support creating pkcs12 bundles. The currently un-released |
| 2.5 version of cryptography supports reading pkcs12, but not |
| creation. This method should be updated to only use |
| cryptography once it supports creating pkcs12 bundles. |
| |
| :param server_cert: A cryptography certificate (x509) object. |
| :param server_key: A cryptography key (x509) object. |
| :returns: A pkcs12 bundle. |
| """ |
| # TODO(johnsom) Replace with cryptography once it supports creating pkcs12 |
| pkcs12 = OpenSSL.crypto.PKCS12() |
| pkcs12.set_privatekey( |
| OpenSSL.crypto.PKey.from_cryptography_key(server_key)) |
| pkcs12.set_certificate(OpenSSL.crypto.X509.from_cryptography(server_cert)) |
| return pkcs12.export() |