# Authors: # Rob Crittenden # # Copyright (C) 2010 Red Hat # see file 'COPYING' for use and warranty information # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ Test the `ipalib.x509` module. """ import base64 from binascii import hexlify from configparser import RawConfigParser import datetime from io import StringIO import pickle import pytest from cryptography import x509 as crypto_x509 from cryptography.x509.general_name import DNSName from ipalib import x509 from ipapython.dn import DN pytestmark = pytest.mark.tier0 # certutil - # certificate for CN=ipa.example.com,O=IPA goodcert = ( b'MIICAjCCAWugAwIBAgICBEUwDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBB' b'IFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDYyNTEzMDA0MloXDTE1' b'MDYyNTEzMDA0MlowKDEMMAoGA1UEChMDSVBBMRgwFgYDVQQDEw9pcGEuZXhhbXBs' b'ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJcZ+H6+cQaN/BlzR8OY' b'kVeJgaU5tCaV9FF1m7Ws/ftPtTJUaSL1ncp6603rjA4tH1aa/B8i8xdC46+ZbY2a' b'u8b9ryGcOsx2uaRpNLEQ2Fy//q1kQC8oM+iD8Nd6osF0a2wnugsgnJHPuJzhViaW' b'xYgzk5DRdP81debokF3f3FX/AgMBAAGjOjA4MBEGCWCGSAGG+EIBAQQEAwIGQDAT' b'BgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEF' b'BQADgYEALD6X9V9w381AzzQPcHsjIjiX3B/AF9RCGocKZUDXkdDhsD9NZ3PLPEf1' b'AMjkraKG963HPB8scyiBbbSuSh6m7TCp0eDgRpo77zNuvd3U4Qpm0Qk+KEjtHQDj' b'NNG6N4ZnCQPmjFPScElvc/GgW7XMbywJy2euF+3/Uip8cnPgSH4=' ) goodcert_headers = ( b'-----BEGIN CERTIFICATE-----\n' + goodcert + b'\n-----END CERTIFICATE-----' ) # The base64-encoded string 'bad cert' badcert = ( b'-----BEGIN CERTIFICATE-----\n' b'YmFkIGNlcnQ=\r\n' b'-----END CERTIFICATE-----' ) good_pkcs7 = ( b'-----BEGIN PKCS7-----\n' b'MIIDvAYJKoZIhvcNAQcCoIIDrTCCA6kCAQExADALBgkqhkiG9w0BBwGgggOPMIID\n' b'izCCAnOgAwIBAgIBATANBgkqhkiG9w0BAQsFADA2MRQwEgYDVQQKDAtFWEFNUExF\n' b'LkNPTTEeMBwGA1UEAwwVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE3MDkyMDIw\n' b'NDI1N1oXDTM3MDkyMDIwNDI1N1owNjEUMBIGA1UECgwLRVhBTVBMRS5DT00xHjAc\n' b'BgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQAD\n' b'ggEPADCCAQoCggEBAMNojX57UCCPTtEn9tQJBS4By5NixwodKm1UqOGsiecDrB0i\n' b'Pw7D6uGP6g4b6srYtbh+YsRJnfekB2L08q1dX3LVEItq2TS0WKqgZuRZkw7DvnGl\n' b'eANMwjHmE8k6/E0yI3GGxJLAfDZYw6CDspLkyN9anjQwVCz5N5z5bpeqi5BeVwin\n' b'O8WVF6FNn3iyL66uwOsTGEzCo3Y5HiwqYgaND73TtdsBHcIqOdRql3CC3IdoXXcW\n' b'044w4Lm2E95MuY729pPBHREtyzVkYtyuoKJ8KApghIY5oCklBkRDjyFK4tE7iF/h\n' b's+valeT9vcz2bHMIpvbjqAu/kqE8MjcNEFPjLhcCAwEAAaOBozCBoDAfBgNVHSME\n' b'GDAWgBTUB04/d1eLhbMtBi4AB65tsAt+2TAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud\n' b'DwEB/wQEAwIBxjAdBgNVHQ4EFgQU1AdOP3dXi4WzLQYuAAeubbALftkwPQYIKwYB\n' b'BQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vaXBhLWNhLmdyZXlvYWsuY29t\n' b'L2NhL29jc3AwDQYJKoZIhvcNAQELBQADggEBADQFwX1uh8tqLq8SqWZWtH95j33o\n' b'5Ze2dW7sVppb/wVnNauG0wDQW7uIx+Ynr7GgufXLNBMn1aP/mA2CdHk7NZz2IB1s\n' b'ZvbIfE8dVxzkA+Hh9d6cdgk4eU5rGf6Fw8ScEJ/48Mmncea3uGkHcOmt+BGLA8a1\n' b'wtruy+iQylOkbv36CbxKV7IsZDP106Zc+cVeOUQZnCLKmvQkotn6UJd8N1X0R2J3\n' b'4/qv0rUtcCnyEBNSgpTGCRlYM4kd98Dqc5W7wUpMcsQMFxQMSYY7pFQkdLPfJEx2\n' b'Mg63SPawxfAgUeukrdsF3wTIKkIBu1TVse+kvRvgmRRrfF2a4ZOv5qORe2uhADEA\n' b'-----END PKCS7-----' ) long_oid_cert = b''' -----BEGIN CERTIFICATE----- MIIFiTCCBHGgAwIBAgITSAAAAAd1bEC5lsOdnQAAAAAABzANBgkqhkiG9w0BAQsF ADBLMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxEjAQBgoJkiaJk/IsZAEZFgJhZDEe MBwGA1UEAxMVYWQtV0lOLVBQSzAxNUY5TURRLUNBMB4XDTE3MDUyNTIzNDg0NVoX DTE5MDUyNTIzNTg0NVowNDESMBAGA1UEChMJSVBBLkxPQ0FMMR4wHAYDVQQDExVD ZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQDyyuty6irlL89hdaSW0UyAGLsOOMgAuJwBAeuRUorR159rsSnUXLcTHIsm EszKhwxp3NkkawRWx/s0UN1m2+RUwMl6gvlw+G80Mz0S77C77M+2lO8HRmZGm+Wu zBNcc9SANHuDQ1NISfZgLiscMS0+l0T3g6/Iqtg1kPWrq/tMevfh6tJEIedSBGo4 3xKEMSDkrvaeTuSVrgn/QT0m+WNccZa0c7X35L/hgR22/l5sr057Ef8F9vL8zUH5 TttFBIuiWJo8A8XX9I1zYIFhWjW3OVDZPBUnhGHH6yNyXGxXMRfcrrc74eTw8ivC 080AQuRtgwvDErB/JPDJ5w5t/ielAgMBAAGjggJ7MIICdzA9BgkrBgEEAYI3FQcE MDAuBiYrBgEEAYI3FQiEoqJGhYq1PoGllQqGi+F4nacAgRODs5gfgozzAAIBZAIB BTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUnSrC yW3CR0e3ilJdN6kL06P3KHMwHwYDVR0jBBgwFoAUj69xtyUNwp8on+NWO+HlxKyg X7AwgdgGA1UdHwSB0DCBzTCByqCBx6CBxIaBwWxkYXA6Ly8vQ049YWQtV0lOLVBQ SzAxNUY5TURRLUNBLENOPVdJTi1QUEswMTVGOU1EUSxDTj1DRFAsQ049UHVibGlj JTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixE Qz1hZCxEQz1sb2NhbD9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2Jq ZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwgcQGCCsGAQUFBwEBBIG3MIG0 MIGxBggrBgEFBQcwAoaBpGxkYXA6Ly8vQ049YWQtV0lOLVBQSzAxNUY5TURRLUNB LENOPUFJQSxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxD Tj1Db25maWd1cmF0aW9uLERDPWFkLERDPWxvY2FsP2NBQ2VydGlmaWNhdGU/YmFz ZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0aG9yaXR5MDMGA1UdIAQsMCow KAYmKwYBBAGCNxUIhKKiRoWKtT6BpZUKhovheJ2nAIEThrXzUYabpA4wDQYJKoZI hvcNAQELBQADggEBAIsFS+Qc/ufTrkuHbMmzksOpxq+OIi9rot8zy9/1Vmj6d+iP kB+vQ1u4/IhdQArJFNhsBzWSY9Pi8ZclovpepFeEZfXPUenyeRCU43HdMXcHXnlP YZfyLQWOugdo1WxK6S9qQSOSlC7BSGZWvKkiAPAwr4zNbbS+ROA2w0xaYMv0rr5W A4UAyzZAdqaGRJBRvCZ/uFHM5wMw0LzNCL4CqKW9jfZX0Fc2tdGx8zbTYxIdgr2D PL25as32r3S/m4uWqoQaK0lxK5Y97eusK2rrmidy32Jctzwl29UWq8kpjRAuD8iR CSc7sKqOf+fn3+fKITR2/DcSVvb0SGCr5fVVnjQ= -----END CERTIFICATE----- ''' ipa_demo_crt = b'''\ -----BEGIN CERTIFICATE----- MIIGFTCCBP2gAwIBAgISA61CoqWtpZoTEyfLCXliPLYFMA0GCSqGSIb3DQEBCwUA MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODA3MjUwNTM2NTlaFw0x ODEwMjMwNTM2NTlaMCAxHjAcBgNVBAMTFWlwYS5kZW1vMS5mcmVlaXBhLm9yZzCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKisvYUdarWE0CS9i+RcNf9Q 41Euw36R4Myf/PUCDVUvGsVXQWSCanbtyxa8Ows4cAHrfqhiKAnSg0IhLqCMJVQ8 8F699FHrP9EfPmZkG3RMLYPxKNrSmOVyNpIEQY9qfkDXZPLung6dk/c225Znoltq bVWLObXA7eP9C/djupg3gUD7vOAMHFmfZ3OKnx1uktL5p707o2/qlkSiEO4Z5ebD M8X0dTkN8V3LCCOjzCp88itGUWJM8Tjb86WkmYkJxmeZx6REd37rDXjqgYhwgXOB bSqDkYKRaihwvd5Up/vE1wApBS1k7b1oEW80teDUbzbaaqp7oBWbZD2Ac1yJF7UC AwEAAaOCAx0wggMZMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcD AQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUUmTMI1CB6qFMXc0+ AGmqpfBAwhIwHwYDVR0jBBgwFoAUqEpqYwR93brm0Tm3pkVl7/Oo7KEwbwYIKwYB BQUHAQEEYzBhMC4GCCsGAQUFBzABhiJodHRwOi8vb2NzcC5pbnQteDMubGV0c2Vu Y3J5cHQub3JnMC8GCCsGAQUFBzAChiNodHRwOi8vY2VydC5pbnQteDMubGV0c2Vu Y3J5cHQub3JnLzAgBgNVHREEGTAXghVpcGEuZGVtbzEuZnJlZWlwYS5vcmcwgf4G A1UdIASB9jCB8zAIBgZngQwBAgEwgeYGCysGAQQBgt8TAQEBMIHWMCYGCCsGAQUF BwIBFhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCBqwYIKwYBBQUHAgIwgZ4M gZtUaGlzIENlcnRpZmljYXRlIG1heSBvbmx5IGJlIHJlbGllZCB1cG9uIGJ5IFJl bHlpbmcgUGFydGllcyBhbmQgb25seSBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIENl cnRpZmljYXRlIFBvbGljeSBmb3VuZCBhdCBodHRwczovL2xldHNlbmNyeXB0Lm9y Zy9yZXBvc2l0b3J5LzCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AMEWSuCnctLU OS3ICsEHcNTwxJvemRpIQMH6B1Fk9jNgAAABZNAnsSAAAAQDAEcwRQIgHkd/UkTZ w8iV1Ox8MPHLrpY33cX6i5FV6w9+7YH3H2kCIQCVcrhsr4fokDyE2ueUqSFxkBVH WND84/w5rFNAPjyO1QB2ACk8UZZUyDlluqpQ/FgH1Ldvv1h6KXLcpMMM9OVFR/R4 AAABZNAnsyUAAAQDAEcwRQIhALDWY2k55abu7IPwnFvMr4Zqd1DYQXEKWZEQLXUP s4XGAiAabjpUwrLKVXpbp4WNLkTNlFjrSJafOzLG68H9AnoD4zANBgkqhkiG9w0B AQsFAAOCAQEAfBNuQn/A2olJHxoBGLfMcQCkkNOfvBpfQeKgni2VVM+r1ZY8YVXx OtVnV6XQ5M+l+6xlRpP1IwDdmJd/yaQgwbmYf4zl94W/s/qq4nlTd9G4ahmJOhlc mWeIQMoEtAmQlIOqWto+Knfakz6Xyo+HVCQEyeoBmYFGZcakeAm6tp/6qtpkej+4 wBjShMPAdSYDPRaAqnZ3BAK2UmmlpAA5tkNvqOaHBCi760zYoxT6j1an7FotG0v9 2+W0aL34eMWKz/g4qhwk+Jiz45LLQWhHGIgXIUoNSzHgLIVuVOQI8DPsguvT6GHW QUs1Hx1wL7mL4U8fKCFDKA+ds2B2xWgoZg== -----END CERTIFICATE----- ''' v1_cert = b'''\ -----BEGIN CERTIFICATE----- MIICwTCCAakCFG3lgHmtal7cilKoevNM/kD4gIToMA0GCSqGSIb3DQEBCwUAMB8x HTAbBgNVBAMMFEV4YW1wbGUtVGVzdC1DQS0xMTg4MB4XDTIxMDYxMTE5NTgwNVoX DTIxMDYxMjE5NTgwNVowGzEZMBcGA1UEAwwQaXBhLmV4YW1wbGUudGVzdDCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALsi+qZj7MB/okR4QFUYBHgLyFXr TVd4ENDYERPhHddMkShWsAD6jG7bo/fvrWdaVKdoawghQZymI0o7VVwwuu5+EVA+ gp/vKQM+QiF2fnbprLKVdZHexqdCyo0lMSGDeSobg3iH8iHiq4StYkGyXuUzcbgf 6avajlASGC7b4W7RahTION+GJFrP/eW392Oceu6idY6rl3Joyo9SY+zX+pAR0tDC +ixaYWkk9UxVuh4ObRToNLlHsnBWs3D6eZUiwBoX5QALWxwtdmsofwEOg3D+a2/h RihBnZzghQUOf9pjcu/jdgUzd0fsH9FpZVad3HjQmGq2Vgy/rT6STG9ojecCAwEA ATANBgkqhkiG9w0BAQsFAAOCAQEAMdB8pCPqEsJY5bnJNdr6EXdEIHk/l2P8tWJs wlpdAcOm5NfeZkOkGVYC4HTPNkMQ+K7K7VqHNT7hDjdNS0Gp/LVoHxBrQPAgsM7I RTZteGkCqIEBUxXvX2hKnMtuuAe9ljYlVF1P+WsV7qXP/M7RsWb2d+9ubA28mYD/ lhW/TB0/2EzP6QuiMh7bURIoQWw/733cfMIoP7XRVGn5Ux2z+o2hl5oOjHl7KBDa /6PWd4wOMU/cY2fOPPJQ7eSGJh4VCe64au3S6zAtoTE8XXweo/cDD70NZnmwdeGQ bswNlxWfohaW0FzTRfTMbIrwoUCWil/Uw2kBYnld15gwzuLDNQ== -----END CERTIFICATE----- ''' class test_x509: """ Test `ipalib.x509` I created the contents of this certificate with a self-signed CA with: % certutil -R -s "CN=ipa.example.com,O=IPA" -d . -a -o example.csr % ./ipa host-add ipa.example.com % ./ipa cert-request --add --principal=test/ipa.example.com example.csr """ def test_1_load_base64_cert(self): """ Test loading a base64-encoded certificate. """ # Load a good cert x509.load_pem_x509_certificate(goodcert_headers) # Load a good cert with headers and leading text newcert = ( b'leading text\n' + goodcert_headers) x509.load_pem_x509_certificate(newcert) # Load a good cert with bad headers newcert = b'-----BEGIN CERTIFICATE-----' + goodcert_headers with pytest.raises((TypeError, ValueError)): x509.load_pem_x509_certificate(newcert) # Load a bad cert with pytest.raises(ValueError): x509.load_pem_x509_certificate(badcert) def test_1_load_der_cert(self): """ Test loading a DER certificate. """ der = base64.b64decode(goodcert) # Load a good cert x509.load_der_x509_certificate(der) def test_3_cert_contents(self): """ Test the contents of a certificate """ # Verify certificate contents. This exercises python-cryptography # more than anything but confirms our usage of it. not_before = datetime.datetime(2010, 6, 25, 13, 0, 42) not_after = datetime.datetime(2015, 6, 25, 13, 0, 42) cert = x509.load_pem_x509_certificate(goodcert_headers) assert DN(cert.subject) == DN(('CN', 'ipa.example.com'), ('O', 'IPA')) assert DN(cert.issuer) == DN(('CN', 'IPA Test Certificate Authority')) assert cert.serial_number == 1093 assert cert.not_valid_before == not_before assert cert.not_valid_after == not_after assert cert.san_general_names == [] assert cert.san_a_label_dns_names == [] assert cert.extended_key_usage == {'1.3.6.1.5.5.7.3.1'} assert cert.extended_key_usage_bytes == ( b'0\x16\x06\x03U\x1d%\x01\x01\xff\x04\x0c0\n\x06\x08' b'+\x06\x01\x05\x05\x07\x03\x01' ) def test_load_pkcs7_pem(self): certlist = x509.pkcs7_to_certs(good_pkcs7, datatype=x509.PEM) assert len(certlist) == 1 cert = certlist[0] assert DN(cert.subject) == DN('CN=Certificate Authority,O=EXAMPLE.COM') assert cert.serial_number == 1 def test_long_oid(self): """ Test cerificate with very long OID. In this case we are using a certificate from an opened case where one of X509v3 Certificate`s Policies OID is longer then 80 chars. """ cert = x509.load_pem_x509_certificate(long_oid_cert) ext = cert.extensions.get_extension_for_class(crypto_x509. CertificatePolicies) assert len(ext.value) == 1 assert ext.value[0].policy_identifier.dotted_string == ( u'1.3.6.1.4.1.311.21.8.8950086.10656446.2706058.12775672.480128.' '147.13466065.13029902') def test_ipa_demo_letsencrypt(self): cert = x509.load_pem_x509_certificate(ipa_demo_crt) assert DN(cert.subject) == DN('CN=ipa.demo1.freeipa.org') assert DN(cert.issuer) == DN( "CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US") assert cert.serial_number == 0x03ad42a2a5ada59a131327cb0979623cb605 not_before = datetime.datetime(2018, 7, 25, 5, 36, 59) not_after = datetime.datetime(2018, 10, 23, 5, 36, 59) assert cert.not_valid_before == not_before assert cert.not_valid_after == not_after assert cert.san_general_names == [DNSName('ipa.demo1.freeipa.org')] assert cert.san_a_label_dns_names == ['ipa.demo1.freeipa.org'] assert cert.extended_key_usage == { '1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2' } assert cert.extended_key_usage_bytes == ( b'0 \x06\x03U\x1d%\x01\x01\xff\x04\x160\x14\x06\x08+\x06\x01' b'\x05\x05\x07\x03\x01\x06\x08+\x06\x01\x05\x05\x07\x03\x02' ) def test_x509_v1_cert(self): with pytest.raises(ValueError): x509.load_pem_x509_certificate(v1_cert) class test_ExternalCAProfile: def test_MSCSTemplateV1_good(self): o = x509.MSCSTemplateV1("MySubCA") assert hexlify(o.get_ext_data()) == b'1e0e004d007900530075006200430041' def test_MSCSTemplateV1_bad(self): with pytest.raises(ValueError): x509.MSCSTemplateV1("MySubCA:1") def test_MSCSTemplateV1_pickle_roundtrip(self): o = x509.MSCSTemplateV1("MySubCA") s = pickle.dumps(o) assert o.get_ext_data() == pickle.loads(s).get_ext_data() def test_MSCSTemplateV2_too_few_parts(self): with pytest.raises(ValueError): x509.MSCSTemplateV2("1.2.3.4") def test_MSCSTemplateV2_too_many_parts(self): with pytest.raises(ValueError): x509.MSCSTemplateV2("1.2.3.4:100:200:300") def test_MSCSTemplateV2_bad_oid(self): with pytest.raises(ValueError): x509.MSCSTemplateV2("not_an_oid:1") def test_MSCSTemplateV2_non_numeric_major_version(self): with pytest.raises(ValueError): x509.MSCSTemplateV2("1.2.3.4:major:200") def test_MSCSTemplateV2_non_numeric_minor_version(self): with pytest.raises(ValueError): x509.MSCSTemplateV2("1.2.3.4:100:minor") def test_MSCSTemplateV2_major_version_lt_zero(self): with pytest.raises(ValueError): x509.MSCSTemplateV2("1.2.3.4:-1:200") def test_MSCSTemplateV2_minor_version_lt_zero(self): with pytest.raises(ValueError): x509.MSCSTemplateV2("1.2.3.4:100:-1") def test_MSCSTemplateV2_major_version_gt_max(self): with pytest.raises(ValueError): x509.MSCSTemplateV2("1.2.3.4:4294967296:200") def test_MSCSTemplateV2_minor_version_gt_max(self): with pytest.raises(ValueError): x509.MSCSTemplateV2("1.2.3.4:100:4294967296") def test_MSCSTemplateV2_good_major(self): o = x509.MSCSTemplateV2("1.2.3.4:4294967295") assert hexlify(o.get_ext_data()) == b'300c06032a0304020500ffffffff' def test_MSCSTemplateV2_good_major_minor(self): o = x509.MSCSTemplateV2("1.2.3.4:4294967295:0") assert hexlify(o.get_ext_data()) \ == b'300f06032a0304020500ffffffff020100' def test_MSCSTemplateV2_pickle_roundtrip(self): o = x509.MSCSTemplateV2("1.2.3.4:4294967295:0") s = pickle.dumps(o) assert o.get_ext_data() == pickle.loads(s).get_ext_data() def test_ExternalCAProfile_dispatch(self): """ Test that constructing ExternalCAProfile actually returns an instance of the appropriate subclass. """ assert isinstance( x509.ExternalCAProfile("MySubCA"), x509.MSCSTemplateV1) assert isinstance( x509.ExternalCAProfile("1.2.3.4:100"), x509.MSCSTemplateV2) def test_write_pkispawn_config_file_MSCSTemplateV1(self): template = x509.MSCSTemplateV1(u"SubCA") expected = ( '[CA]\n' 'pki_req_ext_oid = 1.3.6.1.4.1.311.20.2\n' 'pki_req_ext_data = 1e0a00530075006200430041\n\n' ) self._test_write_pkispawn_config_file(template, expected) def test_write_pkispawn_config_file_MSCSTemplateV2(self): template = x509.MSCSTemplateV2(u"1.2.3.4:4294967295") expected = ( '[CA]\n' 'pki_req_ext_oid = 1.3.6.1.4.1.311.21.7\n' 'pki_req_ext_data = 300c06032a0304020500ffffffff\n\n' ) self._test_write_pkispawn_config_file(template, expected) def _test_write_pkispawn_config_file(self, template, expected): """ Test that the values we read from an ExternalCAProfile object can be used to produce a reasonable-looking pkispawn configuration. """ config = RawConfigParser() config.optionxform = str config.add_section("CA") config.set("CA", "pki_req_ext_oid", template.ext_oid) config.set("CA", "pki_req_ext_data", hexlify(template.get_ext_data()).decode('ascii')) out = StringIO() config.write(out) assert out.getvalue() == expected