Fix generate_pkcs12_bundle for FIPS

generate_pkcs12_bundle used the PKCS12 class of the pyOpenSSL module
which is not compliant with FIPS (uses SHA1).
Switch to the cryptography module for generating the PKCS bundles unless
for really old releases (<=3.0) that don't support it (stable/train is
still on 2.8).

Change-Id: Ibd50e9a6e406683b7faba093d716c83d2b994ad7
diff --git a/octavia_tempest_plugin/common/cert_utils.py b/octavia_tempest_plugin/common/cert_utils.py
index f99ce88..753da6b 100644
--- a/octavia_tempest_plugin/common/cert_utils.py
+++ b/octavia_tempest_plugin/common/cert_utils.py
@@ -17,6 +17,8 @@
 from cryptography.hazmat.backends import default_backend
 from cryptography.hazmat.primitives.asymmetric import rsa
 from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.serialization import NoEncryption
+from cryptography.hazmat.primitives.serialization import pkcs12
 from cryptography import x509
 from cryptography.x509.oid import NameOID
 import OpenSSL
@@ -184,12 +186,29 @@
     :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()
+    # Use the PKCS12 serialization function from cryptography if it exists
+    # (>=3.0), otherwise use the pyOpenSSL module.
+    #
+    # The PKCS12 class of the pyOpenSSL module is not compliant with FIPS.
+    # It uses the SHA1 function [0] which is not allowed when generating
+    # digital signatures [1]
+    #
+    # [0] https://github.com/pyca/pyopenssl/blob/
+    #       65ca53a7a06a7c78c1749200a6b3a007e47d3214/src/OpenSSL/
+    #       crypto.py#L2748-L2749
+    # [1] https://nvlpubs.nist.gov/nistpubs/SpecialPublications/
+    #       NIST.SP.800-131Ar1.pdf
+    if hasattr(pkcs12, 'serialize_key_and_certificates'):
+        p12 = pkcs12.serialize_key_and_certificates(
+            b'', server_key, server_cert,
+            cas=None, encryption_algorithm=NoEncryption())
+    else:
+        p12 = OpenSSL.crypto.PKCS12()
+        p12.set_privatekey(
+            OpenSSL.crypto.PKey.from_cryptography_key(server_key))
+        p12.set_certificate(OpenSSL.crypto.X509.from_cryptography(server_cert))
+        p12 = p12.export()
+    return p12
 
 
 def generate_certificate_revocation_list(ca_cert, ca_key, cert_to_revoke):