Load Balancing as a Service (LBaaS) for OpenStack
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
7.5KB

  1. # Copyright 2014 Rackspace US, Inc
  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. import datetime
  15. from cryptography import exceptions as crypto_exceptions
  16. from cryptography.hazmat import backends
  17. from cryptography.hazmat.primitives import hashes
  18. from cryptography.hazmat.primitives import serialization
  19. from cryptography import x509
  20. import octavia.certificates.generator.local as local_cert_gen
  21. from octavia.tests.unit.certificates.generator import local_csr
  22. class TestLocalGenerator(local_csr.BaseLocalCSRTestCase):
  23. def setUp(self):
  24. super(TestLocalGenerator, self).setUp()
  25. self.signing_digest = "sha256"
  26. # Setup CA data
  27. ca_cert = x509.CertificateBuilder()
  28. valid_from_datetime = datetime.datetime.utcnow()
  29. valid_until_datetime = (datetime.datetime.utcnow() +
  30. datetime.timedelta(
  31. seconds=2 * 365 * 24 * 60 * 60))
  32. ca_cert = ca_cert.not_valid_before(valid_from_datetime)
  33. ca_cert = ca_cert.not_valid_after(valid_until_datetime)
  34. ca_cert = ca_cert.serial_number(1)
  35. subject_name = x509.Name([
  36. x509.NameAttribute(x509.oid.NameOID.COUNTRY_NAME, u"US"),
  37. x509.NameAttribute(x509.oid.NameOID.STATE_OR_PROVINCE_NAME,
  38. u"Oregon"),
  39. x509.NameAttribute(x509.oid.NameOID.LOCALITY_NAME, u"Springfield"),
  40. x509.NameAttribute(x509.oid.NameOID.ORGANIZATION_NAME,
  41. u"Springfield Nuclear Power Plant"),
  42. x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, u"maggie1"),
  43. ])
  44. ca_cert = ca_cert.subject_name(subject_name)
  45. ca_cert = ca_cert.issuer_name(subject_name)
  46. ca_cert = ca_cert.public_key(self.ca_key.public_key())
  47. signed_cert = ca_cert.sign(private_key=self.ca_key,
  48. algorithm=hashes.SHA256(),
  49. backend=backends.default_backend())
  50. self.ca_certificate = signed_cert.public_bytes(
  51. encoding=serialization.Encoding.PEM)
  52. self.cert_generator = local_cert_gen.LocalCertGenerator
  53. def test_sign_cert(self):
  54. # Attempt sign a cert
  55. signed_cert = self.cert_generator.sign_cert(
  56. csr=self.certificate_signing_request,
  57. validity=2 * 365 * 24 * 60 * 60,
  58. ca_cert=self.ca_certificate,
  59. ca_key=self.ca_private_key,
  60. ca_key_pass=self.ca_private_key_passphrase,
  61. ca_digest=self.signing_digest
  62. )
  63. self.assertIn("-----BEGIN CERTIFICATE-----",
  64. signed_cert.decode('ascii'))
  65. # Load the cert for specific tests
  66. cert = x509.load_pem_x509_certificate(
  67. data=signed_cert, backend=backends.default_backend())
  68. # Make sure expiry time is accurate
  69. should_expire = (datetime.datetime.utcnow() +
  70. datetime.timedelta(seconds=2 * 365 * 24 * 60 * 60))
  71. diff = should_expire - cert.not_valid_after
  72. self.assertLess(diff, datetime.timedelta(seconds=10))
  73. # Make sure this is a version 3 X509.
  74. self.assertEqual('v3', cert.version.name)
  75. # Make sure this cert is marked as Server and Client Cert via the
  76. # extended Key Usage extension
  77. self.assertIn(x509.oid.ExtendedKeyUsageOID.SERVER_AUTH,
  78. cert.extensions.get_extension_for_class(
  79. x509.ExtendedKeyUsage).value._usages)
  80. self.assertIn(x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH,
  81. cert.extensions.get_extension_for_class(
  82. x509.ExtendedKeyUsage).value._usages)
  83. # Make sure this cert can't sign other certs
  84. self.assertFalse(cert.extensions.get_extension_for_class(
  85. x509.BasicConstraints).value.ca)
  86. def test_sign_cert_passphrase_none(self):
  87. # Attempt sign a cert
  88. ca_private_key = self.ca_key.private_bytes(
  89. encoding=serialization.Encoding.PEM,
  90. format=serialization.PrivateFormat.TraditionalOpenSSL,
  91. encryption_algorithm=serialization.NoEncryption()
  92. )
  93. signed_cert = self.cert_generator.sign_cert(
  94. csr=self.certificate_signing_request,
  95. validity=2 * 365 * 24 * 60 * 60,
  96. ca_cert=self.ca_certificate,
  97. ca_key=ca_private_key,
  98. ca_key_pass=None,
  99. ca_digest=self.signing_digest
  100. )
  101. self.assertIn("-----BEGIN CERTIFICATE-----",
  102. signed_cert.decode('ascii'))
  103. # Load the cert for specific tests
  104. cert = x509.load_pem_x509_certificate(
  105. data=signed_cert, backend=backends.default_backend())
  106. # Make sure expiry time is accurate
  107. should_expire = (datetime.datetime.utcnow() +
  108. datetime.timedelta(seconds=2 * 365 * 24 * 60 * 60))
  109. diff = should_expire - cert.not_valid_after
  110. self.assertLess(diff, datetime.timedelta(seconds=10))
  111. # Make sure this is a version 3 X509.
  112. self.assertEqual('v3', cert.version.name)
  113. # Make sure this cert is marked as Server and Client Cert via the
  114. # extended Key Usage extension
  115. self.assertIn(x509.oid.ExtendedKeyUsageOID.SERVER_AUTH,
  116. cert.extensions.get_extension_for_class(
  117. x509.ExtendedKeyUsage).value._usages)
  118. self.assertIn(x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH,
  119. cert.extensions.get_extension_for_class(
  120. x509.ExtendedKeyUsage).value._usages)
  121. # Make sure this cert can't sign other certs
  122. self.assertFalse(cert.extensions.get_extension_for_class(
  123. x509.BasicConstraints).value.ca)
  124. def test_sign_cert_invalid_algorithm(self):
  125. self.assertRaises(
  126. crypto_exceptions.UnsupportedAlgorithm,
  127. self.cert_generator.sign_cert,
  128. csr=self.certificate_signing_request,
  129. validity=2 * 365 * 24 * 60 * 60,
  130. ca_cert=self.ca_certificate,
  131. ca_key=self.ca_private_key,
  132. ca_key_pass=self.ca_private_key_passphrase,
  133. ca_digest='not_an_algorithm'
  134. )
  135. def test_generate_cert_key_pair(self):
  136. cn = 'testCN'
  137. bit_length = 512
  138. # Attempt to generate a cert/key pair
  139. cert_object = self.cert_generator.generate_cert_key_pair(
  140. cn=cn,
  141. validity=2 * 365 * 24 * 60 * 60,
  142. bit_length=bit_length,
  143. passphrase=self.ca_private_key_passphrase,
  144. ca_cert=self.ca_certificate,
  145. ca_key=self.ca_private_key,
  146. ca_key_pass=self.ca_private_key_passphrase
  147. )
  148. # Validate that the cert and key are loadable
  149. cert = x509.load_pem_x509_certificate(
  150. data=cert_object.certificate, backend=backends.default_backend())
  151. self.assertIsNotNone(cert)
  152. key = serialization.load_pem_private_key(
  153. data=cert_object.private_key,
  154. password=cert_object.private_key_passphrase,
  155. backend=backends.default_backend())
  156. self.assertIsNotNone(key)