Common TLS utilies
Change-Id: I25c62a9d7cf23c5f89073929d3a1f511f6281934
This commit is contained in:
parent
2fc051b911
commit
6d53b86e4e
|
@ -79,6 +79,19 @@ class MissingArguments(OctaviaException):
|
||||||
message = _("Missing arguments.")
|
message = _("Missing arguments.")
|
||||||
|
|
||||||
|
|
||||||
|
class NeedsPassphrase(OctaviaException):
|
||||||
|
message = _("Passphrase needed to decrypt key but client "
|
||||||
|
"did not provide one.")
|
||||||
|
|
||||||
|
|
||||||
|
class UnreadableCert(OctaviaException):
|
||||||
|
message = _("Could not read X509 from PEM")
|
||||||
|
|
||||||
|
|
||||||
|
class MisMatchedKey(OctaviaException):
|
||||||
|
message = _("Key and x509 certificate do not match")
|
||||||
|
|
||||||
|
|
||||||
class CertificateStorageException(OctaviaException):
|
class CertificateStorageException(OctaviaException):
|
||||||
message = _('Could not store certificate: %(msg)s')
|
message = _('Could not store certificate: %(msg)s')
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
#
|
||||||
|
# Copyright 2014 Rackspace. 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.
|
||||||
|
|
||||||
|
from OpenSSL import crypto
|
||||||
|
from OpenSSL import SSL
|
||||||
|
import pyasn1.codec.der.decoder as decoder
|
||||||
|
import pyasn1_modules.rfc2459 as rfc2459
|
||||||
|
import six
|
||||||
|
|
||||||
|
import octavia.common.exceptions as exceptions
|
||||||
|
|
||||||
|
|
||||||
|
X509_BEG = "-----BEGIN CERTIFICATE-----"
|
||||||
|
X509_END = "-----END CERTIFICATE-----"
|
||||||
|
|
||||||
|
|
||||||
|
def validate_cert(certificate, private_key=None,
|
||||||
|
private_key_passphrase=None, intermediates=None):
|
||||||
|
"""Validate that the certificate is a valid PEM encoded X509 object
|
||||||
|
|
||||||
|
Optionally verify that the private key matches the certificate.
|
||||||
|
Optionally verify that the intermediates are valid X509 objects.
|
||||||
|
|
||||||
|
:param certificate: A PEM encoded certificate
|
||||||
|
:param private_key: The private key for the certificate
|
||||||
|
:param private_key_passphrase: Passphrase for accessing the private key
|
||||||
|
:param intermediates: PEM encoded intermediate certificates
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
x509 = _get_x509_from_pem_bytes(certificate)
|
||||||
|
if intermediates:
|
||||||
|
for x509Pem in _split_x509s(intermediates):
|
||||||
|
_get_x509_from_pem_bytes(x509Pem)
|
||||||
|
if private_key:
|
||||||
|
pkey = _read_privatekey(
|
||||||
|
private_key, passphrase=private_key_passphrase)
|
||||||
|
ctx = SSL.Context(SSL.TLSv1_METHOD)
|
||||||
|
ctx.use_certificate(x509)
|
||||||
|
try:
|
||||||
|
ctx.use_privatekey(pkey)
|
||||||
|
ctx.check_privatekey()
|
||||||
|
except Exception:
|
||||||
|
raise exceptions.MisMatchedKey
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _read_privatekey(privatekey_pem, passphrase=None):
|
||||||
|
def cb(*args):
|
||||||
|
if passphrase:
|
||||||
|
return six.b(passphrase)
|
||||||
|
else:
|
||||||
|
raise exceptions.NeedsPassphrase
|
||||||
|
return crypto.load_privatekey(crypto.FILETYPE_PEM, privatekey_pem, cb)
|
||||||
|
|
||||||
|
|
||||||
|
def _split_x509s(x509Str):
|
||||||
|
"""Split the input string into individual x509 text blocks
|
||||||
|
|
||||||
|
:param x509Str: A large multi x509 certificate blcok
|
||||||
|
:returns: A list of strings where each string represents an
|
||||||
|
X509 pem block surrounded by BEGIN CERTIFICATE,
|
||||||
|
END CERTIFICATE block tags
|
||||||
|
"""
|
||||||
|
curr_pem_block = []
|
||||||
|
inside_x509 = False
|
||||||
|
for line in x509Str.replace("\r", "").split("\n"):
|
||||||
|
if inside_x509:
|
||||||
|
curr_pem_block.append(line)
|
||||||
|
if line == X509_END:
|
||||||
|
yield "\n".join(curr_pem_block)
|
||||||
|
curr_pem_block = []
|
||||||
|
inside_x509 = False
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if line == X509_BEG:
|
||||||
|
curr_pem_block.append(line)
|
||||||
|
inside_x509 = True
|
||||||
|
|
||||||
|
|
||||||
|
def get_host_names(certificate):
|
||||||
|
"""Extract the host names from the Pem encoded X509 certificate
|
||||||
|
|
||||||
|
:param certificate: A PEM encoded certificate
|
||||||
|
:returns: A dictionary containing the following keys:
|
||||||
|
['cn', 'dns_names']
|
||||||
|
where 'cn' is the CN from the SubjectName of the certificate, and
|
||||||
|
'dns_names' is a list of dNSNames (possibly empty) from
|
||||||
|
the SubjectAltNames of the certificate.
|
||||||
|
"""
|
||||||
|
|
||||||
|
x509 = _get_x509_from_pem_bytes(certificate)
|
||||||
|
hostNames = {}
|
||||||
|
if hasattr(x509.get_subject(), 'CN'):
|
||||||
|
hostNames['cn'] = x509.get_subject().CN
|
||||||
|
hostNames['dns_names'] = []
|
||||||
|
num_exts = x509.get_extension_count()
|
||||||
|
for i in range(0, num_exts):
|
||||||
|
ext = x509.get_extension(i)
|
||||||
|
if ext.get_short_name() == 'subjectAltName':
|
||||||
|
data = ext.get_data()
|
||||||
|
|
||||||
|
general_names_container = decoder.decode(
|
||||||
|
data, asn1Spec=rfc2459.GeneralNames())
|
||||||
|
for general_names in general_names_container[0]:
|
||||||
|
if general_names.getName() == 'dNSName':
|
||||||
|
octets = general_names.getComponent().asOctets()
|
||||||
|
hostNames['dns_names'].append(octets.encode('utf-8'))
|
||||||
|
return hostNames
|
||||||
|
|
||||||
|
|
||||||
|
def _get_x509_from_pem_bytes(certificate_pem):
|
||||||
|
"""Parse X509 data from a PEM encoded certificate
|
||||||
|
|
||||||
|
:param certificate_pem: Certificate in PEM format
|
||||||
|
:returns: pyOpenSSL high-level x509 data from the PEM string
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
x509 = crypto.load_certificate(crypto.FILETYPE_PEM,
|
||||||
|
certificate_pem)
|
||||||
|
except Exception:
|
||||||
|
raise exceptions.UnreadableCert
|
||||||
|
return x509
|
|
@ -0,0 +1,256 @@
|
||||||
|
#
|
||||||
|
# Copyright 2014 OpenStack Foundation. 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 octavia.common.exceptions as exceptions
|
||||||
|
import octavia.common.tls_utils.cert_parser as cert_parser
|
||||||
|
from octavia.tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
|
ALT_EXT_CRT = """-----BEGIN CERTIFICATE-----
|
||||||
|
MIIGxDCCBaygAwIBAgIGAUp0fCElMA0GCSqGSIb3DQEBDQUAMIGLMQswCQYDVQQG
|
||||||
|
EwJVUzEOMAwGA1UECAwFVGV4YXMxFDASBgNVBAcMC1NhbiBBbnRvbmlvMR4wHAYD
|
||||||
|
VQQKDBVPcGVuU3RhY2sgRXhwZXJpbWVudHMxFjAUBgNVBAsMDU5ldXRyb24gTGJh
|
||||||
|
YXMxHjAcBgNVBAMMFXd3dy5DTkZyb21TdWJqZWN0Lm9yZzAeFw0xNDExMjIwMDEx
|
||||||
|
MzlaFw0yMjEyMjEwMDExMzlaMIGLMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4
|
||||||
|
YXMxFDASBgNVBAcMC1NhbiBBbnRvbmlvMR4wHAYDVQQKDBVPcGVuU3RhY2sgRXhw
|
||||||
|
ZXJpbWVudHMxFjAUBgNVBAsMDU5ldXRyb24gTGJhYXMxHjAcBgNVBAMMFXd3dy5D
|
||||||
|
TkZyb21TdWJqZWN0Lm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||||
|
ALL1nmbDPUDps84i1sM3rhHrc+Dlu0N/wKQWKZFeiWUtF/pot19V3o0yXDpsg7W5
|
||||||
|
RkLMTFkZEcnQpyGdpAGjTjzmNXMZw99EzxsmrR3l6hUEISifVbvEuftYZT6jPxM5
|
||||||
|
ML6WAjFNaBEZPWtZi8CgX5xdjdrDNndwyHob49n7Nc/h1kVqqBqMILabTqC6yEcx
|
||||||
|
S/B+DugVuuYbEdYYYElQUMfM+mUdULrSqIVl2n5AvvSFjWzWzfgPyp4QKn+f7HVR
|
||||||
|
T62bh/XjQ88n1tMYNAEqixRZTPgqY1LFl9VJVgRp9fdL6ttMurOR3C0STJ5qCdKB
|
||||||
|
L7LrpbY4u8dEragRC6YAyI8CAwEAAaOCAyowggMmMAwGA1UdEwEB/wQCMAAwDgYD
|
||||||
|
VR0PAQH/BAQDAgO4MIIDBAYDVR0RBIIC+zCCAveCGXd3dy5ob3N0RnJvbV9kTlNO
|
||||||
|
YW1lMS5jb22CGXd3dy5ob3N0RnJvbV9kTlNOYW1lMi5jb22CGXd3dy5ob3N0RnJv
|
||||||
|
bV9kTlNOYW1lMy5jb22BEW5vb25lQG5vd2hlcmUub3JnpIGPMIGMMQswCQYDVQQG
|
||||||
|
EwJVUzEOMAwGA1UECAwFVGV4YXMxFDASBgNVBAcMC1NhbiBBbnRvbmlvMR4wHAYD
|
||||||
|
VQQKDBVPcGVuU3RhY2sgRXhwZXJpbWVudHMxFjAUBgNVBAsMDU5ldXRyb24gTGJh
|
||||||
|
YXMxHzAdBgNVBAMMFnd3dy5jbkZyb21BbHROYW1lMS5vcmekgY8wgYwxCzAJBgNV
|
||||||
|
BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEUMBIGA1UEBwwLU2FuIEFudG9uaW8xHjAc
|
||||||
|
BgNVBAoMFU9wZW5TdGFjayBFeHBlcmltZW50czEWMBQGA1UECwwNTmV1dHJvbiBM
|
||||||
|
YmFhczEfMB0GA1UEAwwWd3d3LmNuRnJvbUFsdE5hbWUyLm9yZ6SBjzCBjDELMAkG
|
||||||
|
A1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMRQwEgYDVQQHDAtTYW4gQW50b25pbzEe
|
||||||
|
MBwGA1UECgwVT3BlblN0YWNrIEV4cGVyaW1lbnRzMRYwFAYDVQQLDA1OZXV0cm9u
|
||||||
|
IExiYWFzMR8wHQYDVQQDDBZ3d3cuY25Gcm9tQWx0TmFtZTMub3JnpIGPMIGMMQsw
|
||||||
|
CQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxFDASBgNVBAcMC1NhbiBBbnRvbmlv
|
||||||
|
MR4wHAYDVQQKDBVPcGVuU3RhY2sgRXhwZXJpbWVudHMxFjAUBgNVBAsMDU5ldXRy
|
||||||
|
b24gTGJhYXMxHzAdBgNVBAMMFnd3dy5jbkZyb21BbHROYW1lNC5vcmeHBAoBAgOH
|
||||||
|
EAEjRWeJq83v97PVkeaixICGFmh0dHA6Ly93d3cuZXhhbXBsZS5jb22CGXd3dy5o
|
||||||
|
b3N0RnJvbV9kTlNOYW1lNC5jb20wDQYJKoZIhvcNAQENBQADggEBAICUCDMhDf0f
|
||||||
|
cvX5mVnq4Q3+SM/nl03Gse6J0JdpFivS4hl+uZs0TAFYpfEPpAa7KKxD229kbCiQ
|
||||||
|
kyxf8fzADSl77RQbL6Lxa8K/c66mVNiuVvTHV4r/nDNcRYN9fGArw/Ho7VX+HVQ6
|
||||||
|
UW1t/uvXeyg695t7kzZmvg0ChD5kS848d2rXu2MhwHwXA8rbuK6gxVY97fbzBNlj
|
||||||
|
aiPJUAb8lqZMShd+3yVCgMmV0J20u2b5pSdO+LHQ7NfVqURk2pcHD8slfHzXT58q
|
||||||
|
YB90v0pSVP6mzHGyLxETZZz0nhaH9EjOyFkQI84ORT8Kmd5Y04gSI0LTKKF1eMNE
|
||||||
|
TyNC+MtsRdA=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
"""
|
||||||
|
|
||||||
|
SOME_OTHER_RSA_KEY = """
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIICWwIBAAKBgQDDnJL9dAdDpjoq4tksTJmdM0AjIHa7Y2yc8XwU7YkgrOR0m4Po
|
||||||
|
r7El0NwWf5i/LFudX1cOkfwemMIPwQ+67k0BVu/W3SR+g9ZzVKZtTBJnDoqMZ4RJ
|
||||||
|
jBk4gfwhnQYKPIQvdilDZReH3hFcBvPUkYWSHMn17FBTGmNzp2AnMdLpQQIDAQAB
|
||||||
|
AoGAIlew7tKaG+RpPfJJ0p84MQM4dXJTph6UiRFUiZASjSwNh/Ntu0JtRYhfu4t3
|
||||||
|
U8kD5KNCc4ppyy1ilMV+b4E6/3ydz6syMeJ7G24/PMU8d44zDgZXdM1pf5Nlosh1
|
||||||
|
BVv1Fvb0PBW2xs9VRlO6W62IWVtsZCGXYNayrXDiRZ50IGkCQQDkmOVEqffz3GeD
|
||||||
|
A+XWp9YrXeMqOmtPcrOuvMIO9DwrlXb8eNwvG5GxbuHGuZfOp01tiPyQrkxM0JzU
|
||||||
|
y8iD1pjrAkEA2w9topUzYS/NZt45OD9t5ZBVMfP15AwWRVv7V5uTksTqfZ9tFfh6
|
||||||
|
pN4oWe6xK/kgKAdE9hkjubGKQBjJSC27gwJAGZlRm1XZUXKuGMrX8yjKYALcjH8M
|
||||||
|
Q1JZ8shqhtgs4MiVEYLLTW8t6ou7NtDTwi2UCx8bAWyzWKrH1UCYzMK8TwJAMngU
|
||||||
|
fz+2ra5wuUF7l1ztudUN+8tEHH04aFRvzNhYIJljmPuxCz3LK87PJyEaCpKD+RTr
|
||||||
|
q3NRSsf/nRLY1NtMdwJAVKOdUCwZKGpGyOUZPRbZZAPlojIff2CxJ6E2Pr0RbShD
|
||||||
|
31icKmhIY+e2rP6v5W7hzTGge5PA0hRfCiwyd+zLoQ==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
|
"""
|
||||||
|
|
||||||
|
ALT_EXT_CRT_KEY = """
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEowIBAAKCAQEAsvWeZsM9QOmzziLWwzeuEetz4OW7Q3/ApBYpkV6JZS0X+mi3
|
||||||
|
X1XejTJcOmyDtblGQsxMWRkRydCnIZ2kAaNOPOY1cxnD30TPGyatHeXqFQQhKJ9V
|
||||||
|
u8S5+1hlPqM/EzkwvpYCMU1oERk9a1mLwKBfnF2N2sM2d3DIehvj2fs1z+HWRWqo
|
||||||
|
GowgtptOoLrIRzFL8H4O6BW65hsR1hhgSVBQx8z6ZR1QutKohWXafkC+9IWNbNbN
|
||||||
|
+A/KnhAqf5/sdVFPrZuH9eNDzyfW0xg0ASqLFFlM+CpjUsWX1UlWBGn190vq20y6
|
||||||
|
s5HcLRJMnmoJ0oEvsuultji7x0StqBELpgDIjwIDAQABAoIBAC3DX6FZtfU+jgtd
|
||||||
|
n1vGhk3wzu4o8S0+ow2S2UhiS3JDCMmxM4s+ky26Phl2nGvBGDWGttNl9MWOBN80
|
||||||
|
x7bfgudR20M2yH70wp1n04c8vxJmvu/7ZtogYYrjvOg6qKuKyWtDQwZGjCErOiiU
|
||||||
|
eodku25qAhd6Khh7D9kh/q9EbSteYFXsqJiNrY4ul1+cROMZpHx63xY6AzPmkvSU
|
||||||
|
garkgY4rw9E71t7it2laWkRKVsd+kEjayritdEEliNMVFFtrGEgplYkmLxGf0HLi
|
||||||
|
ROFVMCLRW/P12JpXllFPrBb8rlPL4w1c/s+yStohT0K+o4FLXhsf/inxmfc9XnZX
|
||||||
|
dJm0k/ECgYEA47FpV1caMk+TNPfu318VCGRmjwpXdmkNaUiX2Uvs3xIKQ6KJmpo3
|
||||||
|
sj0YjQEmQVz8s6geStvU1LdPxgsWZfbDt31M6SNwylh82ABQF1bZyrcMRxM8bHhe
|
||||||
|
bhDITM1dAn6aROkS1cBpfR9NJOFD850lmJvBGR9ORVBGyucTKH5uXxkCgYEAyTU0
|
||||||
|
zQKW2aU3J7mTCC9cp+eSD3fubJpa3ML5XfQ8YNID4PsxWglNKPcOTC4yaSfxVmyk
|
||||||
|
S0WIQUazCstszQsvwy9YyHtpkMq+0lyCPvrYnmRV0zx5zT155V2zcEh/oj64eoee
|
||||||
|
W5kvJSs/x6vT+lEN0TDEJ2gKEaJuBt6JG6P04ecCgYBSNw1CbEEZSYJt7dhi74I4
|
||||||
|
tYgSvjk2mFgvW/b4j2HIaksqgNYO7QCPa2AiCfg2Qc09UcceYKJI7Kfxaq97wc6J
|
||||||
|
wsSyqglgBvONSw+gXcvmVpIoV9nJkO0H8SdiFAUxkWVC3KXgaMmuVE8WsgBHRsb8
|
||||||
|
g8EFwTgR7xqgyS8xv/U6gQKBgQCdUr/dSJgAx6EPq5degAHXu0ZGWAUR38MJ+F2Y
|
||||||
|
6/5FyhCEWoRlHP66+CmywTBjbnrSk5IG1PBL8ebOmu6QiJ2o5R1rbKvHLe/0dabV
|
||||||
|
bbfwaQ1+ZDvskZP9Fr3WHqnFh3shO2dDwcvOKTnuetj9UWEXXyUQltXAohubvWbB
|
||||||
|
OPqhowKBgB3t2oUSFJI8fSNQnQNkcespJTddr0oLEwgsIl4Q7rdFHLr+/c46svjJ
|
||||||
|
kPMtpfxDQvkgK2aWpS4OP0E2vSU/IfMEDmlypfKe2SaTtFehZSUwR4R1/ZhSL3iS
|
||||||
|
iMwJYgm98P27s4TEMdhlPNVJrj1FrD+4VrgpOsoM20EkZnTvel9s
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
|
"""
|
||||||
|
|
||||||
|
ENCRYPTED_PKCS8_CRT_KEY_PASSPHRASE = "test_passphrase"
|
||||||
|
|
||||||
|
ENCRYPTED_PKCS8_CRT_KEY = """-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||||
|
MIIE6TAbBgkqhkiG9w0BBQMwDgQIT04zko6pmJICAggABIIEyL/79sqzTQ7BsEjY
|
||||||
|
ao2Uhh3//mpNJfCDhjSZOmWL7s4+161cEqpxrfxo4bHH8fkZ60VZUQP8CjwwQUhP
|
||||||
|
4iwpv2bYbQwzlttZwTC6s28wh7FRtgVoVPTwvXJa6fl2zAjLtsjwLZ/556ez9xIJ
|
||||||
|
67hxkIK2EzGQaeEKI1+vVF5EKsgKiPEmgspOBxRPoVWTx49NooiakGnwaBoDyTob
|
||||||
|
8FMr8mF1EheNQ4kl1bPrl+csD7PPnfbWUdNVvMljEhS3cYamQDPEWyAzvaIr0rHh
|
||||||
|
/6h80L/G2+0fensrTspWJcjX+XDBwQPk+YMic0TJ3KvkC7p2iNJhjNrjhQ+APZWq
|
||||||
|
xYrjfcmdK0RaaoqN+1zeE1P2kWIJx9CQZVMeGhVzzcmPwJPDnJFpkU+8cgTWnUr/
|
||||||
|
Fh8YtDoDzLiAUcmV1Kk7LYtYPHuU8epuz5PYm49TbWzdS7PX5wqFAFmrVt5jysm4
|
||||||
|
D/Ox0r4KV1t7D/1gc1WRIu8oUXkIglCHWNpTyMK0kFPctAf/ua+DUFRE4eSx3rsX
|
||||||
|
ZKIymdF9v/WF1Ud0tsNeudQbVeXWS6UCR8m/rqe81W4npQm/uqUNla+6yaYUmHlk
|
||||||
|
tvw/m6pt+jKhn0XIRkMwHrTpIaMVvInMg0xpkRuc7Xj5A7vNnkypZRNZJHgy7WWC
|
||||||
|
6GpOCWJOltYaNy7tmAkSUHJ6kNjXK5a4fi30HknEaqKjFTQNGvcybulJ3MXUzds0
|
||||||
|
MJoTpvQfLzYQbMYZ/XRGND4lgeEbs29nWLPae8D5XlDeZQMin8EukPko8u8+YGbU
|
||||||
|
eWGOvDc+4/xrWrsq1i6R0uWq+Cyoql8oh0PNBlM04S7GAbu1pOD/tPcq/GNYcv/Q
|
||||||
|
vJcIz9KA3BNepq7tC8D88ggEvFjTsHKeW/OnuCxKducSna4Mq+GebU52tKjkLjFC
|
||||||
|
eLG4Vx0BY5xPH3gd7iyuAf7S+08BbinNZWjHLpdmR3vKK5YbLPiGSfcYQdClr6BK
|
||||||
|
9vNWH4TXmZMV+rWtfSeM/cbhCHwxT5Jx6N0OFAxOblQClWnUD79nGkEgn/GoY/Aj
|
||||||
|
FPNj8u2U/mJHgFHH3ClidYL9jJUvhGpTixB8nGgMjJ0wvFcp+5OysG3TsjqYkwR6
|
||||||
|
RRNBmM+iLEUFTrMZYb+edHvGJsMEMZ0qvjmZDsfDz6ax5M9zH/ORFcGplgIec8kj
|
||||||
|
I106+dqAVVrv1CrBf2N/pxV0OXVhgl6ECe/Ee1xYC2e2CiEgUnQtedu8ekgPgp73
|
||||||
|
tHcAiWMamLPTwXuL7jFtvWaQfkYBmrBdEx54+eZOfH/NgV3o8gbaWNHSxbfbwlXN
|
||||||
|
MvyJidZGkXU0DJtUUnO5i2S7ftKCdOzrrSA8HDTvxFUhxretYpF3NzPYpYkM7WJX
|
||||||
|
GM7bTMn37AWYqLZmdYYdjh1ZOH/wsM/3uxGBpyEyy4Urrr1ux7X1P0cL0O2P/72h
|
||||||
|
GRd499JLrRMrmmtQ4KrN7GCHdctvujhDP8zvmnaEyGVzg88XmDg50ZF3+8DmOOgX
|
||||||
|
EMZEYHO2Wi2uyFotFtZCuqoOJmGPPeGV8QrsRs82hnL1bcd6REUTWk0KsTt13lvF
|
||||||
|
WwMJugHFk5NQuse3P4Hh9smQrRrv1dvnpt7s4yKStKolXUaFWcXJvXVaDfR5266Y
|
||||||
|
p7cuYY1cAyI7gFfl5A==
|
||||||
|
-----END ENCRYPTED PRIVATE KEY-----
|
||||||
|
"""
|
||||||
|
|
||||||
|
UNENCRYPTED_PKCS8_CRT_KEY = """-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCy9Z5mwz1A6bPO
|
||||||
|
ItbDN64R63Pg5btDf8CkFimRXollLRf6aLdfVd6NMlw6bIO1uUZCzExZGRHJ0Kch
|
||||||
|
naQBo0485jVzGcPfRM8bJq0d5eoVBCEon1W7xLn7WGU+oz8TOTC+lgIxTWgRGT1r
|
||||||
|
WYvAoF+cXY3awzZ3cMh6G+PZ+zXP4dZFaqgajCC2m06gushHMUvwfg7oFbrmGxHW
|
||||||
|
GGBJUFDHzPplHVC60qiFZdp+QL70hY1s1s34D8qeECp/n+x1UU+tm4f140PPJ9bT
|
||||||
|
GDQBKosUWUz4KmNSxZfVSVYEafX3S+rbTLqzkdwtEkyeagnSgS+y66W2OLvHRK2o
|
||||||
|
EQumAMiPAgMBAAECggEALcNfoVm19T6OC12fW8aGTfDO7ijxLT6jDZLZSGJLckMI
|
||||||
|
ybEziz6TLbo+GXaca8EYNYa202X0xY4E3zTHtt+C51HbQzbIfvTCnWfThzy/Ema+
|
||||||
|
7/tm2iBhiuO86Dqoq4rJa0NDBkaMISs6KJR6h2S7bmoCF3oqGHsP2SH+r0RtK15g
|
||||||
|
VeyomI2tji6XX5xE4xmkfHrfFjoDM+aS9JSBquSBjivD0TvW3uK3aVpaREpWx36Q
|
||||||
|
SNrKuK10QSWI0xUUW2sYSCmViSYvEZ/QcuJE4VUwItFb8/XYmleWUU+sFvyuU8vj
|
||||||
|
DVz+z7JK2iFPQr6jgUteGx/+KfGZ9z1edld0mbST8QKBgQDjsWlXVxoyT5M09+7f
|
||||||
|
XxUIZGaPCld2aQ1pSJfZS+zfEgpDoomamjeyPRiNASZBXPyzqB5K29TUt0/GCxZl
|
||||||
|
9sO3fUzpI3DKWHzYAFAXVtnKtwxHEzxseF5uEMhMzV0CfppE6RLVwGl9H00k4UPz
|
||||||
|
nSWYm8EZH05FUEbK5xMofm5fGQKBgQDJNTTNApbZpTcnuZMIL1yn55IPd+5smlrc
|
||||||
|
wvld9Dxg0gPg+zFaCU0o9w5MLjJpJ/FWbKRLRYhBRrMKy2zNCy/DL1jIe2mQyr7S
|
||||||
|
XII++tieZFXTPHnNPXnlXbNwSH+iPrh6h55bmS8lKz/Hq9P6UQ3RMMQnaAoRom4G
|
||||||
|
3okbo/Th5wKBgFI3DUJsQRlJgm3t2GLvgji1iBK+OTaYWC9b9viPYchqSyqA1g7t
|
||||||
|
AI9rYCIJ+DZBzT1Rxx5gokjsp/Fqr3vBzonCxLKqCWAG841LD6Bdy+ZWkihX2cmQ
|
||||||
|
7QfxJ2IUBTGRZULcpeBoya5UTxayAEdGxvyDwQXBOBHvGqDJLzG/9TqBAoGBAJ1S
|
||||||
|
v91ImADHoQ+rl16AAde7RkZYBRHfwwn4XZjr/kXKEIRahGUc/rr4KbLBMGNuetKT
|
||||||
|
kgbU8Evx5s6a7pCInajlHWtsq8ct7/R1ptVtt/BpDX5kO+yRk/0WvdYeqcWHeyE7
|
||||||
|
Z0PBy84pOe562P1RYRdfJRCW1cCiG5u9ZsE4+qGjAoGAHe3ahRIUkjx9I1CdA2Rx
|
||||||
|
6yklN12vSgsTCCwiXhDut0Ucuv79zjqy+MmQ8y2l/ENC+SArZpalLg4/QTa9JT8h
|
||||||
|
8wQOaXKl8p7ZJpO0V6FlJTBHhHX9mFIveJKIzAliCb3w/buzhMQx2GU81UmuPUWs
|
||||||
|
P7hWuCk6ygzbQSRmdO96X2w=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXPECTED_IMD_SUBJS = ["IMD3", "IMD2", "IMD1"]
|
||||||
|
|
||||||
|
X509_IMDS = """Junk
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBhDCCAS6gAwIBAgIGAUo7hO/eMA0GCSqGSIb3DQEBCwUAMA8xDTALBgNVBAMT
|
||||||
|
BElNRDIwHhcNMTQxMjExMjI0MjU1WhcNMjUxMTIzMjI0MjU1WjAPMQ0wCwYDVQQD
|
||||||
|
EwRJTUQzMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKHIPXo2pfD5dpnpVDVz4n43
|
||||||
|
zn3VYsjz/mgOZU0WIWjPA97mvulb7mwb4/LB4ijOMzHj9XfwP75GiOFxYFs8O80C
|
||||||
|
AwEAAaNwMG4wDwYDVR0TAQH/BAUwAwEB/zA8BgNVHSMENTAzgBS6rfnABCO3oHEz
|
||||||
|
NUUtov2hfXzfVaETpBEwDzENMAsGA1UEAxMESU1EMYIGAUo7hO/DMB0GA1UdDgQW
|
||||||
|
BBRiLW10LVJiFO/JOLsQFev0ToAcpzANBgkqhkiG9w0BAQsFAANBABtdF+89WuDi
|
||||||
|
TC0FqCocb7PWdTucaItD9Zn55G8KMd93eXrOE/FQDf1ScC+7j0jIHXjhnyu6k3NV
|
||||||
|
8el/x5gUHlc=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
Junk should be ignored by x509 splitter
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBhDCCAS6gAwIBAgIGAUo7hO/DMA0GCSqGSIb3DQEBCwUAMA8xDTALBgNVBAMT
|
||||||
|
BElNRDEwHhcNMTQxMjExMjI0MjU1WhcNMjUxMTIzMjI0MjU1WjAPMQ0wCwYDVQQD
|
||||||
|
EwRJTUQyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJYHqnsisVKTlwVaCSa2wdrv
|
||||||
|
CeJJzqpEVV0RVgAAF6FXjX2Tioii+HkXMR9zFgpE1w4yD7iu9JDb8yTdNh+NxysC
|
||||||
|
AwEAAaNwMG4wDwYDVR0TAQH/BAUwAwEB/zA8BgNVHSMENTAzgBQt3KvN8ncGj4/s
|
||||||
|
if1+wdvIMCoiE6ETpBEwDzENMAsGA1UEAxMEcm9vdIIGAUo7hO+mMB0GA1UdDgQW
|
||||||
|
BBS6rfnABCO3oHEzNUUtov2hfXzfVTANBgkqhkiG9w0BAQsFAANBAIlJODvtmpok
|
||||||
|
eoRPOb81MFwPTTGaIqafebVWfBlR0lmW8IwLhsOUdsQqSzoeypS3SJUBpYT1Uu2v
|
||||||
|
zEDOmgdMsBY=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
Junk should be thrown out like junk
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBfzCCASmgAwIBAgIGAUo7hO+mMA0GCSqGSIb3DQEBCwUAMA8xDTALBgNVBAMT
|
||||||
|
BHJvb3QwHhcNMTQxMjExMjI0MjU1WhcNMjUxMTIzMjI0MjU1WjAPMQ0wCwYDVQQD
|
||||||
|
EwRJTUQxMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI+tSJxr60ogwXFmgqbLMW7K
|
||||||
|
3fkQnh9sZBi7Qo6AzUnfe/AhXoisib651fOxKXCbp57IgzLTv7O9ygq3I+5fQqsC
|
||||||
|
AwEAAaNrMGkwDwYDVR0TAQH/BAUwAwEB/zA3BgNVHSMEMDAugBR73ZKSpjbsz9tZ
|
||||||
|
URkvFwpIO7gB4KETpBEwDzENMAsGA1UEAxMEcm9vdIIBATAdBgNVHQ4EFgQULdyr
|
||||||
|
zfJ3Bo+P7In9fsHbyDAqIhMwDQYJKoZIhvcNAQELBQADQQBenkZ2k7RgZqgj+dxA
|
||||||
|
D7BF8MN1oUAOpyYqAjkGddSEuMyNmwtHKZI1dyQ0gBIQdiU9yAG2oTbUIK4msbBV
|
||||||
|
uJIQ
|
||||||
|
-----END CERTIFICATE-----"""
|
||||||
|
|
||||||
|
|
||||||
|
class TestTLSParseUtils(base.TestCase):
|
||||||
|
def test_alt_subject_name_parses(self):
|
||||||
|
hosts = cert_parser.get_host_names(ALT_EXT_CRT)
|
||||||
|
self.assertEqual(hosts['cn'], 'www.CNFromSubject.org')
|
||||||
|
self.assertEqual(hosts['dns_names'][0], 'www.hostFrom_dNSName1.com')
|
||||||
|
self.assertEqual(hosts['dns_names'][1], 'www.hostFrom_dNSName2.com')
|
||||||
|
self.assertEqual(hosts['dns_names'][2], 'www.hostFrom_dNSName3.com')
|
||||||
|
self.assertEqual(hosts['dns_names'][3], 'www.hostFrom_dNSName4.com')
|
||||||
|
|
||||||
|
def test_x509_parses(self):
|
||||||
|
self.assertRaises(exceptions.UnreadableCert,
|
||||||
|
cert_parser.validate_cert, "BAD CERT")
|
||||||
|
self.assertTrue(cert_parser.validate_cert(ALT_EXT_CRT))
|
||||||
|
self.assertTrue(cert_parser.validate_cert(ALT_EXT_CRT,
|
||||||
|
private_key=UNENCRYPTED_PKCS8_CRT_KEY))
|
||||||
|
|
||||||
|
def test_read_private_key(self):
|
||||||
|
self.assertRaises(exceptions.NeedsPassphrase,
|
||||||
|
cert_parser._read_privatekey,
|
||||||
|
ENCRYPTED_PKCS8_CRT_KEY)
|
||||||
|
epkey = cert_parser._read_privatekey(
|
||||||
|
ENCRYPTED_PKCS8_CRT_KEY,
|
||||||
|
passphrase=ENCRYPTED_PKCS8_CRT_KEY_PASSPHRASE)
|
||||||
|
self.assertTrue(epkey.check())
|
||||||
|
|
||||||
|
def test_validate_cert_and_key_match(self):
|
||||||
|
self.assertTrue(
|
||||||
|
cert_parser.validate_cert(
|
||||||
|
ALT_EXT_CRT, private_key=ALT_EXT_CRT_KEY))
|
||||||
|
self.assertTrue(
|
||||||
|
cert_parser.validate_cert(
|
||||||
|
ALT_EXT_CRT, private_key=ALT_EXT_CRT_KEY,
|
||||||
|
intermediates=X509_IMDS))
|
||||||
|
self.assertRaises(exceptions.MisMatchedKey,
|
||||||
|
cert_parser.validate_cert,
|
||||||
|
ALT_EXT_CRT, private_key=SOME_OTHER_RSA_KEY)
|
||||||
|
|
||||||
|
def test_split_x509s(self):
|
||||||
|
imds = []
|
||||||
|
for x509Pem in cert_parser._split_x509s(X509_IMDS):
|
||||||
|
imds.append(cert_parser._get_x509_from_pem_bytes(x509Pem))
|
||||||
|
|
||||||
|
for i in xrange(0, len(imds)):
|
||||||
|
self.assertEqual(EXPECTED_IMD_SUBJS[i], imds[i].get_subject().CN)
|
|
@ -39,3 +39,5 @@ python-novaclient>=2.17.0
|
||||||
posix_ipc
|
posix_ipc
|
||||||
pyOpenSSL>=0.14
|
pyOpenSSL>=0.14
|
||||||
wsme==0.6.1
|
wsme==0.6.1
|
||||||
|
pyasn1
|
||||||
|
pyasn1_modules
|
||||||
|
|
Loading…
Reference in New Issue