summaryrefslogtreecommitdiffstats
path: root/collections-debian-merged/ansible_collections/community/crypto/tests/integration
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-14 20:03:01 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-14 20:03:01 +0000
commita453ac31f3428614cceb99027f8efbdb9258a40b (patch)
treef61f87408f32a8511cbd91799f9cececb53e0374 /collections-debian-merged/ansible_collections/community/crypto/tests/integration
parentInitial commit. (diff)
downloadansible-upstream.tar.xz
ansible-upstream.zip
Adding upstream version 2.10.7+merged+base+2.10.8+dfsg.upstream/2.10.7+merged+base+2.10.8+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'collections-debian-merged/ansible_collections/community/crypto/tests/integration')
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tasks/impl.yml283
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tasks/main.yml36
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tests/validate.yml137
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tasks/impl.yml82
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tasks/main.yml36
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tests/validate.yml40
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/impl.yml462
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/main.yml107
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/obtain-cert.yml144
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tests/validate.yml144
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/impl.yml89
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/main.yml36
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/obtain-cert.yml144
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tests/validate.yml16
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/tasks/main.yml30
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/tasks/obtain-cert.yml144
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tasks/impl.yml151
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tasks/main.yml36
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tests/validate.yml131
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/aliases1
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-chain.pem22
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-fullchain.pem51
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-root.pem16
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1.pem29
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-altchain.pem32
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-altroot.pem31
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-chain.pem27
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-fullchain.pem72
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-root.pem20
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2.pem45
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots.pem3733
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_Certification_Authority.pem25
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_ECC_Certification_Authority.pem16
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_RSA_Certification_Authority.pem34
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/DST_Root_CA_X3.pem20
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/ISRG_Root_X1.pem31
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/tasks/main.yml84
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/aliases15
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/defaults/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/tasks/main.yml220
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/vars/main.yml52
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/aliases15
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/defaults/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/tasks/main.yml275
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/vars/main.yml15
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/aliases3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/files/bogus_ca.pem18
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/files/process_certs.py28
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/meta/main.yml4
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/tasks/main.yml47
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/tests/validate.yml140
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/aliases7
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/files/keyfile11
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/files/keyfile21
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/main.yml41
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/run-test.yml8
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/create-destroy.yml195
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/device-check.yml56
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/key-management.yml202
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/options.yml49
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/passphrase.yml240
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/tasks/main.yml467
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/tasks/main.yml407
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/tests/validate.yml140
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/vars/main.yml7
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tasks/impl.yml997
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tasks/main.yml50
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tests/validate.yml346
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/tasks/impl.yml94
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/tasks/main.yml168
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/test_plugins/jinja_compatibility.py15
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/tasks/impl.yml92
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/tasks/main.yml41
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tasks/impl.yml101
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tasks/main.yml43
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tests/validate.yml58
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tasks/impl.yml287
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tasks/main.yml9
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tests/validate.yml68
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tasks/impl.yml851
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tasks/main.yml114
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tests/validate.yml215
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/vars/main.yml7
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/tasks/impl.yml178
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/tasks/main.yml77
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/tasks/impl.yml103
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/tasks/main.yml36
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tasks/impl.yml190
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tasks/main.yml54
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tests/validate.yml146
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/aliases3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/tasks/loop.yml28
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/tasks/main.yml113
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/defaults/main.yml4
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/tasks/default.yml64
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/tasks/main.yml27
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/vars/httptester.yml5
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_tests/tasks/main.yml0
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/tasks/main.yml22
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/tasks/obtain-cert.yml144
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/vars/main.yml9
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/tasks/main.yml102
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/Debian.yml4
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/FreeBSD.yml4
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/RedHat.yml4
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/Suse.yml4
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/main.yml9
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pkg_mgr/tasks/main.yml17
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/tasks/main.yml45
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/Debian.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/FreeBSD.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/RedHat.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/Suse.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/aliases1
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/tasks/main.yml13
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/handlers/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/default-cleanup.yml5
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/default.yml11
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/main.yml15
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_agent/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_agent/tasks/main.yml43
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/tasks/main.yml14
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/Debian.yml1
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/RedHat.yml1
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/Suse.yml1
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/tasks/impl.yml69
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/tasks/main.yml121
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/assertonly.yml154
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/expired.yml49
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/impl.yml8
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/main.yml27
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/ownca.yml580
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/removal.yml53
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/selfsigned.yml465
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tests/validate_ownca.yml178
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tests/validate_selfsigned.yml198
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/files/cert1.pem45
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/tasks/impl.yml125
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/tasks/main.yml183
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/test_plugins/jinja_compatibility.py15
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/meta/main.yml3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/tasks/impl.yml237
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/tasks/main.yml40
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/aliases3
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/meta/main.yml2
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tasks/impl.yml388
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tasks/main.yml88
-rw-r--r--collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tests/validate.yml82
199 files changed, 17493 insertions, 0 deletions
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/aliases
new file mode 100644
index 00000000..d7936330
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/aliases
@@ -0,0 +1,2 @@
+shippable/cloud/group1
+cloud/acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/meta/main.yml
new file mode 100644
index 00000000..81d1e7e7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tasks/impl.yml
new file mode 100644
index 00000000..4a0ff616
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tasks/impl.yml
@@ -0,0 +1,283 @@
+- name: Generate account keys
+ command: "{{ openssl_binary }} ecparam -name prime256v1 -genkey -out {{ output_dir }}/{{ item }}.pem"
+ loop:
+ - accountkey
+ - accountkey2
+ - accountkey3
+ - accountkey4
+ - accountkey5
+
+- name: Parse account keys (to ease debugging some test failures)
+ command: "{{ openssl_binary }} ec -in {{ output_dir }}/{{ item }}.pem -noout -text"
+ loop:
+ - accountkey
+ - accountkey2
+ - accountkey3
+ - accountkey4
+ - accountkey5
+
+- name: Do not try to create account
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ allow_creation: no
+ ignore_errors: yes
+ register: account_not_created
+
+- name: Create it now (check mode, diff)
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ allow_creation: yes
+ terms_agreed: yes
+ contact:
+ - mailto:example@example.org
+ check_mode: yes
+ diff: yes
+ register: account_created_check
+
+- name: Create it now
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ allow_creation: yes
+ terms_agreed: yes
+ contact:
+ - mailto:example@example.org
+ register: account_created
+
+- name: Create it now (idempotent)
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ allow_creation: yes
+ terms_agreed: yes
+ contact:
+ - mailto:example@example.org
+ register: account_created_idempotent
+
+- name: Change email address (check mode, diff)
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_content: "{{ lookup('file', output_dir ~ '/accountkey.pem') }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ # allow_creation: no
+ contact:
+ - mailto:example@example.com
+ check_mode: yes
+ diff: yes
+ register: account_modified_check
+
+- name: Change email address
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_content: "{{ lookup('file', output_dir ~ '/accountkey.pem') }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ # allow_creation: no
+ contact:
+ - mailto:example@example.com
+ register: account_modified
+
+- name: Change email address (idempotent)
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ account_uri: "{{ account_created.account_uri }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ # allow_creation: no
+ contact:
+ - mailto:example@example.com
+ register: account_modified_idempotent
+
+- name: Cannot access account with wrong URI
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ account_uri: "{{ account_created.account_uri ~ '12345thisdoesnotexist' }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ contact: []
+ ignore_errors: yes
+ register: account_modified_wrong_uri
+
+- name: Clear contact email addresses (check mode, diff)
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ # allow_creation: no
+ contact: []
+ check_mode: yes
+ diff: yes
+ register: account_modified_2_check
+
+- name: Clear contact email addresses
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ # allow_creation: no
+ contact: []
+ register: account_modified_2
+
+- name: Clear contact email addresses (idempotent)
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ # allow_creation: no
+ contact: []
+ register: account_modified_2_idempotent
+
+- name: Change account key (check mode, diff)
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ new_account_key_src: "{{ output_dir }}/accountkey2.pem"
+ state: changed_key
+ contact:
+ - mailto:example@example.com
+ check_mode: yes
+ diff: yes
+ register: account_change_key_check
+
+- name: Change account key
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ new_account_key_src: "{{ output_dir }}/accountkey2.pem"
+ state: changed_key
+ contact:
+ - mailto:example@example.com
+ register: account_change_key
+
+- name: Deactivate account (check mode, diff)
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey2.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: absent
+ check_mode: yes
+ diff: yes
+ register: account_deactivate_check
+
+- name: Deactivate account
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey2.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: absent
+ register: account_deactivate
+
+- name: Deactivate account (idempotent)
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey2.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: absent
+ register: account_deactivate_idempotent
+
+- name: Do not try to create account II
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey2.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ allow_creation: no
+ ignore_errors: yes
+ register: account_not_created_2
+
+- name: Do not try to create account III
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ allow_creation: no
+ ignore_errors: yes
+ register: account_not_created_3
+
+- name: Create account with External Account Binding
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/{{ item.account }}.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ allow_creation: yes
+ terms_agreed: yes
+ contact:
+ - mailto:example@example.org
+ external_account_binding:
+ kid: "{{ item.kid }}"
+ alg: "{{ item.alg }}"
+ key: "{{ item.key }}"
+ register: account_created_eab
+ ignore_errors: yes
+ loop:
+ - account: accountkey3
+ kid: kid-1
+ alg: HS256
+ key: zWNDZM6eQGHWpSRTPal5eIUYFTu7EajVIoguysqZ9wG44nMEtx3MUAsUDkMTQ12W
+ - account: accountkey4
+ kid: kid-2
+ alg: HS384
+ key: b10lLJs8l1GPIzsLP0s6pMt8O0XVGnfTaCeROxQM0BIt2XrJMDHJZBM5NuQmQJQH
+ - account: accountkey5
+ kid: kid-3
+ alg: HS512
+ key: zWNDZM6eQGHWpSRTPal5eIUYFTu7EajVIoguysqZ9wG44nMEtx3MUAsUDkMTQ12W
+- debug: var=account_created_eab
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tasks/main.yml
new file mode 100644
index 00000000..b7c7452a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tasks/main.yml
@@ -0,0 +1,36 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- block:
+ - name: Running tests with OpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: openssl
+
+ - import_tasks: ../tests/validate.yml
+
+ # Old 0.9.8 versions have insufficient CLI support for signing with EC keys
+ when: openssl_version.stdout is version('1.0.0', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ - import_tasks: ../tests/validate.yml
+
+ when: cryptography_version.stdout is version('1.5', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tests/validate.yml
new file mode 100644
index 00000000..95140f13
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account/tests/validate.yml
@@ -0,0 +1,137 @@
+---
+- name: Validate that account wasn't created in the first step
+ assert:
+ that:
+ - account_not_created is failed
+ - account_not_created.msg == 'Account does not exist or is deactivated.'
+
+- name: Validate that account was created in the second step (check mode)
+ assert:
+ that:
+ - account_created_check is changed
+ - account_created_check.account_uri is none
+ - "'diff' in account_created_check"
+ - "account_created_check.diff.before == {}"
+ - "'after' in account_created_check.diff"
+ - account_created_check.diff.after.contact | length == 1
+ - account_created_check.diff.after.contact[0] == 'mailto:example@example.org'
+
+- name: Validate that account was created in the second step
+ assert:
+ that:
+ - account_created is changed
+ - account_created.account_uri is not none
+
+- name: Validate that account was created in the second step (idempotency)
+ assert:
+ that:
+ - account_created_idempotent is not changed
+ - account_created_idempotent.account_uri is not none
+
+- name: Validate that email address was changed (check mode)
+ assert:
+ that:
+ - account_modified_check is changed
+ - account_modified_check.account_uri is not none
+ - "'diff' in account_modified_check"
+ - account_modified_check.diff.before.contact | length == 1
+ - account_modified_check.diff.before.contact[0] == 'mailto:example@example.org'
+ - account_modified_check.diff.after.contact | length == 1
+ - account_modified_check.diff.after.contact[0] == 'mailto:example@example.com'
+
+- name: Validate that email address was changed
+ assert:
+ that:
+ - account_modified is changed
+ - account_modified.account_uri is not none
+
+- name: Validate that email address was not changed a second time (idempotency)
+ assert:
+ that:
+ - account_modified_idempotent is not changed
+ - account_modified_idempotent.account_uri is not none
+
+- name: Make sure that with the wrong account URI, the account cannot be changed
+ assert:
+ that:
+ - account_modified_wrong_uri is failed
+
+- name: Validate that email address was cleared (check mode)
+ assert:
+ that:
+ - account_modified_2_check is changed
+ - account_modified_2_check.account_uri is not none
+ - "'diff' in account_modified_2_check"
+ - account_modified_2_check.diff.before.contact | length == 1
+ - account_modified_2_check.diff.before.contact[0] == 'mailto:example@example.com'
+ - account_modified_2_check.diff.after.contact | length == 0
+
+- name: Validate that email address was cleared
+ assert:
+ that:
+ - account_modified_2 is changed
+ - account_modified_2.account_uri is not none
+
+- name: Validate that email address was not cleared a second time (idempotency)
+ assert:
+ that:
+ - account_modified_2_idempotent is not changed
+ - account_modified_2_idempotent.account_uri is not none
+
+- name: Validate that the account key was changed (check mode)
+ assert:
+ that:
+ - account_change_key_check is changed
+ - account_change_key_check.account_uri is not none
+ - "'diff' in account_change_key_check"
+ - account_change_key_check.diff.before.public_account_key != account_change_key_check.diff.after.public_account_key
+
+- name: Validate that the account key was changed
+ assert:
+ that:
+ - account_change_key is changed
+ - account_change_key.account_uri is not none
+
+- name: Validate that the account was deactivated (check mode)
+ assert:
+ that:
+ - account_deactivate_check is changed
+ - account_deactivate_check.account_uri is not none
+ - "'diff' in account_deactivate_check"
+ - "account_deactivate_check.diff.before != {}"
+ - "account_deactivate_check.diff.after == {}"
+
+- name: Validate that the account was deactivated
+ assert:
+ that:
+ - account_deactivate is changed
+ - account_deactivate.account_uri is not none
+
+- name: Validate that the account was really deactivated (idempotency)
+ assert:
+ that:
+ - account_deactivate_idempotent is not changed
+ # The next condition should be true for all conforming ACME servers.
+ # In case it is not true, it could be both an error in acme_account
+ # and in the ACME server.
+ - account_deactivate_idempotent.account_uri is none
+
+- name: Validate that the account is gone (new account key)
+ assert:
+ that:
+ - account_not_created_2 is failed
+ - account_not_created_2.msg == 'Account does not exist or is deactivated.'
+
+- name: Validate that the account is gone (old account key)
+ assert:
+ that:
+ - account_not_created_3 is failed
+ - account_not_created_3.msg == 'Account does not exist or is deactivated.'
+
+- name: Validate that the account with External Account Binding has been created
+ assert:
+ that:
+ - account_created_eab.results[0] is changed
+ - account_created_eab.results[1] is changed
+ - account_created_eab.results[2] is failed
+ - "'HS512 key must be at least 64 bytes long' in account_created_eab.results[2].msg"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/aliases
new file mode 100644
index 00000000..d7936330
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/aliases
@@ -0,0 +1,2 @@
+shippable/cloud/group1
+cloud/acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/meta/main.yml
new file mode 100644
index 00000000..81d1e7e7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tasks/impl.yml
new file mode 100644
index 00000000..552fc0b2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tasks/impl.yml
@@ -0,0 +1,82 @@
+---
+- name: Generate account key
+ command: "{{ openssl_binary }} ecparam -name prime256v1 -genkey -out {{ output_dir }}/accountkey.pem"
+
+- name: Generate second account key
+ command: "{{ openssl_binary }} ecparam -name prime256v1 -genkey -out {{ output_dir }}/accountkey2.pem"
+
+- name: Parse account key (to ease debugging some test failures)
+ command: "{{ openssl_binary }} ec -in {{ output_dir }}/accountkey.pem -noout -text"
+
+- name: Check that account does not exist
+ acme_account_info:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ register: account_not_created
+
+- name: Create it now
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ allow_creation: yes
+ terms_agreed: yes
+ contact:
+ - mailto:example@example.org
+
+- name: Check that account exists
+ acme_account_info:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ register: account_created
+
+- name: Clear email address
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_content: "{{ lookup('file', output_dir ~ '/accountkey.pem') }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ state: present
+ allow_creation: no
+ contact: []
+
+- name: Check that account was modified
+ acme_account_info:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_uri: "{{ account_created.account_uri }}"
+ register: account_modified
+
+- name: Check with wrong account URI
+ acme_account_info:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_uri: "{{ account_created.account_uri }}test1234doesnotexists"
+ register: account_not_exist
+
+- name: Check with wrong account key
+ acme_account_info:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/accountkey2.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_uri: "{{ account_created.account_uri }}"
+ ignore_errors: yes
+ register: account_wrong_key
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tasks/main.yml
new file mode 100644
index 00000000..b7c7452a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tasks/main.yml
@@ -0,0 +1,36 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- block:
+ - name: Running tests with OpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: openssl
+
+ - import_tasks: ../tests/validate.yml
+
+ # Old 0.9.8 versions have insufficient CLI support for signing with EC keys
+ when: openssl_version.stdout is version('1.0.0', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ - import_tasks: ../tests/validate.yml
+
+ when: cryptography_version.stdout is version('1.5', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tests/validate.yml
new file mode 100644
index 00000000..5863a8c3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_account_info/tests/validate.yml
@@ -0,0 +1,40 @@
+---
+- name: Validate that account wasn't there
+ assert:
+ that:
+ - not account_not_created.exists
+ - account_not_created.account_uri is none
+ - "'account' not in account_not_created"
+
+- name: Validate that account was created
+ assert:
+ that:
+ - account_created.exists
+ - account_created.account_uri is not none
+ - "'account' in account_created"
+ - "'contact' in account_created.account"
+ - "'public_account_key' in account_created.account"
+ - account_created.account.contact | length == 1
+ - "account_created.account.contact[0] == 'mailto:example@example.org'"
+
+- name: Validate that account email was removed
+ assert:
+ that:
+ - account_modified.exists
+ - account_modified.account_uri is not none
+ - "'account' in account_modified"
+ - "'contact' in account_modified.account"
+ - "'public_account_key' in account_modified.account"
+ - account_modified.account.contact | length == 0
+
+- name: Validate that account does not exist with wrong account URI
+ assert:
+ that:
+ - not account_not_exist.exists
+ - account_not_exist.account_uri is none
+ - "'account' not in account_not_exist"
+
+- name: Validate that account cannot be accessed with wrong key
+ assert:
+ that:
+ - account_wrong_key is failed
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/aliases
new file mode 100644
index 00000000..d7936330
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/aliases
@@ -0,0 +1,2 @@
+shippable/cloud/group1
+cloud/acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/meta/main.yml
new file mode 100644
index 00000000..81d1e7e7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/impl.yml
new file mode 100644
index 00000000..8547245d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/impl.yml
@@ -0,0 +1,462 @@
+---
+## SET UP ACCOUNT KEYS ########################################################################
+- name: Create ECC256 account key
+ command: "{{ openssl_binary }} ecparam -name prime256v1 -genkey -out {{ output_dir }}/account-ec256.pem"
+- name: Create ECC384 account key
+ command: "{{ openssl_binary }} ecparam -name secp384r1 -genkey -out {{ output_dir }}/account-ec384.pem"
+- name: Create RSA account key
+ command: "{{ openssl_binary }} genrsa -out {{ output_dir }}/account-rsa.pem {{ default_rsa_key_size }}"
+## SET UP ACCOUNTS ############################################################################
+- name: Make sure ECC256 account hasn't been created yet
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_key_src: "{{ output_dir }}/account-ec256.pem"
+ state: absent
+- name: Create ECC384 account
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_key_content: "{{ lookup('file', output_dir ~ '/account-ec384.pem') }}"
+ state: present
+ allow_creation: yes
+ terms_agreed: yes
+ contact:
+ - mailto:example@example.org
+ - mailto:example@example.com
+- name: Create RSA account
+ acme_account:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_key_src: "{{ output_dir }}/account-rsa.pem"
+ state: present
+ allow_creation: yes
+ terms_agreed: yes
+ contact: []
+## OBTAIN CERTIFICATES ########################################################################
+- name: Obtain cert 1
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 1
+ certificate_name: cert-1
+ key_type: rsa
+ rsa_bits: "{{ default_rsa_key_size }}"
+ subject_alt_name: "DNS:example.com"
+ subject_alt_name_critical: no
+ account_key: account-ec256
+ challenge: http-01
+ modify_account: yes
+ deactivate_authzs: no
+ force: no
+ remaining_days: 10
+ terms_agreed: yes
+ account_email: "example@example.org"
+ retrieve_all_alternates: yes
+ acme_expected_root_number: 1
+ select_chain:
+ - test_certificates: last
+ issuer: "{{ acme_roots[1].subject }}"
+ use_csr_content: true
+- name: Store obtain results for cert 1
+ set_fact:
+ cert_1_obtain_results: "{{ certificate_obtain_result }}"
+ cert_1_alternate: "{{ 1 if select_crypto_backend == 'cryptography' else 0 }}"
+- name: Obtain cert 2
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 2
+ certificate_name: cert-2
+ key_type: ec256
+ subject_alt_name: "DNS:*.example.com,DNS:example.com"
+ subject_alt_name_critical: yes
+ account_key: account-ec384
+ challenge: dns-01
+ modify_account: no
+ deactivate_authzs: yes
+ force: no
+ remaining_days: 10
+ terms_agreed: no
+ account_email: ""
+ acme_expected_root_number: 0
+ retrieve_all_alternates: yes
+ select_chain:
+ # All intermediates have the same subject, so always the first
+ # chain will be found, and we need a second condition to make sure
+ # that the first condition actually works. (The second condition
+ # has been tested above.)
+ - test_certificates: all
+ subject: "{{ acme_intermediates[0].subject }}"
+ - test_certificates: all
+ issuer: "{{ acme_roots[2].subject }}"
+ use_csr_content: false
+- name: Store obtain results for cert 2
+ set_fact:
+ cert_2_obtain_results: "{{ certificate_obtain_result }}"
+ cert_2_alternate: "{{ 0 if select_crypto_backend == 'cryptography' else 0 }}"
+- name: Obtain cert 3
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 3
+ certificate_name: cert-3
+ key_type: ec384
+ subject_alt_name: "DNS:*.example.com,DNS:example.org,DNS:t1.example.com"
+ subject_alt_name_critical: no
+ account_key_content: "{{ lookup('file', output_dir ~ '/account-rsa.pem') }}"
+ challenge: dns-01
+ modify_account: no
+ deactivate_authzs: no
+ force: no
+ remaining_days: 10
+ terms_agreed: no
+ account_email: ""
+ acme_expected_root_number: 0
+ retrieve_all_alternates: yes
+ select_chain:
+ - test_certificates: last
+ subject: "{{ acme_roots[1].subject }}"
+ use_csr_content: true
+- name: Store obtain results for cert 3
+ set_fact:
+ cert_3_obtain_results: "{{ certificate_obtain_result }}"
+ cert_3_alternate: "{{ 0 if select_crypto_backend == 'cryptography' else 0 }}"
+- name: Obtain cert 4
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 4
+ certificate_name: cert-4
+ key_type: rsa
+ rsa_bits: "{{ default_rsa_key_size }}"
+ subject_alt_name: "DNS:example.com,DNS:t1.example.com,DNS:test.t2.example.com,DNS:example.org,DNS:test.example.org"
+ subject_alt_name_critical: no
+ account_key: account-rsa
+ challenge: http-01
+ modify_account: no
+ deactivate_authzs: yes
+ force: yes
+ remaining_days: 10
+ terms_agreed: no
+ account_email: ""
+ acme_expected_root_number: 2
+ select_chain:
+ - test_certificates: last
+ issuer: "{{ acme_roots[2].subject }}"
+ - test_certificates: last
+ issuer: "{{ acme_roots[1].subject }}"
+ use_csr_content: false
+- name: Store obtain results for cert 4
+ set_fact:
+ cert_4_obtain_results: "{{ certificate_obtain_result }}"
+ cert_4_alternate: "{{ 2 if select_crypto_backend == 'cryptography' else 0 }}"
+- name: Obtain cert 5
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 5, Iteration 1/4
+ certificate_name: cert-5
+ key_type: ec521
+ subject_alt_name: "DNS:t2.example.com"
+ subject_alt_name_critical: no
+ account_key: account-ec384
+ challenge: http-01
+ modify_account: no
+ deactivate_authzs: yes
+ force: yes
+ remaining_days: 10
+ terms_agreed: no
+ account_email: ""
+ use_csr_content: true
+- name: Store obtain results for cert 5a
+ set_fact:
+ cert_5a_obtain_results: "{{ certificate_obtain_result }}"
+ cert_5_alternate: "{{ 0 if select_crypto_backend == 'cryptography' else 0 }}"
+- name: Obtain cert 5 (should not, since already there and valid for more than 10 days)
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 5, Iteration 2/4
+ certificate_name: cert-5
+ key_type: ec521
+ subject_alt_name: "DNS:t2.example.com"
+ subject_alt_name_critical: no
+ account_key: account-ec384
+ challenge: http-01
+ modify_account: no
+ deactivate_authzs: yes
+ force: no
+ remaining_days: 10
+ terms_agreed: no
+ account_email: ""
+ use_csr_content: false
+- name: Store obtain results for cert 5b
+ set_fact:
+ cert_5_recreate_1: "{{ challenge_data is changed }}"
+- name: Obtain cert 5 (should again by less days)
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 5, Iteration 3/4
+ certificate_name: cert-5
+ key_type: ec521
+ subject_alt_name: "DNS:t2.example.com"
+ subject_alt_name_critical: no
+ account_key: account-ec384
+ challenge: http-01
+ modify_account: no
+ deactivate_authzs: yes
+ force: yes
+ remaining_days: 1000
+ terms_agreed: no
+ account_email: ""
+ use_csr_content: true
+- name: Store obtain results for cert 5c
+ set_fact:
+ cert_5_recreate_2: "{{ challenge_data is changed }}"
+ cert_5c_obtain_results: "{{ certificate_obtain_result }}"
+- name: Obtain cert 5 (should again by force)
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 5, Iteration 4/4
+ certificate_name: cert-5
+ key_type: ec521
+ subject_alt_name: "DNS:t2.example.com"
+ subject_alt_name_critical: no
+ account_key_content: "{{ lookup('file', output_dir ~ '/account-ec384.pem') }}"
+ challenge: http-01
+ modify_account: no
+ deactivate_authzs: yes
+ force: yes
+ remaining_days: 10
+ terms_agreed: no
+ account_email: ""
+ use_csr_content: false
+- name: Store obtain results for cert 5d
+ set_fact:
+ cert_5_recreate_3: "{{ challenge_data is changed }}"
+ cert_5d_obtain_results: "{{ certificate_obtain_result }}"
+- name: Obtain cert 6
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 6
+ certificate_name: cert-6
+ key_type: rsa
+ rsa_bits: "{{ default_rsa_key_size }}"
+ subject_alt_name: "DNS:example.org"
+ subject_alt_name_critical: no
+ account_key: account-ec256
+ challenge: tls-alpn-01
+ modify_account: yes
+ deactivate_authzs: no
+ force: no
+ remaining_days: 10
+ terms_agreed: yes
+ account_email: "example@example.org"
+ acme_expected_root_number: 0
+ select_chain:
+ # All intermediates have the same subject key identifier, so always
+ # the first chain will be found, and we need a second condition to
+ # make sure that the first condition actually works. (The second
+ # condition has been tested above.)
+ - test_certificates: first
+ subject_key_identifier: "{{ acme_intermediates[0].subject_key_identifier }}"
+ - test_certificates: last
+ issuer: "{{ acme_roots[1].subject }}"
+ use_csr_content: true
+- name: Store obtain results for cert 6
+ set_fact:
+ cert_6_obtain_results: "{{ certificate_obtain_result }}"
+ cert_6_alternate: "{{ 0 if select_crypto_backend == 'cryptography' else 0 }}"
+- name: Obtain cert 7
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 7
+ certificate_name: cert-7
+ key_type: rsa
+ rsa_bits: "{{ default_rsa_key_size }}"
+ subject_alt_name:
+ - "IP:127.0.0.1"
+ # - "IP:::1"
+ subject_alt_name_critical: no
+ account_key: account-ec256
+ challenge: http-01
+ modify_account: yes
+ deactivate_authzs: no
+ force: no
+ remaining_days: 10
+ terms_agreed: yes
+ account_email: "example@example.org"
+ acme_expected_root_number: 2
+ select_chain:
+ - test_certificates: last
+ authority_key_identifier: "{{ acme_roots[2].subject_key_identifier }}"
+ use_csr_content: false
+- name: Store obtain results for cert 7
+ set_fact:
+ cert_7_obtain_results: "{{ certificate_obtain_result }}"
+ cert_7_alternate: "{{ 2 if select_crypto_backend == 'cryptography' else 0 }}"
+- name: Obtain cert 8
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 8
+ certificate_name: cert-8
+ key_type: rsa
+ rsa_bits: "{{ default_rsa_key_size }}"
+ subject_alt_name:
+ - "IP:127.0.0.1"
+ # IPv4 only since our test validation server doesn't work
+ # with IPv6 (thanks to Python's socketserver).
+ subject_alt_name_critical: no
+ account_key: account-ec256
+ challenge: tls-alpn-01
+ challenge_alpn_tls: acme_challenge_cert_helper
+ modify_account: yes
+ deactivate_authzs: no
+ force: no
+ remaining_days: 10
+ terms_agreed: yes
+ account_email: "example@example.org"
+ use_csr_content: true
+- name: Store obtain results for cert 8
+ set_fact:
+ cert_8_obtain_results: "{{ certificate_obtain_result }}"
+ cert_8_alternate: "{{ 0 if select_crypto_backend == 'cryptography' else 0 }}"
+## DISSECT CERTIFICATES #######################################################################
+# Make sure certificates are valid. Root certificate for Pebble equals the chain certificate.
+- name: Verifying cert 1
+ command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-1-root.pem" -untrusted "{{ output_dir }}/cert-1-chain.pem" "{{ output_dir }}/cert-1.pem"'
+ ignore_errors: yes
+ register: cert_1_valid
+- name: Verifying cert 2
+ command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-2-root.pem" -untrusted "{{ output_dir }}/cert-2-chain.pem" "{{ output_dir }}/cert-2.pem"'
+ ignore_errors: yes
+ register: cert_2_valid
+- name: Verifying cert 3
+ command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-3-root.pem" -untrusted "{{ output_dir }}/cert-3-chain.pem" "{{ output_dir }}/cert-3.pem"'
+ ignore_errors: yes
+ register: cert_3_valid
+- name: Verifying cert 4
+ command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-4-root.pem" -untrusted "{{ output_dir }}/cert-4-chain.pem" "{{ output_dir }}/cert-4.pem"'
+ ignore_errors: yes
+ register: cert_4_valid
+- name: Verifying cert 5
+ command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-5-root.pem" -untrusted "{{ output_dir }}/cert-5-chain.pem" "{{ output_dir }}/cert-5.pem"'
+ ignore_errors: yes
+ register: cert_5_valid
+- name: Verifying cert 6
+ command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-6-root.pem" -untrusted "{{ output_dir }}/cert-6-chain.pem" "{{ output_dir }}/cert-6.pem"'
+ ignore_errors: yes
+ register: cert_6_valid
+- name: Verifying cert 7
+ command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-7-root.pem" -untrusted "{{ output_dir }}/cert-7-chain.pem" "{{ output_dir }}/cert-7.pem"'
+ ignore_errors: yes
+ register: cert_7_valid
+- name: Verifying cert 8
+ command: '{{ openssl_binary }} verify -CAfile "{{ output_dir }}/cert-8-root.pem" -untrusted "{{ output_dir }}/cert-8-chain.pem" "{{ output_dir }}/cert-8.pem"'
+ ignore_errors: yes
+ register: cert_8_valid
+# Dump certificate info
+- name: Dumping cert 1
+ command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-1.pem" -noout -text'
+ register: cert_1_text
+- name: Dumping cert 2
+ command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-2.pem" -noout -text'
+ register: cert_2_text
+- name: Dumping cert 3
+ command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-3.pem" -noout -text'
+ register: cert_3_text
+- name: Dumping cert 4
+ command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-4.pem" -noout -text'
+ register: cert_4_text
+- name: Dumping cert 5
+ command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-5.pem" -noout -text'
+ register: cert_5_text
+- name: Dumping cert 6
+ command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-6.pem" -noout -text'
+ register: cert_6_text
+- name: Dumping cert 7
+ command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-7.pem" -noout -text'
+ register: cert_7_text
+- name: Dumping cert 8
+ command: '{{ openssl_binary }} x509 -in "{{ output_dir }}/cert-8.pem" -noout -text'
+ register: cert_8_text
+# Dump certificate info
+- name: Dumping cert 1
+ x509_certificate_info:
+ path: "{{ output_dir }}/cert-1.pem"
+ register: cert_1_info
+- name: Dumping cert 2
+ x509_certificate_info:
+ path: "{{ output_dir }}/cert-2.pem"
+ register: cert_2_info
+- name: Dumping cert 3
+ x509_certificate_info:
+ path: "{{ output_dir }}/cert-3.pem"
+ register: cert_3_info
+- name: Dumping cert 4
+ x509_certificate_info:
+ path: "{{ output_dir }}/cert-4.pem"
+ register: cert_4_info
+- name: Dumping cert 5
+ x509_certificate_info:
+ path: "{{ output_dir }}/cert-5.pem"
+ register: cert_5_info
+- name: Dumping cert 6
+ x509_certificate_info:
+ path: "{{ output_dir }}/cert-6.pem"
+ register: cert_6_info
+- name: Dumping cert 7
+ x509_certificate_info:
+ path: "{{ output_dir }}/cert-7.pem"
+ register: cert_7_info
+- name: Dumping cert 8
+ x509_certificate_info:
+ path: "{{ output_dir }}/cert-8.pem"
+ register: cert_8_info
+## GET ACCOUNT ORDERS #########################################################################
+- name: Don't retrieve orders
+ acme_account_info:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/account-ec256.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ retrieve_orders: ignore
+ register: account_orders_not
+- name: Retrieve orders as URL list (1/2)
+ acme_account_info:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/account-ec256.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ retrieve_orders: url_list
+ register: account_orders_urls
+- name: Retrieve orders as URL list (2/2)
+ acme_account_info:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/account-ec384.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ retrieve_orders: url_list
+ register: account_orders_urls2
+- name: Retrieve orders as object list (1/2)
+ acme_account_info:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/account-ec256.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ retrieve_orders: object_list
+ register: account_orders_full
+- name: Retrieve orders as object list (2/2)
+ acme_account_info:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/account-ec384.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ retrieve_orders: object_list
+ register: account_orders_full2
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/main.yml
new file mode 100644
index 00000000..2e732466
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/main.yml
@@ -0,0 +1,107 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- block:
+ - name: Obtain root and intermediate certificates
+ get_url:
+ url: "http://{{ acme_host }}:5000/{{ item.0 }}-certificate-for-ca/{{ item.1 }}"
+ dest: "{{ output_dir }}/acme-{{ item.0 }}-{{ item.1 }}.pem"
+ loop: "{{ query('nested', types, root_numbers) }}"
+
+ - name: Analyze root certificates
+ x509_certificate_info:
+ path: "{{ output_dir }}/acme-root-{{ item }}.pem"
+ loop: "{{ root_numbers }}"
+ register: acme_roots
+
+ - name: Analyze intermediate certificates
+ x509_certificate_info:
+ path: "{{ output_dir }}/acme-intermediate-{{ item }}.pem"
+ loop: "{{ root_numbers }}"
+ register: acme_intermediates
+
+ - set_fact:
+ x__: "{{ item | dict2items | selectattr('key', 'in', interesting_keys) | list | items2dict }}"
+ y__: "{{ lookup('file', output_dir ~ '/acme-root-' ~ item.item ~ '.pem', rstrip=False) }}"
+ loop: "{{ acme_roots.results }}"
+ register: acme_roots_tmp
+
+ - set_fact:
+ x__: "{{ item | dict2items | selectattr('key', 'in', interesting_keys) | list | items2dict }}"
+ y__: "{{ lookup('file', output_dir ~ '/acme-intermediate-' ~ item.item ~ '.pem', rstrip=False) }}"
+ loop: "{{ acme_intermediates.results }}"
+ register: acme_intermediates_tmp
+
+ - set_fact:
+ acme_roots: "{{ acme_roots_tmp.results | map(attribute='ansible_facts.x__') | list }}"
+ acme_root_certs: "{{ acme_roots_tmp.results | map(attribute='ansible_facts.y__') | list }}"
+ acme_intermediates: "{{ acme_intermediates_tmp.results | map(attribute='ansible_facts.x__') | list }}"
+ acme_intermediate_certs: "{{ acme_intermediates_tmp.results | map(attribute='ansible_facts.y__') | list }}"
+
+ vars:
+ types:
+ - root
+ - intermediate
+ root_numbers:
+ # The number 3 comes from here: https://github.com/ansible/acme-test-container/blob/master/run.sh#L12
+ - 0
+ - 1
+ - 2
+ - 3
+ interesting_keys:
+ - authority_key_identifier
+ - subject_key_identifier
+ - issuer
+ - subject
+ #- serial_number
+ #- public_key_fingerprints
+
+- name: ACME root certificate info
+ debug:
+ var: acme_roots
+
+#- name: ACME root certificates as PEM
+# debug:
+# var: acme_root_certs
+
+- name: ACME intermediate certificate info
+ debug:
+ var: acme_intermediates
+
+#- name: ACME intermediate certificates as PEM
+# debug:
+# var: acme_intermediate_certs
+
+- block:
+ - name: Running tests with OpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: openssl
+
+ - import_tasks: ../tests/validate.yml
+
+ # Old 0.9.8 versions have insufficient CLI support for signing with EC keys
+ when: openssl_version.stdout is version('1.0.0', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ - import_tasks: ../tests/validate.yml
+
+ when: cryptography_version.stdout is version('1.5', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/obtain-cert.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/obtain-cert.yml
new file mode 100644
index 00000000..ec53510b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tasks/obtain-cert.yml
@@ -0,0 +1,144 @@
+---
+## PRIVATE KEY ################################################################################
+- name: ({{ certgen_title }}) Create cert private key (RSA)
+ command: "{{ openssl_binary }} genrsa -out {{ output_dir }}/{{ certificate_name }}.key {{ rsa_bits if key_type == 'rsa' else default_rsa_key_size }}"
+ when: "key_type == 'rsa'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 256)
+ command: "{{ openssl_binary }} ecparam -name prime256v1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec256'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 384)
+ command: "{{ openssl_binary }} ecparam -name secp384r1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec384'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 512)
+ command: "{{ openssl_binary }} ecparam -name secp521r1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec521'"
+## CSR ########################################################################################
+- name: ({{ certgen_title }}) Create cert CSR
+ openssl_csr:
+ path: "{{ output_dir }}/{{ certificate_name }}.csr"
+ privatekey_path: "{{ output_dir }}/{{ certificate_name }}.key"
+ subject_alt_name: "{{ subject_alt_name }}"
+ subject_alt_name_critical: "{{ subject_alt_name_critical }}"
+ return_content: true
+ register: csr_result
+## ACME STEP 1 ################################################################################
+- name: ({{ certgen_title }}) Obtain cert, step 1
+ acme_certificate:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_key: "{{ (output_dir ~ '/' ~ account_key ~ '.pem') if account_key_content is not defined else omit }}"
+ account_key_content: "{{ account_key_content | default(omit) }}"
+ modify_account: "{{ modify_account }}"
+ csr: "{{ omit if use_csr_content | default(false) else output_dir ~ '/' ~ certificate_name ~ '.csr' }}"
+ csr_content: "{{ csr_result.csr if use_csr_content | default(false) else omit }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}.pem"
+ fullchain_dest: "{{ output_dir }}/{{ certificate_name }}-fullchain.pem"
+ chain_dest: "{{ output_dir }}/{{ certificate_name }}-chain.pem"
+ challenge: "{{ challenge }}"
+ deactivate_authzs: "{{ deactivate_authzs }}"
+ force: "{{ force }}"
+ remaining_days: "{{ remaining_days }}"
+ terms_agreed: "{{ terms_agreed }}"
+ account_email: "{{ account_email }}"
+ register: challenge_data
+- name: ({{ certgen_title }}) Print challenge data
+ debug:
+ var: challenge_data
+- name: ({{ certgen_title }}) Create HTTP challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/http/{{ item.key }}/{{ item.value['http-01'].resource[('.well-known/acme-challenge/'|length):] }}"
+ method: PUT
+ body_format: raw
+ body: "{{ item.value['http-01'].resource_value }}"
+ headers:
+ content-type: "application/octet-stream"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'http-01'"
+- name: ({{ certgen_title }}) Create DNS challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/dns/{{ item.key }}"
+ method: PUT
+ body_format: json
+ body: "{{ item.value }}"
+ with_dict: "{{ challenge_data.challenge_data_dns }}"
+ when: "challenge_data is changed and challenge == 'dns-01'"
+- name: ({{ certgen_title }}) Create TLS ALPN challenges (acm_challenge_cert_helper)
+ acme_challenge_cert_helper:
+ challenge: tls-alpn-01
+ challenge_data: "{{ item.value['tls-alpn-01'] }}"
+ private_key_src: "{{ output_dir }}/{{ certificate_name }}.key"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ register: tls_alpn_challenges
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is defined and challenge_alpn_tls == 'acme_challenge_cert_helper')"
+- name: ({{ certgen_title }}) Set TLS ALPN challenges (acm_challenge_cert_helper)
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.domain }}/{{ item.identifier }}/certificate-and-key"
+ method: PUT
+ body_format: raw
+ body: "{{ item.challenge_certificate }}\n{{ lookup('file', output_dir ~ '/' ~ certificate_name ~ '.key') }}"
+ headers:
+ content-type: "application/pem-certificate-chain"
+ with_items: "{{ tls_alpn_challenges.results }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is defined and challenge_alpn_tls == 'acme_challenge_cert_helper')"
+- name: ({{ certgen_title }}) Create TLS ALPN challenges (der-value-b64)
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.value['tls-alpn-01'].resource }}/{{ item.value['tls-alpn-01'].resource_original }}/der-value-b64"
+ method: PUT
+ body_format: raw
+ body: "{{ item.value['tls-alpn-01'].resource_value }}"
+ headers:
+ content-type: "application/octet-stream"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is not defined or challenge_alpn_tls == 'der-value-b64')"
+## ACME STEP 2 ################################################################################
+- name: ({{ certgen_title }}) Obtain cert, step 2
+ acme_certificate:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_key: "{{ (output_dir ~ '/' ~ account_key ~ '.pem') if account_key_content is not defined else omit }}"
+ account_key_content: "{{ account_key_content | default(omit) }}"
+ account_uri: "{{ challenge_data.account_uri }}"
+ modify_account: "{{ modify_account }}"
+ csr: "{{ omit if use_csr_content | default(false) else output_dir ~ '/' ~ certificate_name ~ '.csr' }}"
+ csr_content: "{{ csr_result.csr if use_csr_content | default(false) else omit }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}.pem"
+ fullchain_dest: "{{ output_dir }}/{{ certificate_name }}-fullchain.pem"
+ chain_dest: "{{ output_dir }}/{{ certificate_name }}-chain.pem"
+ challenge: "{{ challenge }}"
+ deactivate_authzs: "{{ deactivate_authzs }}"
+ force: "{{ force }}"
+ remaining_days: "{{ remaining_days }}"
+ terms_agreed: "{{ terms_agreed }}"
+ account_email: "{{ account_email }}"
+ data: "{{ challenge_data }}"
+ retrieve_all_alternates: "{{ retrieve_all_alternates | default(omit) }}"
+ select_chain: "{{ select_chain | default(omit) if select_crypto_backend == 'cryptography' else omit }}"
+ register: certificate_obtain_result
+ when: challenge_data is changed
+- name: ({{ certgen_title }}) Deleting HTTP challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/http/{{ item.key }}/{{ item.value['http-01'].resource[('.well-known/acme-challenge/'|length):] }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'http-01'"
+- name: ({{ certgen_title }}) Deleting DNS challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/dns/{{ item.key }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data_dns }}"
+ when: "challenge_data is changed and challenge == 'dns-01'"
+- name: ({{ certgen_title }}) Deleting TLS ALPN challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.value['tls-alpn-01'].resource }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01'"
+- name: ({{ certgen_title }}) Get root certificate
+ get_url:
+ url: "http://{{ acme_host }}:5000/root-certificate-for-ca/{{ acme_expected_root_number | default(0) if select_crypto_backend == 'cryptography' else 0 }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}-root.pem"
+###############################################################################################
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tests/validate.yml
new file mode 100644
index 00000000..cd7d28b0
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate/tests/validate.yml
@@ -0,0 +1,144 @@
+---
+- name: Check that certificate 1 is valid
+ assert:
+ that:
+ - cert_1_valid is not failed
+- name: Check that certificate 1 contains correct SANs
+ assert:
+ that:
+ - "'DNS:example.com' in cert_1_text.stdout"
+- name: Check that certificate 1 retrieval got all chains
+ assert:
+ that:
+ - "'all_chains' in cert_1_obtain_results"
+ - "cert_1_obtain_results.all_chains | length > 1"
+ - "'cert' in cert_1_obtain_results.all_chains[cert_1_alternate | int]"
+ - "'chain' in cert_1_obtain_results.all_chains[cert_1_alternate | int]"
+ - "'full_chain' in cert_1_obtain_results.all_chains[cert_1_alternate | int]"
+ - "lookup('file', output_dir ~ '/cert-1.pem', rstrip=False) == cert_1_obtain_results.all_chains[cert_1_alternate | int].cert"
+ - "lookup('file', output_dir ~ '/cert-1-chain.pem', rstrip=False) == cert_1_obtain_results.all_chains[cert_1_alternate | int].chain"
+ - "lookup('file', output_dir ~ '/cert-1-fullchain.pem', rstrip=False) == cert_1_obtain_results.all_chains[cert_1_alternate | int].full_chain"
+
+- name: Check that certificate 2 is valid
+ assert:
+ that:
+ - cert_2_valid is not failed
+- name: Check that certificate 2 contains correct SANs
+ assert:
+ that:
+ - "'DNS:*.example.com' in cert_2_text.stdout"
+ - "'DNS:example.com' in cert_2_text.stdout"
+- name: Check that certificate 1 retrieval got all chains
+ assert:
+ that:
+ - "'all_chains' in cert_2_obtain_results"
+ - "cert_2_obtain_results.all_chains | length > 1"
+ - "'cert' in cert_2_obtain_results.all_chains[cert_2_alternate | int]"
+ - "'chain' in cert_2_obtain_results.all_chains[cert_2_alternate | int]"
+ - "'full_chain' in cert_2_obtain_results.all_chains[cert_2_alternate | int]"
+ - "lookup('file', output_dir ~ '/cert-2.pem', rstrip=False) == cert_2_obtain_results.all_chains[cert_2_alternate | int].cert"
+ - "lookup('file', output_dir ~ '/cert-2-chain.pem', rstrip=False) == cert_2_obtain_results.all_chains[cert_2_alternate | int].chain"
+ - "lookup('file', output_dir ~ '/cert-2-fullchain.pem', rstrip=False) == cert_2_obtain_results.all_chains[cert_2_alternate | int].full_chain"
+
+- name: Check that certificate 3 is valid
+ assert:
+ that:
+ - cert_3_valid is not failed
+- name: Check that certificate 3 contains correct SANs
+ assert:
+ that:
+ - "'DNS:*.example.com' in cert_3_text.stdout"
+ - "'DNS:example.org' in cert_3_text.stdout"
+ - "'DNS:t1.example.com' in cert_3_text.stdout"
+- name: Check that certificate 1 retrieval got all chains
+ assert:
+ that:
+ - "'all_chains' in cert_3_obtain_results"
+ - "cert_3_obtain_results.all_chains | length > 1"
+ - "'cert' in cert_3_obtain_results.all_chains[cert_3_alternate | int]"
+ - "'chain' in cert_3_obtain_results.all_chains[cert_3_alternate | int]"
+ - "'full_chain' in cert_3_obtain_results.all_chains[cert_3_alternate | int]"
+ - "lookup('file', output_dir ~ '/cert-3.pem', rstrip=False) == cert_3_obtain_results.all_chains[cert_3_alternate | int].cert"
+ - "lookup('file', output_dir ~ '/cert-3-chain.pem', rstrip=False) == cert_3_obtain_results.all_chains[cert_3_alternate | int].chain"
+ - "lookup('file', output_dir ~ '/cert-3-fullchain.pem', rstrip=False) == cert_3_obtain_results.all_chains[cert_3_alternate | int].full_chain"
+
+- name: Check that certificate 4 is valid
+ assert:
+ that:
+ - cert_4_valid is not failed
+- name: Check that certificate 4 contains correct SANs
+ assert:
+ that:
+ - "'DNS:example.com' in cert_4_text.stdout"
+ - "'DNS:t1.example.com' in cert_4_text.stdout"
+ - "'DNS:test.t2.example.com' in cert_4_text.stdout"
+ - "'DNS:example.org' in cert_4_text.stdout"
+ - "'DNS:test.example.org' in cert_4_text.stdout"
+- name: Check that certificate 4 retrieval did not get all chains
+ assert:
+ that:
+ - "'all_chains' not in cert_4_obtain_results"
+
+- name: Check that certificate 5 is valid
+ assert:
+ that:
+ - cert_5_valid is not failed
+- name: Check that certificate 5 contains correct SANs
+ assert:
+ that:
+ - "'DNS:t2.example.com' in cert_5_text.stdout"
+- name: Check that certificate 5 was not recreated on the first try
+ assert:
+ that:
+ - cert_5_recreate_1 == False
+- name: Check that certificate 5 was recreated on the second try
+ assert:
+ that:
+ - cert_5_recreate_2 == True
+- name: Check that certificate 5 was recreated on the third try
+ assert:
+ that:
+ - cert_5_recreate_3 == True
+
+- name: Check that certificate 6 is valid
+ assert:
+ that:
+ - cert_6_valid is not failed
+- name: Check that certificate 6 contains correct SANs
+ assert:
+ that:
+ - "'DNS:example.org' in cert_6_text.stdout"
+
+- name: Validate that orders were not retrieved
+ assert:
+ that:
+ - "'account' in account_orders_not"
+ - "'orders' not in account_orders_not"
+
+- name: Validate that orders were retrieved as list of URLs (1/2)
+ assert:
+ that:
+ - "'account' in account_orders_urls"
+ - "'orders' in account_orders_urls"
+ - "account_orders_urls.orders[0] is string"
+
+- name: Validate that orders were retrieved as list of URLs (2/2)
+ assert:
+ that:
+ - "'account' in account_orders_urls2"
+ - "'orders' in account_orders_urls2"
+ - "account_orders_urls2.orders[0] is string"
+
+- name: Validate that orders were retrieved as list of objects (1/2)
+ assert:
+ that:
+ - "'account' in account_orders_full"
+ - "'orders' in account_orders_full"
+ - "account_orders_full.orders[0].status is string"
+
+- name: Validate that orders were retrieved as list of objects (2/2)
+ assert:
+ that:
+ - "'account' in account_orders_full2"
+ - "'orders' in account_orders_full2"
+ - "account_orders_full2.orders[0].status is string"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/aliases
new file mode 100644
index 00000000..d7936330
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/aliases
@@ -0,0 +1,2 @@
+shippable/cloud/group1
+cloud/acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/meta/main.yml
new file mode 100644
index 00000000..81d1e7e7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/impl.yml
new file mode 100644
index 00000000..cafafa99
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/impl.yml
@@ -0,0 +1,89 @@
+---
+## SET UP ACCOUNT KEYS ########################################################################
+- name: Create ECC256 account key
+ command: "{{ openssl_binary }} ecparam -name prime256v1 -genkey -out {{ output_dir }}/account-ec256.pem"
+- name: Create ECC384 account key
+ command: "{{ openssl_binary }} ecparam -name secp384r1 -genkey -out {{ output_dir }}/account-ec384.pem"
+- name: Create RSA account key
+ command: "{{ openssl_binary }} genrsa -out {{ output_dir }}/account-rsa.pem {{ default_rsa_key_size }}"
+## CREATE ACCOUNTS AND OBTAIN CERTIFICATES ####################################################
+- name: Obtain cert 1
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 1 for revocation
+ certificate_name: cert-1
+ key_type: rsa
+ rsa_bits: "{{ default_rsa_key_size }}"
+ subject_alt_name: "DNS:example.com"
+ subject_alt_name_critical: no
+ account_key_content: "{{ lookup('file', output_dir ~ '/account-ec256.pem') }}"
+ challenge: http-01
+ modify_account: yes
+ deactivate_authzs: no
+ force: no
+ remaining_days: 10
+ terms_agreed: yes
+ account_email: "example@example.org"
+- name: Obtain cert 2
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 2 for revocation
+ certificate_name: cert-2
+ key_type: ec256
+ subject_alt_name: "DNS:*.example.com"
+ subject_alt_name_critical: yes
+ account_key: account-ec384
+ challenge: dns-01
+ modify_account: yes
+ deactivate_authzs: yes
+ force: no
+ remaining_days: 10
+ terms_agreed: yes
+ account_email: "example@example.org"
+- name: Obtain cert 3
+ include_tasks: obtain-cert.yml
+ vars:
+ certgen_title: Certificate 3 for revocation
+ certificate_name: cert-3
+ key_type: ec384
+ subject_alt_name: "DNS:t1.example.com"
+ subject_alt_name_critical: no
+ account_key: account-rsa
+ challenge: dns-01
+ modify_account: yes
+ deactivate_authzs: no
+ force: no
+ remaining_days: 10
+ terms_agreed: yes
+ account_email: "example@example.org"
+## REVOKE CERTIFICATES ########################################################################
+- name: Revoke certificate 1 via account key
+ acme_certificate_revoke:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_src: "{{ output_dir }}/account-ec256.pem"
+ certificate: "{{ output_dir }}/cert-1.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ ignore_errors: yes
+ register: cert_1_revoke
+- name: Revoke certificate 2 via certificate private key
+ acme_certificate_revoke:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ private_key_src: "{{ output_dir }}/cert-2.key"
+ certificate: "{{ output_dir }}/cert-2.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ ignore_errors: yes
+ register: cert_2_revoke
+- name: Revoke certificate 3 via account key (fullchain)
+ acme_certificate_revoke:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ account_key_content: "{{ lookup('file', output_dir ~ '/account-rsa.pem') }}"
+ certificate: "{{ output_dir }}/cert-3-fullchain.pem"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ ignore_errors: yes
+ register: cert_3_revoke
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/main.yml
new file mode 100644
index 00000000..b7c7452a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/main.yml
@@ -0,0 +1,36 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- block:
+ - name: Running tests with OpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: openssl
+
+ - import_tasks: ../tests/validate.yml
+
+ # Old 0.9.8 versions have insufficient CLI support for signing with EC keys
+ when: openssl_version.stdout is version('1.0.0', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ - import_tasks: ../tests/validate.yml
+
+ when: cryptography_version.stdout is version('1.5', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/obtain-cert.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/obtain-cert.yml
new file mode 100644
index 00000000..ec53510b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tasks/obtain-cert.yml
@@ -0,0 +1,144 @@
+---
+## PRIVATE KEY ################################################################################
+- name: ({{ certgen_title }}) Create cert private key (RSA)
+ command: "{{ openssl_binary }} genrsa -out {{ output_dir }}/{{ certificate_name }}.key {{ rsa_bits if key_type == 'rsa' else default_rsa_key_size }}"
+ when: "key_type == 'rsa'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 256)
+ command: "{{ openssl_binary }} ecparam -name prime256v1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec256'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 384)
+ command: "{{ openssl_binary }} ecparam -name secp384r1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec384'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 512)
+ command: "{{ openssl_binary }} ecparam -name secp521r1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec521'"
+## CSR ########################################################################################
+- name: ({{ certgen_title }}) Create cert CSR
+ openssl_csr:
+ path: "{{ output_dir }}/{{ certificate_name }}.csr"
+ privatekey_path: "{{ output_dir }}/{{ certificate_name }}.key"
+ subject_alt_name: "{{ subject_alt_name }}"
+ subject_alt_name_critical: "{{ subject_alt_name_critical }}"
+ return_content: true
+ register: csr_result
+## ACME STEP 1 ################################################################################
+- name: ({{ certgen_title }}) Obtain cert, step 1
+ acme_certificate:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_key: "{{ (output_dir ~ '/' ~ account_key ~ '.pem') if account_key_content is not defined else omit }}"
+ account_key_content: "{{ account_key_content | default(omit) }}"
+ modify_account: "{{ modify_account }}"
+ csr: "{{ omit if use_csr_content | default(false) else output_dir ~ '/' ~ certificate_name ~ '.csr' }}"
+ csr_content: "{{ csr_result.csr if use_csr_content | default(false) else omit }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}.pem"
+ fullchain_dest: "{{ output_dir }}/{{ certificate_name }}-fullchain.pem"
+ chain_dest: "{{ output_dir }}/{{ certificate_name }}-chain.pem"
+ challenge: "{{ challenge }}"
+ deactivate_authzs: "{{ deactivate_authzs }}"
+ force: "{{ force }}"
+ remaining_days: "{{ remaining_days }}"
+ terms_agreed: "{{ terms_agreed }}"
+ account_email: "{{ account_email }}"
+ register: challenge_data
+- name: ({{ certgen_title }}) Print challenge data
+ debug:
+ var: challenge_data
+- name: ({{ certgen_title }}) Create HTTP challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/http/{{ item.key }}/{{ item.value['http-01'].resource[('.well-known/acme-challenge/'|length):] }}"
+ method: PUT
+ body_format: raw
+ body: "{{ item.value['http-01'].resource_value }}"
+ headers:
+ content-type: "application/octet-stream"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'http-01'"
+- name: ({{ certgen_title }}) Create DNS challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/dns/{{ item.key }}"
+ method: PUT
+ body_format: json
+ body: "{{ item.value }}"
+ with_dict: "{{ challenge_data.challenge_data_dns }}"
+ when: "challenge_data is changed and challenge == 'dns-01'"
+- name: ({{ certgen_title }}) Create TLS ALPN challenges (acm_challenge_cert_helper)
+ acme_challenge_cert_helper:
+ challenge: tls-alpn-01
+ challenge_data: "{{ item.value['tls-alpn-01'] }}"
+ private_key_src: "{{ output_dir }}/{{ certificate_name }}.key"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ register: tls_alpn_challenges
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is defined and challenge_alpn_tls == 'acme_challenge_cert_helper')"
+- name: ({{ certgen_title }}) Set TLS ALPN challenges (acm_challenge_cert_helper)
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.domain }}/{{ item.identifier }}/certificate-and-key"
+ method: PUT
+ body_format: raw
+ body: "{{ item.challenge_certificate }}\n{{ lookup('file', output_dir ~ '/' ~ certificate_name ~ '.key') }}"
+ headers:
+ content-type: "application/pem-certificate-chain"
+ with_items: "{{ tls_alpn_challenges.results }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is defined and challenge_alpn_tls == 'acme_challenge_cert_helper')"
+- name: ({{ certgen_title }}) Create TLS ALPN challenges (der-value-b64)
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.value['tls-alpn-01'].resource }}/{{ item.value['tls-alpn-01'].resource_original }}/der-value-b64"
+ method: PUT
+ body_format: raw
+ body: "{{ item.value['tls-alpn-01'].resource_value }}"
+ headers:
+ content-type: "application/octet-stream"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is not defined or challenge_alpn_tls == 'der-value-b64')"
+## ACME STEP 2 ################################################################################
+- name: ({{ certgen_title }}) Obtain cert, step 2
+ acme_certificate:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_key: "{{ (output_dir ~ '/' ~ account_key ~ '.pem') if account_key_content is not defined else omit }}"
+ account_key_content: "{{ account_key_content | default(omit) }}"
+ account_uri: "{{ challenge_data.account_uri }}"
+ modify_account: "{{ modify_account }}"
+ csr: "{{ omit if use_csr_content | default(false) else output_dir ~ '/' ~ certificate_name ~ '.csr' }}"
+ csr_content: "{{ csr_result.csr if use_csr_content | default(false) else omit }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}.pem"
+ fullchain_dest: "{{ output_dir }}/{{ certificate_name }}-fullchain.pem"
+ chain_dest: "{{ output_dir }}/{{ certificate_name }}-chain.pem"
+ challenge: "{{ challenge }}"
+ deactivate_authzs: "{{ deactivate_authzs }}"
+ force: "{{ force }}"
+ remaining_days: "{{ remaining_days }}"
+ terms_agreed: "{{ terms_agreed }}"
+ account_email: "{{ account_email }}"
+ data: "{{ challenge_data }}"
+ retrieve_all_alternates: "{{ retrieve_all_alternates | default(omit) }}"
+ select_chain: "{{ select_chain | default(omit) if select_crypto_backend == 'cryptography' else omit }}"
+ register: certificate_obtain_result
+ when: challenge_data is changed
+- name: ({{ certgen_title }}) Deleting HTTP challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/http/{{ item.key }}/{{ item.value['http-01'].resource[('.well-known/acme-challenge/'|length):] }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'http-01'"
+- name: ({{ certgen_title }}) Deleting DNS challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/dns/{{ item.key }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data_dns }}"
+ when: "challenge_data is changed and challenge == 'dns-01'"
+- name: ({{ certgen_title }}) Deleting TLS ALPN challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.value['tls-alpn-01'].resource }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01'"
+- name: ({{ certgen_title }}) Get root certificate
+ get_url:
+ url: "http://{{ acme_host }}:5000/root-certificate-for-ca/{{ acme_expected_root_number | default(0) if select_crypto_backend == 'cryptography' else 0 }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}-root.pem"
+###############################################################################################
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tests/validate.yml
new file mode 100644
index 00000000..7f8f9c54
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_certificate_revoke/tests/validate.yml
@@ -0,0 +1,16 @@
+---
+- name: Check that certificate 1 was revoked
+ assert:
+ that:
+ - cert_1_revoke is changed
+ - cert_1_revoke is not failed
+- name: Check that certificate 2 was revoked
+ assert:
+ that:
+ - cert_2_revoke is changed
+ - cert_2_revoke is not failed
+- name: Check that certificate 3 was revoked
+ assert:
+ that:
+ - cert_3_revoke is changed
+ - cert_3_revoke is not failed
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/aliases
new file mode 100644
index 00000000..d7936330
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/aliases
@@ -0,0 +1,2 @@
+shippable/cloud/group1
+cloud/acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/meta/main.yml
new file mode 100644
index 00000000..81d1e7e7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/tasks/main.yml
new file mode 100644
index 00000000..cd306a4a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/tasks/main.yml
@@ -0,0 +1,30 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- block:
+ - name: Create ECC256 account key
+ command: "{{ openssl_binary }} ecparam -name prime256v1 -genkey -out {{ output_dir }}/account-ec256.pem"
+ - name: Obtain cert 1
+ include_tasks: obtain-cert.yml
+ vars:
+ select_crypto_backend: auto
+ certgen_title: Certificate 1
+ certificate_name: cert-1
+ key_type: rsa
+ rsa_bits: "{{ default_rsa_key_size }}"
+ subject_alt_name: "DNS:example.com"
+ subject_alt_name_critical: no
+ account_key: account-ec256
+ challenge: tls-alpn-01
+ challenge_alpn_tls: acme_challenge_cert_helper
+ modify_account: yes
+ deactivate_authzs: no
+ force: no
+ remaining_days: 10
+ terms_agreed: yes
+ account_email: "example@example.org"
+
+ when: openssl_version.stdout is version('1.0.0', '>=') or cryptography_version.stdout is version('1.5', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/tasks/obtain-cert.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/tasks/obtain-cert.yml
new file mode 100644
index 00000000..ec53510b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_challenge_cert_helper/tasks/obtain-cert.yml
@@ -0,0 +1,144 @@
+---
+## PRIVATE KEY ################################################################################
+- name: ({{ certgen_title }}) Create cert private key (RSA)
+ command: "{{ openssl_binary }} genrsa -out {{ output_dir }}/{{ certificate_name }}.key {{ rsa_bits if key_type == 'rsa' else default_rsa_key_size }}"
+ when: "key_type == 'rsa'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 256)
+ command: "{{ openssl_binary }} ecparam -name prime256v1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec256'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 384)
+ command: "{{ openssl_binary }} ecparam -name secp384r1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec384'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 512)
+ command: "{{ openssl_binary }} ecparam -name secp521r1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec521'"
+## CSR ########################################################################################
+- name: ({{ certgen_title }}) Create cert CSR
+ openssl_csr:
+ path: "{{ output_dir }}/{{ certificate_name }}.csr"
+ privatekey_path: "{{ output_dir }}/{{ certificate_name }}.key"
+ subject_alt_name: "{{ subject_alt_name }}"
+ subject_alt_name_critical: "{{ subject_alt_name_critical }}"
+ return_content: true
+ register: csr_result
+## ACME STEP 1 ################################################################################
+- name: ({{ certgen_title }}) Obtain cert, step 1
+ acme_certificate:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_key: "{{ (output_dir ~ '/' ~ account_key ~ '.pem') if account_key_content is not defined else omit }}"
+ account_key_content: "{{ account_key_content | default(omit) }}"
+ modify_account: "{{ modify_account }}"
+ csr: "{{ omit if use_csr_content | default(false) else output_dir ~ '/' ~ certificate_name ~ '.csr' }}"
+ csr_content: "{{ csr_result.csr if use_csr_content | default(false) else omit }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}.pem"
+ fullchain_dest: "{{ output_dir }}/{{ certificate_name }}-fullchain.pem"
+ chain_dest: "{{ output_dir }}/{{ certificate_name }}-chain.pem"
+ challenge: "{{ challenge }}"
+ deactivate_authzs: "{{ deactivate_authzs }}"
+ force: "{{ force }}"
+ remaining_days: "{{ remaining_days }}"
+ terms_agreed: "{{ terms_agreed }}"
+ account_email: "{{ account_email }}"
+ register: challenge_data
+- name: ({{ certgen_title }}) Print challenge data
+ debug:
+ var: challenge_data
+- name: ({{ certgen_title }}) Create HTTP challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/http/{{ item.key }}/{{ item.value['http-01'].resource[('.well-known/acme-challenge/'|length):] }}"
+ method: PUT
+ body_format: raw
+ body: "{{ item.value['http-01'].resource_value }}"
+ headers:
+ content-type: "application/octet-stream"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'http-01'"
+- name: ({{ certgen_title }}) Create DNS challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/dns/{{ item.key }}"
+ method: PUT
+ body_format: json
+ body: "{{ item.value }}"
+ with_dict: "{{ challenge_data.challenge_data_dns }}"
+ when: "challenge_data is changed and challenge == 'dns-01'"
+- name: ({{ certgen_title }}) Create TLS ALPN challenges (acm_challenge_cert_helper)
+ acme_challenge_cert_helper:
+ challenge: tls-alpn-01
+ challenge_data: "{{ item.value['tls-alpn-01'] }}"
+ private_key_src: "{{ output_dir }}/{{ certificate_name }}.key"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ register: tls_alpn_challenges
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is defined and challenge_alpn_tls == 'acme_challenge_cert_helper')"
+- name: ({{ certgen_title }}) Set TLS ALPN challenges (acm_challenge_cert_helper)
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.domain }}/{{ item.identifier }}/certificate-and-key"
+ method: PUT
+ body_format: raw
+ body: "{{ item.challenge_certificate }}\n{{ lookup('file', output_dir ~ '/' ~ certificate_name ~ '.key') }}"
+ headers:
+ content-type: "application/pem-certificate-chain"
+ with_items: "{{ tls_alpn_challenges.results }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is defined and challenge_alpn_tls == 'acme_challenge_cert_helper')"
+- name: ({{ certgen_title }}) Create TLS ALPN challenges (der-value-b64)
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.value['tls-alpn-01'].resource }}/{{ item.value['tls-alpn-01'].resource_original }}/der-value-b64"
+ method: PUT
+ body_format: raw
+ body: "{{ item.value['tls-alpn-01'].resource_value }}"
+ headers:
+ content-type: "application/octet-stream"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is not defined or challenge_alpn_tls == 'der-value-b64')"
+## ACME STEP 2 ################################################################################
+- name: ({{ certgen_title }}) Obtain cert, step 2
+ acme_certificate:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_key: "{{ (output_dir ~ '/' ~ account_key ~ '.pem') if account_key_content is not defined else omit }}"
+ account_key_content: "{{ account_key_content | default(omit) }}"
+ account_uri: "{{ challenge_data.account_uri }}"
+ modify_account: "{{ modify_account }}"
+ csr: "{{ omit if use_csr_content | default(false) else output_dir ~ '/' ~ certificate_name ~ '.csr' }}"
+ csr_content: "{{ csr_result.csr if use_csr_content | default(false) else omit }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}.pem"
+ fullchain_dest: "{{ output_dir }}/{{ certificate_name }}-fullchain.pem"
+ chain_dest: "{{ output_dir }}/{{ certificate_name }}-chain.pem"
+ challenge: "{{ challenge }}"
+ deactivate_authzs: "{{ deactivate_authzs }}"
+ force: "{{ force }}"
+ remaining_days: "{{ remaining_days }}"
+ terms_agreed: "{{ terms_agreed }}"
+ account_email: "{{ account_email }}"
+ data: "{{ challenge_data }}"
+ retrieve_all_alternates: "{{ retrieve_all_alternates | default(omit) }}"
+ select_chain: "{{ select_chain | default(omit) if select_crypto_backend == 'cryptography' else omit }}"
+ register: certificate_obtain_result
+ when: challenge_data is changed
+- name: ({{ certgen_title }}) Deleting HTTP challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/http/{{ item.key }}/{{ item.value['http-01'].resource[('.well-known/acme-challenge/'|length):] }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'http-01'"
+- name: ({{ certgen_title }}) Deleting DNS challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/dns/{{ item.key }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data_dns }}"
+ when: "challenge_data is changed and challenge == 'dns-01'"
+- name: ({{ certgen_title }}) Deleting TLS ALPN challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.value['tls-alpn-01'].resource }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01'"
+- name: ({{ certgen_title }}) Get root certificate
+ get_url:
+ url: "http://{{ acme_host }}:5000/root-certificate-for-ca/{{ acme_expected_root_number | default(0) if select_crypto_backend == 'cryptography' else 0 }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}-root.pem"
+###############################################################################################
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/aliases
new file mode 100644
index 00000000..d7936330
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/aliases
@@ -0,0 +1,2 @@
+shippable/cloud/group1
+cloud/acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/meta/main.yml
new file mode 100644
index 00000000..81d1e7e7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tasks/impl.yml
new file mode 100644
index 00000000..3f5c561f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tasks/impl.yml
@@ -0,0 +1,151 @@
+---
+- name: Generate account key
+ command: "{{ openssl_binary }} ecparam -name prime256v1 -genkey -out {{ output_dir }}/accountkey.pem"
+
+- name: Parse account key (to ease debugging some test failures)
+ command: "{{ openssl_binary }} ec -in {{ output_dir }}/accountkey.pem -noout -text"
+
+- name: Get directory
+ acme_inspect:
+ acme_directory: https://{{ acme_host }}:14000/dir
+ acme_version: 2
+ validate_certs: no
+ method: directory-only
+ register: directory
+- debug: var=directory
+
+- name: Create an account
+ acme_inspect:
+ acme_directory: https://{{ acme_host }}:14000/dir
+ acme_version: 2
+ validate_certs: no
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ url: "{{ directory.directory.newAccount}}"
+ method: post
+ content: '{"termsOfServiceAgreed":true}'
+ register: account_creation
+ # account_creation.headers.location contains the account URI
+ # if creation was successful
+- debug: var=account_creation
+
+- name: Get account information
+ acme_inspect:
+ acme_directory: https://{{ acme_host }}:14000/dir
+ acme_version: 2
+ validate_certs: no
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ account_uri: "{{ account_creation.headers.location }}"
+ url: "{{ account_creation.headers.location }}"
+ method: get
+ register: account_get
+- debug: var=account_get
+
+- name: Update account contacts
+ acme_inspect:
+ acme_directory: https://{{ acme_host }}:14000/dir
+ acme_version: 2
+ validate_certs: no
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ account_uri: "{{ account_creation.headers.location }}"
+ url: "{{ account_creation.headers.location }}"
+ method: post
+ content: '{{ account_info | to_json }}'
+ vars:
+ account_info:
+ # For valid values, see
+ # https://www.rfc-editor.org/rfc/rfc8555.html#section-7.3
+ contact:
+ - mailto:me@example.com
+ register: account_update
+- debug: var=account_update
+
+- name: Create certificate order
+ acme_inspect:
+ acme_directory: https://{{ acme_host }}:14000/dir
+ acme_version: 2
+ validate_certs: no
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ account_uri: "{{ account_creation.headers.location }}"
+ url: "{{ directory.directory.newOrder }}"
+ method: post
+ content: '{{ create_order | to_json }}'
+ vars:
+ create_order:
+ # For valid values, see
+ # https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4 and
+ # https://www.rfc-editor.org/rfc/rfc8738.html
+ identifiers:
+ - type: dns
+ value: example.com
+ - type: dns
+ value: example.org
+ register: new_order
+- debug: var=new_order
+
+- name: Get order information
+ acme_inspect:
+ acme_directory: https://{{ acme_host }}:14000/dir
+ acme_version: 2
+ validate_certs: no
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ account_uri: "{{ account_creation.headers.location }}"
+ url: "{{ new_order.headers.location }}"
+ method: get
+ register: order
+- debug: var=order
+
+- name: Get authzs for order
+ acme_inspect:
+ acme_directory: https://{{ acme_host }}:14000/dir
+ acme_version: 2
+ validate_certs: no
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ account_uri: "{{ account_creation.headers.location }}"
+ url: "{{ item }}"
+ method: get
+ loop: "{{ order.output_json.authorizations }}"
+ register: authz
+- debug: var=authz
+
+- name: Get HTTP-01 challenge for authz
+ acme_inspect:
+ acme_directory: https://{{ acme_host }}:14000/dir
+ acme_version: 2
+ validate_certs: no
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ account_uri: "{{ account_creation.headers.location }}"
+ url: "{{ (item.challenges | selectattr('type', 'equalto', 'http-01') | list)[0].url }}"
+ method: get
+ register: http01challenge
+ loop: "{{ authz.results | map(attribute='output_json') | list }}"
+- debug: var=http01challenge
+
+- name: Activate HTTP-01 challenge manually
+ acme_inspect:
+ acme_directory: https://{{ acme_host }}:14000/dir
+ acme_version: 2
+ validate_certs: no
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ account_uri: "{{ account_creation.headers.location }}"
+ url: "{{ item.url }}"
+ method: post
+ content: '{}'
+ register: activation
+ loop: "{{ http01challenge.results | map(attribute='output_json') | list }}"
+- debug: var=activation
+
+- name: Get HTTP-01 challenge results
+ acme_inspect:
+ acme_directory: https://{{ acme_host }}:14000/dir
+ acme_version: 2
+ validate_certs: no
+ account_key_src: "{{ output_dir }}/accountkey.pem"
+ account_uri: "{{ account_creation.headers.location }}"
+ url: "{{ item.url }}"
+ method: get
+ register: validation_result
+ loop: "{{ http01challenge.results | map(attribute='output_json') | list }}"
+ until: "validation_result.output_json.status != 'pending'"
+ retries: 20
+ delay: 1
+- debug: var=validation_result
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tasks/main.yml
new file mode 100644
index 00000000..b7c7452a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tasks/main.yml
@@ -0,0 +1,36 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- block:
+ - name: Running tests with OpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: openssl
+
+ - import_tasks: ../tests/validate.yml
+
+ # Old 0.9.8 versions have insufficient CLI support for signing with EC keys
+ when: openssl_version.stdout is version('1.0.0', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ - import_tasks: ../tests/validate.yml
+
+ when: cryptography_version.stdout is version('1.5', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tests/validate.yml
new file mode 100644
index 00000000..a45b512f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/acme_inspect/tests/validate.yml
@@ -0,0 +1,131 @@
+---
+- name: Check directory output
+ assert:
+ that:
+ - directory is not changed
+ - "'directory' in directory"
+ - "'newAccount' in directory.directory"
+ - "'newOrder' in directory.directory"
+ - "'newNonce' in directory.directory"
+ - "'headers' not in directory"
+ - "'output_text' not in directory"
+ - "'output_json' not in directory"
+
+- name: Check account creation output
+ assert:
+ that:
+ - account_creation is changed
+ - "'directory' in account_creation"
+ - "'headers' in account_creation"
+ - "'output_text' in account_creation"
+ - "'output_json' in account_creation"
+ - account_creation.headers.status == 201
+ - "'location' in account_creation.headers"
+ - account_creation.output_json.status == 'valid'
+ - not (account_creation.output_json.contact | default([]))
+ - account_creation.output_text | from_json == account_creation.output_json
+
+- name: Check account get output
+ assert:
+ that:
+ - account_get is not changed
+ - "'directory' in account_get"
+ - "'headers' in account_get"
+ - "'output_text' in account_get"
+ - "'output_json' in account_get"
+ - account_get.headers.status == 200
+ - account_get.output_json == account_creation.output_json
+
+- name: Check account update output
+ assert:
+ that:
+ - account_update is changed
+ - "'directory' in account_update"
+ - "'headers' in account_update"
+ - "'output_text' in account_update"
+ - "'output_json' in account_update"
+ - account_update.output_json.status == 'valid'
+ - account_update.output_json.contact | length == 1
+ - account_update.output_json.contact[0] == 'mailto:me@example.com'
+
+- name: Check certificate request output
+ assert:
+ that:
+ - new_order is changed
+ - "'directory' in new_order"
+ - "'headers' in new_order"
+ - "'output_text' in new_order"
+ - "'output_json' in new_order"
+ - new_order.output_json.authorizations | length == 2
+ - new_order.output_json.identifiers | length == 2
+ - new_order.output_json.status == 'pending'
+ - "'finalize' in new_order.output_json"
+
+- name: Check get order output
+ assert:
+ that:
+ - order is not changed
+ - "'directory' in order"
+ - "'headers' in order"
+ - "'output_text' in order"
+ - "'output_json' in order"
+ # The order of identifiers and authorizations is randomized!
+ # - new_order.output_json == order.output_json
+
+- name: Check get authz output
+ assert:
+ that:
+ - item is not changed
+ - "'directory' in item"
+ - "'headers' in item"
+ - "'output_text' in item"
+ - "'output_json' in item"
+ - item.output_json.challenges | length >= 3
+ - item.output_json.identifier.type == 'dns'
+ - item.output_json.status == 'pending'
+ loop: "{{ authz.results }}"
+
+- name: Check get challenge output
+ assert:
+ that:
+ - item is not changed
+ - "'directory' in item"
+ - "'headers' in item"
+ - "'output_text' in item"
+ - "'output_json' in item"
+ - item.output_json.status == 'pending'
+ - item.output_json.type == 'http-01'
+ - item.output_json.url == item.invocation.module_args.url
+ - "'token' in item.output_json"
+ loop: "{{ http01challenge.results }}"
+
+- name: Check challenge activation output
+ assert:
+ that:
+ - item is changed
+ - "'directory' in item"
+ - "'headers' in item"
+ - "'output_text' in item"
+ - "'output_json' in item"
+ - item.output_json.status == 'pending'
+ - item.output_json.type == 'http-01'
+ - item.output_json.url == item.invocation.module_args.url
+ - "'token' in item.output_json"
+ loop: "{{ activation.results }}"
+
+- name: Check validation result
+ assert:
+ that:
+ - item is not changed
+ - "'directory' in item"
+ - "'headers' in item"
+ - "'output_text' in item"
+ - "'output_json' in item"
+ - item.output_json.status == 'invalid'
+ - item.output_json.type == 'http-01'
+ - item.output_json.url == item.invocation.module_args.url
+ - "'token' in item.output_json"
+ - "'validated' in item.output_json"
+ - "'error' in item.output_json"
+ - item.output_json.error.type == 'urn:ietf:params:acme:error:unauthorized'
+ loop: "{{ validation_result.results }}"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/aliases
new file mode 100644
index 00000000..a6dafcf8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/aliases
@@ -0,0 +1 @@
+shippable/posix/group1
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-chain.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-chain.pem
new file mode 100644
index 00000000..3e0f6c08
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-chain.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAyWgAwIBAgIQWyXOaQfEJlVm0zkMmalUrTAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwOTI1MDAw
+MDAwWhcNMjkwOTI0MjM1OTU5WjCBkjELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxODA2BgNVBAMTL0NPTU9ETyBFQ0MgRG9tYWluIFZhbGlk
+YXRpb24gU2VjdXJlIFNlcnZlciBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
+QgAEAjgZgTrJaYRwWQKOqIofMN+83gP8eR06JSxrQSEYgur5PkrkM8wSzypD/A7y
+ZADA4SVQgiTNtkk4DyVHkUikraOCAWYwggFiMB8GA1UdIwQYMBaAFHVxpxlIGbyd
+nepBR9+UxEh3mdN5MB0GA1UdDgQWBBRACWFn8LyDcU/eEggsb9TUK3Y9ljAOBgNV
+HQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHSUEFjAUBggrBgEF
+BQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgGBmeBDAECATBMBgNV
+HR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9FQ0ND
+ZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDByBggrBgEFBQcBAQRmMGQwOwYIKwYB
+BQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET0VDQ0FkZFRydXN0
+Q0EuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQuY29tMAoG
+CCqGSM49BAMDA2gAMGUCMQCsaEclgBNPE1bAojcJl1pQxOfttGHLKIoKETKm4nHf
+EQGJbwd6IGZrGNC5LkP3Um8CMBKFfI4TZpIEuppFCZRKMGHRSdxv6+ctyYnPHmp8
+7IXOMCVZuoFwNLg0f+cB0eLLUg==
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-fullchain.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-fullchain.pem
new file mode 100644
index 00000000..e12a7ca8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-fullchain.pem
@@ -0,0 +1,51 @@
+-----BEGIN CERTIFICATE-----
+MIIFBTCCBKugAwIBAgIQL+c9oQXpvdcOD3BKAncbgDAKBggqhkjOPQQDAjCBkjEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMT
+L0NPTU9ETyBFQ0MgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQSAy
+MB4XDTE4MDcxMTAwMDAwMFoXDTE5MDExNzIzNTk1OVowbDEhMB8GA1UECxMYRG9t
+YWluIENvbnRyb2wgVmFsaWRhdGVkMSEwHwYDVQQLExhQb3NpdGl2ZVNTTCBNdWx0
+aS1Eb21haW4xJDAiBgNVBAMTG3NzbDgwMzAyNS5jbG91ZGZsYXJlc3NsLmNvbTBZ
+MBMGByqGSM49AgEGCCqGSM49AwEHA0IABMap9sMZnCzTXID1chTOmtOk8p6+SHbG
+3fmyJJljI7sN9RddlLKar9VBS48WguVv1R6trvERIYj8TzKCVBzu9mmjggMGMIID
+AjAfBgNVHSMEGDAWgBRACWFn8LyDcU/eEggsb9TUK3Y9ljAdBgNVHQ4EFgQUd/6a
+t8j7v5DsL7xWacf8VyzOLJcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAw
+HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCME8GA1UdIARIMEYwOgYLKwYB
+BAGyMQECAgcwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNv
+bS9DUFMwCAYGZ4EMAQIBMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwuY29t
+b2RvY2E0LmNvbS9DT01PRE9FQ0NEb21haW5WYWxpZGF0aW9uU2VjdXJlU2VydmVy
+Q0EyLmNybDCBiAYIKwYBBQUHAQEEfDB6MFEGCCsGAQUFBzAChkVodHRwOi8vY3J0
+LmNvbW9kb2NhNC5jb20vQ09NT0RPRUNDRG9tYWluVmFsaWRhdGlvblNlY3VyZVNl
+cnZlckNBMi5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLmNvbW9kb2NhNC5j
+b20wSAYDVR0RBEEwP4Ibc3NsODAzMDI1LmNsb3VkZmxhcmVzc2wuY29tghAqLmhz
+Y29zY2RuNDAubmV0gg5oc2Nvc2NkbjQwLm5ldDCCAQMGCisGAQQB1nkCBAIEgfQE
+gfEA7wB2AO5Lvbd1zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAABZIbVA88A
+AAQDAEcwRQIhANtN489Izy3iss/eF8rUw/gir8rqyA2t3lpxnco+J2NlAiBBku5M
+iGD8whW5/31byPj0/ype1MmG0QYrq3qWvYiQ3QB1AHR+2oMxrTMQkSGcziVPQnDC
+v/1eQiAIxjc1eeYQe8xWAAABZIbVBB4AAAQDAEYwRAIgSjcL7B4cbgm2XED69G7/
+iFPe2zkWhxnkgGISSwuXw1gCICzwPmfbjEfwDNXEuBs7JXkPRaT1pi7hZ9aR5wJJ
+TKH9MAoGCCqGSM49BAMCA0gAMEUCIQDqxmFLcme3Ldd+jiMQf7fT5pSezZfMOL0S
+cNmfGvNtPQIgec3sO/ylnnaztCy5KDjYsnh+rm01bxs+nz2DnOPF+xo=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAyWgAwIBAgIQWyXOaQfEJlVm0zkMmalUrTAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwOTI1MDAw
+MDAwWhcNMjkwOTI0MjM1OTU5WjCBkjELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxODA2BgNVBAMTL0NPTU9ETyBFQ0MgRG9tYWluIFZhbGlk
+YXRpb24gU2VjdXJlIFNlcnZlciBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
+QgAEAjgZgTrJaYRwWQKOqIofMN+83gP8eR06JSxrQSEYgur5PkrkM8wSzypD/A7y
+ZADA4SVQgiTNtkk4DyVHkUikraOCAWYwggFiMB8GA1UdIwQYMBaAFHVxpxlIGbyd
+nepBR9+UxEh3mdN5MB0GA1UdDgQWBBRACWFn8LyDcU/eEggsb9TUK3Y9ljAOBgNV
+HQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHSUEFjAUBggrBgEF
+BQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgGBmeBDAECATBMBgNV
+HR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9FQ0ND
+ZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDByBggrBgEFBQcBAQRmMGQwOwYIKwYB
+BQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET0VDQ0FkZFRydXN0
+Q0EuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQuY29tMAoG
+CCqGSM49BAMDA2gAMGUCMQCsaEclgBNPE1bAojcJl1pQxOfttGHLKIoKETKm4nHf
+EQGJbwd6IGZrGNC5LkP3Um8CMBKFfI4TZpIEuppFCZRKMGHRSdxv6+ctyYnPHmp8
+7IXOMCVZuoFwNLg0f+cB0eLLUg==
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-root.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-root.pem
new file mode 100644
index 00000000..546c95e3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1-root.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1.pem
new file mode 100644
index 00000000..d00d252d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert1.pem
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIFBTCCBKugAwIBAgIQL+c9oQXpvdcOD3BKAncbgDAKBggqhkjOPQQDAjCBkjEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMT
+L0NPTU9ETyBFQ0MgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQSAy
+MB4XDTE4MDcxMTAwMDAwMFoXDTE5MDExNzIzNTk1OVowbDEhMB8GA1UECxMYRG9t
+YWluIENvbnRyb2wgVmFsaWRhdGVkMSEwHwYDVQQLExhQb3NpdGl2ZVNTTCBNdWx0
+aS1Eb21haW4xJDAiBgNVBAMTG3NzbDgwMzAyNS5jbG91ZGZsYXJlc3NsLmNvbTBZ
+MBMGByqGSM49AgEGCCqGSM49AwEHA0IABMap9sMZnCzTXID1chTOmtOk8p6+SHbG
+3fmyJJljI7sN9RddlLKar9VBS48WguVv1R6trvERIYj8TzKCVBzu9mmjggMGMIID
+AjAfBgNVHSMEGDAWgBRACWFn8LyDcU/eEggsb9TUK3Y9ljAdBgNVHQ4EFgQUd/6a
+t8j7v5DsL7xWacf8VyzOLJcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAw
+HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCME8GA1UdIARIMEYwOgYLKwYB
+BAGyMQECAgcwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNv
+bS9DUFMwCAYGZ4EMAQIBMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwuY29t
+b2RvY2E0LmNvbS9DT01PRE9FQ0NEb21haW5WYWxpZGF0aW9uU2VjdXJlU2VydmVy
+Q0EyLmNybDCBiAYIKwYBBQUHAQEEfDB6MFEGCCsGAQUFBzAChkVodHRwOi8vY3J0
+LmNvbW9kb2NhNC5jb20vQ09NT0RPRUNDRG9tYWluVmFsaWRhdGlvblNlY3VyZVNl
+cnZlckNBMi5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLmNvbW9kb2NhNC5j
+b20wSAYDVR0RBEEwP4Ibc3NsODAzMDI1LmNsb3VkZmxhcmVzc2wuY29tghAqLmhz
+Y29zY2RuNDAubmV0gg5oc2Nvc2NkbjQwLm5ldDCCAQMGCisGAQQB1nkCBAIEgfQE
+gfEA7wB2AO5Lvbd1zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAABZIbVA88A
+AAQDAEcwRQIhANtN489Izy3iss/eF8rUw/gir8rqyA2t3lpxnco+J2NlAiBBku5M
+iGD8whW5/31byPj0/ype1MmG0QYrq3qWvYiQ3QB1AHR+2oMxrTMQkSGcziVPQnDC
+v/1eQiAIxjc1eeYQe8xWAAABZIbVBB4AAAQDAEYwRAIgSjcL7B4cbgm2XED69G7/
+iFPe2zkWhxnkgGISSwuXw1gCICzwPmfbjEfwDNXEuBs7JXkPRaT1pi7hZ9aR5wJJ
+TKH9MAoGCCqGSM49BAMCA0gAMEUCIQDqxmFLcme3Ldd+jiMQf7fT5pSezZfMOL0S
+cNmfGvNtPQIgec3sO/ylnnaztCy5KDjYsnh+rm01bxs+nz2DnOPF+xo=
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-altchain.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-altchain.pem
new file mode 100644
index 00000000..4e82cb56
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-altchain.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw
+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1
+WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
+RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX
+NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf
+89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl
+Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc
+Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz
+uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB
+AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU
+BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB
+FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo
+SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js
+LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF
+BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG
+AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD
+VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB
+ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx
+A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM
+UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2
+DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1
+eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu
+OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw
+p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY
+2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0
+ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR
+PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b
+rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-altroot.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-altroot.pem
new file mode 100644
index 00000000..b85c8037
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-altroot.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
+WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
+ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
+h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
+A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
+T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
+B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
+B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
+KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
+OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
+jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
+qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
+rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
+hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
+ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
+3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
+NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
+ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
+TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
+jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
+oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
+4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
+mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
+emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-chain.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-chain.pem
new file mode 100644
index 00000000..0002462c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-chain.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
+MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
+SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
+GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
+q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
+SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
+Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
+a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
+/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
+AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
+CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
+bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
+c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
+VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
+ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
+MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
+Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
+AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
+uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
+wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
+X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
+PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
+KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-fullchain.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-fullchain.pem
new file mode 100644
index 00000000..cf75a331
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-fullchain.pem
@@ -0,0 +1,72 @@
+-----BEGIN CERTIFICATE-----
+MIIH5jCCBs6gAwIBAgISA2gSCm/BtvCR2e2bIap5YbXaMA0GCSqGSIb3DQEBCwUA
+MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
+ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODA3MjcxNzMxMjdaFw0x
+ODEwMjUxNzMxMjdaMB4xHDAaBgNVBAMTE3d3dy5sZXRzZW5jcnlwdC5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDpL8ZjVL0MUkUAIbYO9+ZCni+c
+ghGd9WhM2Ztaay6Wyh6lNoCdltdqTwUhE4O+d7UFModjM3G/KMyfuujr06c5iGKL
+3saPmIzLaRPIEOUlB2rKgasKhe8mDRyRLzQSXXgnsaKcTBBuhIHvtP51ZMr05nJJ
+sX/5FGjj96w+KJel6E/Ux1a1ZDOFkAYNSIrJJhA5jjIvUPr+Ri6Oc6UlhF9oueKI
+uWBILxQpC778tBWdHoZeBCNTHA1VvtwC53OeuHvdZm1jB/e30Mgf5DtVizYpFXVD
+mztkrd6z/3B6ZwPyfCE4KgzSf70/byOz971OJxNKTUVWedKHHDlrMxfsPclbAgMB
+AAGjggTwMIIE7DAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
+CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFG1w4j/KDrYSFu7m9DPE
+xRR0E5gzMB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUF
+BwEBBGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNy
+eXB0Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNy
+eXB0Lm9yZy8wggHxBgNVHREEggHoMIIB5IIbY2VydC5pbnQteDEubGV0c2VuY3J5
+cHQub3JnghtjZXJ0LmludC14Mi5sZXRzZW5jcnlwdC5vcmeCG2NlcnQuaW50LXgz
+LmxldHNlbmNyeXB0Lm9yZ4IbY2VydC5pbnQteDQubGV0c2VuY3J5cHQub3Jnghxj
+ZXJ0LnJvb3QteDEubGV0c2VuY3J5cHQub3Jngh9jZXJ0LnN0YWdpbmcteDEubGV0
+c2VuY3J5cHQub3Jngh9jZXJ0LnN0Zy1pbnQteDEubGV0c2VuY3J5cHQub3JngiBj
+ZXJ0LnN0Zy1yb290LXgxLmxldHNlbmNyeXB0Lm9yZ4ISY3AubGV0c2VuY3J5cHQu
+b3JnghpjcC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZ4ITY3BzLmxldHNlbmNyeXB0
+Lm9yZ4IbY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3Jnghtjcmwucm9vdC14MS5s
+ZXRzZW5jcnlwdC5vcmeCD2xldHNlbmNyeXB0Lm9yZ4IWb3JpZ2luLmxldHNlbmNy
+eXB0Lm9yZ4IXb3JpZ2luMi5sZXRzZW5jcnlwdC5vcmeCFnN0YXR1cy5sZXRzZW5j
+cnlwdC5vcmeCE3d3dy5sZXRzZW5jcnlwdC5vcmcwgf4GA1UdIASB9jCB8zAIBgZn
+gQwBAgEwgeYGCysGAQQBgt8TAQEBMIHWMCYGCCsGAQUFBwIBFhpodHRwOi8vY3Bz
+LmxldHNlbmNyeXB0Lm9yZzCBqwYIKwYBBQUHAgIwgZ4MgZtUaGlzIENlcnRpZmlj
+YXRlIG1heSBvbmx5IGJlIHJlbGllZCB1cG9uIGJ5IFJlbHlpbmcgUGFydGllcyBh
+bmQgb25seSBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIENlcnRpZmljYXRlIFBvbGlj
+eSBmb3VuZCBhdCBodHRwczovL2xldHNlbmNyeXB0Lm9yZy9yZXBvc2l0b3J5LzCC
+AQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AMEWSuCnctLUOS3ICsEHcNTwxJvemRpI
+QMH6B1Fk9jNgAAABZN0ChToAAAQDAEcwRQIgblal8oXnfoopr1+dWVhvBx+sqHT0
+eLYxJHBTaRp3j1QCIQDhFQqMk6DDXUgcU12K36zLVFwJTdAJI4RBisnX+g+W0AB2
+ACk8UZZUyDlluqpQ/FgH1Ldvv1h6KXLcpMMM9OVFR/R4AAABZN0Chz4AAAQDAEcw
+RQIhAImOjvkritUNKJZB7dcUtjoyIbfNwdCspvRiEzXuvVQoAiAZryoyg3TcMun5
+Gb2dEn1cttMnPW9u670/JdRjvjU/wTANBgkqhkiG9w0BAQsFAAOCAQEAGepCmckP
+Tn9Sz268FEwkdD+6wWaPfeYlh+9nacFh90nQ35EYQMOK8a+X7ixHGbRz19On3Wt4
+1fcbPa9SefocTjAintMwwreCxpRTmwGACYojd7vRWEmA6q7+/HO2BfZahWzclOjw
+mSDBycDEm8R0ZK52vYjzVno8x0mrsmSO0403S/6syYB/guH6P17kIBw+Tgx6/i/c
+I1C6MoFkuaAKUUcZmgGGBgE+L/7cWtWjbkVXyA3ZQQy9G7rcBT+N/RrDfBh4iZDq
+jAN5UIIYL8upBhjiMYVuoJrH2nklzEwr5SWKcccJX5eWkGLUwlcY9LGAA8+17l2I
+l1Ou20Dm9TxnNw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
+MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
+SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
+GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
+q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
+SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
+Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
+a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
+/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
+AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
+CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
+bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
+c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
+VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
+ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
+MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
+Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
+AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
+uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
+wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
+X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
+PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
+KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-root.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-root.pem
new file mode 100644
index 00000000..b2e43c93
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2-root.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
+MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
+PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
+Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
+rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
+OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
+xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
+7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
+aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
+SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
+ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
+AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
+R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
+JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
+Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2.pem
new file mode 100644
index 00000000..834eedc4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/cert2.pem
@@ -0,0 +1,45 @@
+-----BEGIN CERTIFICATE-----
+MIIH5jCCBs6gAwIBAgISA2gSCm/BtvCR2e2bIap5YbXaMA0GCSqGSIb3DQEBCwUA
+MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
+ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODA3MjcxNzMxMjdaFw0x
+ODEwMjUxNzMxMjdaMB4xHDAaBgNVBAMTE3d3dy5sZXRzZW5jcnlwdC5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDpL8ZjVL0MUkUAIbYO9+ZCni+c
+ghGd9WhM2Ztaay6Wyh6lNoCdltdqTwUhE4O+d7UFModjM3G/KMyfuujr06c5iGKL
+3saPmIzLaRPIEOUlB2rKgasKhe8mDRyRLzQSXXgnsaKcTBBuhIHvtP51ZMr05nJJ
+sX/5FGjj96w+KJel6E/Ux1a1ZDOFkAYNSIrJJhA5jjIvUPr+Ri6Oc6UlhF9oueKI
+uWBILxQpC778tBWdHoZeBCNTHA1VvtwC53OeuHvdZm1jB/e30Mgf5DtVizYpFXVD
+mztkrd6z/3B6ZwPyfCE4KgzSf70/byOz971OJxNKTUVWedKHHDlrMxfsPclbAgMB
+AAGjggTwMIIE7DAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
+CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFG1w4j/KDrYSFu7m9DPE
+xRR0E5gzMB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUF
+BwEBBGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNy
+eXB0Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNy
+eXB0Lm9yZy8wggHxBgNVHREEggHoMIIB5IIbY2VydC5pbnQteDEubGV0c2VuY3J5
+cHQub3JnghtjZXJ0LmludC14Mi5sZXRzZW5jcnlwdC5vcmeCG2NlcnQuaW50LXgz
+LmxldHNlbmNyeXB0Lm9yZ4IbY2VydC5pbnQteDQubGV0c2VuY3J5cHQub3Jnghxj
+ZXJ0LnJvb3QteDEubGV0c2VuY3J5cHQub3Jngh9jZXJ0LnN0YWdpbmcteDEubGV0
+c2VuY3J5cHQub3Jngh9jZXJ0LnN0Zy1pbnQteDEubGV0c2VuY3J5cHQub3JngiBj
+ZXJ0LnN0Zy1yb290LXgxLmxldHNlbmNyeXB0Lm9yZ4ISY3AubGV0c2VuY3J5cHQu
+b3JnghpjcC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZ4ITY3BzLmxldHNlbmNyeXB0
+Lm9yZ4IbY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3Jnghtjcmwucm9vdC14MS5s
+ZXRzZW5jcnlwdC5vcmeCD2xldHNlbmNyeXB0Lm9yZ4IWb3JpZ2luLmxldHNlbmNy
+eXB0Lm9yZ4IXb3JpZ2luMi5sZXRzZW5jcnlwdC5vcmeCFnN0YXR1cy5sZXRzZW5j
+cnlwdC5vcmeCE3d3dy5sZXRzZW5jcnlwdC5vcmcwgf4GA1UdIASB9jCB8zAIBgZn
+gQwBAgEwgeYGCysGAQQBgt8TAQEBMIHWMCYGCCsGAQUFBwIBFhpodHRwOi8vY3Bz
+LmxldHNlbmNyeXB0Lm9yZzCBqwYIKwYBBQUHAgIwgZ4MgZtUaGlzIENlcnRpZmlj
+YXRlIG1heSBvbmx5IGJlIHJlbGllZCB1cG9uIGJ5IFJlbHlpbmcgUGFydGllcyBh
+bmQgb25seSBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIENlcnRpZmljYXRlIFBvbGlj
+eSBmb3VuZCBhdCBodHRwczovL2xldHNlbmNyeXB0Lm9yZy9yZXBvc2l0b3J5LzCC
+AQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AMEWSuCnctLUOS3ICsEHcNTwxJvemRpI
+QMH6B1Fk9jNgAAABZN0ChToAAAQDAEcwRQIgblal8oXnfoopr1+dWVhvBx+sqHT0
+eLYxJHBTaRp3j1QCIQDhFQqMk6DDXUgcU12K36zLVFwJTdAJI4RBisnX+g+W0AB2
+ACk8UZZUyDlluqpQ/FgH1Ldvv1h6KXLcpMMM9OVFR/R4AAABZN0Chz4AAAQDAEcw
+RQIhAImOjvkritUNKJZB7dcUtjoyIbfNwdCspvRiEzXuvVQoAiAZryoyg3TcMun5
+Gb2dEn1cttMnPW9u670/JdRjvjU/wTANBgkqhkiG9w0BAQsFAAOCAQEAGepCmckP
+Tn9Sz268FEwkdD+6wWaPfeYlh+9nacFh90nQ35EYQMOK8a+X7ixHGbRz19On3Wt4
+1fcbPa9SefocTjAintMwwreCxpRTmwGACYojd7vRWEmA6q7+/HO2BfZahWzclOjw
+mSDBycDEm8R0ZK52vYjzVno8x0mrsmSO0403S/6syYB/guH6P17kIBw+Tgx6/i/c
+I1C6MoFkuaAKUUcZmgGGBgE+L/7cWtWjbkVXyA3ZQQy9G7rcBT+N/RrDfBh4iZDq
+jAN5UIIYL8upBhjiMYVuoJrH2nklzEwr5SWKcccJX5eWkGLUwlcY9LGAA8+17l2I
+l1Ou20Dm9TxnNw==
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots.pem
new file mode 100644
index 00000000..ee6c058d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots.pem
@@ -0,0 +1,3733 @@
+# ACCVRAIZ1
+-----BEGIN CERTIFICATE-----
+MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE
+AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw
+CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ
+BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND
+VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb
+qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY
+HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo
+G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA
+lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr
+IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/
+0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH
+k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47
+4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO
+m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa
+cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl
+uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI
+KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls
+ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG
+AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
+VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT
+VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG
+CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA
+cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA
+QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA
+7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA
+cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA
+QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA
+czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu
+aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt
+aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud
+DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF
+BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp
+D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU
+JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m
+AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD
+vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms
+tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH
+7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
+I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA
+h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF
+d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H
+pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7
+-----END CERTIFICATE-----
+
+# AC RAIZ FNMT-RCM
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx
+CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ
+WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ
+BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG
+Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/
+yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf
+BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz
+WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF
+tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z
+374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC
+IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL
+mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7
+wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS
+MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2
+ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet
+UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H
+YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3
+LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
+nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1
+RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM
+LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf
+77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N
+JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm
+fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp
+6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp
+1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B
+9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok
+RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv
+uu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
+-----END CERTIFICATE-----
+
+# Actalis Authentication Root CA
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE
+BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w
+MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC
+SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1
+ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv
+UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX
+4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9
+KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/
+gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb
+rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ
+51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F
+be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe
+KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F
+v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn
+fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7
+jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz
+ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL
+e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70
+jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz
+WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V
+SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j
+pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX
+X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok
+fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R
+K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU
+ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU
+LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT
+LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
+
+# AddTrust External Root
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
+IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
+MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
+FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
+bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
+H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
+uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
+mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
+a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
+E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
+WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
+VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
+Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
+cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
+IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
+AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
+YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
+Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
+c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
+mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----
+
+# AffirmTrust Commercial
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+# AffirmTrust Networking
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+# AffirmTrust Premium
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
+KeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+# AffirmTrust Premium ECC
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
+-----END CERTIFICATE-----
+
+# Amazon Root CA 1
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
+ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
+9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
+IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
+VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
+93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
+jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
+A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
+U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
+N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
+o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
+5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
+rqXRfboQnoZsG4q5WTP468SQvvG5
+-----END CERTIFICATE-----
+
+# Amazon Root CA 2
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK
+gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ
+W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg
+1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K
+8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r
+2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me
+z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR
+8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj
+mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz
+7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6
++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI
+0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm
+UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2
+LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS
+k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl
+7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm
+btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl
+urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+
+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63
+n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE
+76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H
+9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT
+4PsJYGw=
+-----END CERTIFICATE-----
+
+# Amazon Root CA 3
+-----BEGIN CERTIFICATE-----
+MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
+ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
+ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
+BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
+YyRIHN8wfdVoOw==
+-----END CERTIFICATE-----
+
+# Amazon Root CA 4
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
+9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
+M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
+MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
+CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
+1KyLa2tJElMzrdfkviT8tQp21KW8EA==
+-----END CERTIFICATE-----
+
+# Atos TrustedRoot 2011
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
+
+# Autoridad de Certificacion Firmaprofesional CIF A62634068
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE
+BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h
+cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy
+MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg
+Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9
+thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM
+cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG
+L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i
+NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h
+X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b
+m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy
+Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja
+EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T
+KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF
+6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh
+OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD
+VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
+cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv
+ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl
+AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF
+661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9
+am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1
+ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481
+PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS
+3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k
+SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF
+3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM
+ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g
+StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz
+Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB
+jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
+-----END CERTIFICATE-----
+
+# Baltimore CyberTrust Root
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+# Buypass Class 2 Root CA
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr
+6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV
+L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91
+1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx
+MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ
+QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB
+arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr
+Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi
+FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS
+P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN
+9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz
+uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h
+9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t
+OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo
++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7
+KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2
+DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us
+H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ
+I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7
+5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h
+3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz
+Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA=
+-----END CERTIFICATE-----
+
+# Buypass Class 3 Root CA
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y
+ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E
+N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9
+tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX
+0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c
+/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X
+KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY
+zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS
+O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D
+34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP
+K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv
+Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj
+QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS
+IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2
+HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa
+O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv
+033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u
+dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE
+kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41
+3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD
+u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq
+4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc=
+-----END CERTIFICATE-----
+
+# CA Disig Root R2
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV
+BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu
+MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy
+MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx
+EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe
+NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH
+PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I
+x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe
+QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR
+yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO
+QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912
+H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ
+QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD
+i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs
+nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1
+rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI
+hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf
+GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb
+lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka
++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal
+TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i
+nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3
+gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr
+G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os
+zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x
+L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL
+-----END CERTIFICATE-----
+
+# Certigna
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV
+BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X
+DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ
+BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4
+QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny
+gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw
+zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q
+130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2
+JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw
+ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT
+AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj
+AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG
+9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h
+bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc
+fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu
+HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w
+t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
+
+# Certinomis - Root CA
+-----BEGIN CERTIFICATE-----
+MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET
+MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb
+BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz
+MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx
+FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g
+Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2
+fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl
+LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV
+WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF
+TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb
+5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc
+CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri
+wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ
+wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG
+m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4
+F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng
+WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0
+2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF
+AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/
+0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw
+F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS
+g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj
+qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN
+h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/
+ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V
+btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj
+Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ
+8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW
+gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE=
+-----END CERTIFICATE-----
+
+# Certplus Class 2 Primary CA
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw
+PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz
+cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9
+MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz
+IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ
+ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR
+VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL
+kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd
+EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas
+H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0
+HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud
+DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4
+QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu
+Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/
+AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8
+yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR
+FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA
+ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB
+kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
+l7+ijrRU
+-----END CERTIFICATE-----
+
+# Certplus Root CA G1
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA
+MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy
+dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa
+MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy
+dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a
+iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt
+6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP
+0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f
+6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE
+EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN
+1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc
+h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT
+mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV
+4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO
+WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud
+DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd
+Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq
+hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh
+66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7
+/SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS
+S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j
+2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R
+Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr
+RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy
+6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV
+V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5
+g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl
+++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo=
+-----END CERTIFICATE-----
+
+# Certplus Root CA G2
+-----BEGIN CERTIFICATE-----
+MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x
+CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs
+dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x
+CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs
+dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat
+93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x
+Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P
+AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj
+FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG
+SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch
+p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal
+U5ORGpOucGpnutee5WEaXw==
+-----END CERTIFICATE-----
+
+# certSIGN ROOT CA
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT
+AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD
+QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP
+MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do
+0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ
+UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d
+RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ
+OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv
+JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C
+AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O
+BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ
+LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY
+MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ
+44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I
+Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw
+i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN
+9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
+
+# Certum Trusted Network CA 2
+-----BEGIN CERTIFICATE-----
+MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB
+gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu
+QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG
+A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz
+OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ
+VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3
+b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA
+DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn
+0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB
+OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE
+fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E
+Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m
+o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i
+sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW
+OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez
+Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS
+adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n
+3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ
+F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf
+CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29
+XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm
+djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/
+WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb
+AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq
+P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko
+b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj
+XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P
+5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi
+DrW5viSP
+-----END CERTIFICATE-----
+
+# Certum Trusted Network CA
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM
+MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D
+ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU
+cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3
+WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg
+Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw
+IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH
+UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM
+TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU
+BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM
+kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x
+AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y
+sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL
+I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8
+J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY
+VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
+
+# CFCA EV ROOT
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD
+TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx
+MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j
+aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP
+T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03
+sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL
+TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5
+/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp
+7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz
+EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt
+hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP
+a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot
+aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg
+TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV
+PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv
+cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL
+tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd
+BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
+ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT
+ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL
+jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS
+ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy
+P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19
+xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d
+Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN
+5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe
+/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z
+AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ
+5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
+-----END CERTIFICATE-----
+
+# Chambers of Commerce Root - 2008
+-----BEGIN CERTIFICATE-----
+MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD
+VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0
+IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3
+MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz
+IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz
+MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj
+dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw
+EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp
+MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9
+28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq
+VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q
+DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR
+5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL
+ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a
+Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl
+UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s
++12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5
+Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
+ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx
+hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV
+HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1
++HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN
+YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t
+L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy
+ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt
+IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV
+HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w
+DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW
+PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF
+5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1
+glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH
+FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2
+pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD
+xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG
+tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq
+jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De
+fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
+OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ
+d0jQ
+-----END CERTIFICATE-----
+
+# Comodo AAA Services root
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+# COMODO Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
+
+# COMODO ECC Certification Authority
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+# COMODO RSA Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
+NVOFBkpdn627G190
+-----END CERTIFICATE-----
+
+# Cybertrust Global Root
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG
+A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh
+bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE
+ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS
+b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5
+7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS
+J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y
+HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP
+t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz
+FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY
+XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/
+MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw
+hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js
+MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA
+A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj
+Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx
+XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o
+omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc
+A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
+WL1WMRJOEcgh4LMRkWXbtKaIOM5V
+-----END CERTIFICATE-----
+
+# Deutsche Telekom Root CA 2
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc
+MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj
+IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB
+IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE
+RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl
+U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290
+IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU
+ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC
+QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr
+rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S
+NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc
+QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH
+txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP
+BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC
+AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp
+tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa
+IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl
+6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+
+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
+Cm26OWMohpLzGITY+9HPBVZkVw==
+-----END CERTIFICATE-----
+
+# DigiCert Assured ID Root CA
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+# DigiCert Assured ID Root G2
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA
+n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc
+biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp
+EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA
+bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu
+YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB
+AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW
+BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI
+QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I
+0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni
+lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9
+B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv
+ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
+IhNzbM8m9Yop5w==
+-----END CERTIFICATE-----
+
+# DigiCert Assured ID Root G3
+-----BEGIN CERTIFICATE-----
+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
+RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf
+Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q
+RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD
+AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY
+JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv
+6pZjamVFkpUBtA==
+-----END CERTIFICATE-----
+
+# DigiCert Global Root CA
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+# DigiCert Global Root G2
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
+MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
+2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
+1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
+q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
+tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
+vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
+5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
+1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
+NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
+Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
+8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
+pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
+MrY=
+-----END CERTIFICATE-----
+
+# DigiCert Global Root G3
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
+Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw
+EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
+IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG
+fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO
+Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd
+BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx
+AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/
+oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8
+sycX
+-----END CERTIFICATE-----
+
+# DigiCert High Assurance EV Root CA
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
+
+# DigiCert Trusted Root G4
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
+RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y
+ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If
+xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV
+ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO
+DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ
+jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/
+CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi
+EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM
+fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY
+uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK
+chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t
+9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2
+SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd
++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc
+fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa
+sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N
+cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N
+0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie
+4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI
+r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1
+/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm
+gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+
+-----END CERTIFICATE-----
+
+# DST Root CA X3
+-----BEGIN CERTIFICATE-----
+MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
+MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
+PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
+Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
+rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
+OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
+xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
+7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
+aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
+SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
+ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
+AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
+R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
+JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
+Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+-----END CERTIFICATE-----
+
+# D-TRUST Root Class 3 CA 2 2009
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha
+ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM
+HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03
+UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42
+tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R
+ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM
+lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp
+/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G
+A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy
+MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl
+cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js
+L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL
+BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni
+acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
+o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K
+zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8
+PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y
+Johw1+qRzT65ysCQblrGXnRl11z+o+I=
+-----END CERTIFICATE-----
+
+# D-TRUST Root Class 3 CA 2 EV 2009
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw
+NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV
+BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn
+ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0
+3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z
+qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR
+p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8
+HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw
+ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea
+HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw
+Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh
+c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E
+RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt
+dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku
+Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp
+3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
+nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF
+CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na
+xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX
+KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1
+-----END CERTIFICATE-----
+
+# EC-ACC
+-----BEGIN CERTIFICATE-----
+MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB
+8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy
+dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1
+YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3
+dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh
+IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD
+LUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQG
+EwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8g
+KE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBD
+ZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQu
+bmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMg
+ZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUNDMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R
+85iKw5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm
+4CgPukLjbo73FCeTae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaV
+HMf5NLWUhdWZXqBIoH7nF2W4onW4HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNd
+QlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0aE9jD2z3Il3rucO2n5nzbcc8t
+lGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw0JDnJwIDAQAB
+o4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4
+opvpXY0wfwYDVR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBo
+dHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidW
+ZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAwDQYJKoZIhvcN
+AQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJlF7W2u++AVtd0x7Y
+/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNaAl6k
+SBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhy
+Rp/7SNVel+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOS
+Agu+TGbrIP65y7WZf+a2E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xl
+nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI=
+-----END CERTIFICATE-----
+
+# EE Certification Centre Root CA
+-----BEGIN CERTIFICATE-----
+MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1
+MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1
+czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG
+CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy
+MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl
+ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS
+b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy
+euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO
+bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw
+WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d
+MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE
+1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/
+zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB
+BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF
+BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV
+v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG
+E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
+uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW
+iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v
+GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0=
+-----END CERTIFICATE-----
+
+# Entrust.net Premium 2048 Secure Server CA
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
+MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
+j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
+U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
+u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
+bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
+fF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+# Entrust Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
+0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+# Entrust Root Certification Authority - EC1
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG
+A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3
+d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu
+dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq
+RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy
+MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD
+VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g
+Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi
+A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt
+ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH
+Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC
+R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX
+hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
+
+# Entrust Root Certification Authority - G2
+-----BEGIN CERTIFICATE-----
+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50
+cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs
+IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz
+dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy
+NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu
+dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt
+dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0
+aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T
+RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN
+cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW
+wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1
+U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0
+jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN
+BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/
+jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v
+1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R
+nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH
+VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g==
+-----END CERTIFICATE-----
+
+# ePKI Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe
+MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
+ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw
+IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL
+SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH
+SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh
+ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X
+DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1
+TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ
+fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA
+sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU
+WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS
+nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH
+dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip
+NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC
+AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF
+MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB
+uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl
+PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP
+JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/
+gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2
+j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6
+5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB
+o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS
+/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z
+Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE
+W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D
+hNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
+
+# E-Tugra Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV
+BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC
+aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV
+BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1
+Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz
+MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+
+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp
+em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
+ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY
+B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH
+D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF
+Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo
+q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D
+k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH
+fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut
+dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM
+ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8
+zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
+rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX
+U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6
+Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5
+XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF
+Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR
+HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY
+GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c
+77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3
++GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK
+vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6
+FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl
+yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P
+AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD
+y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d
+NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA==
+-----END CERTIFICATE-----
+
+# GDCA TrustAUTH R5 ROOT
+-----BEGIN CERTIFICATE-----
+MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE
+BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
+IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0
+MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV
+BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w
+HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj
+Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj
+TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u
+KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj
+qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm
+MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12
+ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP
+zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk
+L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC
+jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA
+HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC
+AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
+p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm
+DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5
+COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry
+L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf
+JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg
+IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io
+2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV
+09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ
+XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq
+T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe
+MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
+-----END CERTIFICATE-----
+
+# GeoTrust Global CA
+-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
+R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
+9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
+fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
+iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
+1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
+MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
+ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
+uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
+Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
+tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
+PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
+hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
+5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
+-----END CERTIFICATE-----
+
+# GeoTrust Primary Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY
+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo
+R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx
+MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
+Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9
+AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA
+ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0
+7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W
+kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI
+mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ
+KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1
+6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl
+4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K
+oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj
+UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU
+AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
+-----END CERTIFICATE-----
+
+# GeoTrust Primary Certification Authority - G2
+-----BEGIN CERTIFICATE-----
+MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL
+MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj
+KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2
+MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
+eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV
+BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw
+NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV
+BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH
+MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL
+So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal
+tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG
+CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT
+qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz
+rD6ogRLQy7rQkgu2npaqBA+K
+-----END CERTIFICATE-----
+
+# GeoTrust Primary Certification Authority - G3
+-----BEGIN CERTIFICATE-----
+MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB
+mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT
+MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
+eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ
+BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
+MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0
+BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz
++uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm
+hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn
+5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W
+JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL
+DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC
+huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
+HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB
+AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB
+zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN
+kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
+AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH
+SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G
+spki4cErx5z481+oghLrGREt
+-----END CERTIFICATE-----
+
+# GeoTrust Universal CA
+-----BEGIN CERTIFICATE-----
+MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy
+c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE
+BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0
+IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV
+VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8
+cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT
+QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh
+F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v
+c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w
+mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd
+VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX
+teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ
+f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe
+Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+
+nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB
+/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY
+MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG
+9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
+aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX
+IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn
+ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z
+uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN
+Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja
+QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW
+koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9
+ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt
+DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm
+bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw=
+-----END CERTIFICATE-----
+
+# GeoTrust Universal CA 2
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy
+c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD
+VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1
+c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81
+WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG
+FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq
+XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL
+se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb
+KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd
+IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73
+y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt
+hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc
+QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4
+Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV
+HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
+KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
+dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ
+L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr
+Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo
+ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY
+T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz
+GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m
+1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV
+OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH
+6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX
+QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
+-----END CERTIFICATE-----
+
+# Global Chambersign Root - 2008
+-----BEGIN CERTIFICATE-----
+MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD
+VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0
+IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3
+MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
+aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx
+MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy
+cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG
+A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl
+BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed
+KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7
+G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2
+zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4
+ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG
+HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2
+Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V
+yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e
+beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r
+6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
+wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog
+zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW
+BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr
+ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp
+ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk
+cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt
+YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC
+CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow
+KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI
+hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ
+UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz
+X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x
+fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz
+a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd
+Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd
+SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O
+AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso
+M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge
+v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
+09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
+-----END CERTIFICATE-----
+
+# GlobalSign ECC Root CA - R4
+-----BEGIN CERTIFICATE-----
+MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ
+FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F
+uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX
+kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs
+ewv4n4Q=
+-----END CERTIFICATE-----
+
+# GlobalSign ECC Root CA - R5
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc
+8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke
+hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI
+KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg
+515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO
+xwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
+
+# GlobalSign Root CA
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+# GlobalSign Root CA - R2
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
+MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
+v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
+eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
+tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
+C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
+zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
+mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
+V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
+bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
+3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
+J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
+291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
+ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
+AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
+
+# GlobalSign Root CA - R3
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
+
+# Go Daddy Class 2 CA
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
+
+# Go Daddy Root Certificate Authority - G2
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+# Hellenic Academic and Research Institutions ECC RootCA 2015
+-----BEGIN CERTIFICATE-----
+MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN
+BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl
+bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv
+b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ
+BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj
+YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5
+MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0
+dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg
+QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa
+jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi
+C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep
+lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof
+TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
+-----END CERTIFICATE-----
+
+# Hellenic Academic and Research Institutions RootCA 2011
+-----BEGIN CERTIFICATE-----
+MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix
+RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
+dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p
+YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw
+NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK
+EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl
+cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz
+dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ
+fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns
+bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD
+75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP
+FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV
+HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp
+5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu
+b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA
+A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p
+6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
+TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7
+dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys
+Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI
+l7WdmplNsDz4SgCbZN2fOUvRJ9e4
+-----END CERTIFICATE-----
+
+# Hellenic Academic and Research Institutions RootCA 2015
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix
+DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k
+IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT
+N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v
+dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG
+A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh
+ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx
+QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
+dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA
+4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0
+AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10
+4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C
+ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV
+9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD
+gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6
+Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq
+NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko
+LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
+Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd
+ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I
+XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI
+M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot
+9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V
+Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea
+j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh
+X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ
+l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf
+bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4
+pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK
+e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0
+vm9qp/UsQu0yrbYhnr68
+-----END CERTIFICATE-----
+
+# Hongkong Post Root CA 1
+-----BEGIN CERTIFICATE-----
+MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx
+FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg
+Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG
+A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr
+b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ
+jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn
+PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh
+ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9
+nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h
+q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED
+MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC
+mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3
+7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB
+oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs
+EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO
+fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi
+AmvZWg==
+-----END CERTIFICATE-----
+
+# IdenTrust Commercial Root CA 1
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu
+VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw
+MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw
+JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT
+3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU
++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp
+S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1
+bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi
+T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL
+vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK
+Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK
+dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT
+c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv
+l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N
+iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD
+ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
+6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt
+LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93
+nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3
++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK
+W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT
+AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq
+l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG
+4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ
+mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A
+7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H
+-----END CERTIFICATE-----
+
+# IdenTrust Public Sector Root CA 1
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu
+VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN
+MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0
+MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7
+ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy
+RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS
+bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF
+/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R
+3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw
+EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy
+9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V
+GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ
+2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV
+WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD
+W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN
+AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
+t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV
+DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9
+TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G
+lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW
+mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df
+WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5
++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ
+tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA
+GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv
+8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c
+-----END CERTIFICATE-----
+
+# ISRG Root X1
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
+WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
+ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
+h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
+A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
+T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
+B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
+B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
+KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
+OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
+jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
+qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
+rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
+hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
+ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
+3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
+NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
+ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
+TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
+jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
+oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
+4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
+mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
+emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
+-----END CERTIFICATE-----
+
+# Izenpe.com
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4
+MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6
+ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD
+VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j
+b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq
+scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO
+xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H
+LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX
+uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD
+yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+
+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q
+rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN
+BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L
+hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB
+QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+
+HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu
+Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg
+QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB
+BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA
+A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb
+laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56
+awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo
+JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw
+LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT
+VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk
+LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb
+UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/
+QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+
+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls
+QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
+
+# LuxTrust Global Root 2
+-----BEGIN CERTIFICATE-----
+MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQEL
+BQAwRjELMAkGA1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNV
+BAMMFkx1eFRydXN0IEdsb2JhbCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUw
+MzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEWMBQGA1UECgwNTHV4VHJ1c3QgUy5B
+LjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wmKb3F
+ibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTem
+hfY7RBi2xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1
+EMShduxq3sVs35a0VkBCwGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsn
+Xpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4
+zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkmFRseTJIpgp7VkoGSQXAZ
+96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niFwpN6cj5m
+j5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4g
+DEa/a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+
+8kPREd8vZS9kzl8UubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2j
+X5t/Lax5Gw5CMZdjpPuKadUiDTSQMC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmH
+hFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB/zBCBgNVHSAEOzA5MDcGByuB
+KwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5Lmx1eHRydXN0
+Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
++Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQEL
+BQADggIBAGoZFO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9
+BzZAcg4atmpZ1gDlaCDdLnINH2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTO
+jFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW7MM3LGVYvlcAGvI1+ut7MV3CwRI9
+loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIuZY+kt9J/Z93I055c
+qqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWAVWe+
+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/
+JEAdemrRTxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKre
+zrnK+T+Tb/mjuuqlPpmt/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQf
+LSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+
+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31IiyBMz2TWuJdGsE7RKlY6
+oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
+-----END CERTIFICATE-----
+
+# Microsec e-Szigno Root CA 2009
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
+VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0
+ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G
+CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y
+OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx
+FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp
+Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP
+kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc
+cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U
+fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7
+N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC
+xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1
++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM
+Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG
+SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h
+mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk
+ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c
+2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t
+HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
+
+# NetLock Arany (Class Gold) Főtanúsítvány
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG
+EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3
+MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl
+cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR
+dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB
+pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM
+b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm
+aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz
+IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT
+lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz
+AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5
+VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG
+ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2
+BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG
+AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M
+U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh
+bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C
++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F
+uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2
+XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
+
+# Network Solutions Certificate Authority
+-----BEGIN CERTIFICATE-----
+MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi
+MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
+MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp
+dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV
+UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO
+ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz
+c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP
+OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl
+mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF
+BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4
+qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw
+gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu
+bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp
+dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8
+6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/
+h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH
+/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
+wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN
+pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
+-----END CERTIFICATE-----
+
+# OISTE WISeKey Global Root GA CA
+-----BEGIN CERTIFICATE-----
+MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB
+ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly
+aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
+ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w
+NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G
+A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD
+VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX
+SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR
+VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2
+w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF
+mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg
+4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9
+4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw
+EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx
+SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2
+ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8
+vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
+hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi
+Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ
+/L7fCg0=
+-----END CERTIFICATE-----
+
+# OISTE WISeKey Global Root GB CA
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt
+MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg
+Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i
+YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x
+CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG
+b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
+bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3
+HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx
+WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX
+1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk
+u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P
+99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r
+M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB
+BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh
+cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5
+gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO
+ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf
+aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
+Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
+-----END CERTIFICATE-----
+
+# OpenTrust Root CA G1
+-----BEGIN CERTIFICATE-----
+MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA
+MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w
+ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw
+MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU
+T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b
+wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX
+/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0
+77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP
+uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx
+p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx
+Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2
+TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W
+G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw
+vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY
+EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1
+2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw
+DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E
+PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf
+gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS
+FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0
+V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P
+XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I
+i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t
+TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91
+09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky
+Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ
+AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj
+1oxx
+-----END CERTIFICATE-----
+
+# OpenTrust Root CA G2
+-----BEGIN CERTIFICATE-----
+MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA
+MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w
+ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw
+MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU
+T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh
+/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e
+CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6
+1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE
+FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS
+gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X
+G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy
+YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH
+vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4
+t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/
+gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3
+5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w
+DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz
+Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0
+nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT
+RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT
+wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2
+t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa
+TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2
+o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU
+3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA
+iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f
+WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM
+S1IK
+-----END CERTIFICATE-----
+
+# OpenTrust Root CA G3
+-----BEGIN CERTIFICATE-----
+MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx
+CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U
+cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow
+QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl
+blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm
+3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d
+oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G
+A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5
+DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK
+BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q
+j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx
+4nxp5V2a+EEfOzmTk51V6s2N8fvB
+-----END CERTIFICATE-----
+
+# QuoVadis Root CA 1 G3
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00
+MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV
+wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe
+rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341
+68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh
+4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp
+UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o
+abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc
+3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G
+KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt
+hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO
+Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt
+zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD
+ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
+MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2
+cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN
+qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5
+YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv
+b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2
+8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k
+NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj
+ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp
+q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt
+nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD
+-----END CERTIFICATE-----
+
+# QuoVadis Root CA 2
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa
+GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg
+Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J
+WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB
+rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp
++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1
+ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i
+Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz
+PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og
+/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH
+oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI
+yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud
+EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2
+A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL
+MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f
+BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn
+g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl
+fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K
+WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha
+B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc
+hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR
+TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD
+mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z
+ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y
+4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza
+8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+
+# QuoVadis Root CA
+-----BEGIN CERTIFICATE-----
+MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz
+MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw
+IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR
+dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp
+li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D
+rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ
+WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug
+F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU
+xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC
+Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv
+dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw
+ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl
+IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh
+c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy
+ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
+Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI
+KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T
+KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq
+y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p
+dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD
+VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL
+MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk
+fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8
+7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R
+cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y
+mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW
+xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK
+SnQ2+Q==
+-----END CERTIFICATE-----
+
+# QuoVadis Root CA 2 G3
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00
+MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf
+qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW
+n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym
+c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+
+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1
+o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j
+IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq
+IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz
+8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh
+vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l
+7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG
+cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD
+ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
+AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC
+roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga
+W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n
+lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE
++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV
+csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd
+dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg
+KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM
+HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4
+WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M
+-----END CERTIFICATE-----
+
+# QuoVadis Root CA 3
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM
+V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB
+4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr
+H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd
+8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv
+vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT
+mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe
+btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc
+T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt
+WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ
+c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A
+4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD
+VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG
+CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0
+aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu
+dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw
+czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G
+A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg
+Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0
+7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem
+d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd
++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B
+4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN
+t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x
+DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57
+k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s
+zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j
+Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT
+mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK
+4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
+
+# QuoVadis Root CA 3 G3
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00
+MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR
+/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu
+FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR
+U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c
+ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR
+FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k
+A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw
+eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl
+sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp
+VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q
+A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+
+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD
+ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
+KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI
+FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv
+oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg
+u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP
+0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf
+3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl
+8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+
+DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN
+PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/
+ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0
+-----END CERTIFICATE-----
+
+# Secure Global CA
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx
+MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg
+Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ
+iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa
+/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ
+jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI
+HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7
+sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w
+gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw
+KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG
+AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L
+URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO
+H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm
+I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY
+iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
+
+# SecureSign RootCA11
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr
+MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG
+A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0
+MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp
+Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD
+QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz
+i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8
+h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV
+MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9
+UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni
+8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC
+h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD
+VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB
+AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm
+KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ
+X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr
+QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5
+pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN
+QSdJQO7e5iNEOdyhIta6A/I=
+-----END CERTIFICATE-----
+
+# SecureTrust CA
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
+MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
+cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
+Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
+0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
+wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
+7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
+8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
+BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
+JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
+6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
+3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
+D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
+CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+
+# Security Communication Root CA
+-----BEGIN CERTIFICATE-----
+MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY
+MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t
+dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5
+WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD
+VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8
+9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ
+DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9
+Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N
+QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ
+xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G
+A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG
+kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr
+Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5
+Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU
+JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot
+RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw==
+-----END CERTIFICATE-----
+
+# Security Communication RootCA2
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl
+MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe
+U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX
+DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy
+dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj
+YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV
+OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr
+zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM
+VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ
+hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO
+ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw
+awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs
+OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF
+coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc
+okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8
+t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy
+1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/
+SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
+
+# Sonera Class 2 Root CA
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP
+MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx
+MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV
+BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o
+Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt
+5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s
+3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej
+vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu
+8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw
+DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG
+MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil
+zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/
+3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD
+FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6
+Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2
+ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M
+-----END CERTIFICATE-----
+
+# SSL.com EV Root Certification Authority ECC
+-----BEGIN CERTIFICATE-----
+MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx
+NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv
+bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49
+AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA
+VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku
+WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP
+MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX
+5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ
+ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg
+h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
+-----END CERTIFICATE-----
+
+# SSL.com EV Root Certification Authority RSA R2
+-----BEGIN CERTIFICATE-----
+MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV
+BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE
+CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy
+MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G
+A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD
+DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq
+M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf
+OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa
+4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9
+HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR
+aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA
+b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ
+Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV
+PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO
+pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu
+UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY
+MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
+HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4
+9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW
+s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5
+Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg
+cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM
+79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz
+/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt
+ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm
+Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK
+QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ
+w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi
+S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07
+mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
+-----END CERTIFICATE-----
+
+# SSL.com Root Certification Authority ECC
+-----BEGIN CERTIFICATE-----
+MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz
+WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0
+b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS
+b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI
+7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg
+CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud
+EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD
+VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T
+kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+
+gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
+-----END CERTIFICATE-----
+
+# SSL.com Root Certification Authority RSA
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE
+BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK
+DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz
+OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
+bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R
+xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX
+qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC
+C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3
+6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh
+/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF
+YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E
+JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc
+US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8
+ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm
++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi
+M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G
+A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV
+cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc
+Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs
+PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/
+q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0
+cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr
+a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I
+H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y
+K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu
+nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf
+oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY
+Ic2wBlX7Jz9TkHCpBB5XJ7k=
+-----END CERTIFICATE-----
+
+# Staat der Nederlanden EV Root CA
+-----BEGIN CERTIFICATE-----
+MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO
+TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y
+MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg
+TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS
+b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS
+M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC
+UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d
+Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p
+rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l
+pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb
+j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC
+KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS
+/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X
+cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH
+1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP
+px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7
+MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
+eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u
+2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS
+v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC
+wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy
+CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e
+vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6
+Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa
+Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL
+eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8
+FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc
+7uzXLg==
+-----END CERTIFICATE-----
+
+# Staat der Nederlanden Root CA - G2
+-----BEGIN CERTIFICATE-----
+MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO
+TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX
+DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl
+ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv
+b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291
+qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp
+uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU
+Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE
+pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp
+5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M
+UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN
+GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy
+5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv
+6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK
+eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6
+B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/
+BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov
+L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG
+SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS
+CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen
+5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897
+IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK
+gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL
++63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL
+vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm
+bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk
+N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC
+Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z
+ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ==
+-----END CERTIFICATE-----
+
+# Staat der Nederlanden Root CA - G3
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO
+TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX
+DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl
+ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv
+b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP
+cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW
+IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX
+xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy
+KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR
+9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az
+5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8
+6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7
+Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP
+bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt
+BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt
+XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF
+MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd
+INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
+U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp
+LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8
+Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp
+gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh
+/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw
+0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A
+fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq
+4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR
+1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/
+QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM
+94B7IWcnMFk=
+-----END CERTIFICATE-----
+
+# Starfield Class 2 CA
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+# Starfield Root Certificate Authority - G2
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+# Starfield Services Root Certificate Authority - G2
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
+ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
+VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
+ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
+dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
+OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
+8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
+Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
+hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
+6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
+AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
+bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
+ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
+qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
+0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
+sSi6
+-----END CERTIFICATE-----
+
+# SwissSign Gold CA - G2
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln
+biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF
+MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT
+d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8
+76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+
+bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c
+6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE
+emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd
+MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt
+MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y
+MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y
+FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi
+aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM
+gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB
+qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7
+lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn
+8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6
+45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO
+UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5
+O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC
+bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv
+GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a
+77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC
+hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3
+92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp
+Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w
+ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt
+Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
+
+# SwissSign Silver CA - G2
+-----BEGIN CERTIFICATE-----
+MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE
+BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu
+IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow
+RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY
+U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv
+Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br
+YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF
+nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH
+6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt
+eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/
+c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ
+MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH
+HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf
+jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6
+5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB
+rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
+F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c
+wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
+cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB
+AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp
+WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9
+xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ
+2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ
+IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8
+aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X
+em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR
+dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/
+OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+
+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy
+tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
+-----END CERTIFICATE-----
+
+# SZAFIR ROOT CA2
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL
+BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6
+ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw
+NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L
+cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg
+Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN
+QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT
+3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw
+3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6
+3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5
+BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN
+XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF
+AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw
+8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG
+nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP
+oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy
+d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg
+LvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
+-----END CERTIFICATE-----
+
+# Taiwan GRCA
+-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/
+MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow
+PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR
+IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q
+gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy
+yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts
+F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2
+jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx
+ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC
+VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK
+YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH
+EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN
+Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud
+DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE
+MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK
+UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
+TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf
+qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK
+ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE
+JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7
+hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1
+EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm
+nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX
+udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz
+ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe
+LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl
+pYYsfPQS
+-----END CERTIFICATE-----
+
+# TeliaSonera Root CA v1
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw
+NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv
+b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD
+VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F
+VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1
+7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X
+Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+
+/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs
+81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm
+dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe
+Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu
+sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4
+pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs
+slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ
+arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD
+VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG
+9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl
+dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
+0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj
+TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed
+Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7
+Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI
+OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7
+vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW
+t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn
+HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx
+SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
+-----END CERTIFICATE-----
+
+# thawte Primary Root CA
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB
+qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
+Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
+MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV
+BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw
+NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j
+LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG
+A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs
+W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta
+3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk
+6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6
+Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J
+NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP
+r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU
+DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz
+YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
+xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2
+/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/
+LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7
+jVaMaA==
+-----END CERTIFICATE-----
+
+# thawte Primary Root CA - G2
+-----BEGIN CERTIFICATE-----
+MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp
+IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi
+BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw
+MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
+d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig
+YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v
+dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/
+BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6
+papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K
+DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3
+KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox
+XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
+-----END CERTIFICATE-----
+
+# thawte Primary Root CA - G3
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB
+rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
+Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
+MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV
+BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa
+Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl
+LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u
+MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl
+ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm
+gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8
+YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf
+b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9
+9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S
+zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk
+OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
+HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA
+2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW
+oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
+t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c
+KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM
+m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu
+MdRAGmI0Nj81Aa6sY6A=
+-----END CERTIFICATE-----
+
+# TrustCor ECA-1
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD
+VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk
+MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
+cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y
+IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV
+BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw
+IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy
+dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig
+RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb
+3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA
+BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5
+3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou
+owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/
+wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF
+ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf
+BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/
+MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv
+civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2
+AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F
+hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50
+soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI
+WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi
+tJ/X5g==
+-----END CERTIFICATE-----
+
+# TrustCor RootCert CA-1
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD
+VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk
+MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
+cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y
+IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB
+pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h
+IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG
+A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU
+cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid
+RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V
+seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme
+9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV
+EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW
+hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/
+DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw
+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD
+ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I
+/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf
+ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ
+yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts
+L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN
+zl/HHk484IkzlQsPpTLWPFp5LBk=
+-----END CERTIFICATE-----
+
+# TrustCor RootCert CA-2
+-----BEGIN CERTIFICATE-----
+MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV
+BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw
+IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy
+dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig
+Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk
+MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg
+Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD
+VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy
+dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+
+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq
+1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp
+2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK
+DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape
+az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF
+3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88
+oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM
+g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3
+mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh
+8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd
+BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U
+nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw
+DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX
+dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+
+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL
+/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX
+CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa
+ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW
+2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7
+N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3
+Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB
+As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp
+5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu
+1uwJ
+-----END CERTIFICATE-----
+
+# Trustis FPS Root CA
+-----BEGIN CERTIFICATE-----
+MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF
+MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL
+ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx
+MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc
+MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+
+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH
+iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj
+vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA
+0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB
+OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/
+BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E
+FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01
+GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW
+zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4
+1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE
+f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F
+jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN
+ZetX2fNXlrtIzYE=
+-----END CERTIFICATE-----
+
+# T-TeleSec GlobalRoot Class 2
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd
+AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC
+FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi
+1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq
+jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ
+wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/
+WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy
+NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC
+uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw
+IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6
+g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
+9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP
+BSeOE6Fuwg==
+-----END CERTIFICATE-----
+
+# T-TeleSec GlobalRoot Class 3
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN
+8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/
+RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4
+hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5
+ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM
+EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1
+A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy
+WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ
+1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30
+6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT
+91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p
+TpPDpFQUWw==
+-----END CERTIFICATE-----
+
+# TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
+-----BEGIN CERTIFICATE-----
+MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx
+GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp
+bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w
+KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0
+BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy
+dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG
+EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll
+IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU
+QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT
+TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg
+LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7
+a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr
+LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr
+N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X
+YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/
+iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f
+AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH
+V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
+AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf
+IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4
+lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c
+8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf
+lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
+-----END CERTIFICATE-----
+
+# TWCA Global Root CA
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx
+EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT
+VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5
+NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT
+B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF
+10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz
+0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh
+MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH
+zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc
+46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2
+yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi
+laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP
+oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA
+BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE
+qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm
+4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL
+1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
+LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF
+H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo
+RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+
+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh
+15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW
+6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW
+nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j
+wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz
+aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy
+KwbQBM0=
+-----END CERTIFICATE-----
+
+# TWCA Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES
+MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU
+V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz
+WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO
+LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE
+AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH
+K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX
+RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z
+rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx
+3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq
+hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC
+MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls
+XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D
+lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn
+aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ
+YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
+
+# USERTrust ECC Certification Authority
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl
+eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT
+JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
+Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg
+VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo
+I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng
+o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G
+A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB
+zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW
+RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
+
+# USERTrust RSA Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
+MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
+BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
+3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
+tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
+Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
+VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
+79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
+c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
+Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
+c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
+UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
+Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
+Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
+VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
+ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
+8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
+iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
+Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
+XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
+qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
+VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
+L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
+jjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
+
+# Verisign Class 3 Public Primary Certification Authority - G3
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
+cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
+LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
+aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
+VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
+aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
+bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
+IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
+N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
+KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
+kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
+CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
+Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
+imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
+2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
+DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
+/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
+F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
+TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
+-----END CERTIFICATE-----
+
+# VeriSign Class 3 Public Primary Certification Authority - G4
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp
+U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg
+SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln
+biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm
+GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve
+fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ
+aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj
+aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW
+kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC
+4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga
+FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
+-----END CERTIFICATE-----
+
+# VeriSign Class 3 Public Primary Certification Authority - G5
+-----BEGIN CERTIFICATE-----
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
+nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
+t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
+SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
+BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
+rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
+NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
+BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
+BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
+MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
+p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
+5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
+WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
+4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
+hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
+-----END CERTIFICATE-----
+
+# VeriSign Universal Root Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB
+vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W
+ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX
+MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0
+IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y
+IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh
+bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF
+9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH
+H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H
+LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN
+/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT
+rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw
+WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs
+exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
+DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4
+sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+
+seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz
+4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+
+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR
+lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3
+7M2CYfE45k+XmCpajQ==
+-----END CERTIFICATE-----
+
+# Visa eCommerce Root
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr
+MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl
+cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
+bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw
+CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h
+dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l
+cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h
+2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E
+lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV
+ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq
+299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t
+vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL
+dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF
+AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR
+zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3
+LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd
+7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw
+++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
+398znM/jra6O1I7mT1GvFpLgXPYHDw==
+-----END CERTIFICATE-----
+
+# XRamp Global CA Root
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB
+gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk
+MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY
+UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx
+NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3
+dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy
+dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6
+38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP
+KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q
+DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4
+qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa
+JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi
+PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P
+BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs
+jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0
+eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD
+ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR
+vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa
+IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy
+i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ
+O+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
+
+# CAcert Class 3 Root
+-----BEGIN CERTIFICATE-----
+MIIHWTCCBUGgAwIBAgIDCkGKMA0GCSqGSIb3DQEBCwUAMHkxEDAOBgNVBAoTB1Jv
+b3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEiMCAGA1UEAxMZ
+Q0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYSc3VwcG9y
+dEBjYWNlcnQub3JnMB4XDTExMDUyMzE3NDgwMloXDTIxMDUyMDE3NDgwMlowVDEU
+MBIGA1UEChMLQ0FjZXJ0IEluYy4xHjAcBgNVBAsTFWh0dHA6Ly93d3cuQ0FjZXJ0
+Lm9yZzEcMBoGA1UEAxMTQ0FjZXJ0IENsYXNzIDMgUm9vdDCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBAKtJNRFIfNImflOUz0Op3SjXQiqL84d4GVh8D57a
+iX3h++tykA10oZZkq5+gJJlz2uJVdscXe/UErEa4w75/ZI0QbCTzYZzA8pD6Ueb1
+aQFjww9W4kpCz+JEjCUoqMV5CX1GuYrz6fM0KQhF5Byfy5QEHIGoFLOYZcRD7E6C
+jQnRvapbjZLQ7N6QxX8KwuPr5jFaXnQ+lzNZ6MMDPWAzv/fRb0fEze5ig1JuLgia
+pNkVGJGmhZJHsK5I6223IeyFGmhyNav/8BBdwPSUp2rVO5J+TJAFfpPBLIukjmJ0
+FXFuC3ED6q8VOJrU0gVyb4z5K+taciX5OUbjchs+BMNkJyIQKopPWKcDrb60LhPt
+XapI19V91Cp7XPpGBFDkzA5CW4zt2/LP/JaT4NsRNlRiNDiPDGCbO5dWOK3z0luL
+oFvqTpa4fNfVoIZwQNORKbeiPK31jLvPGpKK5DR7wNhsX+kKwsOnIJpa3yxdUly6
+R9Wb7yQocDggL9V/KcCyQQNokszgnMyXS0XvOhAKq3A6mJVwrTWx6oUrpByAITGp
+rmB6gCZIALgBwJNjVSKRPFbnr9s6JfOPMVTqJouBWfmh0VMRxXudA/Z0EeBtsSw/
+LIaRmXGapneLNGDRFLQsrJ2vjBDTn8Rq+G8T/HNZ92ZCdB6K4/jc0m+YnMtHmJVA
+BfvpAgMBAAGjggINMIICCTAdBgNVHQ4EFgQUdahxYEyIE/B42Yl3tW3Fid+8sXow
+gaMGA1UdIwSBmzCBmIAUFrUyG9TH8+DmjvO90rA67rI5GNGhfaR7MHkxEDAOBgNV
+BAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEiMCAG
+A1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYS
+c3VwcG9ydEBjYWNlcnQub3JnggEAMA8GA1UdEwEB/wQFMAMBAf8wXQYIKwYBBQUH
+AQEEUTBPMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5DQWNlcnQub3JnLzAoBggr
+BgEFBQcwAoYcaHR0cDovL3d3dy5DQWNlcnQub3JnL2NhLmNydDBKBgNVHSAEQzBB
+MD8GCCsGAQQBgZBKMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuQ0FjZXJ0Lm9y
+Zy9pbmRleC5waHA/aWQ9MTAwNAYJYIZIAYb4QgEIBCcWJWh0dHA6Ly93d3cuQ0Fj
+ZXJ0Lm9yZy9pbmRleC5waHA/aWQ9MTAwUAYJYIZIAYb4QgENBEMWQVRvIGdldCB5
+b3VyIG93biBjZXJ0aWZpY2F0ZSBmb3IgRlJFRSwgZ28gdG8gaHR0cDovL3d3dy5D
+QWNlcnQub3JnMA0GCSqGSIb3DQEBCwUAA4ICAQApKIWuRKm5r6R5E/CooyuXYPNc
+7uMvwfbiZqARrjY3OnYVBFPqQvX56sAV2KaC2eRhrnILKVyQQ+hBsuF32wITRHhH
+Va9Y/MyY9kW50SD42CEH/m2qc9SzxgfpCYXMO/K2viwcJdVxjDm1Luq+GIG6sJO4
+D+Pm1yaMMVpyA4RS5qb1MyJFCsgLDYq4Nm+QCaGrvdfVTi5xotSu+qdUK+s1jVq3
+VIgv7nSf7UgWyg1I0JTTrKSi9iTfkuO960NAkW4cGI5WtIIS86mTn9S8nK2cde5a
+lxuV53QtHA+wLJef+6kzOXrnAzqSjiL2jA3k2X4Ndhj3AfnvlpaiVXPAPHG0HRpW
+Q7fDCo1y/OIQCQtBzoyUoPkD/XFzS4pXM+WOdH4VAQDmzEoc53+VGS3FpQyLu7Xt
+hbNc09+4ufLKxw0BFKxwWMWMjTPUnWajGlCVI/xI4AZDEtnNp4Y5LzZyo4AQ5OHz
+0ctbGsDkgJp8E3MGT9ujayQKurMcvEp4u+XjdTilSKeiHq921F73OIZWWonO1sOn
+ebJSoMbxhbQljPI/lrMQ2Y1sVzufb4Y6GIIiNsiwkTjbKqGTqoQ/9SdlrnPVyNXT
+d+pLncdBu8fA46A/5H2kjXPmEkvfoXNzczqA6NXLji/L6hOn1kGLrPo8idck9U60
+4GGSt/M3mMS+lqO3ig==
+-----END CERTIFICATE-----
+
+# CA Cert Signing Authority
+-----BEGIN CERTIFICATE-----
+MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290
+IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB
+IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA
+Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO
+BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi
+MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ
+ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ
+8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6
+zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y
+fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7
+w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc
+G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k
+epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q
+laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ
+QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU
+fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826
+YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w
+ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY
+gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe
+MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0
+IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy
+dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw
+czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0
+dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl
+aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC
+AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg
+b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB
+ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc
+nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg
+18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c
+gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl
+Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY
+sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T
+SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF
+CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum
+GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk
+zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW
+omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_Certification_Authority.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_Certification_Authority.pem
new file mode 100644
index 00000000..6146dcb5
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_Certification_Authority.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_ECC_Certification_Authority.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_ECC_Certification_Authority.pem
new file mode 100644
index 00000000..546c95e3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_ECC_Certification_Authority.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_RSA_Certification_Authority.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_RSA_Certification_Authority.pem
new file mode 100644
index 00000000..6508d1e8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/COMODO_RSA_Certification_Authority.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
+NVOFBkpdn627G190
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/DST_Root_CA_X3.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/DST_Root_CA_X3.pem
new file mode 100644
index 00000000..b2e43c93
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/DST_Root_CA_X3.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
+MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
+PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
+Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
+rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
+OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
+xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
+7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
+aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
+SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
+ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
+AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
+R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
+JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
+Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/ISRG_Root_X1.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/ISRG_Root_X1.pem
new file mode 100644
index 00000000..b85c8037
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/files/roots/ISRG_Root_X1.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
+WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
+ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
+h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
+A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
+T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
+B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
+B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
+KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
+OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
+jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
+qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
+rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
+hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
+ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
+3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
+NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
+ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
+TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
+jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
+oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
+4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
+mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
+emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/meta/main.yml
new file mode 100644
index 00000000..1810d4be
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_remote_tmp_dir
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/tasks/main.yml
new file mode 100644
index 00000000..a718349c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/certificate_complete_chain/tasks/main.yml
@@ -0,0 +1,84 @@
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: register cryptography version
+ command: '{{ ansible_python.executable }} -c ''import cryptography; print(cryptography.__version__)'''
+ register: cryptography_version
+- block:
+ - name: Make sure testhost directory exists
+ file:
+ path: '{{ remote_tmp_dir }}/files/'
+ state: directory
+ when: ansible_version.string is version('2.10', '<')
+ - name: Copy test files to testhost
+ copy:
+ src: '{{ role_path }}/files/'
+ dest: '{{ remote_tmp_dir }}/files/'
+ remote_src: yes
+ - name: Find root for cert 1
+ certificate_complete_chain:
+ input_chain: '{{ lookup(''file'', ''cert1-fullchain.pem'', rstrip=False) }}'
+ root_certificates:
+ - '{{ remote_tmp_dir }}/files/roots/'
+ register: cert1_root
+ - name: Verify root for cert 1
+ assert:
+ that:
+ - cert1_root.complete_chain | join('') == (lookup('file', 'cert1.pem', rstrip=False) ~ lookup('file', 'cert1-chain.pem', rstrip=False) ~ lookup('file', 'cert1-root.pem', rstrip=False))
+ - cert1_root.root == lookup('file', 'cert1-root.pem', rstrip=False)
+ - name: Find rootchain for cert 1
+ certificate_complete_chain:
+ input_chain: '{{ lookup(''file'', ''cert1.pem'', rstrip=False) }}'
+ intermediate_certificates:
+ - '{{ remote_tmp_dir }}/files/cert1-chain.pem'
+ root_certificates:
+ - '{{ remote_tmp_dir }}/files/roots.pem'
+ register: cert1_rootchain
+ - name: Verify rootchain for cert 1
+ assert:
+ that:
+ - cert1_rootchain.complete_chain | join('') == (lookup('file', 'cert1.pem', rstrip=False) ~ lookup('file', 'cert1-chain.pem', rstrip=False) ~ lookup('file', 'cert1-root.pem', rstrip=False))
+ - cert1_rootchain.chain[:-1] | join('') == lookup('file', 'cert1-chain.pem', rstrip=False)
+ - cert1_rootchain.root == lookup('file', 'cert1-root.pem', rstrip=False)
+ - name: Find root for cert 2
+ certificate_complete_chain:
+ input_chain: '{{ lookup(''file'', ''cert2-fullchain.pem'', rstrip=False) }}'
+ root_certificates:
+ - '{{ remote_tmp_dir }}/files/roots/'
+ register: cert2_root
+ - name: Verify root for cert 2
+ assert:
+ that:
+ - cert2_root.complete_chain | join('') == (lookup('file', 'cert2.pem', rstrip=False) ~ lookup('file', 'cert2-chain.pem', rstrip=False) ~ lookup('file', 'cert2-root.pem', rstrip=False))
+ - cert2_root.root == lookup('file', 'cert2-root.pem', rstrip=False)
+ - name: Find rootchain for cert 2
+ certificate_complete_chain:
+ input_chain: '{{ lookup(''file'', ''cert2.pem'', rstrip=False) }}'
+ intermediate_certificates:
+ - '{{ remote_tmp_dir }}/files/cert2-chain.pem'
+ root_certificates:
+ - '{{ remote_tmp_dir }}/files/roots.pem'
+ register: cert2_rootchain
+ - name: Verify rootchain for cert 2
+ assert:
+ that:
+ - cert2_rootchain.complete_chain | join('') == (lookup('file', 'cert2.pem', rstrip=False) ~ lookup('file', 'cert2-chain.pem', rstrip=False) ~ lookup('file', 'cert2-root.pem', rstrip=False))
+ - cert2_rootchain.chain[:-1] | join('') == lookup('file', 'cert2-chain.pem', rstrip=False)
+ - cert2_rootchain.root == lookup('file', 'cert2-root.pem', rstrip=False)
+ - name: Find alternate rootchain for cert 2
+ certificate_complete_chain:
+ input_chain: '{{ lookup(''file'', ''cert2.pem'', rstrip=True) }}'
+ intermediate_certificates:
+ - '{{ remote_tmp_dir }}/files/cert2-altchain.pem'
+ root_certificates:
+ - '{{ remote_tmp_dir }}/files/roots.pem'
+ register: cert2_rootchain_alt
+ - name: Verify rootchain for cert 2
+ assert:
+ that:
+ - cert2_rootchain_alt.complete_chain | join('') == (lookup('file', 'cert2.pem', rstrip=False) ~ lookup('file', 'cert2-altchain.pem', rstrip=False) ~ lookup('file', 'cert2-altroot.pem', rstrip=False))
+ - cert2_rootchain_alt.chain[:-1] | join('') == lookup('file', 'cert2-altchain.pem', rstrip=False)
+ - cert2_rootchain_alt.root == lookup('file', 'cert2-altroot.pem', rstrip=False)
+ when: cryptography_version.stdout is version('1.5', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/aliases
new file mode 100644
index 00000000..f320bbb3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/aliases
@@ -0,0 +1,15 @@
+# Not enabled due to lack of access to test environments. May be enabled using custom integration_config.yml
+# Example integation_config.yml
+# ---
+# entrust_api_user:
+# entrust_api_key:
+# entrust_api_client_cert_path: /var/integration-testing/publicCert.pem
+# entrust_api_client_cert_key_path: /var/integration-testing/privateKey.pem
+# entrust_api_ip_address: 127.0.0.1
+# entrust_cloud_ip_address: 127.0.0.1
+# # Used for certificate path validation of QA environments - we chose not to support disabling path validation ever.
+# cacerts_bundle_path_local: /var/integration-testing/cacerts
+
+### WARNING: This test will update HOSTS file and CERTIFICATE STORE of target host, in order to be able to validate
+# to a QA environment. ###
+unsupported
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/defaults/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/defaults/main.yml
new file mode 100644
index 00000000..86bc36c3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+# defaults file for test_ecs_certificate
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/meta/main.yml
new file mode 100644
index 00000000..a35b3306
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - prepare_tests
+ - setup_openssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/tasks/main.yml
new file mode 100644
index 00000000..0b8fc662
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/tasks/main.yml
@@ -0,0 +1,220 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+## Verify that integration_config was specified
+- block:
+ - assert:
+ that:
+ - entrust_api_user is defined
+ - entrust_api_key is defined
+ - entrust_api_ip_address is defined
+ - entrust_cloud_ip_address is defined
+ - entrust_api_client_cert_path is defined or entrust_api_client_cert_contents is defined
+ - entrust_api_client_cert_key_path is defined or entrust_api_client_cert_key_contents
+ - cacerts_bundle_path_local is defined
+
+## SET UP TEST ENVIRONMENT ########################################################################
+- name: copy the files needed for verifying test server certificate to the host
+ copy:
+ src: '{{ cacerts_bundle_path_local }}/'
+ dest: '{{ cacerts_bundle_path }}'
+
+- name: Update the CA certificates for our QA certs (collection may need updating if new QA environments used)
+ command: c_rehash {{ cacerts_bundle_path }}
+
+- name: Update hosts file
+ lineinfile:
+ path: /etc/hosts
+ state: present
+ regexp: 'api.entrust.net$'
+ line: '{{ entrust_api_ip_address }} api.entrust.net'
+
+- name: Update hosts file
+ lineinfile:
+ path: /etc/hosts
+ state: present
+ regexp: 'cloud.entrust.net$'
+ line: '{{ entrust_cloud_ip_address }} cloud.entrust.net'
+
+- name: Clear out the temporary directory for storing the API connection information
+ file:
+ path: '{{ tmpdir_path }}'
+ state: absent
+
+- name: Create a directory for storing the API connection Information
+ file:
+ path: '{{ tmpdir_path }}'
+ state: directory
+
+- name: Copy the files needed for the connection to entrust API to the host
+ copy:
+ src: '{{ entrust_api_client_cert_path }}'
+ dest: '{{ entrust_api_cert }}'
+
+- name: Copy the files needed for the connection to entrust API to the host
+ copy:
+ src: '{{ entrust_api_client_cert_key_path }}'
+ dest: '{{ entrust_api_cert_key }}'
+
+## SETUP CSR TO REQUEST
+- name: Generate a 2048 bit RSA private key
+ openssl_privatekey:
+ path: '{{ privatekey_path }}'
+ passphrase: '{{ privatekey_passphrase }}'
+ cipher: auto
+ type: RSA
+ size: 2048
+
+- name: Generate a certificate signing request using the generated key
+ openssl_csr:
+ path: '{{ csr_path }}'
+ privatekey_path: '{{ privatekey_path }}'
+ privatekey_passphrase: '{{ privatekey_passphrase }}'
+ common_name: '{{ common_name }}'
+ organization_name: '{{ organization_name | default(omit) }}'
+ organizational_unit_name: '{{ organizational_unit_name | default(omit) }}'
+ country_name: '{{ country_name | default(omit) }}'
+ state_or_province_name: '{{ state_or_province_name | default(omit) }}'
+ digest: sha256
+
+- block:
+ - name: Have ECS generate a signed certificate
+ ecs_certificate:
+ backup: True
+ path: '{{ example1_cert_path }}'
+ full_chain_path: '{{ example1_chain_path }}'
+ csr: '{{ csr_path }}'
+ cert_type: '{{ example1_cert_type }}'
+ requester_name: '{{ entrust_requester_name }}'
+ requester_email: '{{ entrust_requester_email }}'
+ requester_phone: '{{ entrust_requester_phone }}'
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: example1_result
+
+ - assert:
+ that:
+ - example1_result is not failed
+ - example1_result.changed
+ - example1_result.tracking_id > 0
+ - example1_result.serial_number is string
+
+ # Internal CA refuses to issue certificates with the same DN in a short time frame
+ - name: Sleep for 5 seconds so we don't run into duplicate-request errors
+ pause:
+ seconds: 5
+
+ - name: Attempt to have ECS generate a signed certificate, but existing one is valid
+ ecs_certificate:
+ backup: True
+ path: '{{ example1_cert_path }}'
+ full_chain_path: '{{ example1_chain_path }}'
+ csr: '{{ csr_path }}'
+ cert_type: '{{ example1_cert_type }}'
+ requester_name: '{{ entrust_requester_name }}'
+ requester_email: '{{ entrust_requester_email }}'
+ requester_phone: '{{ entrust_requester_phone }}'
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: example2_result
+
+ - assert:
+ that:
+ - example2_result is not failed
+ - not example2_result.changed
+ - example2_result.backup_file is undefined
+ - example2_result.backup_full_chain_file is undefined
+ - example2_result.serial_number == example1_result.serial_number
+ - example2_result.tracking_id == example1_result.tracking_id
+
+ # Internal CA refuses to issue certificates with the same DN in a short time frame
+ - name: Sleep for 5 seconds so we don't run into duplicate-request errors
+ pause:
+ seconds: 5
+
+ - name: Force a reissue with no CSR, verify that contents changed
+ ecs_certificate:
+ backup: True
+ force: True
+ path: '{{ example1_cert_path }}'
+ full_chain_path: '{{ example1_chain_path }}'
+ cert_type: '{{ example1_cert_type }}'
+ request_type: reissue
+ requester_name: '{{ entrust_requester_name }}'
+ requester_email: '{{ entrust_requester_email }}'
+ requester_phone: '{{ entrust_requester_phone }}'
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: example3_result
+
+ - assert:
+ that:
+ - example3_result is not failed
+ - example3_result.changed
+ - example3_result.backup_file is string
+ - example3_result.backup_full_chain_file is string
+ - example3_result.tracking_id > 0
+ - example3_result.tracking_id != example1_result.tracking_id
+ - example3_result.serial_number != example1_result.serial_number
+
+ # Internal CA refuses to issue certificates with the same DN in a short time frame
+ - name: Sleep for 5 seconds so we don't run into duplicate-request errors
+ pause:
+ seconds: 5
+
+ - name: Test a request with all of the various optional possible fields populated
+ ecs_certificate:
+ path: '{{ example4_cert_path }}'
+ full_chain_path: '{{ example4_full_chain_path }}'
+ csr: '{{ csr_path }}'
+ subject_alt_name: '{{ example4_subject_alt_name }}'
+ eku: '{{ example4_eku }}'
+ ct_log: True
+ cert_type: '{{ example4_cert_type }}'
+ org: '{{ example4_org }}'
+ ou: '{{ example4_ou }}'
+ tracking_info: '{{ example4_tracking_info }}'
+ additional_emails: '{{ example4_additional_emails }}'
+ custom_fields: '{{ example4_custom_fields }}'
+ cert_expiry: '{{ example4_cert_expiry }}'
+ requester_name: '{{ entrust_requester_name }}'
+ requester_email: '{{ entrust_requester_email }}'
+ requester_phone: '{{ entrust_requester_phone }}'
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: example4_result
+
+ - assert:
+ that:
+ - example4_result is not failed
+ - example4_result.changed
+ - example4_result.backup_file is undefined
+ - example4_result.backup_full_chain_file is undefined
+ - example4_result.tracking_id > 0
+ - example4_result.serial_number is string
+
+ # For bug 61738, verify that the full chain is valid
+ - name: Verify that the full chain path can be successfully imported
+ command: '{{ openssl_binary }} verify "{{ example4_full_chain_path }}"'
+ register: openssl_result
+
+ - assert:
+ that:
+ - "' OK' in openssl_result.stdout_lines[0]"
+
+ always:
+ - name: clean-up temporary folder
+ file:
+ path: '{{ tmpdir_path }}'
+ state: absent
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/vars/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/vars/main.yml
new file mode 100644
index 00000000..8e617618
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_certificate/vars/main.yml
@@ -0,0 +1,52 @@
+---
+# vars file for test_ecs_certificate
+
+# Path on various hosts that cacerts need to be put as a prerequisite to API server cert validation.
+# May need to be customized for some environments based on SSL implementations
+# that ansible "urls" module utility is using as a backing.
+cacerts_bundle_path: /etc/pki/tls/certs
+
+common_name: '{{ ansible_date_time.epoch }}.ansint.testcertificates.com'
+organization_name: CMS API, Inc.
+organizational_unit_name: RSA
+country_name: US
+state_or_province_name: MA
+privatekey_passphrase: Passphrase452!
+tmpdir_path: /tmp/ecs_cert_test/{{ ansible_date_time.epoch }}
+privatekey_path: '{{ tmpdir_path }}/testcertificates.key'
+entrust_api_cert: '{{ tmpdir_path }}/authcert.cer'
+entrust_api_cert_key: '{{ tmpdir_path }}/authkey.cer'
+csr_path: '{{ tmpdir_path }}/request.csr'
+
+entrust_requester_name: C Trufan
+entrust_requester_email: CTIntegrationTests@entrustdatacard.com
+entrust_requester_phone: 1-555-555-5555 # e.g. 15555555555
+
+# TEST 1
+example1_cert_path: '{{ tmpdir_path }}/issuedcert_1.pem'
+example1_chain_path: '{{ tmpdir_path }}/issuedcert_1_chain.pem'
+example1_cert_type: EV_SSL
+
+example4_cert_path: '{{ tmpdir_path }}/issuedcert_2.pem'
+example4_subject_alt_name:
+ - ansible.testcertificates.com
+ - www.testcertificates.com
+example4_eku: SERVER_AND_CLIENT_AUTH
+example4_cert_type: UC_SSL
+# Test a secondary org and special characters
+example4_org: Cañon City, Inc.
+example4_ou:
+ - StringrsaString
+example4_tracking_info: Submitted via Ansible Integration
+example4_additional_emails:
+ - itsupport@testcertificates.com
+ - jsmith@ansible.com
+example4_custom_fields:
+ text1: Admin
+ text2: Invoice 25
+ number1: 342
+ date3: '2018-01-01'
+ email2: sales@ansible.testcertificates.com
+ dropdown2: Dropdown 2 Value 1
+example4_cert_expiry: 2020-08-15
+example4_full_chain_path: '{{ tmpdir_path }}/issuedcert_2_chain.pem'
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/aliases
new file mode 100644
index 00000000..f320bbb3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/aliases
@@ -0,0 +1,15 @@
+# Not enabled due to lack of access to test environments. May be enabled using custom integration_config.yml
+# Example integation_config.yml
+# ---
+# entrust_api_user:
+# entrust_api_key:
+# entrust_api_client_cert_path: /var/integration-testing/publicCert.pem
+# entrust_api_client_cert_key_path: /var/integration-testing/privateKey.pem
+# entrust_api_ip_address: 127.0.0.1
+# entrust_cloud_ip_address: 127.0.0.1
+# # Used for certificate path validation of QA environments - we chose not to support disabling path validation ever.
+# cacerts_bundle_path_local: /var/integration-testing/cacerts
+
+### WARNING: This test will update HOSTS file and CERTIFICATE STORE of target host, in order to be able to validate
+# to a QA environment. ###
+unsupported
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/defaults/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/defaults/main.yml
new file mode 100644
index 00000000..69034c4b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+# defaults file for test_ecs_domain
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/meta/main.yml
new file mode 100644
index 00000000..07faa217
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - prepare_tests
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/tasks/main.yml
new file mode 100644
index 00000000..b91b6f43
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/tasks/main.yml
@@ -0,0 +1,275 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+## Verify that integration_config was specified
+- block:
+ - assert:
+ that:
+ - entrust_api_user is defined
+ - entrust_api_key is defined
+ - entrust_api_ip_address is defined
+ - entrust_cloud_ip_address is defined
+ - entrust_api_client_cert_path is defined or entrust_api_client_cert_contents is defined
+ - entrust_api_client_cert_key_path is defined or entrust_api_client_cert_key_contents
+ - cacerts_bundle_path_local is defined
+
+## SET UP TEST ENVIRONMENT ########################################################################
+- name: copy the files needed for verifying test server certificate to the host
+ copy:
+ src: '{{ cacerts_bundle_path_local }}/'
+ dest: '{{ cacerts_bundle_path }}'
+
+- name: Update the CA certificates for our QA certs (collection may need updating if new QA environments used)
+ command: c_rehash {{ cacerts_bundle_path }}
+
+- name: Update hosts file
+ lineinfile:
+ path: /etc/hosts
+ state: present
+ regexp: 'api.entrust.net$'
+ line: '{{ entrust_api_ip_address }} api.entrust.net'
+
+- name: Update hosts file
+ lineinfile:
+ path: /etc/hosts
+ state: present
+ regexp: 'cloud.entrust.net$'
+ line: '{{ entrust_cloud_ip_address }} cloud.entrust.net'
+
+- name: Clear out the temporary directory for storing the API connection information
+ file:
+ path: '{{ tmpdir_path }}'
+ state: absent
+
+- name: Create a directory for storing the API connection Information
+ file:
+ path: '{{ tmpdir_path }}'
+ state: directory
+
+- name: Copy the files needed for the connection to entrust API to the host
+ copy:
+ src: '{{ entrust_api_client_cert_path }}'
+ dest: '{{ entrust_api_cert }}'
+
+- name: Copy the files needed for the connection to entrust API to the host
+ copy:
+ src: '{{ entrust_api_client_cert_key_path }}'
+ dest: '{{ entrust_api_cert_key }}'
+
+- block:
+ - name: Have ECS request a domain validation via dns
+ ecs_domain:
+ domain_name: dns.{{ common_name }}
+ verification_method: dns
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: dns_result
+
+ - assert:
+ that:
+ - dns_result is not failed
+ - dns_result.changed
+ - dns_result.domain_status == 'INITIAL_VERIFICATION'
+ - dns_result.verification_method == 'dns'
+ - dns_result.dns_location is string
+ - dns_result.dns_contents is string
+ - dns_result.dns_resource_type is string
+ - dns_result.file_location is undefined
+ - dns_result.file_contents is undefined
+ - dns_result.emails is undefined
+
+ - name: Have ECS request a domain validation via web_server
+ ecs_domain:
+ domain_name: FILE.{{ common_name }}
+ verification_method: web_server
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: file_result
+
+ - assert:
+ that:
+ - file_result is not failed
+ - file_result.changed
+ - file_result.domain_status == 'INITIAL_VERIFICATION'
+ - file_result.verification_method == 'web_server'
+ - file_result.dns_location is undefined
+ - file_result.dns_contents is undefined
+ - file_result.dns_resource_type is undefined
+ - file_result.file_location is string
+ - file_result.file_contents is string
+ - file_result.emails is undefined
+
+ - name: Have ECS request a domain validation via email
+ ecs_domain:
+ domain_name: email.{{ common_name }}
+ verification_method: email
+ verification_email: admin@testcertificates.com
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: email_result
+
+ - assert:
+ that:
+ - email_result is not failed
+ - email_result.changed
+ - email_result.domain_status == 'INITIAL_VERIFICATION'
+ - email_result.verification_method == 'email'
+ - email_result.dns_location is undefined
+ - email_result.dns_contents is undefined
+ - email_result.dns_resource_type is undefined
+ - email_result.file_location is undefined
+ - email_result.file_contents is undefined
+ - email_result.emails[0] == 'admin@testcertificates.com'
+
+ - name: Have ECS request a domain validation via email with no address provided
+ ecs_domain:
+ domain_name: email2.{{ common_name }}
+ verification_method: email
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: email_result2
+
+ - assert:
+ that:
+ - email_result2 is not failed
+ - email_result2.changed
+ - email_result2.domain_status == 'INITIAL_VERIFICATION'
+ - email_result2.verification_method == 'email'
+ - email_result2.dns_location is undefined
+ - email_result2.dns_contents is undefined
+ - email_result2.dns_resource_type is undefined
+ - email_result2.file_location is undefined
+ - email_result2.file_contents is undefined
+ - email_result2.emails is defined
+
+ - name: Have ECS request a domain validation via manual
+ ecs_domain:
+ domain_name: manual.{{ common_name }}
+ verification_method: manual
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: manual_result
+
+ - assert:
+ that:
+ - manual_result is not failed
+ - manual_result.changed
+ - manual_result.domain_status == 'INITIAL_VERIFICATION'
+ - manual_result.verification_method == 'manual'
+ - manual_result.dns_location is undefined
+ - manual_result.dns_contents is undefined
+ - manual_result.dns_resource_type is undefined
+ - manual_result.file_location is undefined
+ - manual_result.file_contents is undefined
+ - manual_result.emails is undefined
+
+ - name: Have ECS request a domain validation via dns that remains unchanged
+ ecs_domain:
+ domain_name: dns.{{ common_name }}
+ verification_method: dns
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: dns_result2
+
+ - assert:
+ that:
+ - dns_result2 is not failed
+ - not dns_result2.changed
+ - dns_result2.domain_status == 'INITIAL_VERIFICATION'
+ - dns_result2.verification_method == 'dns'
+ - dns_result2.dns_location is string
+ - dns_result2.dns_contents is string
+ - dns_result2.dns_resource_type is string
+ - dns_result2.file_location is undefined
+ - dns_result2.file_contents is undefined
+ - dns_result2.emails is undefined
+
+ - name: Have ECS request a domain validation via FILE for dns, to change verification method
+ ecs_domain:
+ domain_name: dns.{{ common_name }}
+ verification_method: web_server
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: dns_result_now_file
+
+ - assert:
+ that:
+ - dns_result_now_file is not failed
+ - dns_result_now_file.changed
+ - dns_result_now_file.domain_status == 'INITIAL_VERIFICATION'
+ - dns_result_now_file.verification_method == 'web_server'
+ - dns_result_now_file.dns_location is undefined
+ - dns_result_now_file.dns_contents is undefined
+ - dns_result_now_file.dns_resource_type is undefined
+ - dns_result_now_file.file_location is string
+ - dns_result_now_file.file_contents is string
+ - dns_result_now_file.emails is undefined
+
+ - name: Request revalidation of an approved domain
+ ecs_domain:
+ domain_name: '{{ existing_domain_common_name }}'
+ verification_method: manual
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: manual_existing_domain
+
+ - assert:
+ that:
+ - manual_existing_domain is not failed
+ - not manual_existing_domain.changed
+ - manual_existing_domain.domain_status == 'RE_VERIFICATION'
+ - manual_existing_domain.dns_location is undefined
+ - manual_existing_domain.dns_contents is undefined
+ - manual_existing_domain.dns_resource_type is undefined
+ - manual_existing_domain.file_location is undefined
+ - manual_existing_domain.file_contents is undefined
+ - manual_existing_domain.emails is undefined
+
+ - name: Request revalidation of an approved domain
+ ecs_domain:
+ domain_name: '{{ existing_domain_common_name }}'
+ verification_method: web_server
+ entrust_api_user: '{{ entrust_api_user }}'
+ entrust_api_key: '{{ entrust_api_key }}'
+ entrust_api_client_cert_path: '{{ entrust_api_cert }}'
+ entrust_api_client_cert_key_path: '{{ entrust_api_cert_key }}'
+ register: file_existing_domain_revalidate
+
+ - assert:
+ that:
+ - file_existing_domain_revalidate is not failed
+ - file_existing_domain_revalidate.changed
+ - file_existing_domain_revalidate.domain_status == 'RE_VERIFICATION'
+ - file_existing_domain_revalidate.verification_method == 'web_server'
+ - file_existing_domain_revalidate.dns_location is undefined
+ - file_existing_domain_revalidate.dns_contents is undefined
+ - file_existing_domain_revalidate.dns_resource_type is undefined
+ - file_existing_domain_revalidate.file_location is string
+ - file_existing_domain_revalidate.file_contents is string
+ - file_existing_domain_revalidate.emails is undefined
+
+
+ always:
+ - name: clean-up temporary folder
+ file:
+ path: '{{ tmpdir_path }}'
+ state: absent
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/vars/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/vars/main.yml
new file mode 100644
index 00000000..9cf9fdb7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/ecs_domain/vars/main.yml
@@ -0,0 +1,15 @@
+---
+# vars file for test_ecs_certificate
+
+# Path on various hosts that cacerts need to be put as a prerequisite to API server cert validation.
+# May need to be customized for some environments based on SSL implementations
+# that ansible "urls" module utility is using as a backing.
+cacerts_bundle_path: /etc/pki/tls/certs
+
+common_name: '{{ ansible_date_time.epoch }}.testcertificates.com'
+existing_domain_common_name: 'testcertificates.com'
+
+tmpdir_path: /tmp/ecs_cert_test/{{ ansible_date_time.epoch }}
+
+entrust_api_cert: '{{ tmpdir_path }}/authcert.cer'
+entrust_api_cert_key: '{{ tmpdir_path }}/authkey.cer'
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/aliases
new file mode 100644
index 00000000..db2a5672
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/aliases
@@ -0,0 +1,3 @@
+shippable/posix/group1
+destructive
+needs/httptester
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/files/bogus_ca.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/files/bogus_ca.pem
new file mode 100644
index 00000000..16119c9e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/files/bogus_ca.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC+DCCAeACCQCWuDvGDH3otTANBgkqhkiG9w0BAQsFADA+MQswCQYDVQQGEwJV
+UzEOMAwGA1UECAwFQm9ndXMxEDAOBgNVBAcMB0JhbG9uZXkxDTALBgNVBAoMBEFD
+TUUwHhcNMTgwNzEyMTgxNDA0WhcNMjMwNzExMTgxNDA0WjA+MQswCQYDVQQGEwJV
+UzEOMAwGA1UECAwFQm9ndXMxEDAOBgNVBAcMB0JhbG9uZXkxDTALBgNVBAoMBEFD
+TUUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLTGCpn8b+/2qdpkvK
+iwXU8PMOXBOmRa+GmzxsxMr1QZcY0m6pY3uuIvqErMFf4qp4BMxQF+VpDLVJUJX/
+1oKCM7J3hEfgmKRD4RmKhBlnWVv5YGZmvlXRJBl1AsDTONZy8iKJB5NYnB3ZyrJq
+H2GAgyJ55aYckoU55vwjRzKp49dZmzX5YS04Kzzzw/SmOuW8kMypZV5TJH+NXqKc
+pw3u3cJ4yJ9DHSU5pnhC5BeKl8XDMO42jRWt5/7C7JDiCbZ9lu5jQiv/4DhsRsHF
+A8/Lgl47sNDaBMbha786I9laPHLlVycpYaP6pwtizhN9ZRTdDOHmWi/vjiamERLL
+FjjLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAA+1uj3tHaCai+A1H/kOgTN5e0eW
+/wmaxu8gNK5eiHrecNJNAlFxVTrCwhvv4nUW7NXVcW/1WUqSO0QMiPJhCsSLVAMF
+8MuYH73B+ctRqAGdeOAWF+ftCywZTEj5h5F0XiWB+TmkPlTVNShMiPFelDJpLy7u
+9MfiPEJjo4sZotQl8/pZ6R9cY6GpEXWnttcuhLJCEuiB8fWO7epiWYCt/Ak+CVmZ
+OzfI/euV6Upaen22lNu8V3ZwWEFtmU5CioKJ3S8DK5Mw/LJIJw1ZY9E+fTtn8x0k
+xlI4e7urD2FYhTdv2fFUG8Z5arb/3bICgsUYQZ+G1c3wjWtJg9zcy8hpnZQ=
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/files/process_certs.py b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/files/process_certs.py
new file mode 100644
index 00000000..8a21af71
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/files/process_certs.py
@@ -0,0 +1,28 @@
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+from sys import argv
+from subprocess import Popen, PIPE, STDOUT
+
+p = Popen(["openssl", "s_client", "-host", argv[1], "-port", "443", "-prexit", "-showcerts"], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
+stdout = p.communicate(input=b'\n')[0]
+data = stdout.decode()
+
+certs = []
+cert = ""
+capturing = False
+for line in data.split('\n'):
+ if line == '-----BEGIN CERTIFICATE-----':
+ capturing = True
+
+ if capturing:
+ cert = "{0}{1}\n".format(cert, line)
+
+ if line == '-----END CERTIFICATE-----':
+ capturing = False
+ certs.append(cert)
+ cert = ""
+
+with open(argv[2], 'w') as f:
+ for cert in set(certs):
+ f.write(cert)
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/meta/main.yml
new file mode 100644
index 00000000..fe62e922
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/meta/main.yml
@@ -0,0 +1,4 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
+ - prepare_http_tests
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/tasks/main.yml
new file mode 100644
index 00000000..fae5ab7e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/tasks/main.yml
@@ -0,0 +1,47 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- block:
+
+ - name: Get servers certificate with backend auto-detection
+ get_certificate:
+ host: "{{ httpbin_host }}"
+ port: 443
+
+ when: |
+ pyopenssl_version.stdout is version('0.15', '>=') or
+ (cryptography_version.stdout is version('1.6', '>=') and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6))
+
+- block:
+
+ - include_tasks: ../tests/validate.yml
+ vars:
+ select_crypto_backend: pyopenssl
+
+ when: pyopenssl_version.stdout is version('0.15', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+
+ - include_tasks: ../tests/validate.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ # The module doesn't work with CentOS 6. Since the pyOpenSSL installed there is too old,
+ # we never noticed before. This becomes a problem with the new cryptography backend,
+ # since there is a new enough cryptography version...
+ when: |
+ cryptography_version.stdout is version('1.6', '>=') and
+ (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/tests/validate.yml
new file mode 100644
index 00000000..d77f0119
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/get_certificate/tests/validate.yml
@@ -0,0 +1,140 @@
+---
+- name: Get servers certificate for SNI test part 1
+ get_certificate:
+ host: "{{ httpbin_host }}"
+ port: 443
+ server_name: "{{ sni_host }}"
+ register: result
+
+- debug: var=result
+
+- assert:
+ that:
+ # This module should never change anything
+ - result is not changed
+ - result is not failed
+ # We got the correct ST from the cert
+ - "'{{ sni_host }}' == result.subject.CN"
+
+- name: Get servers certificate for SNI test part 2
+ get_certificate:
+ host: "{{ sni_host }}"
+ port: 443
+ server_name: "{{ httpbin_host }}"
+ register: result
+
+- debug: var=result
+
+- assert:
+ that:
+ # This module should never change anything
+ - result is not changed
+ - result is not failed
+ # We got the correct ST from the cert
+ - "'{{ httpbin_host }}' == result.subject.CN"
+
+- name: Get servers certificate
+ get_certificate:
+ host: "{{ httpbin_host }}"
+ port: 443
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: result
+
+- debug: var=result
+
+- assert:
+ that:
+ # This module should never change anything
+ - result is not changed
+ - result is not failed
+ # We got the correct ST from the cert
+ - "'North Carolina' == result.subject.ST"
+
+- name: Connect to http port (will fail because there is no SSL cert to get)
+ get_certificate:
+ host: "{{ httpbin_host }}"
+ port: 80
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: result
+ ignore_errors: true
+
+- assert:
+ that:
+ - result is not changed
+ - result is failed
+ # We got the expected error message
+ - "'The handshake operation timed out' in result.msg or 'unknown protocol' in result.msg or 'wrong version number' in result.msg"
+
+- name: Test timeout option
+ get_certificate:
+ host: "{{ httpbin_host }}"
+ port: 1234
+ timeout: 1
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: result
+ ignore_errors: true
+
+- assert:
+ that:
+ - result is not changed
+ - result is failed
+ # We got the expected error message
+ - "'Failed to get cert from port with error: timed out' == result.msg or 'Connection refused' in result.msg"
+
+- name: Test failure if ca_cert is not a valid file
+ get_certificate:
+ host: "{{ httpbin_host }}"
+ port: 443
+ ca_cert: dn.e
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: result
+ ignore_errors: true
+
+- assert:
+ that:
+ - result is not changed
+ - result is failed
+ # We got the correct response from the module
+ - "'ca_cert file does not exist' == result.msg"
+
+- name: Download CA Cert as pem from server
+ get_url:
+ url: "http://ansible.http.tests/cacert.pem"
+ dest: "{{ output_dir }}/temp.pem"
+
+- name: Get servers certificate comparing it to its own ca_cert file
+ get_certificate:
+ ca_cert: '{{ output_dir }}/temp.pem'
+ host: "{{ httpbin_host }}"
+ port: 443
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: result
+
+- assert:
+ that:
+ - result is not changed
+ - result is not failed
+
+- name: Get a temp directory
+ tempfile:
+ state: directory
+ register: my_temp_dir
+
+- name: Deploy the bogus_ca.pem file
+ copy:
+ src: "bogus_ca.pem"
+ dest: "{{ my_temp_dir.path }}/bogus_ca.pem"
+
+- name: Get servers certificate comparing it to an invalid ca_cert file
+ get_certificate:
+ ca_cert: '{{ my_temp_dir.path }}/bogus_ca.pem'
+ host: "{{ httpbin_host }}"
+ port: 443
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: result
+ ignore_errors: true
+
+- assert:
+ that:
+ - result is not changed
+ - result.failed
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/aliases
new file mode 100644
index 00000000..f0df7981
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/aliases
@@ -0,0 +1,7 @@
+shippable/posix/group1
+skip/osx
+skip/macos
+skip/freebsd
+skip/docker
+needs/root
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/files/keyfile1 b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/files/keyfile1
new file mode 100644
index 00000000..5e40c087
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/files/keyfile1
@@ -0,0 +1 @@
+asdf \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/files/keyfile2 b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/files/keyfile2
new file mode 100644
index 00000000..5e4f2565
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/files/keyfile2
@@ -0,0 +1 @@
+test1234 \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/main.yml
new file mode 100644
index 00000000..81862c8c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/main.yml
@@ -0,0 +1,41 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Make sure cryptsetup is installed
+ package:
+ name: cryptsetup
+ state: present
+ become: yes
+- name: Create cryptfile
+ command: dd if=/dev/zero of={{ output_dir.replace('~', ansible_env.HOME) }}/cryptfile bs=1M count=32
+- name: Create lookback device
+ command: losetup -f {{ output_dir.replace('~', ansible_env.HOME) }}/cryptfile
+ become: yes
+- name: Determine loop device name
+ command: losetup -j {{ output_dir.replace('~', ansible_env.HOME) }}/cryptfile --output name
+ become: yes
+ register: cryptfile_device_output
+- set_fact:
+ cryptfile_device: "{{ cryptfile_device_output.stdout_lines[1] }}"
+ cryptfile_passphrase1: "uNiJ9vKG2mUOEWDiQVuBHJlfMHE"
+ cryptfile_passphrase2: "HW4Ak2HtE2vvne0qjJMPTtmbV4M"
+ cryptfile_passphrase3: "qQJqsjabO9pItV792k90VvX84MM"
+- block:
+ - include_tasks: run-test.yml
+ with_fileglob:
+ - "tests/*.yml"
+ always:
+ - name: Make sure LUKS device is gone
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: absent
+ become: yes
+ ignore_errors: yes
+ - command: losetup -d "{{ cryptfile_device }}"
+ become: yes
+ - file:
+ dest: "{{ output_dir }}/cryptfile"
+ state: absent
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/run-test.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/run-test.yml
new file mode 100644
index 00000000..a2ec73b2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/run-test.yml
@@ -0,0 +1,8 @@
+---
+- name: Make sure LUKS device is gone
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: absent
+ become: yes
+- name: "Loading tasks from {{ item }}"
+ include_tasks: "{{ item }}"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/create-destroy.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/create-destroy.yml
new file mode 100644
index 00000000..9e4e1f3f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/create-destroy.yml
@@ -0,0 +1,195 @@
+---
+- name: Create (check)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ pbkdf:
+ iteration_time: 0.1
+ check_mode: yes
+ become: yes
+ register: create_check
+- name: Create
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ pbkdf:
+ iteration_time: 0.1
+ become: yes
+ register: create
+- name: Create (idempotent)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ pbkdf:
+ iteration_time: 0.1
+ become: yes
+ register: create_idem
+- name: Create (idempotent, check)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ pbkdf:
+ iteration_time: 0.1
+ check_mode: yes
+ become: yes
+ register: create_idem_check
+- assert:
+ that:
+ - create_check is changed
+ - create is changed
+ - create_idem is not changed
+ - create_idem_check is not changed
+
+- name: Open (check)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile1"
+ check_mode: yes
+ become: yes
+ register: open_check
+- name: Open
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile1"
+ become: yes
+ register: open
+- name: Open (idempotent)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile1"
+ become: yes
+ register: open_idem
+- name: Open (idempotent, check)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile1"
+ check_mode: yes
+ become: yes
+ register: open_idem_check
+- assert:
+ that:
+ - open_check is changed
+ - open is changed
+ - open_idem is not changed
+ - open_idem_check is not changed
+
+- name: Closed (via name, check)
+ luks_device:
+ name: "{{ open.name }}"
+ state: closed
+ check_mode: yes
+ become: yes
+ register: close_check
+- name: Closed (via name)
+ luks_device:
+ name: "{{ open.name }}"
+ state: closed
+ become: yes
+ register: close
+- name: Closed (via name, idempotent)
+ luks_device:
+ name: "{{ open.name }}"
+ state: closed
+ become: yes
+ register: close_idem
+- name: Closed (via name, idempotent, check)
+ luks_device:
+ name: "{{ open.name }}"
+ state: closed
+ check_mode: yes
+ become: yes
+ register: close_idem_check
+- assert:
+ that:
+ - close_check is changed
+ - close is changed
+ - close_idem is not changed
+ - close_idem_check is not changed
+
+- name: Re-open
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile1"
+ become: yes
+
+- name: Closed (via device, check)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ check_mode: yes
+ become: yes
+ register: close_check
+- name: Closed (via device)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ become: yes
+ register: close
+- name: Closed (via device, idempotent)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ become: yes
+ register: close_idem
+- name: Closed (via device, idempotent, check)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ check_mode: yes
+ become: yes
+ register: close_idem_check
+- assert:
+ that:
+ - close_check is changed
+ - close is changed
+ - close_idem is not changed
+ - close_idem_check is not changed
+
+- name: Re-opened
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile1"
+ become: yes
+
+- name: Absent (check)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: absent
+ check_mode: yes
+ become: yes
+ register: absent_check
+- name: Absent
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: absent
+ become: yes
+ register: absent
+- name: Absent (idempotence)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: absent
+ become: yes
+ register: absent_idem
+- name: Absent (idempotence, check)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: absent
+ check_mode: yes
+ become: yes
+ register: absent_idem_check
+- assert:
+ that:
+ - absent_check is changed
+ - absent is changed
+ - absent_idem is not changed
+ - absent_idem_check is not changed
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/device-check.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/device-check.yml
new file mode 100644
index 00000000..56797f91
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/device-check.yml
@@ -0,0 +1,56 @@
+---
+- name: Create with invalid device name (check)
+ luks_device:
+ device: /dev/asdfasdfasdf
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ pbkdf:
+ iteration_time: 0.1
+ check_mode: yes
+ ignore_errors: yes
+ become: yes
+ register: create_check
+- name: Create with invalid device name
+ luks_device:
+ device: /dev/asdfasdfasdf
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ pbkdf:
+ iteration_time: 0.1
+ ignore_errors: yes
+ become: yes
+ register: create
+- assert:
+ that:
+ - create_check is failed
+ - create is failed
+ - "'o such file or directory' in create_check.msg"
+ - "'o such file or directory' in create.msg"
+
+- name: Create with something which is not a device (check)
+ luks_device:
+ device: /tmp/
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ pbkdf:
+ iteration_time: 0.1
+ check_mode: yes
+ ignore_errors: yes
+ become: yes
+ register: create_check
+- name: Create with something which is not a device
+ luks_device:
+ device: /tmp/
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ pbkdf:
+ iteration_time: 0.1
+ ignore_errors: yes
+ become: yes
+ register: create
+- assert:
+ that:
+ - create_check is failed
+ - create is failed
+ - "'is not a device' in create_check.msg"
+ - "'is not a device' in create.msg"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/key-management.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/key-management.yml
new file mode 100644
index 00000000..cdf1d594
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/key-management.yml
@@ -0,0 +1,202 @@
+---
+- name: Create with keyfile1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ keyfile: "{{ role_path }}/files/keyfile1"
+ pbkdf:
+ iteration_time: 0.1
+ become: yes
+
+# Access: keyfile1
+
+- name: Try to open with keyfile1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile1"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is not failed
+- name: Close
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ become: yes
+
+- name: Try to open with keyfile2
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile2"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is failed
+
+- name: Give access to keyfile2
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ keyfile: "{{ role_path }}/files/keyfile1"
+ new_keyfile: "{{ role_path }}/files/keyfile2"
+ pbkdf:
+ iteration_time: 0.1
+ become: yes
+ register: result_1
+
+- name: Give access to keyfile2 (idempotent)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ keyfile: "{{ role_path }}/files/keyfile1"
+ new_keyfile: "{{ role_path }}/files/keyfile2"
+ become: yes
+ register: result_2
+
+- assert:
+ that:
+ - result_1 is changed
+ - result_2 is not changed
+
+# Access: keyfile1 and keyfile2
+
+- name: Try to open with keyfile2
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile2"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is not failed
+- name: Close
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ become: yes
+
+- name: Dump LUKS header
+ command: "cryptsetup luksDump {{ cryptfile_device }}"
+ become: yes
+
+- name: Remove access from keyfile1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ keyfile: "{{ role_path }}/files/keyfile1"
+ remove_keyfile: "{{ role_path }}/files/keyfile1"
+ become: yes
+ register: result_1
+
+- name: Remove access from keyfile1 (idempotent)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ keyfile: "{{ role_path }}/files/keyfile1"
+ remove_keyfile: "{{ role_path }}/files/keyfile1"
+ become: yes
+ register: result_2
+
+- assert:
+ that:
+ - result_1 is changed
+ - result_2 is not changed
+
+# Access: keyfile2
+
+- name: Try to open with keyfile1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile1"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is failed
+
+- name: Try to open with keyfile2
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile2"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is not failed
+- name: Close
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ become: yes
+
+- name: Dump LUKS header
+ command: "cryptsetup luksDump {{ cryptfile_device }}"
+ become: yes
+
+- name: Remove access from keyfile2
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ keyfile: "{{ role_path }}/files/keyfile2"
+ remove_keyfile: "{{ role_path }}/files/keyfile2"
+ become: yes
+ ignore_errors: yes
+ register: remove_last_key
+- assert:
+ that:
+ - remove_last_key is failed
+ - "'force_remove_last_key' in remove_last_key.msg"
+
+# Access: keyfile2
+
+- name: Try to open with keyfile2
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile2"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is not failed
+- name: Close
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ become: yes
+
+- name: Remove access from keyfile2
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ keyfile: "{{ role_path }}/files/keyfile2"
+ remove_keyfile: "{{ role_path }}/files/keyfile2"
+ force_remove_last_key: yes
+ become: yes
+
+# Access: none
+
+- name: Try to open with keyfile2
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile2"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is failed
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/options.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/options.yml
new file mode 100644
index 00000000..62ac3e9b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/options.yml
@@ -0,0 +1,49 @@
+---
+- name: Create with keysize
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ keysize: 256
+ pbkdf:
+ iteration_count: 1000
+ become: yes
+ register: create_with_keysize
+- name: Create with keysize (idempotent)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ keysize: 256
+ pbkdf:
+ iteration_count: 1000
+ become: yes
+ register: create_idem_with_keysize
+- name: Create with different keysize (idempotent since we do not update keysize)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ keysize: 512
+ pbkdf:
+ iteration_count: 1000
+ become: yes
+ register: create_idem_with_diff_keysize
+- name: Create with ambiguous arguments
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: present
+ keyfile: "{{ role_path }}/files/keyfile1"
+ passphrase: "{{ cryptfile_passphrase1 }}"
+ pbkdf:
+ iteration_count: 1000
+ ignore_errors: yes
+ become: yes
+ register: create_with_ambiguous
+
+- assert:
+ that:
+ - create_with_keysize is changed
+ - create_idem_with_keysize is not changed
+ - create_idem_with_diff_keysize is not changed
+ - create_with_ambiguous is failed
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/passphrase.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/passphrase.yml
new file mode 100644
index 00000000..d91bb8c6
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/luks_device/tasks/tests/passphrase.yml
@@ -0,0 +1,240 @@
+---
+- name: Create with passphrase1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ passphrase: "{{ cryptfile_passphrase1 }}"
+ pbkdf:
+ iteration_time: 0.1
+ algorithm: argon2i
+ memory: 1000
+ parallel: 1
+ become: yes
+ ignore_errors: yes
+ register: create_passphrase_1
+
+- name: Make sure that the previous task only fails because the LUKS version used cannot handle the PBKDF parameters
+ assert:
+ that:
+ - create_passphrase_1 is not failed or 'Failed to set pbkdf parameters' in create_passphrase_1.msg
+
+- name: Create with passphrase1 (without argon2i)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ passphrase: "{{ cryptfile_passphrase1 }}"
+ pbkdf:
+ iteration_time: 0.1
+ become: yes
+ when: create_passphrase_1 is failed and 'Failed to set pbkdf parameters' in create_passphrase_1.msg
+
+- name: Open with passphrase1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ passphrase: "{{ cryptfile_passphrase1 }}"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is not failed
+- name: Close
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ become: yes
+
+- name: Give access with ambiguous new_ arguments
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ passphrase: "{{ cryptfile_passphrase1 }}"
+ new_passphrase: "{{ cryptfile_passphrase2 }}"
+ new_keyfile: "{{ role_path }}/files/keyfile1"
+ pbkdf:
+ iteration_time: 0.1
+ become: yes
+ ignore_errors: yes
+ register: new_try
+- assert:
+ that:
+ - new_try is failed
+
+- name: Try to open with passphrase2
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ passphrase: "{{ cryptfile_passphrase2 }}"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is failed
+
+- name: Give access to passphrase2
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ passphrase: "{{ cryptfile_passphrase1 }}"
+ new_passphrase: "{{ cryptfile_passphrase2 }}"
+ pbkdf:
+ iteration_time: 0.1
+ become: yes
+ register: result_1
+
+- name: Give access to passphrase2 (idempotent)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ passphrase: "{{ cryptfile_passphrase1 }}"
+ new_passphrase: "{{ cryptfile_passphrase2 }}"
+ become: yes
+ register: result_2
+
+- assert:
+ that:
+ - result_1 is changed
+ - result_2 is not changed
+
+- name: Open with passphrase2
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ passphrase: "{{ cryptfile_passphrase2 }}"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is not failed
+- name: Close
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ become: yes
+
+- name: Try to open with keyfile1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile1"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is failed
+
+- name: Give access to keyfile1 from passphrase1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ passphrase: "{{ cryptfile_passphrase1 }}"
+ new_keyfile: "{{ role_path }}/files/keyfile1"
+ pbkdf:
+ iteration_time: 0.1
+ become: yes
+
+- name: Remove access with ambiguous remove_ arguments
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ remove_keyfile: "{{ role_path }}/files/keyfile1"
+ remove_passphrase: "{{ cryptfile_passphrase1 }}"
+ become: yes
+ ignore_errors: yes
+ register: remove_try
+- assert:
+ that:
+ - remove_try is failed
+
+- name: Open with keyfile1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ keyfile: "{{ role_path }}/files/keyfile1"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is not failed
+- name: Close
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ become: yes
+
+- name: Remove access for passphrase1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ remove_passphrase: "{{ cryptfile_passphrase1 }}"
+ become: yes
+ register: result_1
+
+- name: Remove access for passphrase1 (idempotent)
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ remove_passphrase: "{{ cryptfile_passphrase1 }}"
+ become: yes
+ register: result_2
+
+- assert:
+ that:
+ - result_1 is changed
+ - result_2 is not changed
+
+- name: Try to open with passphrase1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ passphrase: "{{ cryptfile_passphrase1 }}"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is failed
+
+- name: Try to open with passphrase3
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ passphrase: "{{ cryptfile_passphrase3 }}"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is failed
+
+- name: Give access to passphrase3 from keyfile1
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ keyfile: "{{ role_path }}/files/keyfile1"
+ new_passphrase: "{{ cryptfile_passphrase3 }}"
+ pbkdf:
+ iteration_time: 0.1
+ become: yes
+
+- name: Open with passphrase3
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: opened
+ passphrase: "{{ cryptfile_passphrase3 }}"
+ become: yes
+ ignore_errors: yes
+ register: open_try
+- assert:
+ that:
+ - open_try is not failed
+- name: Close
+ luks_device:
+ device: "{{ cryptfile_device }}"
+ state: closed
+ become: yes
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/meta/main.yml
new file mode 100644
index 00000000..476cfb39
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_ssh_keygen
+ - setup_ssh_agent
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/tasks/main.yml
new file mode 100644
index 00000000..15782613
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_cert/tasks/main.yml
@@ -0,0 +1,467 @@
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: openssh_cert integration tests
+ when: not (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6")
+ block:
+ - name: Generate keypair
+ openssh_keypair:
+ path: '{{ output_dir }}/id_key'
+ type: rsa
+ size: 2048
+ - name: Generate always valid cert (check mode)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: always
+ valid_to: forever
+ check_mode: yes
+ - name: Generate always valid cert
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: always
+ valid_to: forever
+ - name: Generate always valid cert (idempotent)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: always
+ valid_to: forever
+ - name: Generate always valid cert (idempotent, check mode)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: always
+ valid_to: forever
+ check_mode: yes
+ - name: Generate restricted validity cert with valid_at (check mode)
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: +0s
+ valid_to: +32w
+ valid_at: +2w
+ check_mode: yes
+ - name: Generate restricted validity cert with valid_at
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: +0s
+ valid_to: +32w
+ valid_at: +2w
+ - name: Generate restricted validity cert with valid_at (idempotent)
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: +0s
+ valid_to: +32w
+ valid_at: +2w
+ - name: Generate restricted validity cert with valid_at (idempotent, check mode)
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: +0s
+ valid_to: +32w
+ valid_at: +2w
+ check_mode: yes
+ - name: Generate always valid cert only for example.com and examplehost (check mode)
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: always
+ valid_to: forever
+ principals:
+ - example.com
+ - examplehost
+ check_mode: yes
+ - name: Generate always valid cert only for example.com and examplehost
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: always
+ valid_to: forever
+ principals:
+ - example.com
+ - examplehost
+ - name: Generate always valid cert only for example.com and examplehost (idempotent)
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: always
+ valid_to: forever
+ principals:
+ - example.com
+ - examplehost
+ - name: Generate always valid cert only for example.com and examplehost (idempotent, check mode)
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: always
+ valid_to: forever
+ principals:
+ - example.com
+ - examplehost
+ check_mode: yes
+ - name: Generate always valid cert only for example.com and examplehost (idempotent, switch)
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: always
+ valid_to: forever
+ principals:
+ - examplehost
+ - example.com
+ - name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019 (check mode)
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: "2001-01-21"
+ valid_to: "2019-01-21"
+ check_mode: yes
+ - name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: "2001-01-21"
+ valid_to: "2019-01-21"
+ - name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019 (idempotent)
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: "2001-01-21"
+ valid_to: "2019-01-21"
+ - name: Generate OpenSSH host Certificate that is valid from 21.1.2001 to 21.1.2019 (idempotent, check mode)
+ openssh_cert:
+ type: host
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ valid_from: "2001-01-21"
+ valid_to: "2019-01-21"
+ check_mode: yes
+ - name: Generate an OpenSSH user Certificate with clear and force-command option (check mode)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ options:
+ - "clear"
+ - "force-command=/tmp/bla/foo"
+ valid_from: "2001-01-21"
+ valid_to: "2019-01-21"
+ check_mode: yes
+ - name: Generate an OpenSSH user Certificate with clear and force-command option
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ options:
+ - "clear"
+ - "force-command=/tmp/bla/foo"
+ valid_from: "2001-01-21"
+ valid_to: "2019-01-21"
+ - name: Generate an OpenSSH user Certificate with clear and force-command option (idempotent)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ options:
+ - "clear"
+ - "force-command=/tmp/bla/foo"
+ valid_from: "2001-01-21"
+ valid_to: "2019-01-21"
+ - name: Generate an OpenSSH user Certificate with clear and force-command option (idempotent, check mode)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ options:
+ - "clear"
+ - "force-command=/tmp/bla/foo"
+ valid_from: "2001-01-21"
+ valid_to: "2019-01-21"
+ check_mode: yes
+ - name: Generate an OpenSSH user Certificate with clear and force-command option (idempotent, switch)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert'
+ options:
+ - "force-command=/tmp/bla/foo"
+ - "clear"
+ valid_from: "2001-01-21"
+ valid_to: "2019-01-21"
+ - name: Generate cert without serial
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_no_serial'
+ valid_from: always
+ valid_to: forever
+ register: rc_no_serial_number
+ - name: check default serial
+ assert:
+ that:
+ - "'Serial: 0' in rc_no_serial_number.info"
+ msg: OpenSSH user certificate contains the default serial number.
+ - name: Generate cert without serial (idempotent)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_no_serial'
+ valid_from: always
+ valid_to: forever
+ register: rc_no_serial_number_idempotent
+ - name: check idempotent
+ assert:
+ that:
+ - rc_no_serial_number_idempotent is not changed
+ msg: OpenSSH certificate generation without serial number is idempotent.
+ - name: Generate cert with serial 42
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_serial_42'
+ valid_from: always
+ valid_to: forever
+ serial_number: 42
+ register: rc_serial_number
+ - name: check serial 42
+ assert:
+ that:
+ - "'Serial: 42' in rc_serial_number.info"
+ msg: OpenSSH user certificate contains the serial number from the params.
+ - name: Generate cert with serial 42 (idempotent)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_serial_42'
+ valid_from: always
+ valid_to: forever
+ serial_number: 42
+ register: rc_serial_number_idempotent
+ - name: check idempotent
+ assert:
+ that:
+ - rc_serial_number_idempotent is not changed
+ msg: OpenSSH certificate generation with serial number is idempotent.
+ - name: Generate cert with changed serial number
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_serial_42'
+ valid_from: always
+ valid_to: forever
+ serial_number: 1337
+ register: rc_serial_number_changed
+ - name: check changed
+ assert:
+ that:
+ - rc_serial_number_changed is changed
+ msg: OpenSSH certificate regenerated upon serial number change.
+ - name: Generate cert with removed serial number
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_serial_42'
+ valid_from: always
+ valid_to: forever
+ serial_number: 0
+ register: rc_serial_number_removed
+ - name: check changed
+ assert:
+ that:
+ - rc_serial_number_removed is changed
+ msg: OpenSSH certificate regenerated upon serial number removal.
+ - name: Generate a new cert with serial number
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_serial_ignore'
+ valid_from: always
+ valid_to: forever
+ serial_number: 42
+ - name: Generate cert again, omitting the parameter serial_number (idempotent)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_serial_ignore'
+ valid_from: always
+ valid_to: forever
+ register: rc_serial_number_ignored
+ - name: check idempotent
+ assert:
+ that:
+ - rc_serial_number_ignored is not changed
+ msg: OpenSSH certificate generation with omitted serial number is idempotent.
+ - name: Remove certificate (check mode)
+ openssh_cert:
+ state: absent
+ path: '{{ output_dir }}/id_cert'
+ #type: user
+ #signing_key: '{{ output_dir }}/id_key'
+ #public_key: '{{ output_dir }}/id_key.pub'
+ #valid_from: "2001-01-21"
+ #valid_to: "2019-01-21"
+ check_mode: yes
+ - name: Remove certificate
+ openssh_cert:
+ state: absent
+ path: '{{ output_dir }}/id_cert'
+ #type: user
+ #signing_key: '{{ output_dir }}/id_key'
+ #public_key: '{{ output_dir }}/id_key.pub'
+ #valid_from: "2001-01-21"
+ #valid_to: "2019-01-21"
+ - name: Remove certificate (idempotent)
+ openssh_cert:
+ state: absent
+ path: '{{ output_dir }}/id_cert'
+ #type: user
+ #signing_key: '{{ output_dir }}/id_key'
+ #public_key: '{{ output_dir }}/id_key.pub'
+ #valid_from: "2001-01-21"
+ #valid_to: "2019-01-21"
+ - name: Remove certificate (idempotent, check mode)
+ openssh_cert:
+ state: absent
+ path: '{{ output_dir }}/id_cert'
+ #type: user
+ #signing_key: '{{ output_dir }}/id_key'
+ #public_key: '{{ output_dir }}/id_key.pub'
+ #valid_from: "2001-01-21"
+ #valid_to: "2019-01-21"
+ check_mode: yes
+ - name: Remove keypair
+ openssh_keypair:
+ path: '{{ output_dir }}/id_key'
+ state: absent
+
+- name: openssh_cert integration tests that require ssh-agent
+ when: openssh_version is version("7.6",">=")
+ environment:
+ SSH_AUTH_SOCK: "{{ openssh_agent_sock }}"
+ block:
+ - name: Generate keypair for agent tests
+ openssh_keypair:
+ path: '{{ output_dir }}/id_key'
+ type: rsa
+ size: 2048
+ - name: Generate always valid cert using agent without key in agent (should fail)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_with_agent'
+ use_agent: yes
+ valid_from: always
+ valid_to: forever
+ register: rc_no_key_in_agent
+ ignore_errors: yes
+ - name: Make sure cert creation with agent fails if key not in agent
+ assert:
+ that:
+ - rc_no_key_in_agent is failed
+ - "'agent contains no identities' in rc_no_key_in_agent.msg or 'not found in agent' in rc_no_key_in_agent.msg"
+ - name: Add key to agent
+ command: 'ssh-add {{ output_dir }}/id_key'
+ - name: Generate always valid cert with agent (check mode)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_with_agent'
+ use_agent: yes
+ valid_from: always
+ valid_to: forever
+ check_mode: yes
+ - name: Generate always valid cert with agent
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_with_agent'
+ use_agent: yes
+ valid_from: always
+ valid_to: forever
+ - name: Generate always valid cert with agent (idempotent)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_with_agent'
+ use_agent: yes
+ valid_from: always
+ valid_to: forever
+ register: rc_cert_with_agent_idempotent
+ - name: Check agent idempotency
+ assert:
+ that:
+ - rc_cert_with_agent_idempotent is not changed
+ msg: OpenSSH certificate generation without serial number is idempotent.
+ - name: Generate always valid cert with agent (idempotent, check mode)
+ openssh_cert:
+ type: user
+ signing_key: '{{ output_dir }}/id_key'
+ public_key: '{{ output_dir }}/id_key.pub'
+ path: '{{ output_dir }}/id_cert_with_agent'
+ use_agent: yes
+ valid_from: always
+ valid_to: forever
+ check_mode: yes
+ - name: Remove keypair for agent tests
+ openssh_keypair:
+ path: '{{ output_dir }}/id_key'
+ state: absent
+ - name: Remove certificate
+ openssh_cert:
+ state: absent
+ path: '{{ output_dir }}/id_cert_with_agent'
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/meta/main.yml
new file mode 100644
index 00000000..dc973f4e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_ssh_keygen
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/tasks/main.yml
new file mode 100644
index 00000000..993c8ad4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/tasks/main.yml
@@ -0,0 +1,407 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Generate privatekey1 - standard (check mode)
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey1'
+ size: 2048
+ register: privatekey1_result_check
+ check_mode: true
+
+- name: Generate privatekey1 - standard
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey1'
+ size: 2048
+ register: privatekey1_result
+
+- name: Generate privatekey1 - standard (check mode idempotent)
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey1'
+ size: 2048
+ register: privatekey1_idem_result_check
+ check_mode: true
+
+- name: Generate privatekey1 - standard (idempotent)
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey1'
+ size: 2048
+ register: privatekey1_idem_result
+
+- name: Generate privatekey2 - default size
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey2'
+
+- name: Generate privatekey3 - type dsa
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey3'
+ type: dsa
+
+- name: Generate privatekey4 - standard
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey4'
+ size: 2048
+
+- name: Delete privatekey4 - standard
+ openssh_keypair:
+ state: absent
+ path: '{{ output_dir }}/privatekey4'
+
+- name: Generate privatekey5 - standard
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey5'
+ size: 2048
+ register: publickey_gen
+
+- name: Generate privatekey6
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey6'
+ type: rsa
+ size: 2048
+
+- name: Regenerate privatekey6 via force
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey6'
+ type: rsa
+ size: 2048
+ force: yes
+ register: output_regenerated_via_force
+
+- name: Create broken key
+ copy:
+ dest: '{{ item }}'
+ content: ''
+ mode: '0700'
+ loop:
+ - '{{ output_dir }}/privatekeybroken'
+ - '{{ output_dir }}/privatekeybroken.pub'
+
+- name: Regenerate broken key - should fail
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekeybroken'
+ type: rsa
+ size: 2048
+ register: output_broken
+ ignore_errors: yes
+
+- name: Regenerate broken key with force
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekeybroken'
+ type: rsa
+ force: yes
+ size: 2048
+ register: output_broken_force
+
+- name: Generate read-only private key
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekeyreadonly'
+ type: rsa
+ mode: '0200'
+ size: 2048
+
+- name: Regenerate read-only private key via force
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekeyreadonly'
+ type: rsa
+ force: yes
+ size: 2048
+ register: output_read_only
+
+- name: Generate privatekey7 - standard with comment
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey7'
+ comment: 'test@privatekey7'
+ size: 2048
+ register: privatekey7_result
+
+- name: Modify privatekey7 comment
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey7'
+ comment: 'test_modified@privatekey7'
+ size: 2048
+ register: privatekey7_modified_result
+
+- name: Generate password protected key
+ command: 'ssh-keygen -f {{ output_dir }}/privatekey8 -N password'
+
+- name: Try to modify the password protected key - should fail
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey8'
+ size: 2048
+ register: privatekey8_result
+ ignore_errors: yes
+
+- name: Try to modify the password protected key with force=yes
+ openssh_keypair:
+ path: '{{ output_dir }}/privatekey8'
+ force: yes
+ size: 2048
+ register: privatekey8_result_force
+
+- import_tasks: ../tests/validate.yml
+
+
+# Test regenerate option
+
+- name: Regenerate - setup simple keys
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}'
+ type: rsa
+ size: 1024
+ loop: "{{ regenerate_values }}"
+- name: Regenerate - setup password protected keys
+ command: 'ssh-keygen -f {{ output_dir }}/regenerate-b-{{ item }} -N password'
+ loop: "{{ regenerate_values }}"
+- name: Regenerate - setup broken keys
+ copy:
+ dest: '{{ output_dir }}/regenerate-c-{{ item.0 }}{{ item.1 }}'
+ content: 'broken key'
+ mode: '0700'
+ with_nested:
+ - "{{ regenerate_values }}"
+ - [ '', '.pub' ]
+
+- name: Regenerate - modify broken keys (check mode)
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-c-{{ item }}'
+ type: rsa
+ size: 1024
+ regenerate: '{{ item }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
+ - result.results[1] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: Regenerate - modify broken keys
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-c-{{ item }}'
+ type: rsa
+ size: 1024
+ regenerate: '{{ item }}'
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
+ - result.results[1] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: Regenerate - modify password protected keys (check mode)
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-b-{{ item }}'
+ type: rsa
+ size: 1024
+ regenerate: '{{ item }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
+ - result.results[1] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: Regenerate - modify password protected keys
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-b-{{ item }}'
+ type: rsa
+ size: 1024
+ regenerate: '{{ item }}'
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
+ - result.results[1] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: Regenerate - not modify regular keys (check mode)
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}'
+ type: rsa
+ size: 1024
+ regenerate: '{{ item }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ register: result
+- assert:
+ that:
+ - result.results[0] is not changed
+ - result.results[1] is not changed
+ - result.results[2] is not changed
+ - result.results[3] is not changed
+ - result.results[4] is changed
+
+- name: Regenerate - not modify regular keys
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}'
+ type: rsa
+ size: 1024
+ regenerate: '{{ item }}'
+ loop: "{{ regenerate_values }}"
+ register: result
+- assert:
+ that:
+ - result.results[0] is not changed
+ - result.results[1] is not changed
+ - result.results[2] is not changed
+ - result.results[3] is not changed
+ - result.results[4] is changed
+
+- name: Regenerate - adjust key size (check mode)
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}'
+ type: rsa
+ size: 1048
+ regenerate: '{{ item }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is success and result.results[0] is not changed
+ - result.results[1] is failed
+ - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: Regenerate - adjust key size
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}'
+ type: rsa
+ size: 1048
+ regenerate: '{{ item }}'
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is success and result.results[0] is not changed
+ - result.results[1] is failed
+ - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: Regenerate - redistribute keys
+ copy:
+ src: '{{ output_dir }}/regenerate-a-always{{ item.1 }}'
+ dest: '{{ output_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
+ remote_src: true
+ with_nested:
+ - "{{ regenerate_values }}"
+ - [ '', '.pub' ]
+ when: "item.0 != 'always'"
+
+- name: Regenerate - adjust key type (check mode)
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}'
+ type: dsa
+ size: 1024
+ regenerate: '{{ item }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is success and result.results[0] is not changed
+ - result.results[1] is failed
+ - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: Regenerate - adjust key type
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}'
+ type: dsa
+ size: 1024
+ regenerate: '{{ item }}'
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is success and result.results[0] is not changed
+ - result.results[1] is failed
+ - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: Regenerate - redistribute keys
+ copy:
+ src: '{{ output_dir }}/regenerate-a-always{{ item.1 }}'
+ dest: '{{ output_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
+ remote_src: true
+ with_nested:
+ - "{{ regenerate_values }}"
+ - [ '', '.pub' ]
+ when: "item.0 != 'always'"
+
+- name: Regenerate - adjust comment (check mode)
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}'
+ type: dsa
+ size: 1024
+ comment: test comment
+ regenerate: '{{ item }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result is changed
+
+- name: Regenerate - adjust comment
+ openssh_keypair:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}'
+ type: dsa
+ size: 1024
+ comment: test comment
+ regenerate: '{{ item }}'
+ loop: "{{ regenerate_values }}"
+ register: result
+- assert:
+ that:
+ - result is changed
+ # for all values but 'always', the key should have not been regenerated.
+ # verify this by comparing fingerprints:
+ - result.results[0].fingerprint == result.results[1].fingerprint
+ - result.results[0].fingerprint == result.results[2].fingerprint
+ - result.results[0].fingerprint == result.results[3].fingerprint
+ - result.results[0].fingerprint != result.results[4].fingerprint
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/tests/validate.yml
new file mode 100644
index 00000000..e9d76a7a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/tests/validate.yml
@@ -0,0 +1,140 @@
+---
+- name: Log privatekey1 return values
+ debug:
+ var: privatekey1_result
+
+- name: Validate general behavior
+ assert:
+ that:
+ - privatekey1_result_check is changed
+ - privatekey1_result is changed
+ - privatekey1_idem_result_check is not changed
+ - privatekey1_idem_result is not changed
+
+- name: Validate privatekey1 return fingerprint
+ assert:
+ that:
+ - privatekey1_result["fingerprint"] is string
+ - privatekey1_result["fingerprint"].startswith("SHA256:")
+ # only distro old enough that it still gives md5 with no prefix
+ when: ansible_distribution != 'CentOS' and ansible_distribution_major_version != '6'
+
+- name: Validate privatekey1 return public_key
+ assert:
+ that:
+ - privatekey1_result["public_key"] is string
+ - privatekey1_result["public_key"].startswith("ssh-rsa ")
+
+- name: Validate privatekey1 return size value
+ assert:
+ that:
+ - privatekey1_result["size"]|type_debug == 'int'
+ - privatekey1_result["size"] == 2048
+
+- name: Validate privatekey1 return key type
+ assert:
+ that:
+ - privatekey1_result["type"] is string
+ - privatekey1_result["type"] == "rsa"
+
+- name: Validate privatekey1 (test - RSA key with size 2048 bits)
+ shell: "ssh-keygen -lf {{ output_dir }}/privatekey1 | grep -o -E '^[0-9]+'"
+ register: privatekey1
+
+- name: Validate privatekey1 (assert - RSA key with size 2048 bits)
+ assert:
+ that:
+ - privatekey1.stdout == '2048'
+
+- name: Validate privatekey1 idempotence
+ assert:
+ that:
+ - privatekey1_idem_result is not changed
+
+
+- name: Validate privatekey2 (test - RSA key with default size 4096 bits)
+ shell: "ssh-keygen -lf {{ output_dir }}/privatekey2 | grep -o -E '^[0-9]+'"
+ register: privatekey2
+
+- name: Validate privatekey2 (assert - RSA key with size 4096 bits)
+ assert:
+ that:
+ - privatekey2.stdout == '4096'
+
+
+- name: Validate privatekey3 (test - DSA key with size 1024 bits)
+ shell: "ssh-keygen -lf {{ output_dir }}/privatekey3 | grep -o -E '^[0-9]+'"
+ register: privatekey3
+
+- name: Validate privatekey3 (assert - DSA key with size 4096 bits)
+ assert:
+ that:
+ - privatekey3.stdout == '1024'
+
+
+- name: Validate privatekey4 (test - Ensure key has been removed)
+ stat:
+ path: '{{ output_dir }}/privatekey4'
+ register: privatekey4
+
+- name: Validate privatekey4 (assert - Ensure key has been removed)
+ assert:
+ that:
+ - privatekey4.stat.exists == False
+
+
+- name: Validate privatekey5 (assert - Public key module output equal to the public key on host)
+ assert:
+ that:
+ - "publickey_gen.public_key == lookup('file', output_dir ~ '/privatekey5.pub').strip('\n')"
+
+- name: Verify that privatekey6 will be regenerated via force
+ assert:
+ that:
+ - output_regenerated_via_force is changed
+
+
+- name: Verify that broken key will cause failure
+ assert:
+ that:
+ - output_broken is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken.' in output_broken.msg"
+
+
+- name: Verify that broken key will be regenerated if force=yes is specified
+ assert:
+ that:
+ - output_broken_force is changed
+
+
+- name: Verify that read-only key will be regenerated
+ assert:
+ that:
+ - output_read_only is changed
+
+
+- name: Validate privatekey7 (assert - Public key remains the same after comment change)
+ assert:
+ that:
+ - privatekey7_result.public_key == privatekey7_modified_result.public_key
+
+- name: Validate privatekey7 comment on creation
+ assert:
+ that:
+ - privatekey7_result.comment == 'test@privatekey7'
+
+- name: Validate privatekey7 comment update
+ assert:
+ that:
+ - privatekey7_modified_result.comment == 'test_modified@privatekey7'
+
+- name: Check that password protected key made module fail
+ assert:
+ that:
+ - privatekey8_result is failed
+ - "'Unable to read the key. The key is protected with a passphrase or broken.' in privatekey8_result.msg"
+
+- name: Check that password protected key was regenerated with force=yes
+ assert:
+ that:
+ - privatekey8_result_force is changed
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/vars/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/vars/main.yml
new file mode 100644
index 00000000..81eb611f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssh_keypair/vars/main.yml
@@ -0,0 +1,7 @@
+---
+regenerate_values:
+ - never
+ - fail
+ - partial_idempotence
+ - full_idempotence
+ - always
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tasks/impl.yml
new file mode 100644
index 00000000..20227ce9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tasks/impl.yml
@@ -0,0 +1,997 @@
+---
+- name: "({{ select_crypto_backend }}) Generate privatekey"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey.pem'
+ size: '{{ default_rsa_key_size }}'
+
+- name: "({{ select_crypto_backend }}) Generate CSR (check mode)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ check_mode: yes
+ register: generate_csr_check
+
+- name: "({{ select_crypto_backend }}) Generate CSR"
+ openssl_csr:
+ path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: generate_csr
+
+- name: "({{ select_crypto_backend }}) Generate CSR (idempotent)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: generate_csr_idempotent
+
+- name: "({{ select_crypto_backend }}) Generate CSR (idempotent, check mode)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ check_mode: yes
+ register: generate_csr_idempotent_check
+
+- name: "({{ select_crypto_backend }}) Generate CSR without SAN (check mode)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr-nosan.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ useCommonNameForSAN: no
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: generate_csr_nosan_check
+
+- name: "({{ select_crypto_backend }}) Generate CSR without SAN"
+ openssl_csr:
+ path: '{{ output_dir }}/csr-nosan.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ useCommonNameForSAN: no
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: generate_csr_nosan
+
+- name: "({{ select_crypto_backend }}) Generate CSR without SAN (idempotent)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr-nosan.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ useCommonNameForSAN: no
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: generate_csr_nosan_check_idempotent
+
+- name: "({{ select_crypto_backend }}) Generate CSR without SAN (idempotent, check mode)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr-nosan.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ useCommonNameForSAN: no
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: generate_csr_nosan_check_idempotent_check
+
+# keyUsage longname and shortname should be able to be used
+# interchangeably. Hence the long name is specified here
+# but the short name is used to test idempotency for ipsecuser
+# and vice-versa for biometricInfo
+- name: "({{ select_crypto_backend }}) Generate CSR with KU and XKU"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ku_xku.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ CN: www.ansible.com
+ keyUsage:
+ - digitalSignature
+ - keyAgreement
+ extendedKeyUsage:
+ - qcStatements
+ - DVCS
+ - IPSec User
+ - biometricInfo
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Generate CSR with KU and XKU (test idempotency)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ku_xku.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: 'www.ansible.com'
+ keyUsage:
+ - Key Agreement
+ - digitalSignature
+ extendedKeyUsage:
+ - ipsecUser
+ - qcStatements
+ - DVCS
+ - Biometric Info
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: csr_ku_xku
+
+- name: "({{ select_crypto_backend }}) Generate CSR with KU and XKU (test XKU change)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ku_xku.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: 'www.ansible.com'
+ keyUsage:
+ - digitalSignature
+ - keyAgreement
+ extendedKeyUsage:
+ - ipsecUser
+ - qcStatements
+ - Biometric Info
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: csr_ku_xku_change
+
+- name: "({{ select_crypto_backend }}) Generate CSR with KU and XKU (test KU change)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ku_xku.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: 'www.ansible.com'
+ keyUsage:
+ - digitalSignature
+ extendedKeyUsage:
+ - ipsecUser
+ - qcStatements
+ - Biometric Info
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: csr_ku_xku_change_2
+
+- name: "({{ select_crypto_backend }}) Generate CSR with old API"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_oldapi.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Generate CSR with invalid SAN (1/2)"
+ openssl_csr:
+ path: '{{ output_dir }}/csrinvsan.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject_alt_name: invalid-san.example.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: generate_csr_invalid_san
+ ignore_errors: yes
+
+- name: "({{ select_crypto_backend }}) Generate CSR with invalid SAN (2/2)"
+ openssl_csr:
+ path: '{{ output_dir }}/csrinvsan2.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject_alt_name: "DNS:system:kube-controller-manager"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: generate_csr_invalid_san_2
+ ignore_errors: yes
+
+- name: "({{ select_crypto_backend }}) Generate CSR with OCSP Must Staple"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ocsp.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject_alt_name: "DNS:www.ansible.com"
+ ocsp_must_staple: true
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Generate CSR with OCSP Must Staple (test idempotency)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ocsp.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject_alt_name: "DNS:www.ansible.com"
+ ocsp_must_staple: true
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: csr_ocsp_idempotency
+
+- name: "({{ select_crypto_backend }}) Generate ECC privatekey"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey2.pem'
+ type: ECC
+ curve: secp384r1
+
+- name: "({{ select_crypto_backend }}) Generate CSR with ECC privatekey"
+ openssl_csr:
+ path: '{{ output_dir }}/csr2.csr'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Generate CSR with text common name"
+ openssl_csr:
+ path: '{{ output_dir }}/csr3.csr'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ subject:
+ commonName: This is for Ansible
+ useCommonNameForSAN: no
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Generate CSR with country name"
+ openssl_csr:
+ path: '{{ output_dir }}/csr4.csr'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ country_name: de
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: country_idempotent_1
+
+- name: "({{ select_crypto_backend }}) Generate CSR with country name (idempotent)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr4.csr'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ country_name: de
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: country_idempotent_2
+
+- name: "({{ select_crypto_backend }}) Generate CSR with country name (idempotent 2)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr4.csr'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ subject:
+ C: de
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: country_idempotent_3
+
+- name: "({{ select_crypto_backend }}) Generate CSR with country name (bad country name)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr4.csr'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ subject:
+ C: dex
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: country_fail_4
+ ignore_errors: yes
+
+- name: "({{ select_crypto_backend }}) Generate privatekey with password"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: auto
+ select_crypto_backend: cryptography
+ size: '{{ default_rsa_key_size }}'
+
+- name: "({{ select_crypto_backend }}) Generate CSR with privatekey passphrase"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_pw.csr'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ privatekey_passphrase: hunter2
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: passphrase_1
+
+- name: "({{ select_crypto_backend }}) Generate CSR (failed passphrase 1)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_pw1.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ privatekey_passphrase: hunter2
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_1
+
+- name: "({{ select_crypto_backend }}) Generate CSR (failed passphrase 2)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_pw2.csr'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ privatekey_passphrase: wrong_password
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_2
+
+- name: "({{ select_crypto_backend }}) Generate CSR (failed passphrase 3)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_pw3.csr'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_3
+
+- name: "({{ select_crypto_backend }}) Create broken CSR"
+ copy:
+ dest: "{{ output_dir }}/csrbroken.csr"
+ content: "broken"
+- name: "({{ select_crypto_backend }}) Regenerate broken CSR"
+ openssl_csr:
+ path: '{{ output_dir }}/csrbroken.csr'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ subject:
+ commonName: This is for Ansible
+ useCommonNameForSAN: no
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: output_broken
+
+- name: "({{ select_crypto_backend }}) Generate CSR"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_backup.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: csr_backup_1
+- name: "({{ select_crypto_backend }}) Generate CSR (idempotent)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_backup.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: csr_backup_2
+- name: "({{ select_crypto_backend }}) Generate CSR (change)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_backup.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: ansible.com
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: csr_backup_3
+- name: "({{ select_crypto_backend }}) Generate CSR (remove)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_backup.csr'
+ state: absent
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: csr_backup_4
+- name: "({{ select_crypto_backend }}) Generate CSR (remove, idempotent)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_backup.csr'
+ state: absent
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: csr_backup_5
+
+- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ski.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ subject_key_identifier: "00:11:22:33"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: subject_key_identifier_1
+
+- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier (idempotency)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ski.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ subject_key_identifier: "00:11:22:33"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: subject_key_identifier_2
+
+- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier (change)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ski.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ subject_key_identifier: "44:55:66:77:88"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: subject_key_identifier_3
+
+- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier (auto-create)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ski.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ create_subject_key_identifier: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: subject_key_identifier_4
+
+- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier (auto-create idempotency)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ski.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ create_subject_key_identifier: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: subject_key_identifier_5
+
+- name: "({{ select_crypto_backend }}) Generate CSR with subject key identifier (remove)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ski.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: subject_key_identifier_6
+
+- name: "({{ select_crypto_backend }}) Generate CSR with authority key identifier"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_aki.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ authority_key_identifier: "00:11:22:33"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: authority_key_identifier_1
+
+- name: "({{ select_crypto_backend }}) Generate CSR with authority key identifier (idempotency)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_aki.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ authority_key_identifier: "00:11:22:33"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: authority_key_identifier_2
+
+- name: "({{ select_crypto_backend }}) Generate CSR with authority key identifier (change)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_aki.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ authority_key_identifier: "44:55:66:77:88"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: authority_key_identifier_3
+
+- name: "({{ select_crypto_backend }}) Generate CSR with authority key identifier (remove)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_aki.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: authority_key_identifier_4
+
+- name: "({{ select_crypto_backend }}) Generate CSR with authority cert issuer / serial number"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_acisn.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+ authority_cert_serial_number: 12345
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: authority_cert_issuer_sn_1
+
+- name: "({{ select_crypto_backend }}) Generate CSR with authority cert issuer / serial number (idempotency)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_acisn.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+ authority_cert_serial_number: 12345
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: authority_cert_issuer_sn_2
+
+- name: "({{ select_crypto_backend }}) Generate CSR with authority cert issuer / serial number (change issuer)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_acisn.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ authority_cert_issuer:
+ - "IP:1.2.3.4"
+ - "DNS:ca.example.org"
+ authority_cert_serial_number: 12345
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: authority_cert_issuer_sn_3
+
+- name: "({{ select_crypto_backend }}) Generate CSR with authority cert issuer / serial number (change serial number)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_acisn.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ authority_cert_issuer:
+ - "IP:1.2.3.4"
+ - "DNS:ca.example.org"
+ authority_cert_serial_number: 54321
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: authority_cert_issuer_sn_4
+
+- name: "({{ select_crypto_backend }}) Generate CSR with authority cert issuer / serial number (remove)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_acisn.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ when: select_crypto_backend != 'pyopenssl'
+ register: authority_cert_issuer_sn_5
+
+- name: "({{ select_crypto_backend }}) Generate CSR with everything"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_everything.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.example.com
+ C: de
+ L: Somewhere
+ ST: Zurich
+ streetAddress: Welcome Street
+ O: Ansible
+ organizationalUnitName: Crypto Department
+ serialNumber: "1234"
+ SN: Last Name
+ GN: First Name
+ title: Chief
+ pseudonym: test
+ UID: asdf
+ emailAddress: test@example.com
+ postalAddress: 1234 Somewhere
+ postalCode: "1234"
+ useCommonNameForSAN: no
+ key_usage:
+ - digitalSignature
+ - keyAgreement
+ - Non Repudiation
+ - Key Encipherment
+ - dataEncipherment
+ - Certificate Sign
+ - cRLSign
+ - Encipher Only
+ - decipherOnly
+ key_usage_critical: yes
+ extended_key_usage: '{{ value_for_extended_key_usage if select_crypto_backend != "pyopenssl" else value_for_extended_key_usage_pyopenssl }}'
+ subject_alt_name: '{{ value_for_san if select_crypto_backend != "pyopenssl" else value_for_san_pyopenssl }}'
+ basic_constraints:
+ - "CA:TRUE"
+ - "pathlen:23"
+ basic_constraints_critical: yes
+ name_constraints_permitted: '{{ value_for_name_constraints_permitted if select_crypto_backend != "pyopenssl" else value_for_name_constraints_permitted_pyopenssl }}'
+ name_constraints_excluded:
+ - "DNS:.example.com"
+ - "DNS:.org"
+ name_constraints_critical: yes
+ ocsp_must_staple: yes
+ subject_key_identifier: '{{ "00:11:22:33" if select_crypto_backend != "pyopenssl" else omit }}'
+ authority_key_identifier: '{{ "44:55:66:77" if select_crypto_backend != "pyopenssl" else omit }}'
+ authority_cert_issuer: '{{ value_for_authority_cert_issuer if select_crypto_backend != "pyopenssl" else omit }}'
+ authority_cert_serial_number: '{{ 12345 if select_crypto_backend != "pyopenssl" else omit }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ vars:
+ value_for_extended_key_usage_pyopenssl:
+ - serverAuth # the same as "TLS Web Server Authentication"
+ - TLS Web Server Authentication
+ - TLS Web Client Authentication
+ - Code Signing
+ - E-mail Protection
+ - timeStamping
+ - OCSPSigning
+ - Any Extended Key Usage
+ - qcStatements
+ - DVCS
+ - IPSec User
+ - biometricInfo
+ value_for_extended_key_usage:
+ - serverAuth # the same as "TLS Web Server Authentication"
+ - TLS Web Server Authentication
+ - TLS Web Client Authentication
+ - Code Signing
+ - E-mail Protection
+ - timeStamping
+ - OCSPSigning
+ - Any Extended Key Usage
+ - qcStatements
+ - DVCS
+ - IPSec User
+ - biometricInfo
+ - 1.2.3.4.5.6
+ value_for_authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+ value_for_san_pyopenssl:
+ - "DNS:www.ansible.com"
+ - "IP:1.2.3.4"
+ - "IP:::1"
+ - "email:test@example.org"
+ - "URI:https://example.org/test/index.html"
+ - "RID:1.2.3.4"
+ value_for_san:
+ - "DNS:www.ansible.com"
+ - "IP:1.2.3.4"
+ - "IP:::1"
+ - "email:test@example.org"
+ - "URI:https://example.org/test/index.html"
+ - "RID:1.2.3.4"
+ - "otherName:1.2.3.4;0c:07:63:65:72:74:72:65:71"
+ - "otherName:1.3.6.1.4.1.311.20.2.3;UTF8:bob@localhost"
+ - "dirName:O = Example Net, CN = example.net"
+ - "dirName:/O=Example Com/CN=example.com"
+ value_for_name_constraints_permitted:
+ - "DNS:www.example.com"
+ - "IP:1.2.3.0/24"
+ - "IP:::1:0:0/112"
+ value_for_name_constraints_permitted_pyopenssl:
+ - "DNS:www.example.com"
+ - "IP:1.2.3.0/255.255.255.0"
+ register: everything_1
+
+- name: "({{ select_crypto_backend }}) Generate CSR with everything (idempotent, check mode)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_everything.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.example.com
+ C: de
+ L: Somewhere
+ ST: Zurich
+ streetAddress: Welcome Street
+ O: Ansible
+ organizationalUnitName: Crypto Department
+ serialNumber: "1234"
+ SN: Last Name
+ GN: First Name
+ title: Chief
+ pseudonym: test
+ UID: asdf
+ emailAddress: test@example.com
+ postalAddress: 1234 Somewhere
+ postalCode: "1234"
+ useCommonNameForSAN: no
+ key_usage:
+ - digitalSignature
+ - keyAgreement
+ - Non Repudiation
+ - Key Encipherment
+ - dataEncipherment
+ - Certificate Sign
+ - cRLSign
+ - Encipher Only
+ - decipherOnly
+ key_usage_critical: yes
+ extended_key_usage: '{{ value_for_extended_key_usage if select_crypto_backend != "pyopenssl" else value_for_extended_key_usage_pyopenssl }}'
+ subject_alt_name: '{{ value_for_san if select_crypto_backend != "pyopenssl" else value_for_san_pyopenssl }}'
+ basic_constraints:
+ - "CA:TRUE"
+ - "pathlen:23"
+ basic_constraints_critical: yes
+ name_constraints_permitted: '{{ value_for_name_constraints_permitted if select_crypto_backend != "pyopenssl" else value_for_name_constraints_permitted_pyopenssl }}'
+ name_constraints_excluded:
+ - "DNS:.org"
+ - "DNS:.example.com"
+ name_constraints_critical: yes
+ ocsp_must_staple: yes
+ subject_key_identifier: '{{ "00:11:22:33" if select_crypto_backend != "pyopenssl" else omit }}'
+ authority_key_identifier: '{{ "44:55:66:77" if select_crypto_backend != "pyopenssl" else omit }}'
+ authority_cert_issuer: '{{ value_for_authority_cert_issuer if select_crypto_backend != "pyopenssl" else omit }}'
+ authority_cert_serial_number: '{{ 12345 if select_crypto_backend != "pyopenssl" else omit }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ vars:
+ value_for_extended_key_usage_pyopenssl:
+ - serverAuth # the same as "TLS Web Server Authentication"
+ - TLS Web Server Authentication
+ - TLS Web Client Authentication
+ - Code Signing
+ - E-mail Protection
+ - timeStamping
+ - OCSPSigning
+ - Any Extended Key Usage
+ - qcStatements
+ - DVCS
+ - IPSec User
+ - biometricInfo
+ value_for_extended_key_usage:
+ - serverAuth # the same as "TLS Web Server Authentication"
+ - TLS Web Server Authentication
+ - TLS Web Client Authentication
+ - Code Signing
+ - E-mail Protection
+ - timeStamping
+ - OCSPSigning
+ - Any Extended Key Usage
+ - qcStatements
+ - DVCS
+ - IPSec User
+ - biometricInfo
+ - 1.2.3.4.5.6
+ value_for_authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+ value_for_san_pyopenssl:
+ - "DNS:www.ansible.com"
+ - "IP:1.2.3.4"
+ - "IP:::1"
+ - "email:test@example.org"
+ - "URI:https://example.org/test/index.html"
+ - "RID:1.2.3.4"
+ value_for_san:
+ - "DNS:www.ansible.com"
+ - "IP:1.2.3.4"
+ - "IP:::1"
+ - "email:test@example.org"
+ - "URI:https://example.org/test/index.html"
+ - "RID:1.2.3.4"
+ - "otherName:1.2.3.4;0c:07:63:65:72:74:72:65:71"
+ - "otherName:1.3.6.1.4.1.311.20.2.3;UTF8:bob@localhost"
+ - "dirName:O=Example Net,CN=example.net"
+ - "dirName:/O = Example Com/CN = example.com"
+ value_for_name_constraints_permitted:
+ - "DNS:www.example.com"
+ - "IP:1.2.3.0/255.255.255.0"
+ - "IP:0::0:1:0:0/112"
+ value_for_name_constraints_permitted_pyopenssl:
+ - "DNS:www.example.com"
+ - "IP:1.2.3.0/255.255.255.0"
+ check_mode: yes
+ register: everything_2
+
+- name: "({{ select_crypto_backend }}) Generate CSR with everything (idempotent)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_everything.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.example.com
+ C: de
+ L: Somewhere
+ ST: Zurich
+ streetAddress: Welcome Street
+ O: Ansible
+ organizationalUnitName: Crypto Department
+ serialNumber: "1234"
+ SN: Last Name
+ GN: First Name
+ title: Chief
+ pseudonym: test
+ UID: asdf
+ emailAddress: test@example.com
+ postalAddress: 1234 Somewhere
+ postalCode: "1234"
+ useCommonNameForSAN: no
+ key_usage:
+ - digitalSignature
+ - keyAgreement
+ - Non Repudiation
+ - Key Encipherment
+ - dataEncipherment
+ - Certificate Sign
+ - cRLSign
+ - Encipher Only
+ - decipherOnly
+ key_usage_critical: yes
+ extended_key_usage: '{{ value_for_extended_key_usage if select_crypto_backend != "pyopenssl" else value_for_extended_key_usage_pyopenssl }}'
+ subject_alt_name: '{{ value_for_san if select_crypto_backend != "pyopenssl" else value_for_san_pyopenssl }}'
+ basic_constraints:
+ - "CA:TRUE"
+ - "pathlen:23"
+ basic_constraints_critical: yes
+ name_constraints_permitted: '{{ value_for_name_constraints_permitted if select_crypto_backend != "pyopenssl" else value_for_name_constraints_permitted_pyopenssl }}'
+ name_constraints_excluded:
+ - "DNS:.org"
+ - "DNS:.example.com"
+ name_constraints_critical: yes
+ ocsp_must_staple: yes
+ subject_key_identifier: '{{ "00:11:22:33" if select_crypto_backend != "pyopenssl" else omit }}'
+ authority_key_identifier: '{{ "44:55:66:77" if select_crypto_backend != "pyopenssl" else omit }}'
+ authority_cert_issuer: '{{ value_for_authority_cert_issuer if select_crypto_backend != "pyopenssl" else omit }}'
+ authority_cert_serial_number: '{{ 12345 if select_crypto_backend != "pyopenssl" else omit }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ vars:
+ value_for_extended_key_usage_pyopenssl:
+ - serverAuth # the same as "TLS Web Server Authentication"
+ - TLS Web Server Authentication
+ - TLS Web Client Authentication
+ - Code Signing
+ - E-mail Protection
+ - timeStamping
+ - OCSPSigning
+ - Any Extended Key Usage
+ - qcStatements
+ - DVCS
+ - IPSec User
+ - biometricInfo
+ value_for_extended_key_usage:
+ - serverAuth # the same as "TLS Web Server Authentication"
+ - TLS Web Server Authentication
+ - TLS Web Client Authentication
+ - Code Signing
+ - E-mail Protection
+ - timeStamping
+ - OCSPSigning
+ - Any Extended Key Usage
+ - qcStatements
+ - DVCS
+ - IPSec User
+ - biometricInfo
+ - 1.2.3.4.5.6
+ value_for_authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+ value_for_san_pyopenssl:
+ - "DNS:www.ansible.com"
+ - "IP:1.2.3.4"
+ - "IP:::1"
+ - "email:test@example.org"
+ - "URI:https://example.org/test/index.html"
+ - "RID:1.2.3.4"
+ value_for_san:
+ - "DNS:www.ansible.com"
+ - "IP:1.2.3.4"
+ - "IP:::1"
+ - "email:test@example.org"
+ - "URI:https://example.org/test/index.html"
+ - "RID:1.2.3.4"
+ - "otherName:1.2.3.4;0c:07:63:65:72:74:72:65:71"
+ - "otherName:1.3.6.1.4.1.311.20.2.3;UTF8:bob@localhost"
+ - "dirName:O =Example Net, CN= example.net"
+ - "dirName:/O =Example Com/CN= example.com"
+ value_for_name_constraints_permitted:
+ - "DNS:www.example.com"
+ - "IP:1.2.3.0/255.255.255.0"
+ - "IP:0::0:1:0:0/112"
+ value_for_name_constraints_permitted_pyopenssl:
+ - "DNS:www.example.com"
+ - "IP:1.2.3.0/255.255.255.0"
+ register: everything_3
+
+- name: "({{ select_crypto_backend }}) Get info from CSR with everything"
+ community.crypto.openssl_csr_info:
+ path: '{{ output_dir }}/csr_everything.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: everything_info
+
+- name: "({{ select_crypto_backend }}) Ed25519 and Ed448 tests (for cryptography >= 2.6)"
+ block:
+ - name: "({{ select_crypto_backend }}) Generate privatekeys"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_{{ item }}.pem'
+ type: '{{ item }}'
+ loop:
+ - Ed25519
+ - Ed448
+ register: generate_csr_ed25519_ed448_privatekey
+ ignore_errors: yes
+
+ - name: "({{ select_crypto_backend }}) Generate CSR if private key generation succeeded"
+ when: generate_csr_ed25519_ed448_privatekey is not failed
+ block:
+
+ - name: "({{ select_crypto_backend }}) Generate CSR"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_{{ item }}.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - Ed25519
+ - Ed448
+ register: generate_csr_ed25519_ed448
+ ignore_errors: yes
+
+ - name: "({{ select_crypto_backend }}) Generate CSR (idempotent)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_{{ item }}.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - Ed25519
+ - Ed448
+ register: generate_csr_ed25519_ed448_idempotent
+ ignore_errors: yes
+
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=')
+
+- name: "({{ select_crypto_backend }}) CRL distribution endpoints (for cryptography >= 1.6)"
+ block:
+ - name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_crl_d_e.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ crl_distribution_points:
+ - full_name:
+ - "URI:https://ca.example.com/revocations.crl"
+ crl_issuer:
+ - "URI:https://ca.example.com/"
+ reasons:
+ - key_compromise
+ - ca_compromise
+ - cessation_of_operation
+ - relative_name:
+ - CN=ca.example.com
+ reasons:
+ - certificate_hold
+ - {}
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: crl_distribution_endpoints_1
+
+ - name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints (idempotence)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_crl_d_e.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ crl_distribution_points:
+ - full_name:
+ - "URI:https://ca.example.com/revocations.crl"
+ crl_issuer:
+ - "URI:https://ca.example.com/"
+ reasons:
+ - key_compromise
+ - ca_compromise
+ - cessation_of_operation
+ - relative_name:
+ - CN=ca.example.com
+ reasons:
+ - certificate_hold
+ - {}
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: crl_distribution_endpoints_2
+
+ - name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints (change)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_crl_d_e.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ crl_distribution_points:
+ - full_name:
+ - "URI:https://ca.example.com/revocations.crl"
+ crl_issuer:
+ - "URI:https://ca.example.com/"
+ reasons:
+ - key_compromise
+ - ca_compromise
+ - cessation_of_operation
+ - relative_name:
+ - CN=ca.example.com
+ reasons:
+ - certificate_hold
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: crl_distribution_endpoints_3
+
+ - name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints (no endpoints)"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_crl_d_e.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: crl_distribution_endpoints_4
+
+ - name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints"
+ openssl_csr:
+ path: '{{ output_dir }}/csr_crl_d_e.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ crl_distribution_points:
+ - full_name:
+ - "URI:https://ca.example.com/revocations.crl"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: crl_distribution_endpoints_5
+
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.6', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tasks/main.yml
new file mode 100644
index 00000000..575bc79d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tasks/main.yml
@@ -0,0 +1,50 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Prepare private key for backend autodetection test
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_backend_selection.pem'
+ size: '{{ default_rsa_key_size }}'
+- name: Run module with backend autodetection
+ openssl_csr:
+ path: '{{ output_dir }}/csr_backend_selection.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_backend_selection.pem'
+ subject:
+ commonName: www.ansible.com
+
+- block:
+ - name: Running tests with pyOpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: pyopenssl
+
+ - import_tasks: ../tests/validate.yml
+ vars:
+ select_crypto_backend: pyopenssl
+
+ when: pyopenssl_version.stdout is version('0.15', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ - import_tasks: ../tests/validate.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ when: cryptography_version.stdout is version('1.3', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tests/validate.yml
new file mode 100644
index 00000000..8958a7ae
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr/tests/validate.yml
@@ -0,0 +1,346 @@
+---
+- name: "({{ select_crypto_backend }}) Validate CSR (test - privatekey modulus)"
+ shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ output_dir }}/privatekey.pem'
+ register: privatekey_modulus
+
+- name: "({{ select_crypto_backend }}) Validate CSR (test - Common Name)"
+ shell: "{{ openssl_binary }} req -noout -subject -in {{ output_dir }}/csr.csr -nameopt oneline,-space_eq"
+ register: csr_cn
+
+- name: "({{ select_crypto_backend }}) Validate CSR (test - csr modulus)"
+ shell: '{{ openssl_binary }} req -noout -modulus -in {{ output_dir }}/csr.csr'
+ register: csr_modulus
+
+- name: "({{ select_crypto_backend }}) Validate CSR (assert)"
+ assert:
+ that:
+ - csr_cn.stdout.split('=')[-1] == 'www.ansible.com'
+ - csr_modulus.stdout == privatekey_modulus.stdout
+
+- name: "({{ select_crypto_backend }}) Validate CSR (check mode, idempotency)"
+ assert:
+ that:
+ - generate_csr_check is changed
+ - generate_csr is changed
+ - generate_csr_idempotent is not changed
+ - generate_csr_idempotent_check is not changed
+
+- name: "({{ select_crypto_backend }}) Validate CSR (data retrieval)"
+ assert:
+ that:
+ - generate_csr_check.csr is none
+ - generate_csr.csr == lookup('file', output_dir ~ '/csr.csr', rstrip=False)
+ - generate_csr.csr == generate_csr_idempotent.csr
+ - generate_csr.csr == generate_csr_idempotent_check.csr
+
+- name: "({{ select_crypto_backend }}) Validate CSR without SAN (check mode, idempotency)"
+ assert:
+ that:
+ - generate_csr_nosan_check is changed
+ - generate_csr_nosan is changed
+ - generate_csr_nosan_check_idempotent is not changed
+ - generate_csr_nosan_check_idempotent_check is not changed
+
+- name: "({{ select_crypto_backend }}) Validate CSR_KU_XKU (assert idempotency, change)"
+ assert:
+ that:
+ - csr_ku_xku is not changed
+ - csr_ku_xku_change is changed
+ - csr_ku_xku_change_2 is changed
+
+- name: "({{ select_crypto_backend }}) Validate old_API CSR (test - Common Name)"
+ shell: "{{ openssl_binary }} req -noout -subject -in {{ output_dir }}/csr_oldapi.csr -nameopt oneline,-space_eq"
+ register: csr_oldapi_cn
+
+- name: "({{ select_crypto_backend }}) Validate old_API CSR (test - csr modulus)"
+ shell: '{{ openssl_binary }} req -noout -modulus -in {{ output_dir }}/csr_oldapi.csr'
+ register: csr_oldapi_modulus
+
+- name: "({{ select_crypto_backend }}) Validate old_API CSR (assert)"
+ assert:
+ that:
+ - csr_oldapi_cn.stdout.split('=')[-1] == 'www.ansible.com'
+ - csr_oldapi_modulus.stdout == privatekey_modulus.stdout
+
+- name: "({{ select_crypto_backend }}) Validate invalid SAN (1/2)"
+ assert:
+ that:
+ - generate_csr_invalid_san is failed
+ - "'Subject Alternative Name' in generate_csr_invalid_san.msg"
+
+- name: "({{ select_crypto_backend }}) Validate invalid SAN (2/2)"
+ # Note that pyOpenSSL simply accepts this name, and modern cryptography versions do so as well.
+ # The error has been observed with cryptography 1.7.2 and 1.9, but not with 2.3 and newer.
+ assert:
+ that:
+ - generate_csr_invalid_san_2 is failed
+ - "'The label system:kube-controller-manager is not a valid A-label' in generate_csr_invalid_san_2.msg"
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.0', '<')
+
+- name: "({{ select_crypto_backend }}) Validate OCSP Must Staple CSR (test - everything)"
+ shell: "{{ openssl_binary }} req -noout -in {{ output_dir }}/csr_ocsp.csr -text"
+ register: csr_ocsp
+
+- name: "({{ select_crypto_backend }}) Validate OCSP Must Staple CSR (assert)"
+ assert:
+ that:
+ - "(csr_ocsp.stdout is search('\\s+TLS Feature:\\s*\\n\\s+status_request\\s+')) or
+ (csr_ocsp.stdout is search('\\s+1.3.6.1.5.5.7.1.24:\\s*\\n\\s+0\\.\\.\\.\\.\\s+'))"
+
+- name: "({{ select_crypto_backend }}) Validate OCSP Must Staple CSR (assert idempotency)"
+ assert:
+ that:
+ - csr_ocsp_idempotency is not changed
+
+- name: "({{ select_crypto_backend }}) Validate ECC CSR (test - privatekey's public key)"
+ shell: '{{ openssl_binary }} ec -pubout -in {{ output_dir }}/privatekey2.pem'
+ register: privatekey_ecc_key
+
+- name: "({{ select_crypto_backend }}) Validate ECC CSR (test - Common Name)"
+ shell: "{{ openssl_binary }} req -noout -subject -in {{ output_dir }}/csr2.csr -nameopt oneline,-space_eq"
+ register: csr_ecc_cn
+
+- name: "({{ select_crypto_backend }}) Validate ECC CSR (test - CSR pubkey)"
+ shell: '{{ openssl_binary }} req -noout -pubkey -in {{ output_dir }}/csr2.csr'
+ register: csr_ecc_pubkey
+
+- name: "({{ select_crypto_backend }}) Validate ECC CSR (assert)"
+ assert:
+ that:
+ - csr_ecc_cn.stdout.split('=')[-1] == 'www.ansible.com'
+ - csr_ecc_pubkey.stdout == privatekey_ecc_key.stdout
+
+- name: "({{ select_crypto_backend }}) Validate CSR (text common name - Common Name)"
+ shell: "{{ openssl_binary }} req -noout -subject -in {{ output_dir }}/csr3.csr -nameopt oneline,-space_eq"
+ register: csr3_cn
+
+- name: "({{ select_crypto_backend }}) Validate CSR (assert)"
+ assert:
+ that:
+ - csr3_cn.stdout.split('=')[-1] == 'This is for Ansible'
+
+- name: "({{ select_crypto_backend }}) Validate country name idempotency and validation"
+ assert:
+ that:
+ - country_idempotent_1 is changed
+ - country_idempotent_2 is not changed
+ - country_idempotent_3 is not changed
+ - country_fail_4 is failed
+
+- name:
+ assert:
+ that:
+ - passphrase_error_1 is failed
+ - "'assphrase' in passphrase_error_1.msg or 'assword' in passphrase_error_1.msg"
+ - passphrase_error_2 is failed
+ - "'assphrase' in passphrase_error_2.msg or 'assword' in passphrase_error_2.msg or 'serializ' in passphrase_error_2.msg"
+ - passphrase_error_3 is failed
+ - "'assphrase' in passphrase_error_3.msg or 'assword' in passphrase_error_3.msg or 'serializ' in passphrase_error_3.msg"
+
+- name: "({{ select_crypto_backend }}) Verify that broken CSR will be regenerated"
+ assert:
+ that:
+ - output_broken is changed
+
+- name: "({{ select_crypto_backend }}) Verify that subject key identifier handling works"
+ assert:
+ that:
+ - subject_key_identifier_1 is changed
+ - subject_key_identifier_2 is not changed
+ - subject_key_identifier_3 is changed
+ - subject_key_identifier_4 is changed
+ - subject_key_identifier_5 is not changed
+ - subject_key_identifier_6 is changed
+ when: select_crypto_backend != 'pyopenssl'
+
+- name: "({{ select_crypto_backend }}) Verify that authority key identifier handling works"
+ assert:
+ that:
+ - authority_key_identifier_1 is changed
+ - authority_key_identifier_2 is not changed
+ - authority_key_identifier_3 is changed
+ - authority_key_identifier_4 is changed
+ when: select_crypto_backend != 'pyopenssl'
+
+- name: "({{ select_crypto_backend }}) Verify that authority cert issuer / serial number handling works"
+ assert:
+ that:
+ - authority_cert_issuer_sn_1 is changed
+ - authority_cert_issuer_sn_2 is not changed
+ - authority_cert_issuer_sn_3 is changed
+ - authority_cert_issuer_sn_4 is changed
+ - authority_cert_issuer_sn_5 is changed
+ when: select_crypto_backend != 'pyopenssl'
+
+- name: "({{ select_crypto_backend }}) Check backup"
+ assert:
+ that:
+ - csr_backup_1 is changed
+ - csr_backup_1.backup_file is undefined
+ - csr_backup_2 is not changed
+ - csr_backup_2.backup_file is undefined
+ - csr_backup_3 is changed
+ - csr_backup_3.backup_file is string
+ - csr_backup_4 is changed
+ - csr_backup_4.backup_file is string
+ - csr_backup_5 is not changed
+ - csr_backup_5.backup_file is undefined
+ - csr_backup_4.csr is none
+
+- name: "({{ select_crypto_backend }}) Check CSR with everything"
+ assert:
+ that:
+ - everything_1 is changed
+ - everything_2 is not changed
+ - everything_3 is not changed
+ - everything_info.basic_constraints == [
+ "CA:TRUE",
+ "pathlen:23",
+ ]
+ - everything_info.basic_constraints_critical == true
+ - everything_info.extended_key_usage_critical == false
+ - everything_info.key_usage == [
+ "CRL Sign",
+ "Certificate Sign",
+ "Data Encipherment",
+ "Decipher Only",
+ "Digital Signature",
+ "Encipher Only",
+ "Key Agreement",
+ "Key Encipherment",
+ "Non Repudiation"
+ ]
+ - everything_info.key_usage_critical == true
+ - everything_info.ocsp_must_staple == true
+ - everything_info.ocsp_must_staple_critical == false
+ - everything_info.signature_valid == true
+ - everything_info.subject.commonName == "www.example.com"
+ - everything_info.subject.countryName == "de"
+ - everything_info.subject.emailAddress == "test@example.com"
+ - everything_info.subject.givenName == "First Name"
+ - everything_info.subject.localityName == "Somewhere"
+ - everything_info.subject.organizationName == "Ansible"
+ - everything_info.subject.organizationalUnitName == "Crypto Department"
+ - everything_info.subject.postalAddress == "1234 Somewhere"
+ - everything_info.subject.postalCode == "1234"
+ - everything_info.subject.pseudonym == "test"
+ - everything_info.subject.serialNumber == "1234"
+ - everything_info.subject.stateOrProvinceName == "Zurich"
+ - everything_info.subject.streetAddress == "Welcome Street"
+ - everything_info.subject.surname == "Last Name"
+ - everything_info.subject.title == "Chief"
+ - everything_info.subject.userId == "asdf"
+ - everything_info.subject | length == 16
+ - everything_info.subject_alt_name_critical == false
+ - everything_info.name_constraints_excluded == [
+ "DNS:.example.com",
+ "DNS:.org",
+ ]
+ - everything_info.name_constraints_critical == true
+
+- name: "({{ select_crypto_backend }}) Check CSR with everything (pyOpenSSL specific)"
+ assert:
+ that:
+ - everything_info.subject_alt_name == [
+ "DNS:www.ansible.com",
+ "IP:1.2.3.4",
+ "IP:::1",
+ "email:test@example.org",
+ "URI:https://example.org/test/index.html",
+ "RID:1.2.3.4",
+ ]
+ - everything_info.extended_key_usage == [
+ "Any Extended Key Usage",
+ "Biometric Info",
+ "Code Signing",
+ "E-mail Protection",
+ "IPSec User",
+ "OCSP Signing",
+ "TLS Web Client Authentication",
+ "TLS Web Server Authentication",
+ "TLS Web Server Authentication",
+ "Time Stamping",
+ "dvcs",
+ "qcStatements",
+ ]
+ - everything_info.name_constraints_permitted == [
+ "DNS:www.example.com",
+ "IP:1.2.3.0/24",
+ ]
+ when: select_crypto_backend == 'pyopenssl'
+
+- name: "({{ select_crypto_backend }}) Check CSR with everything (non-pyOpenSSL specific)"
+ assert:
+ that:
+ - everything_info.authority_cert_issuer == [
+ "DNS:ca.example.org",
+ "IP:1.2.3.4"
+ ]
+ - everything_info.authority_cert_serial_number == 12345
+ - everything_info.authority_key_identifier == "44:55:66:77"
+ - everything_info.subject_alt_name == [
+ "DNS:www.ansible.com",
+ "IP:1.2.3.4",
+ "IP:::1",
+ "email:test@example.org",
+ "URI:https://example.org/test/index.html",
+ "RID:1.2.3.4",
+ "otherName:1.2.3.4;0c:07:63:65:72:74:72:65:71",
+ "otherName:1.3.6.1.4.1.311.20.2.3;0c:0d:62:6f:62:40:6c:6f:63:61:6c:68:6f:73:74",
+ "dirName:/O=Example Net/CN=example.net",
+ "dirName:/O=Example Com/CN=example.com"
+ ]
+ - everything_info.subject_key_identifier == "00:11:22:33"
+ - everything_info.extended_key_usage == [
+ "1.2.3.4.5.6",
+ "Any Extended Key Usage",
+ "Biometric Info",
+ "Code Signing",
+ "E-mail Protection",
+ "IPSec User",
+ "OCSP Signing",
+ "TLS Web Client Authentication",
+ "TLS Web Server Authentication",
+ "TLS Web Server Authentication",
+ "Time Stamping",
+ "dvcs",
+ "qcStatements",
+ ]
+ - everything_info.name_constraints_permitted == [
+ "DNS:www.example.com",
+ "IP:1.2.3.0/24",
+ "IP:::1:0:0/112",
+ ]
+ when: select_crypto_backend != 'pyopenssl'
+
+- name: "({{ select_crypto_backend }}) Verify Ed25519 and Ed448 tests (for cryptography >= 2.6, < 2.8)"
+ assert:
+ that:
+ - generate_csr_ed25519_ed448.results[0] is failed
+ - generate_csr_ed25519_ed448.results[1] is failed
+ - generate_csr_ed25519_ed448.results[0].msg == 'Signing with Ed25519 and Ed448 keys requires cryptography 2.8 or newer.'
+ - generate_csr_ed25519_ed448.results[1].msg == 'Signing with Ed25519 and Ed448 keys requires cryptography 2.8 or newer.'
+ - generate_csr_ed25519_ed448_idempotent.results[0] is failed
+ - generate_csr_ed25519_ed448_idempotent.results[1] is failed
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=') and cryptography_version.stdout is version('2.8', '<') and generate_csr_ed25519_ed448_privatekey is not failed
+
+- name: "({{ select_crypto_backend }}) Verify Ed25519 and Ed448 tests (for cryptography >= 2.8)"
+ assert:
+ that:
+ - generate_csr_ed25519_ed448 is succeeded
+ - generate_csr_ed25519_ed448.results[0] is changed
+ - generate_csr_ed25519_ed448.results[1] is changed
+ - generate_csr_ed25519_ed448_idempotent is succeeded
+ - generate_csr_ed25519_ed448_idempotent.results[0] is not changed
+ - generate_csr_ed25519_ed448_idempotent.results[1] is not changed
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.8', '>=') and generate_csr_ed25519_ed448_privatekey is not failed
+
+- name: "({{ select_crypto_backend }}) Verify CRL distribution endpoints (for cryptography >= 1.6)"
+ assert:
+ that:
+ - crl_distribution_endpoints_1 is changed
+ - crl_distribution_endpoints_2 is not changed
+ - crl_distribution_endpoints_3 is changed
+ - crl_distribution_endpoints_4 is changed
+ - crl_distribution_endpoints_5 is changed
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.6', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/tasks/impl.yml
new file mode 100644
index 00000000..bc9037eb
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/tasks/impl.yml
@@ -0,0 +1,94 @@
+---
+- debug:
+ msg: "Executing tests with backend {{ select_crypto_backend }}"
+
+- name: "({{ select_crypto_backend }}) Get CSR info"
+ openssl_csr_info:
+ path: '{{ output_dir }}/csr_1.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: "({{ select_crypto_backend }}) Check whether subject behaves as expected"
+ assert:
+ that:
+ - result.subject.organizationalUnitName == 'ACME Department'
+ - "['organizationalUnitName', 'Crypto Department'] in result.subject_ordered"
+ - "['organizationalUnitName', 'ACME Department'] in result.subject_ordered"
+
+- name: "({{ select_crypto_backend }}) Check SubjectKeyIdentifier and AuthorityKeyIdentifier"
+ assert:
+ that:
+ - result.subject_key_identifier == "00:11:22:33"
+ - result.authority_key_identifier == "44:55:66:77"
+ - result.authority_cert_issuer == expected_authority_cert_issuer
+ - result.authority_cert_serial_number == 12345
+ vars:
+ expected_authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+ when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
+
+- name: "({{ select_crypto_backend }}) Update result list"
+ set_fact:
+ info_results: "{{ info_results + [result] }}"
+
+- name: "({{ select_crypto_backend }}) Get CSR info directly"
+ openssl_csr_info:
+ content: '{{ lookup("file", output_dir ~ "/csr_1.csr") }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result_direct
+
+- name: "({{ select_crypto_backend }}) Compare output of direct and loaded info"
+ assert:
+ that:
+ - result == result_direct
+
+- name: "({{ select_crypto_backend }}) Get CSR info"
+ openssl_csr_info:
+ path: '{{ output_dir }}/csr_2.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: "({{ select_crypto_backend }}) Update result list"
+ set_fact:
+ info_results: "{{ info_results + [result] }}"
+
+- name: "({{ select_crypto_backend }}) Get CSR info"
+ openssl_csr_info:
+ path: '{{ output_dir }}/csr_3.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: "({{ select_crypto_backend }}) Check AuthorityKeyIdentifier"
+ assert:
+ that:
+ - result.authority_key_identifier is none
+ - result.authority_cert_issuer == expected_authority_cert_issuer
+ - result.authority_cert_serial_number == 12345
+ vars:
+ expected_authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+ when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
+
+- name: "({{ select_crypto_backend }}) Update result list"
+ set_fact:
+ info_results: "{{ info_results + [result] }}"
+
+- name: "({{ select_crypto_backend }}) Get CSR info"
+ openssl_csr_info:
+ path: '{{ output_dir }}/csr_4.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: "({{ select_crypto_backend }}) Check AuthorityKeyIdentifier"
+ assert:
+ that:
+ - result.authority_key_identifier == "44:55:66:77"
+ - result.authority_cert_issuer is none
+ - result.authority_cert_serial_number is none
+ when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
+
+- name: "({{ select_crypto_backend }}) Update result list"
+ set_fact:
+ info_results: "{{ info_results + [result] }}"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/tasks/main.yml
new file mode 100644
index 00000000..e55ffa44
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/tasks/main.yml
@@ -0,0 +1,168 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Generate privatekey
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey.pem'
+ size: '{{ default_rsa_key_size }}'
+
+- name: Generate privatekey with password
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: auto
+ select_crypto_backend: cryptography
+ size: '{{ default_rsa_key_size }}'
+
+- name: Generate CSR 1
+ openssl_csr:
+ path: '{{ output_dir }}/csr_1.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.example.com
+ C: de
+ L: Somewhere
+ ST: Zurich
+ streetAddress: Welcome Street
+ O: Ansible
+ organizationalUnitName:
+ - Crypto Department
+ - ACME Department
+ serialNumber: "1234"
+ SN: Last Name
+ GN: First Name
+ title: Chief
+ pseudonym: test
+ UID: asdf
+ emailAddress: test@example.com
+ postalAddress: 1234 Somewhere
+ postalCode: "1234"
+ useCommonNameForSAN: no
+ key_usage:
+ - digitalSignature
+ - keyAgreement
+ - Non Repudiation
+ - Key Encipherment
+ - dataEncipherment
+ - Certificate Sign
+ - cRLSign
+ - Encipher Only
+ - decipherOnly
+ key_usage_critical: yes
+ extended_key_usage:
+ - serverAuth # the same as "TLS Web Server Authentication"
+ - TLS Web Server Authentication
+ - TLS Web Client Authentication
+ - Code Signing
+ - E-mail Protection
+ - timeStamping
+ - OCSPSigning
+ - Any Extended Key Usage
+ - qcStatements
+ - DVCS
+ - IPSec User
+ - biometricInfo
+ subject_alt_name:
+ - "DNS:www.ansible.com"
+ - "IP:1.2.3.4"
+ - "IP:::1"
+ - "email:test@example.org"
+ - "URI:https://example.org/test/index.html"
+ basic_constraints:
+ - "CA:TRUE"
+ - "pathlen:23"
+ basic_constraints_critical: yes
+ ocsp_must_staple: yes
+ subject_key_identifier: '{{ "00:11:22:33" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ vars:
+ value_for_authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+
+- name: Generate CSR 2
+ openssl_csr:
+ path: '{{ output_dir }}/csr_2.csr'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ privatekey_passphrase: hunter2
+ useCommonNameForSAN: no
+ basic_constraints:
+ - "CA:TRUE"
+
+- name: Generate CSR 3
+ openssl_csr:
+ path: '{{ output_dir }}/csr_3.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ useCommonNameForSAN: no
+ subject_alt_name:
+ - "DNS:*.ansible.com"
+ - "DNS:*.example.org"
+ - "IP:DEAD:BEEF::1"
+ basic_constraints:
+ - "CA:FALSE"
+ authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ vars:
+ value_for_authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+
+- name: Generate CSR 4
+ openssl_csr:
+ path: '{{ output_dir }}/csr_4.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ useCommonNameForSAN: no
+ authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+
+- name: Prepare result list
+ set_fact:
+ info_results: []
+
+- name: Running tests with pyOpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: pyopenssl
+ when: pyopenssl_version.stdout is version('0.15', '>=')
+
+- name: Prepare result list
+ set_fact:
+ pyopenssl_info_results: "{{ info_results }}"
+ info_results: []
+
+- name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+ when: cryptography_version.stdout is version('1.3', '>=')
+
+- name: Prepare result list
+ set_fact:
+ cryptography_info_results: "{{ info_results }}"
+
+- block:
+ - name: Dump pyOpenSSL results
+ debug:
+ var: pyopenssl_info_results
+ - name: Dump cryptography results
+ debug:
+ var: cryptography_info_results
+ - name: Compare results
+ assert:
+ that:
+ - ' (item.0 | dict2items | rejectattr("key", "in", keys_to_ignore) | list | items2dict)
+ == (item.1 | dict2items | rejectattr("key", "in", keys_to_ignore) | list | items2dict)'
+ quiet: yes
+ loop: "{{ pyopenssl_info_results | zip(cryptography_info_results) | list }}"
+ when: pyopenssl_version.stdout is version('0.15', '>=') and cryptography_version.stdout is version('1.3', '>=')
+ vars:
+ keys_to_ignore:
+ - deprecations
+ - subject_key_identifier
+ - authority_key_identifier
+ - authority_cert_issuer
+ - authority_cert_serial_number
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/test_plugins/jinja_compatibility.py b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/test_plugins/jinja_compatibility.py
new file mode 100644
index 00000000..fc2b5f0f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_info/test_plugins/jinja_compatibility.py
@@ -0,0 +1,15 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+def compatibility_in_test(a, b):
+ return a in b
+
+
+class TestModule:
+ ''' Ansible math jinja2 tests '''
+
+ def tests(self):
+ return {
+ 'in': compatibility_in_test,
+ }
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/tasks/impl.yml
new file mode 100644
index 00000000..844ed77e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/tasks/impl.yml
@@ -0,0 +1,92 @@
+---
+- name: "({{ select_crypto_backend }}) Generate privatekey"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey.pem'
+ size: '{{ default_rsa_key_size }}'
+
+- name: "({{ select_crypto_backend }}) Generate CSR (check mode)"
+ openssl_csr_pipe:
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: generate_csr_check
+
+- name: "({{ select_crypto_backend }}) Generate CSR"
+ openssl_csr_pipe:
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: generate_csr
+
+- name: "({{ select_crypto_backend }}) Generate CSR (idempotent)"
+ openssl_csr_pipe:
+ content: "{{ generate_csr.csr }}"
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: generate_csr_idempotent
+
+- name: "({{ select_crypto_backend }}) Generate CSR (idempotent, check mode)"
+ openssl_csr_pipe:
+ content: "{{ generate_csr.csr }}"
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: generate_csr_idempotent_check
+
+- name: "({{ select_crypto_backend }}) Generate CSR (changed)"
+ openssl_csr_pipe:
+ content: "{{ generate_csr.csr }}"
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: generate_csr_changed
+
+- name: "({{ select_crypto_backend }}) Generate CSR (changed, check mode)"
+ openssl_csr_pipe:
+ content: "{{ generate_csr.csr }}"
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: generate_csr_changed_check
+
+- name: "({{ select_crypto_backend }}) Validate CSR (test - privatekey modulus)"
+ shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ output_dir }}/privatekey.pem'
+ register: privatekey_modulus
+
+- name: "({{ select_crypto_backend }}) Validate CSR (test - Common Name)"
+ shell: "{{ openssl_binary }} req -noout -subject -in /dev/stdin -nameopt oneline,-space_eq"
+ args:
+ stdin: "{{ generate_csr.csr }}"
+ register: csr_cn
+
+- name: "({{ select_crypto_backend }}) Validate CSR (test - csr modulus)"
+ shell: '{{ openssl_binary }} req -noout -modulus -in /dev/stdin'
+ args:
+ stdin: "{{ generate_csr.csr }}"
+ register: csr_modulus
+
+- name: "({{ select_crypto_backend }}) Validate CSR (assert)"
+ assert:
+ that:
+ - csr_cn.stdout.split('=')[-1] == 'www.ansible.com'
+ - csr_modulus.stdout == privatekey_modulus.stdout
+
+- name: "({{ select_crypto_backend }}) Validate CSR (check mode, idempotency)"
+ assert:
+ that:
+ - generate_csr_check is changed
+ - generate_csr is changed
+ - generate_csr_idempotent is not changed
+ - generate_csr_idempotent_check is not changed
+ - generate_csr_changed is changed
+ - generate_csr_changed_check is changed
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/tasks/main.yml
new file mode 100644
index 00000000..8f3d9c59
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_csr_pipe/tasks/main.yml
@@ -0,0 +1,41 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Prepare private key for backend autodetection test
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_backend_selection.pem'
+ size: '{{ default_rsa_key_size }}'
+- name: Run module with backend autodetection
+ openssl_csr_pipe:
+ privatekey_path: '{{ output_dir }}/privatekey_backend_selection.pem'
+ subject:
+ commonName: www.ansible.com
+
+- block:
+ - name: Running tests with pyOpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: pyopenssl
+
+ when: pyopenssl_version.stdout is version('0.15', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ when: cryptography_version.stdout is version('1.3', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/meta/main.yml
new file mode 100644
index 00000000..800aff64
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_openssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tasks/impl.yml
new file mode 100644
index 00000000..d367436d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tasks/impl.yml
@@ -0,0 +1,101 @@
+---
+# The tests for this module generate unsafe parameters for testing purposes;
+# otherwise tests would be too slow. Use sizes of at least 2048 in production!
+- name: "[{{ select_crypto_backend }}] Generate parameter"
+ openssl_dhparam:
+ size: 768
+ path: '{{ output_dir }}/dh768.pem'
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ return_content: yes
+ register: dhparam
+
+- name: "[{{ select_crypto_backend }}] Don't regenerate parameters with no change"
+ openssl_dhparam:
+ size: 768
+ path: '{{ output_dir }}/dh768.pem'
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ return_content: yes
+ register: dhparam_changed
+
+- name: "[{{ select_crypto_backend }}] Generate parameters with size option"
+ openssl_dhparam:
+ path: '{{ output_dir }}/dh512.pem'
+ size: 512
+ select_crypto_backend: "{{ select_crypto_backend }}"
+
+- name: "[{{ select_crypto_backend }}] Don't regenerate parameters with size option and no change"
+ openssl_dhparam:
+ path: '{{ output_dir }}/dh512.pem'
+ size: 512
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: dhparam_changed_512
+
+- copy:
+ src: '{{ output_dir }}/dh768.pem'
+ remote_src: yes
+ dest: '{{ output_dir }}/dh512.pem'
+
+- name: "[{{ select_crypto_backend }}] Re-generate if size is different"
+ openssl_dhparam:
+ path: '{{ output_dir }}/dh512.pem'
+ size: 512
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: dhparam_changed_to_512
+
+- name: "[{{ select_crypto_backend }}] Force re-generate parameters with size option"
+ openssl_dhparam:
+ path: '{{ output_dir }}/dh512.pem'
+ size: 512
+ force: yes
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: dhparam_changed_force
+
+- name: "[{{ select_crypto_backend }}] Create broken params"
+ copy:
+ dest: "{{ output_dir }}/dhbroken.pem"
+ content: "broken"
+- name: "[{{ select_crypto_backend }}] Regenerate broken params"
+ openssl_dhparam:
+ path: '{{ output_dir }}/dhbroken.pem'
+ size: 512
+ force: yes
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: output_broken
+
+- name: "[{{ select_crypto_backend }}] Generate params"
+ openssl_dhparam:
+ path: '{{ output_dir }}/dh_backup.pem'
+ size: 512
+ backup: yes
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: dhparam_backup_1
+- name: "[{{ select_crypto_backend }}] Generate params (idempotent)"
+ openssl_dhparam:
+ path: '{{ output_dir }}/dh_backup.pem'
+ size: 512
+ backup: yes
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: dhparam_backup_2
+- name: "[{{ select_crypto_backend }}] Generate params (change)"
+ openssl_dhparam:
+ path: '{{ output_dir }}/dh_backup.pem'
+ size: 512
+ force: yes
+ backup: yes
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: dhparam_backup_3
+- name: "[{{ select_crypto_backend }}] Generate params (remove)"
+ openssl_dhparam:
+ path: '{{ output_dir }}/dh_backup.pem'
+ state: absent
+ backup: yes
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ return_content: yes
+ register: dhparam_backup_4
+- name: "[{{ select_crypto_backend }}] Generate params (remove, idempotent)"
+ openssl_dhparam:
+ path: '{{ output_dir }}/dh_backup.pem'
+ state: absent
+ backup: yes
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: dhparam_backup_5
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tasks/main.yml
new file mode 100644
index 00000000..b0339dfa
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tasks/main.yml
@@ -0,0 +1,43 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+# The tests for this module generate unsafe parameters for testing purposes;
+# otherwise tests would be too slow. Use sizes of at least 2048 in production!
+
+- name: Run module with backend autodetection
+ openssl_dhparam:
+ path: '{{ output_dir }}/dh_backend_selection.pem'
+ size: 512
+
+- block:
+ - name: Running tests with OpenSSL backend
+ include_tasks: impl.yml
+
+ - include_tasks: ../tests/validate.yml
+
+ vars:
+ select_crypto_backend: openssl
+ # when: openssl_version.stdout is version('1.0.0', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+
+ - include_tasks: ../tests/validate.yml
+
+ vars:
+ select_crypto_backend: cryptography
+ when: cryptography_version.stdout is version('2.0', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tests/validate.yml
new file mode 100644
index 00000000..a9ed03ef
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_dhparam/tests/validate.yml
@@ -0,0 +1,58 @@
+---
+- name: "[{{ select_crypto_backend }}] Validate generated params"
+ shell: '{{ openssl_binary }} dhparam -in {{ output_dir }}/{{ item }}.pem -noout -check'
+ with_items:
+ - dh768
+ - dh512
+
+- name: "[{{ select_crypto_backend }}] Get bit size of 768"
+ shell: '{{ openssl_binary }} dhparam -noout -in {{ output_dir }}/dh768.pem -text | head -n1 | sed -ne "s@.*(\\([[:digit:]]\{1,\}\\) bit).*@\\1@p"'
+ register: bit_size_dhparam
+
+- name: "[{{ select_crypto_backend }}] Check bit size of default"
+ assert:
+ that:
+ - bit_size_dhparam.stdout == "768"
+
+- name: "[{{ select_crypto_backend }}] Get bit size of 512"
+ shell: '{{ openssl_binary }} dhparam -noout -in {{ output_dir }}/dh512.pem -text | head -n1 | sed -ne "s@.*(\\([[:digit:]]\{1,\}\\) bit).*@\\1@p"'
+ register: bit_size_dhparam_512
+
+- name: "[{{ select_crypto_backend }}] Check bit size of default"
+ assert:
+ that:
+ - bit_size_dhparam_512.stdout == "512"
+
+- name: "[{{ select_crypto_backend }}] Check if changed works correctly"
+ assert:
+ that:
+ - dhparam_changed is not changed
+ - dhparam_changed_512 is not changed
+ - dhparam_changed_to_512 is changed
+ - dhparam_changed_force is changed
+
+- name: "[{{ select_crypto_backend }}] Make sure correct values are returned"
+ assert:
+ that:
+ - dhparam.dhparams == lookup('file', output_dir ~ '/dh768.pem', rstrip=False)
+ - dhparam.dhparams == dhparam_changed.dhparams
+
+- name: "[{{ select_crypto_backend }}] Verify that broken params will be regenerated"
+ assert:
+ that:
+ - output_broken is changed
+
+- name: "[{{ select_crypto_backend }}] Check backup"
+ assert:
+ that:
+ - dhparam_backup_1 is changed
+ - dhparam_backup_1.backup_file is undefined
+ - dhparam_backup_2 is not changed
+ - dhparam_backup_2.backup_file is undefined
+ - dhparam_backup_3 is changed
+ - dhparam_backup_3.backup_file is string
+ - dhparam_backup_4 is changed
+ - dhparam_backup_4.backup_file is string
+ - dhparam_backup_5 is not changed
+ - dhparam_backup_5.backup_file is undefined
+ - dhparam_backup_4.dhparams is none
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tasks/impl.yml
new file mode 100644
index 00000000..9b36027f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tasks/impl.yml
@@ -0,0 +1,287 @@
+- block:
+ - name: Generate privatekey
+ openssl_privatekey:
+ path: '{{ output_dir }}/ansible_pkey.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+ - name: Generate privatekey2
+ openssl_privatekey:
+ path: '{{ output_dir }}/ansible_pkey2.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+ - name: Generate privatekey3
+ openssl_privatekey:
+ path: '{{ output_dir }}/ansible_pkey3.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+ - name: Generate CSR
+ openssl_csr:
+ path: '{{ output_dir }}/ansible.csr'
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ commonName: www.ansible.com
+ - name: Generate CSR 2
+ openssl_csr:
+ path: '{{ output_dir }}/ansible2.csr'
+ privatekey_path: '{{ output_dir }}/ansible_pkey2.pem'
+ commonName: www2.ansible.com
+ - name: Generate CSR 3
+ openssl_csr:
+ path: '{{ output_dir }}/ansible3.csr'
+ privatekey_path: '{{ output_dir }}/ansible_pkey3.pem'
+ commonName: www3.ansible.com
+ - name: Generate certificate
+ x509_certificate:
+ path: '{{ output_dir }}/{{ item.name }}.crt'
+ privatekey_path: '{{ output_dir }}/{{ item.pkey }}'
+ csr_path: '{{ output_dir }}/{{ item.name }}.csr'
+ provider: selfsigned
+ loop:
+ - name: ansible
+ pkey: ansible_pkey.pem
+ - name: ansible2
+ pkey: ansible_pkey2.pem
+ - name: ansible3
+ pkey: ansible_pkey3.pem
+ - name: Generate concatenated PEM file
+ copy:
+ dest: '{{ output_dir }}/ansible23.crt'
+ content: |
+ {{ lookup("file", output_dir ~ "/ansible2.crt") }}
+ {{ lookup("file", output_dir ~ "/ansible3.crt") }}
+ - name: Generate PKCS#12 file
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ return_content: true
+ register: p12_standard
+ - name: Generate PKCS#12 file again, idempotency
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ return_content: true
+ register: p12_standard_idempotency
+ - name: Read ansible.p12
+ slurp:
+ src: '{{ output_dir }}/ansible.p12'
+ register: ansible_p12_content
+ - name: Validate PKCS#12
+ assert:
+ that:
+ - p12_standard.pkcs12 == ansible_p12_content.content
+ - p12_standard_idempotency.pkcs12 == p12_standard.pkcs12
+ - name: Generate PKCS#12 file (force)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ force: true
+ register: p12_force
+ - name: Generate PKCS#12 file (force + change mode)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ force: true
+ mode: '0644'
+ register: p12_force_and_mode
+ - name: Dump PKCS#12
+ openssl_pkcs12:
+ src: '{{ output_dir }}/ansible.p12'
+ path: '{{ output_dir }}/ansible_parse.pem'
+ action: parse
+ state: present
+ register: p12_dumped
+ - name: Dump PKCS#12 file again, idempotency
+ openssl_pkcs12:
+ src: '{{ output_dir }}/ansible.p12'
+ path: '{{ output_dir }}/ansible_parse.pem'
+ action: parse
+ state: present
+ register: p12_dumped_idempotency
+ - name: Dump PKCS#12, check mode
+ openssl_pkcs12:
+ src: '{{ output_dir }}/ansible.p12'
+ path: '{{ output_dir }}/ansible_parse.pem'
+ action: parse
+ state: present
+ check_mode: true
+ register: p12_dumped_check_mode
+ - name: Generate PKCS#12 file with multiple certs
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_multi_certs.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ other_certificates:
+ - '{{ output_dir }}/ansible2.crt'
+ - '{{ output_dir }}/ansible3.crt'
+ state: present
+ register: p12_multiple_certs
+ - name: Generate PKCS#12 file with multiple certs, again (idempotency)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_multi_certs.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ other_certificates:
+ - '{{ output_dir }}/ansible2.crt'
+ - '{{ output_dir }}/ansible3.crt'
+ state: present
+ register: p12_multiple_certs_idempotency
+ - name: Dump PKCS#12 with multiple certs
+ openssl_pkcs12:
+ src: '{{ output_dir }}/ansible_multi_certs.p12'
+ path: '{{ output_dir }}/ansible_parse_multi_certs.pem'
+ action: parse
+ state: present
+ - name: Generate privatekey with password
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: auto
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: cryptography
+ - name: Generate PKCS#12 file (password fail 1)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_pw1.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ privatekey_passphrase: hunter2
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ ignore_errors: true
+ register: passphrase_error_1
+ - name: Generate PKCS#12 file (password fail 2)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_pw2.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ privatekey_passphrase: wrong_password
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ ignore_errors: true
+ register: passphrase_error_2
+ - name: Generate PKCS#12 file (password fail 3)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_pw3.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ ignore_errors: true
+ register: passphrase_error_3
+ - name: Generate PKCS#12 file, no privatekey
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_no_pkey.p12'
+ friendly_name: abracadabra
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ register: p12_no_pkey
+ - name: Create broken PKCS#12
+ copy:
+ dest: '{{ output_dir }}/broken.p12'
+ content: broken
+ - name: Regenerate broken PKCS#12
+ openssl_pkcs12:
+ path: '{{ output_dir }}/broken.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ force: true
+ mode: '0644'
+ register: output_broken
+ - name: Generate PKCS#12 file
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_backup.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ backup: true
+ register: p12_backup_1
+ - name: Generate PKCS#12 file (idempotent)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_backup.p12'
+ friendly_name: abracadabra
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ backup: true
+ register: p12_backup_2
+ - name: Generate PKCS#12 file (change)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_backup.p12'
+ friendly_name: abra
+ privatekey_path: '{{ output_dir }}/ansible_pkey.pem'
+ certificate_path: '{{ output_dir }}/ansible.crt'
+ state: present
+ force: true
+ backup: true
+ register: p12_backup_3
+ - name: Generate PKCS#12 file (remove)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_backup.p12'
+ state: absent
+ backup: true
+ return_content: true
+ register: p12_backup_4
+ - name: Generate PKCS#12 file (remove, idempotent)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_backup.p12'
+ state: absent
+ backup: true
+ register: p12_backup_5
+ - name: Generate 'empty' PKCS#12 file
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_empty.p12'
+ friendly_name: abracadabra
+ other_certificates:
+ - '{{ output_dir }}/ansible2.crt'
+ - '{{ output_dir }}/ansible3.crt'
+ state: present
+ register: p12_empty
+ - name: Generate 'empty' PKCS#12 file (idempotent)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_empty.p12'
+ friendly_name: abracadabra
+ other_certificates:
+ - '{{ output_dir }}/ansible3.crt'
+ - '{{ output_dir }}/ansible2.crt'
+ state: present
+ register: p12_empty_idem
+ - name: Generate 'empty' PKCS#12 file (idempotent, concatenated other certificates)
+ openssl_pkcs12:
+ path: '{{ output_dir }}/ansible_empty.p12'
+ friendly_name: abracadabra
+ other_certificates:
+ - '{{ output_dir }}/ansible23.crt'
+ other_certificates_parse_all: true
+ state: present
+ register: p12_empty_concat_idem
+ - name: Generate 'empty' PKCS#12 file (parse)
+ openssl_pkcs12:
+ src: '{{ output_dir }}/ansible_empty.p12'
+ path: '{{ output_dir }}/ansible_empty.pem'
+ action: parse
+ - import_tasks: ../tests/validate.yml
+ always:
+ - name: Delete PKCS#12 file
+ openssl_pkcs12:
+ state: absent
+ path: '{{ output_dir }}/{{ item }}.p12'
+ loop:
+ - ansible
+ - ansible_no_pkey
+ - ansible_multi_certs
+ - ansible_pw1
+ - ansible_pw2
+ - ansible_pw3
+ - ansible_empty
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tasks/main.yml
new file mode 100644
index 00000000..8d57ff45
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tasks/main.yml
@@ -0,0 +1,9 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Run tests
+ include_tasks: impl.yml
+ when: pyopenssl_version.stdout is version('17.1.0', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tests/validate.yml
new file mode 100644
index 00000000..86e4115d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_pkcs12/tests/validate.yml
@@ -0,0 +1,68 @@
+---
+- name: 'Validate PKCS#12'
+ command: "{{ openssl_binary }} pkcs12 -info -in {{ output_dir }}/ansible.p12 -nodes -passin pass:''"
+ register: p12
+
+- name: 'Validate PKCS#12 with no private key'
+ command: "{{ openssl_binary }} pkcs12 -info -in {{ output_dir }}/ansible_no_pkey.p12 -nodes -passin pass:''"
+ register: p12_validate_no_pkey
+
+- name: 'Validate PKCS#12 with multiple certs'
+ shell: "{{ openssl_binary }} pkcs12 -info -in {{ output_dir }}/ansible_multi_certs.p12 -nodes -passin pass:'' | grep subject"
+ register: p12_validate_multi_certs
+
+- name: 'Validate PKCS#12 (assert)'
+ assert:
+ that:
+ - p12.stdout_lines[2].split(':')[-1].strip() == 'abracadabra'
+ - p12_standard.mode == '0400'
+ - p12_no_pkey.changed
+ - p12_validate_no_pkey.stdout_lines[-1] == '-----END CERTIFICATE-----'
+ - p12_force.changed
+ - p12_force_and_mode.mode == '0644' and p12_force_and_mode.changed
+ - p12_dumped.changed
+ - not p12_standard_idempotency.changed
+ - not p12_multiple_certs_idempotency.changed
+ - not p12_dumped_idempotency.changed
+ - not p12_dumped_check_mode.changed
+ - "'www.' in p12_validate_multi_certs.stdout"
+ - "'www2.' in p12_validate_multi_certs.stdout"
+ - "'www3.' in p12_validate_multi_certs.stdout"
+
+- name: Check passphrase on private key
+ assert:
+ that:
+ - passphrase_error_1 is failed
+ - "'assphrase' in passphrase_error_1.msg or 'assword' in passphrase_error_1.msg"
+ - passphrase_error_2 is failed
+ - "'assphrase' in passphrase_error_2.msg or 'assword' in passphrase_error_2.msg or 'serializ' in passphrase_error_2.msg"
+ - passphrase_error_3 is failed
+ - "'assphrase' in passphrase_error_3.msg or 'assword' in passphrase_error_3.msg or 'serializ' in passphrase_error_3.msg"
+
+- name: "Verify that broken PKCS#12 will be regenerated"
+ assert:
+ that:
+ - output_broken is changed
+
+- name: Check backup
+ assert:
+ that:
+ - p12_backup_1 is changed
+ - p12_backup_1.backup_file is undefined
+ - p12_backup_2 is not changed
+ - p12_backup_2.backup_file is undefined
+ - p12_backup_3 is changed
+ - p12_backup_3.backup_file is string
+ - p12_backup_4 is changed
+ - p12_backup_4.backup_file is string
+ - p12_backup_5 is not changed
+ - p12_backup_5.backup_file is undefined
+ - p12_backup_4.pkcs12 is none
+
+- name: Check 'empty' file
+ assert:
+ that:
+ - p12_empty is changed
+ - p12_empty_idem is not changed
+ - p12_empty_concat_idem is not changed
+ - "lookup('file', output_dir ~ '/ansible_empty.pem') == lookup('file', output_dir ~ '/ansible3.crt') ~ '\n' ~ lookup('file', output_dir ~ '/ansible2.crt')"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tasks/impl.yml
new file mode 100644
index 00000000..6fb8def8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tasks/impl.yml
@@ -0,0 +1,851 @@
+---
+- name: "({{ select_crypto_backend }}) Generate privatekey1 - standard"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey1.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: privatekey1
+
+- name: "({{ select_crypto_backend }}) Generate privatekey1 - standard (idempotence)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey1.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: privatekey1_idempotence
+
+- name: "({{ select_crypto_backend }}) Generate privatekey2 - size 2048"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey2.pem'
+ size: 2048
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Generate privatekey3 - type DSA"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey3.pem'
+ type: DSA
+ size: 3072
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Generate privatekey4 - standard"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey4.pem'
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Delete privatekey4 - standard"
+ openssl_privatekey:
+ state: absent
+ path: '{{ output_dir }}/privatekey4.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: privatekey4_delete
+
+- name: "({{ select_crypto_backend }}) Delete privatekey4 - standard (idempotence)"
+ openssl_privatekey:
+ state: absent
+ path: '{{ output_dir }}/privatekey4.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey4_delete_idempotence
+
+- name: "({{ select_crypto_backend }}) Generate privatekey5 - standard - with passphrase"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey5.pem'
+ passphrase: ansible
+ cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Generate privatekey5 - standard - idempotence"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey5.pem'
+ passphrase: ansible
+ cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey5_idempotence
+
+- name: "({{ select_crypto_backend }}) Generate privatekey6 - standard - with non-ASCII passphrase"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey6.pem'
+ passphrase: ànsïblé
+ cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- set_fact:
+ ecc_types: []
+ when: select_crypto_backend == 'pyopenssl'
+- set_fact:
+ ecc_types:
+ - curve: secp384r1
+ openssl_name: secp384r1
+ min_cryptography_version: "0.5"
+ - curve: secp521r1
+ openssl_name: secp521r1
+ min_cryptography_version: "0.5"
+ - curve: secp224r1
+ openssl_name: secp224r1
+ min_cryptography_version: "0.5"
+ - curve: secp192r1
+ openssl_name: prime192v1
+ min_cryptography_version: "0.5"
+ - curve: secp256r1
+ openssl_name: secp256r1
+ min_cryptography_version: "0.5"
+ - curve: secp256k1
+ openssl_name: secp256k1
+ min_cryptography_version: "0.9"
+ - curve: brainpoolP256r1
+ openssl_name: brainpoolP256r1
+ min_cryptography_version: "2.2"
+ - curve: brainpoolP384r1
+ openssl_name: brainpoolP384r1
+ min_cryptography_version: "2.2"
+ - curve: brainpoolP512r1
+ openssl_name: brainpoolP512r1
+ min_cryptography_version: "2.2"
+ - curve: sect571k1
+ openssl_name: sect571k1
+ min_cryptography_version: "0.5"
+ - curve: sect409k1
+ openssl_name: sect409k1
+ min_cryptography_version: "0.5"
+ - curve: sect283k1
+ openssl_name: sect283k1
+ min_cryptography_version: "0.5"
+ - curve: sect233k1
+ openssl_name: sect233k1
+ min_cryptography_version: "0.5"
+ - curve: sect163k1
+ openssl_name: sect163k1
+ min_cryptography_version: "0.5"
+ - curve: sect571r1
+ openssl_name: sect571r1
+ min_cryptography_version: "0.5"
+ - curve: sect409r1
+ openssl_name: sect409r1
+ min_cryptography_version: "0.5"
+ - curve: sect283r1
+ openssl_name: sect283r1
+ min_cryptography_version: "0.5"
+ - curve: sect233r1
+ openssl_name: sect233r1
+ min_cryptography_version: "0.5"
+ - curve: sect163r2
+ openssl_name: sect163r2
+ min_cryptography_version: "0.5"
+ when: select_crypto_backend == 'cryptography'
+
+- name: "({{ select_crypto_backend }}) Test ECC key generation"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey-{{ item.curve }}.pem'
+ type: ECC
+ curve: "{{ item.curve }}"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: |
+ cryptography_version.stdout is version(item.min_cryptography_version, '>=') and
+ item.openssl_name in openssl_ecc_list
+ loop: "{{ ecc_types }}"
+ loop_control:
+ label: "{{ item.curve }}"
+ register: privatekey_ecc_generate
+
+- name: "({{ select_crypto_backend }}) Test ECC key generation (idempotency)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey-{{ item.curve }}.pem'
+ type: ECC
+ curve: "{{ item.curve }}"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: |
+ cryptography_version.stdout is version(item.min_cryptography_version, '>=') and
+ item.openssl_name in openssl_ecc_list
+ loop: "{{ ecc_types }}"
+ loop_control:
+ label: "{{ item.curve }}"
+ register: privatekey_ecc_idempotency
+
+- block:
+ - name: "({{ select_crypto_backend }}) Test other type generation"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey-{{ item.type }}.pem'
+ type: "{{ item.type }}"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: cryptography_version.stdout is version(item.min_version, '>=')
+ loop: "{{ types }}"
+ loop_control:
+ label: "{{ item.type }}"
+ ignore_errors: yes
+ register: privatekey_t1_generate
+
+ - name: "({{ select_crypto_backend }}) Test other type generation (idempotency)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey-{{ item.type }}.pem'
+ type: "{{ item.type }}"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: cryptography_version.stdout is version(item.min_version, '>=')
+ loop: "{{ types }}"
+ loop_control:
+ label: "{{ item.type }}"
+ ignore_errors: yes
+ register: privatekey_t1_idempotency
+
+ when: select_crypto_backend == 'cryptography'
+ vars:
+ types:
+ - type: X25519
+ min_version: '2.5'
+ - type: Ed25519
+ min_version: '2.6'
+ - type: Ed448
+ min_version: '2.6'
+ - type: X448
+ min_version: '2.6'
+
+- name: "({{ select_crypto_backend }}) Generate privatekey with passphrase"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ backup: yes
+ register: passphrase_1
+
+- name: "({{ select_crypto_backend }}) Generate privatekey with passphrase (idempotent)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ backup: yes
+ register: passphrase_2
+
+- name: "({{ select_crypto_backend }}) Regenerate privatekey without passphrase"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ backup: yes
+ register: passphrase_3
+
+- name: "({{ select_crypto_backend }}) Regenerate privatekey without passphrase (idempotent)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ backup: yes
+ register: passphrase_4
+
+- name: "({{ select_crypto_backend }}) Regenerate privatekey with passphrase"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ backup: yes
+ register: passphrase_5
+
+- name: "({{ select_crypto_backend }}) Create broken key"
+ copy:
+ dest: "{{ output_dir }}/broken"
+ content: "broken"
+- name: "({{ select_crypto_backend }}) Regenerate broken key"
+ openssl_privatekey:
+ path: '{{ output_dir }}/broken.pem'
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: output_broken
+
+- name: "({{ select_crypto_backend }}) Remove module"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ backup: yes
+ state: absent
+ register: remove_1
+
+- name: "({{ select_crypto_backend }}) Remove module (idempotent)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ backup: yes
+ state: absent
+ register: remove_2
+
+- name: "({{ select_crypto_backend }}) Generate privatekey_mode (mode 0400)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_mode.pem'
+ mode: '0400'
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_mode_1
+- name: "({{ select_crypto_backend }}) Stat for privatekey_mode"
+ stat:
+ path: '{{ output_dir }}/privatekey_mode.pem'
+ register: privatekey_mode_1_stat
+
+- name: "({{ select_crypto_backend }}) Generate privatekey_mode (mode 0400, idempotency)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_mode.pem'
+ mode: '0400'
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_mode_2
+
+- name: Make sure that mtime actually changes.
+ # The "privatekey_mode_1_stat.stat.mtime != privatekey_mode_3_stat.stat.mtime" test should be
+ # changed to compare content instead of mtime. On macOS 10.15, mtime resolution is one second,
+ # and the machine (VM) is fast enough that both modifications can happen in the same second.
+ pause:
+ seconds: 1
+
+- name: "({{ select_crypto_backend }}) Generate privatekey_mode (mode 0400, force)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_mode.pem'
+ mode: '0400'
+ force: yes
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_mode_3
+- name: "({{ select_crypto_backend }}) Stat for privatekey_mode"
+ stat:
+ path: '{{ output_dir }}/privatekey_mode.pem'
+ register: privatekey_mode_3_stat
+
+- block:
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - auto format"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_1.pem'
+ format: auto
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_fmt_1_step_1
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - auto format (idempotent)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_1.pem'
+ format: auto
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_fmt_1_step_2
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS1 format"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_1.pem'
+ format: pkcs1
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_fmt_1_step_3
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS8 format"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_1.pem'
+ format: pkcs8
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_fmt_1_step_4
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS8 format (idempotent)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_1.pem'
+ format: pkcs8
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_fmt_1_step_5
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - auto format (ignore)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_1.pem'
+ format: auto_ignore
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_fmt_1_step_6
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - auto format (no ignore)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_1.pem'
+ format: auto
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_fmt_1_step_7
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - raw format (fail)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_1.pem'
+ format: raw
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: privatekey_fmt_1_step_8
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS8 format (convert)"
+ openssl_privatekey_info:
+ path: '{{ output_dir }}/privatekey_fmt_1.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_fmt_1_step_9_before
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS8 format (convert)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_1.pem'
+ format: pkcs8
+ format_mismatch: convert
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_fmt_1_step_9
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_1 - PKCS8 format (convert)"
+ openssl_privatekey_info:
+ path: '{{ output_dir }}/privatekey_fmt_1.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey_fmt_1_step_9_after
+
+ when: 'select_crypto_backend == "cryptography"'
+
+- block:
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - PKCS8 format"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_2.pem'
+ type: X448
+ format: pkcs8
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: privatekey_fmt_2_step_1
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - PKCS8 format (idempotent)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_2.pem'
+ type: X448
+ format: pkcs8
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: privatekey_fmt_2_step_2
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - raw format"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_2.pem'
+ type: X448
+ format: raw
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ ignore_errors: yes
+ register: privatekey_fmt_2_step_3
+
+ - name: "({{ select_crypto_backend }}) Read privatekey_fmt_2.pem"
+ slurp:
+ src: "{{ output_dir }}/privatekey_fmt_2.pem"
+ ignore_errors: yes
+ register: content
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - verify that returned content is base64 encoded"
+ assert:
+ that:
+ - privatekey_fmt_2_step_3.privatekey == content.content
+ when: privatekey_fmt_2_step_1 is not failed
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - raw format (idempotent)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_2.pem'
+ type: X448
+ format: raw
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ ignore_errors: yes
+ register: privatekey_fmt_2_step_4
+
+ - name: "({{ select_crypto_backend }}) Read privatekey_fmt_2.pem"
+ slurp:
+ src: "{{ output_dir }}/privatekey_fmt_2.pem"
+ ignore_errors: yes
+ register: content
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - verify that returned content is base64 encoded"
+ assert:
+ that:
+ - privatekey_fmt_2_step_4.privatekey == content.content
+ when: privatekey_fmt_2_step_1 is not failed
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - auto format (ignore)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_2.pem'
+ type: X448
+ format: auto_ignore
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ ignore_errors: yes
+ register: privatekey_fmt_2_step_5
+
+ - name: "({{ select_crypto_backend }}) Read privatekey_fmt_2.pem"
+ slurp:
+ src: "{{ output_dir }}/privatekey_fmt_2.pem"
+ ignore_errors: yes
+ register: content
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - verify that returned content is base64 encoded"
+ assert:
+ that:
+ - privatekey_fmt_2_step_5.privatekey == content.content
+ when: privatekey_fmt_2_step_1 is not failed
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - auto format (no ignore)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_fmt_2.pem'
+ type: X448
+ format: auto
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ ignore_errors: yes
+ register: privatekey_fmt_2_step_6
+
+ - name: "({{ select_crypto_backend }}) Generate privatekey_fmt_2 - verify that returned content is not base64 encoded"
+ assert:
+ that:
+ - privatekey_fmt_2_step_6.privatekey == lookup('file', output_dir ~ '/privatekey_fmt_2.pem', rstrip=False)
+ when: privatekey_fmt_2_step_1 is not failed
+
+ when: 'select_crypto_backend == "cryptography" and cryptography_version.stdout is version("2.6", ">=")'
+
+
+
+# Test regenerate option
+
+- name: "({{ select_crypto_backend }}) Regenerate - setup simple keys"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ type: RSA
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop: "{{ regenerate_values }}"
+- name: "({{ select_crypto_backend }}) Regenerate - setup password protected keys"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-b-{{ item }}.pem'
+ type: RSA
+ size: '{{ default_rsa_key_size }}'
+ passphrase: hunter2
+ cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop: "{{ regenerate_values }}"
+- name: "({{ select_crypto_backend }}) Regenerate - setup broken keys"
+ copy:
+ dest: '{{ output_dir }}/regenerate-c-{{ item }}.pem'
+ content: 'broken key'
+ mode: '0700'
+ loop: "{{ regenerate_values }}"
+
+- name: "({{ select_crypto_backend }}) Regenerate - modify broken keys (check mode)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-c-{{ item }}.pem'
+ type: RSA
+ size: '{{ default_rsa_key_size }}'
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[0].msg or 'Cannot load raw key' in result.results[0].msg"
+ - result.results[1] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[1].msg or 'Cannot load raw key' in result.results[1].msg"
+ - result.results[2] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[2].msg or 'Cannot load raw key' in result.results[2].msg"
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: "({{ select_crypto_backend }}) Regenerate - modify broken keys"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-c-{{ item }}.pem'
+ type: RSA
+ size: '{{ default_rsa_key_size }}'
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[0].msg or 'Cannot load raw key' in result.results[0].msg"
+ - result.results[1] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[1].msg or 'Cannot load raw key' in result.results[1].msg"
+ - result.results[2] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[2].msg or 'Cannot load raw key' in result.results[2].msg"
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: "({{ select_crypto_backend }}) Regenerate - modify password protected keys (check mode)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-b-{{ item }}.pem'
+ type: RSA
+ size: '{{ default_rsa_key_size }}'
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[0].msg"
+ - result.results[1] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[2].msg"
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: "({{ select_crypto_backend }}) Regenerate - modify password protected keys"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-b-{{ item }}.pem'
+ type: RSA
+ size: '{{ default_rsa_key_size }}'
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[0].msg"
+ - result.results[1] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is failed
+ - "'Unable to read the key. The key is protected with a another passphrase / no passphrase or broken. Will not proceed.' in result.results[2].msg"
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: "({{ select_crypto_backend }}) Regenerate - not modify regular keys (check mode)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ type: RSA
+ size: '{{ default_rsa_key_size }}'
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ register: result
+- assert:
+ that:
+ - result.results[0] is not changed
+ - result.results[1] is not changed
+ - result.results[2] is not changed
+ - result.results[3] is not changed
+ - result.results[4] is changed
+
+- name: "({{ select_crypto_backend }}) Regenerate - not modify regular keys"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ type: RSA
+ size: '{{ default_rsa_key_size }}'
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop: "{{ regenerate_values }}"
+ register: result
+- assert:
+ that:
+ - result.results[0] is not changed
+ - result.results[1] is not changed
+ - result.results[2] is not changed
+ - result.results[3] is not changed
+ - result.results[4] is changed
+
+- name: "({{ select_crypto_backend }}) Regenerate - adjust key size (check mode)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ type: RSA
+ size: '{{ default_rsa_key_size + 20 }}'
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is success and result.results[0] is not changed
+ - result.results[1] is failed
+ - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: "({{ select_crypto_backend }}) Regenerate - adjust key size"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ type: RSA
+ size: '{{ default_rsa_key_size + 20 }}'
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is success and result.results[0] is not changed
+ - result.results[1] is failed
+ - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: "({{ select_crypto_backend }}) Regenerate - redistribute keys"
+ copy:
+ src: '{{ output_dir }}/regenerate-a-always.pem'
+ dest: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ remote_src: true
+ loop: "{{ regenerate_values }}"
+ when: "item != 'always'"
+
+- name: "({{ select_crypto_backend }}) Regenerate - adjust key type (check mode)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ type: DSA
+ size: '{{ default_rsa_key_size }}'
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is success and result.results[0] is not changed
+ - result.results[1] is failed
+ - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- name: "({{ select_crypto_backend }}) Regenerate - adjust key type"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ type: DSA
+ size: '{{ default_rsa_key_size }}'
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+- assert:
+ that:
+ - result.results[0] is success and result.results[0] is not changed
+ - result.results[1] is failed
+ - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+- block:
+ - name: "({{ select_crypto_backend }}) Regenerate - redistribute keys"
+ copy:
+ src: '{{ output_dir }}/regenerate-a-always.pem'
+ dest: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ remote_src: true
+ loop: "{{ regenerate_values }}"
+ when: "item != 'always'"
+
+ - name: "({{ select_crypto_backend }}) Regenerate - format mismatch (check mode)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ type: DSA
+ size: '{{ default_rsa_key_size }}'
+ format: pkcs8
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+ - assert:
+ that:
+ - result.results[0] is success and result.results[0] is not changed
+ - result.results[1] is failed
+ - "'Key has wrong format. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+ - name: "({{ select_crypto_backend }}) Regenerate - format mismatch"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ type: DSA
+ size: '{{ default_rsa_key_size }}'
+ format: pkcs8
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop: "{{ regenerate_values }}"
+ ignore_errors: yes
+ register: result
+ - assert:
+ that:
+ - result.results[0] is success and result.results[0] is not changed
+ - result.results[1] is failed
+ - "'Key has wrong format. Will not proceed.' in result.results[1].msg"
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+ - name: "({{ select_crypto_backend }}) Regenerate - redistribute keys"
+ copy:
+ src: '{{ output_dir }}/regenerate-a-always.pem'
+ dest: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ remote_src: true
+ loop: "{{ regenerate_values }}"
+ when: "item != 'always'"
+
+ - name: "({{ select_crypto_backend }}) Regenerate - convert format (check mode)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ type: DSA
+ size: '{{ default_rsa_key_size }}'
+ format: pkcs1
+ format_mismatch: convert
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ loop: "{{ regenerate_values }}"
+ register: result
+ - assert:
+ that:
+ - result.results[0] is changed
+ - result.results[1] is changed
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+
+ - name: "({{ select_crypto_backend }}) Regenerate - convert format"
+ openssl_privatekey:
+ path: '{{ output_dir }}/regenerate-a-{{ item }}.pem'
+ type: DSA
+ size: '{{ default_rsa_key_size }}'
+ format: pkcs1
+ format_mismatch: convert
+ regenerate: '{{ item }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop: "{{ regenerate_values }}"
+ register: result
+ - assert:
+ that:
+ - result.results[0] is changed
+ - result.results[1] is changed
+ - result.results[2] is changed
+ - result.results[3] is changed
+ - result.results[4] is changed
+ # for all values but 'always', the key should have not been regenerated.
+ # verify this by comparing fingerprints:
+ - result.results[0].fingerprint == result.results[1].fingerprint
+ - result.results[0].fingerprint == result.results[2].fingerprint
+ - result.results[0].fingerprint == result.results[3].fingerprint
+ - result.results[0].fingerprint != result.results[4].fingerprint
+ when: 'select_crypto_backend == "cryptography" and cryptography_version.stdout is version("2.6", ">=")'
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tasks/main.yml
new file mode 100644
index 00000000..057a7b9a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tasks/main.yml
@@ -0,0 +1,114 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Find out which elliptic curves are supported by installed OpenSSL
+ command: "{{ openssl_binary }} ecparam -list_curves"
+ register: openssl_ecc
+
+- name: Compile list of elliptic curves supported by OpenSSL
+ set_fact:
+ openssl_ecc_list: |
+ {{
+ openssl_ecc.stdout_lines
+ | map('regex_search', '^ *([a-zA-Z0-9_-]+) *: .*$')
+ | select()
+ | map('regex_replace', '^ *([a-zA-Z0-9_-]+) *: .*$', '\1')
+ | list
+ }}
+ when: ansible_distribution != 'CentOS' or ansible_distribution_major_version != '6'
+ # CentOS comes with a very old jinja2 which does not include the map() filter...
+- name: Compile list of elliptic curves supported by OpenSSL (CentOS 6)
+ set_fact:
+ openssl_ecc_list:
+ - secp384r1
+ - secp521r1
+ - prime256v1
+ when: ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6'
+
+- name: List of elliptic curves supported by OpenSSL
+ debug: var=openssl_ecc_list
+
+- name: Run module with backend autodetection
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_backend_selection.pem'
+ size: '{{ default_rsa_key_size }}'
+
+- block:
+ - name: Running tests with pyOpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: pyopenssl
+
+ - import_tasks: ../tests/validate.yml
+ vars:
+ select_crypto_backend: pyopenssl
+
+ # FIXME: minimal pyOpenSSL version?!
+ when: pyopenssl_version.stdout is version('0.6', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ - import_tasks: ../tests/validate.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ when: cryptography_version.stdout is version('0.5', '>=')
+
+- name: Check that fingerprints do not depend on the backend
+ block:
+ - name: "Fingerprint comparison: pyOpenSSL"
+ openssl_privatekey:
+ path: '{{ output_dir }}/fingerprint-{{ item }}.pem'
+ type: "{{ item }}"
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: pyopenssl
+ loop:
+ - RSA
+ - DSA
+ register: fingerprint_pyopenssl
+
+ - name: "Fingerprint comparison: cryptography"
+ openssl_privatekey:
+ path: '{{ output_dir }}/fingerprint-{{ item }}.pem'
+ type: "{{ item }}"
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: cryptography
+ loop:
+ - RSA
+ - DSA
+ register: fingerprint_cryptography
+
+ - name: Verify that keys were not regenerated
+ assert:
+ that:
+ - fingerprint_cryptography is not changed
+
+ - name: Verify that fingerprints match
+ assert:
+ that: item.0.fingerprint[item.2] == item.1.fingerprint[item.2]
+ when: item.0 is not skipped and item.1 is not skipped
+ loop: |
+ {{ query('nested',
+ fingerprint_pyopenssl.results | zip(fingerprint_cryptography.results),
+ fingerprint_pyopenssl.results[0].fingerprint.keys()
+ ) if fingerprint_pyopenssl.results[0].fingerprint else [] }}
+ loop_control:
+ label: "{{ [item.0.item, item.2] }}"
+ when: pyopenssl_version.stdout is version('0.6', '>=') and cryptography_version.stdout is version('0.5', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tests/validate.yml
new file mode 100644
index 00000000..5672d927
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/tests/validate.yml
@@ -0,0 +1,215 @@
+---
+- set_fact:
+ system_potentially_has_no_algorithm_support: "{{ ansible_os_family == 'FreeBSD' }}"
+
+- name: "({{ select_crypto_backend }}) Validate privatekey1 idempotency and content returned"
+ assert:
+ that:
+ - privatekey1_idempotence is not changed
+ - privatekey1.privatekey == lookup('file', output_dir ~ '/privatekey1.pem', rstrip=False)
+ - privatekey1.privatekey == privatekey1_idempotence.privatekey
+
+
+- name: "({{ select_crypto_backend }}) Validate privatekey1 (test - RSA key with size 4096 bits)"
+ shell: "{{ openssl_binary }} rsa -noout -text -in {{ output_dir }}/privatekey1.pem | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
+ register: privatekey1
+
+- name: "({{ select_crypto_backend }}) Validate privatekey1 (assert - RSA key with size 4096 bits)"
+ assert:
+ that:
+ - privatekey1.stdout == '4096'
+
+
+- name: "({{ select_crypto_backend }}) Validate privatekey2 (test - RSA key with size 2048 bits)"
+ shell: "{{ openssl_binary }} rsa -noout -text -in {{ output_dir }}/privatekey2.pem | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
+ register: privatekey2
+
+- name: "({{ select_crypto_backend }}) Validate privatekey2 (assert - RSA key with size 2048 bits)"
+ assert:
+ that:
+ - privatekey2.stdout == '2048'
+
+
+- name: "({{ select_crypto_backend }}) Validate privatekey3 (test - DSA key with size 3072 bits)"
+ shell: "{{ openssl_binary }} dsa -noout -text -in {{ output_dir }}/privatekey3.pem | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
+ register: privatekey3
+
+- name: Validate privatekey3 (assert - DSA key with size 3072 bits)
+ assert:
+ that:
+ - privatekey3.stdout == '3072'
+
+
+- name: "({{ select_crypto_backend }}) Validate privatekey4 (test - Ensure key has been removed)"
+ stat:
+ path: '{{ output_dir }}/privatekey4.pem'
+ register: privatekey4
+
+- name: "({{ select_crypto_backend }}) Validate privatekey4 (assert - Ensure key has been removed)"
+ assert:
+ that:
+ - privatekey4.stat.exists == False
+
+- name: "({{ select_crypto_backend }}) Validate privatekey4 removal behavior"
+ assert:
+ that:
+ - privatekey4_delete is changed
+ - privatekey4_delete.privatekey is none
+ - privatekey4_delete_idempotence is not changed
+
+
+- name: "({{ select_crypto_backend }}) Validate privatekey5 (test - Passphrase protected key + idempotence)"
+ shell: "{{ openssl_binary }} rsa -noout -text -in {{ output_dir }}/privatekey5.pem -passin pass:ansible | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
+ register: privatekey5
+ # Current version of OS/X that runs in the CI (10.11) does not have an up to date version of the OpenSSL library
+ # leading to this test to fail when run in the CI. However, this test has been run for 10.12 and has returned succesfully.
+ when: openssl_version.stdout is version('0.9.8zh', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate privatekey5 (assert - Passphrase protected key + idempotence)"
+ assert:
+ that:
+ - privatekey5.stdout == '{{ default_rsa_key_size }}'
+ when: openssl_version.stdout is version('0.9.8zh', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate privatekey5 idempotence (assert - Passphrase protected key + idempotence)"
+ assert:
+ that:
+ - privatekey5_idempotence is not changed
+
+
+- name: "({{ select_crypto_backend }}) Validate privatekey6 (test - Passphrase protected key with non ascii character)"
+ shell: "{{ openssl_binary }} rsa -noout -text -in {{ output_dir }}/privatekey6.pem -passin pass:ànsïblé | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
+ register: privatekey6
+ when: openssl_version.stdout is version('0.9.8zh', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate privatekey6 (assert - Passphrase protected key with non ascii character)"
+ assert:
+ that:
+ - privatekey6.stdout == '{{ default_rsa_key_size }}'
+ when: openssl_version.stdout is version('0.9.8zh', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate ECC generation (dump with OpenSSL)"
+ shell: "{{ openssl_binary }} ec -in {{ output_dir }}/privatekey-{{ item.item.curve }}.pem -noout -text | grep 'ASN1 OID: ' | sed 's/ASN1 OID: \\([^ ]*\\)/\\1/'"
+ loop: "{{ privatekey_ecc_generate.results }}"
+ register: privatekey_ecc_dump
+ when: openssl_version.stdout is version('0.9.8zh', '>=') and 'skip_reason' not in item
+ loop_control:
+ label: "{{ item.item.curve }}"
+
+- name: "({{ select_crypto_backend }}) Validate ECC generation"
+ assert:
+ that:
+ - item is changed
+ loop: "{{ privatekey_ecc_generate.results }}"
+ when: "'skip_reason' not in item"
+ loop_control:
+ label: "{{ item.item.curve }}"
+
+- name: "({{ select_crypto_backend }}) Validate ECC generation (curve type)"
+ assert:
+ that:
+ - "'skip_reason' in item or item.item.item.openssl_name == item.stdout"
+ loop: "{{ privatekey_ecc_dump.results }}"
+ when: "'skip_reason' not in item"
+ loop_control:
+ label: "{{ item.item.item }} - {{ item.stdout if 'stdout' in item else '<unsupported>' }}"
+
+- name: "({{ select_crypto_backend }}) Validate ECC generation idempotency"
+ assert:
+ that:
+ - item is not changed
+ loop: "{{ privatekey_ecc_idempotency.results }}"
+ when: "'skip_reason' not in item"
+ loop_control:
+ label: "{{ item.item.curve }}"
+
+- name: "({{ select_crypto_backend }}) Validate other type generation (just check changed)"
+ assert:
+ that:
+ - (item is succeeded and item is changed) or
+ (item is failed and 'Cryptography backend does not support the algorithm required for ' in item.msg and system_potentially_has_no_algorithm_support)
+ loop: "{{ privatekey_t1_generate.results }}"
+ when: "'skip_reason' not in item"
+ loop_control:
+ label: "{{ item.item.type }}"
+
+- name: "({{ select_crypto_backend }}) Validate other type generation idempotency"
+ assert:
+ that:
+ - (item is succeeded and item is not changed) or
+ (item is failed and 'Cryptography backend does not support the algorithm required for ' in item.msg and system_potentially_has_no_algorithm_support)
+ loop: "{{ privatekey_t1_idempotency.results }}"
+ when: "'skip_reason' not in item"
+ loop_control:
+ label: "{{ item.item.type }}"
+
+- name: "({{ select_crypto_backend }}) Validate passphrase changing"
+ assert:
+ that:
+ - passphrase_1 is changed
+ - passphrase_2 is not changed
+ - passphrase_3 is changed
+ - passphrase_4 is not changed
+ - passphrase_5 is changed
+ - passphrase_1.backup_file is undefined
+ - passphrase_2.backup_file is undefined
+ - passphrase_3.backup_file is string
+ - passphrase_4.backup_file is undefined
+ - passphrase_5.backup_file is string
+
+- name: "({{ select_crypto_backend }}) Verify that broken key will be regenerated"
+ assert:
+ that:
+ - output_broken is changed
+
+- name: "({{ select_crypto_backend }}) Validate remove"
+ assert:
+ that:
+ - remove_1 is changed
+ - remove_2 is not changed
+ - remove_1.backup_file is string
+ - remove_2.backup_file is undefined
+
+- name: "({{ select_crypto_backend }}) Validate mode"
+ assert:
+ that:
+ - privatekey_mode_1 is changed
+ - privatekey_mode_1_stat.stat.mode == '0400'
+ - privatekey_mode_2 is not changed
+ - privatekey_mode_3 is changed
+ - privatekey_mode_3_stat.stat.mode == '0400'
+ - privatekey_mode_1_stat.stat.mtime != privatekey_mode_3_stat.stat.mtime
+
+- name: "({{ select_crypto_backend }}) Validate format 1"
+ assert:
+ that:
+ - privatekey_fmt_1_step_1 is changed
+ - privatekey_fmt_1_step_2 is not changed
+ - privatekey_fmt_1_step_3 is not changed
+ - privatekey_fmt_1_step_4 is changed
+ - privatekey_fmt_1_step_5 is not changed
+ - privatekey_fmt_1_step_6 is not changed
+ - privatekey_fmt_1_step_7 is changed
+ - privatekey_fmt_1_step_8 is failed
+ - privatekey_fmt_1_step_9 is changed
+ - privatekey_fmt_1_step_9_before.public_key == privatekey_fmt_1_step_9_after.public_key
+ when: 'select_crypto_backend == "cryptography"'
+
+- name: "({{ select_crypto_backend }}) Validate format 2 (failed)"
+ assert:
+ that:
+ - system_potentially_has_no_algorithm_support
+ - privatekey_fmt_2_step_1 is failed
+ - "'Cryptography backend does not support the algorithm required for ' in privatekey_fmt_2_step_1.msg"
+ when: 'select_crypto_backend == "cryptography" and cryptography_version.stdout is version("2.6", ">=") and privatekey_fmt_2_step_1 is failed'
+
+- name: "({{ select_crypto_backend }}) Validate format 2"
+ assert:
+ that:
+ - privatekey_fmt_2_step_1 is succeeded and privatekey_fmt_2_step_1 is changed
+ - privatekey_fmt_2_step_2 is succeeded and privatekey_fmt_2_step_2 is not changed
+ - privatekey_fmt_2_step_3 is succeeded and privatekey_fmt_2_step_3 is changed
+ - privatekey_fmt_2_step_4 is succeeded and privatekey_fmt_2_step_4 is not changed
+ - privatekey_fmt_2_step_5 is succeeded and privatekey_fmt_2_step_5 is not changed
+ - privatekey_fmt_2_step_6 is succeeded and privatekey_fmt_2_step_6 is changed
+ when: 'select_crypto_backend == "cryptography" and cryptography_version.stdout is version("2.6", ">=") and privatekey_fmt_2_step_1 is not failed'
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/vars/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/vars/main.yml
new file mode 100644
index 00000000..81eb611f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey/vars/main.yml
@@ -0,0 +1,7 @@
+---
+regenerate_values:
+ - never
+ - fail
+ - partial_idempotence
+ - full_idempotence
+ - always
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/tasks/impl.yml
new file mode 100644
index 00000000..2ecbb48a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/tasks/impl.yml
@@ -0,0 +1,178 @@
+---
+- debug:
+ msg: "Executing tests with backend {{ select_crypto_backend }}"
+
+- name: ({{select_crypto_backend}}) Get key 1 info
+ openssl_privatekey_info:
+ path: '{{ output_dir }}/privatekey_1.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: Check that RSA key info is ok
+ assert:
+ that:
+ - "'public_key' in result"
+ - "'public_key_fingerprints' in result"
+ - "'type' in result"
+ - "result.type == 'RSA'"
+ - "'public_data' in result"
+ - "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
+ - "result.public_data.exponent > 5"
+ - "'private_data' not in result"
+
+- name: Update result list
+ set_fact:
+ info_results: "{{ info_results | combine({'key1': result}) }}"
+
+- name: ({{select_crypto_backend}}) Get key 1 info directly
+ openssl_privatekey_info:
+ content: '{{ lookup("file", output_dir ~ "/privatekey_1.pem") }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result_direct
+
+- name: ({{select_crypto_backend}}) Compare output of direct and loaded info
+ assert:
+ that:
+ - result == result_direct
+
+- name: ({{select_crypto_backend}}) Get key 2 info
+ openssl_privatekey_info:
+ path: '{{ output_dir }}/privatekey_2.pem'
+ return_private_key_data: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: Check that RSA key info is ok
+ assert:
+ that:
+ - "'public_key' in result"
+ - "'public_key_fingerprints' in result"
+ - "'type' in result"
+ - "result.type == 'RSA'"
+ - "'public_data' in result"
+ - "result.public_data.size == default_rsa_key_size"
+ - "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
+ - "result.public_data.exponent > 5"
+ - "'private_data' in result"
+ - "result.public_data.modulus == result.private_data.p * result.private_data.q"
+ - "result.private_data.exponent > 5"
+
+- name: Update result list
+ set_fact:
+ info_results: "{{ info_results | combine({'key2': result}) }}"
+
+- name: ({{select_crypto_backend}}) Get key 3 info (without passphrase)
+ openssl_privatekey_info:
+ path: '{{ output_dir }}/privatekey_3.pem'
+ return_private_key_data: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: result
+
+- name: Check that loading passphrase protected key without passphrase failed
+ assert:
+ that:
+ - result is failed
+ # Check that return values are there
+ - result.can_load_key is defined
+ - result.can_parse_key is defined
+ # Check that return values are correct
+ - result.can_load_key
+ - not result.can_parse_key
+ # Check that additional data isn't there
+ - "'pulic_key' not in result"
+ - "'pulic_key_fingerprints' not in result"
+ - "'type' not in result"
+ - "'public_data' not in result"
+ - "'private_data' not in result"
+
+- name: ({{select_crypto_backend}}) Get key 3 info (with passphrase)
+ openssl_privatekey_info:
+ path: '{{ output_dir }}/privatekey_3.pem'
+ passphrase: hunter2
+ return_private_key_data: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: Check that RSA key info is ok
+ assert:
+ that:
+ - "'public_key' in result"
+ - "'public_key_fingerprints' in result"
+ - "'type' in result"
+ - "result.type == 'RSA'"
+ - "'public_data' in result"
+ - "2 ** (result.public_data.size - 1) < result.public_data.modulus < 2 ** result.public_data.size"
+ - "result.public_data.exponent > 5"
+ - "'private_data' in result"
+ - "result.public_data.modulus == result.private_data.p * result.private_data.q"
+ - "result.private_data.exponent > 5"
+
+- name: Update result list
+ set_fact:
+ info_results: "{{ info_results | combine({'key3': result}) }}"
+
+- name: ({{select_crypto_backend}}) Get key 4 info
+ openssl_privatekey_info:
+ path: '{{ output_dir }}/privatekey_4.pem'
+ return_private_key_data: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- block:
+ - name: Check that ECC key info is ok
+ assert:
+ that:
+ - "'public_key' in result"
+ - "'public_key_fingerprints' in result"
+ - "'type' in result"
+ - "result.type == 'ECC'"
+ - "'public_data' in result"
+ - "result.public_data.curve is string"
+ - "result.public_data.x != 0"
+ - "result.public_data.y != 0"
+ - "result.public_data.exponent_size == (521 if (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6') else 256)"
+ - "'private_data' in result"
+ - "result.private_data.multiplier > 1024"
+
+ - name: Update result list
+ set_fact:
+ info_results: "{{ info_results | combine({'key4': result}) }}"
+ when: select_crypto_backend != 'pyopenssl' or (pyopenssl_version.stdout is version('16.1.0', '>=') and cryptography_version.stdout is version('0.0', '>'))
+
+- name: Check that ECC key info is ok
+ assert:
+ that:
+ - "'public_key' in result"
+ - "'public_key_fingerprints' in result"
+ - "'type' in result"
+ - "result.type.startswith('unknown ')"
+ - "'public_data' in result"
+ - "'private_data' in result"
+ when: select_crypto_backend == 'pyopenssl' and not (pyopenssl_version.stdout is version('16.1.0', '>=') and cryptography_version.stdout is version('0.0', '>'))
+
+- name: ({{select_crypto_backend}}) Get key 5 info
+ openssl_privatekey_info:
+ path: '{{ output_dir }}/privatekey_5.pem'
+ return_private_key_data: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: Check that DSA key info is ok
+ assert:
+ that:
+ - "'public_key' in result"
+ - "'public_key_fingerprints' in result"
+ - "'type' in result"
+ - "result.type == 'DSA'"
+ - "'public_data' in result"
+ - "result.public_data.p > 2"
+ - "result.public_data.q > 2"
+ - "result.public_data.g >= 2"
+ - "result.public_data.y > 2"
+ - "'private_data' in result"
+ - "result.private_data.x > 2"
+
+- name: Update result list
+ set_fact:
+ info_results: "{{ info_results | combine({'key5': result}) }}"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/tasks/main.yml
new file mode 100644
index 00000000..c477d194
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_info/tasks/main.yml
@@ -0,0 +1,77 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Generate privatekey 1
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_1.pem'
+
+- name: Generate privatekey 2 (less bits)
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_2.pem'
+ type: RSA
+ size: '{{ default_rsa_key_size }}'
+
+- name: Generate privatekey 3 (with password)
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_3.pem'
+ passphrase: hunter2
+ cipher: auto
+ size: '{{ default_rsa_key_size }}'
+ select_crypto_backend: cryptography
+
+- name: Generate privatekey 4 (ECC)
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_4.pem'
+ type: ECC
+ curve: "{{ (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6') | ternary('secp521r1', 'secp256k1') }}"
+ # ^ cryptography on CentOS6 doesn't support secp256k1, so we use secp521r1 instead
+ select_crypto_backend: cryptography
+
+- name: Generate privatekey 5 (DSA)
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_5.pem'
+ type: DSA
+ size: 1024
+
+- name: Prepare result list
+ set_fact:
+ info_results: {}
+
+- name: Running tests with pyOpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: pyopenssl
+ when: pyopenssl_version.stdout is version('0.15', '>=')
+
+- name: Prepare result list
+ set_fact:
+ pyopenssl_info_results: "{{ info_results }}"
+ info_results: {}
+
+- name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+ when: cryptography_version.stdout is version('1.2.3', '>=')
+
+- name: Prepare result list
+ set_fact:
+ cryptography_info_results: "{{ info_results }}"
+
+- block:
+ - name: Dump pyOpenSSL results
+ debug:
+ var: pyopenssl_info_results
+ - name: Dump cryptography results
+ debug:
+ var: cryptography_info_results
+ - name: Compare results
+ assert:
+ that:
+ - ' (pyopenssl_info_results[item] | dict2items | rejectattr("key", "equalto", "deprecations") | list | items2dict)
+ == (cryptography_info_results[item] | dict2items | rejectattr("key", "equalto", "deprecations") | list | items2dict)'
+ loop: "{{ pyopenssl_info_results.keys() | intersect(cryptography_info_results.keys()) | list }}"
+ when: pyopenssl_version.stdout is version('0.15', '>=') and cryptography_version.stdout is version('1.2.3', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/tasks/impl.yml
new file mode 100644
index 00000000..bee4fce6
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/tasks/impl.yml
@@ -0,0 +1,103 @@
+---
+- name: ({{select_crypto_backend}}) Create key
+ openssl_privatekey_pipe:
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: ({{select_crypto_backend}}) Get key info
+ openssl_privatekey_info:
+ content: "{{ result.privatekey }}"
+ register: result_info
+
+- assert:
+ that:
+ - result is changed
+ - result.privatekey.startswith('----')
+ - result_info.type == 'RSA'
+ - result_info.public_data.size == 4096
+ - result_info.public_data.exponent >= 5
+
+- assert:
+ that:
+ - result_info.public_key_fingerprints.sha256 | length > 10
+ - result.fingerprint.sha256 == result_info.public_key_fingerprints.sha256
+ when: result.fingerprint is not none
+
+- name: ({{select_crypto_backend}}) Update key (check mode)
+ openssl_privatekey_pipe:
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ content: "{{ result.privatekey }}"
+ size: '{{ default_rsa_key_size }}'
+ register: update_check
+ check_mode: true
+
+- name: ({{select_crypto_backend}}) Update key (check mode, with return_current_key=true)
+ openssl_privatekey_pipe:
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ content: "{{ result.privatekey }}"
+ size: '{{ default_rsa_key_size }}'
+ return_current_key: true
+ register: update_check_return
+ check_mode: true
+
+- name: ({{select_crypto_backend}}) Update key
+ openssl_privatekey_pipe:
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ content: "{{ result.privatekey }}"
+ size: '{{ default_rsa_key_size }}'
+ register: update
+
+- name: ({{select_crypto_backend}}) Update key (idempotent, check mode)
+ openssl_privatekey_pipe:
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ content: "{{ update.privatekey }}"
+ size: '{{ default_rsa_key_size }}'
+ register: update_idempotent_check
+ check_mode: true
+
+- name: ({{select_crypto_backend}}) Update key (idempotent)
+ openssl_privatekey_pipe:
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ content: "{{ update.privatekey }}"
+ size: '{{ default_rsa_key_size }}'
+ register: update_idempotent
+
+- name: ({{select_crypto_backend}}) Update key (idempotent, check mode, with return_current_key=true)
+ openssl_privatekey_pipe:
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ content: "{{ update.privatekey }}"
+ size: '{{ default_rsa_key_size }}'
+ return_current_key: true
+ register: update_idempotent_return_check
+ check_mode: true
+
+- name: ({{select_crypto_backend}}) Update key (idempotent, with return_current_key=true)
+ openssl_privatekey_pipe:
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ content: "{{ update.privatekey }}"
+ size: '{{ default_rsa_key_size }}'
+ return_current_key: true
+ register: update_idempotent_return
+
+- name: ({{select_crypto_backend}}) Get key info
+ openssl_privatekey_info:
+ content: "{{ update.privatekey }}"
+ register: update_info
+
+- assert:
+ that:
+ - update_check is changed
+ - update_check.privatekey == 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER'
+ - update_check_return is changed
+ - update_check_return.privatekey == result.privatekey
+ - update is changed
+ - update.privatekey != result.privatekey
+ - update_info.public_data.size == default_rsa_key_size
+ - update_idempotent_check is not changed
+ - update_idempotent_check.privatekey is undefined
+ - update_idempotent is not changed
+ - update_idempotent.privatekey is undefined
+ - update_idempotent_return_check is not changed
+ - update_idempotent_return_check.privatekey == update.privatekey
+ - update_idempotent_return is not changed
+ - update_idempotent_return.privatekey == update.privatekey
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/tasks/main.yml
new file mode 100644
index 00000000..c8205aeb
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_privatekey_pipe/tasks/main.yml
@@ -0,0 +1,36 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Run module with backend autodetection
+ openssl_privatekey_pipe:
+ size: '{{ default_rsa_key_size }}'
+
+- block:
+ - name: Running tests with pyOpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: pyopenssl
+
+ # FIXME: minimal pyOpenSSL version?!
+ when: pyopenssl_version.stdout is version('0.6', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ when: cryptography_version.stdout is version('0.5', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tasks/impl.yml
new file mode 100644
index 00000000..cfe930fd
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tasks/impl.yml
@@ -0,0 +1,190 @@
+---
+- name: "({{ select_crypto_backend }}) Generate privatekey"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey.pem'
+ size: '{{ default_rsa_key_size }}'
+
+- name: "({{ select_crypto_backend }}) Generate publickey - PEM format"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: publickey
+
+- name: "({{ select_crypto_backend }}) Generate publickey - PEM format (idempotence)"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: publickey_idempotence
+
+- name: "({{ select_crypto_backend }}) Generate publickey - OpenSSH format"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey-ssh.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ format: OpenSSH
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
+
+- name: "({{ select_crypto_backend }}) Generate publickey - OpenSSH format - test idempotence (issue 33256)"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey-ssh.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ format: OpenSSH
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
+ register: publickey_ssh_idempotence
+
+- name: "({{ select_crypto_backend }}) Generate publickey2 - standard"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey2.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Delete publickey2 - standard"
+ openssl_publickey:
+ state: absent
+ path: '{{ output_dir }}/publickey2.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: publickey2_absent
+
+- name: "({{ select_crypto_backend }}) Delete publickey2 - standard (idempotence)"
+ openssl_publickey:
+ state: absent
+ path: '{{ output_dir }}/publickey2.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: publickey2_absent_idempotence
+
+- name: "({{ select_crypto_backend }}) Generate privatekey3 - with passphrase"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey3.pem'
+ passphrase: ansible
+ cipher: aes256
+ size: '{{ default_rsa_key_size }}'
+
+- name: "({{ select_crypto_backend }}) Generate publickey3 - with passphrase protected privatekey"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey3.pub'
+ privatekey_path: '{{ output_dir }}/privatekey3.pem'
+ privatekey_passphrase: ansible
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Generate publickey3 - with passphrase protected privatekey - idempotence"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey3.pub'
+ privatekey_path: '{{ output_dir }}/privatekey3.pem'
+ privatekey_passphrase: ansible
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: publickey3_idempotence
+
+- name: "({{ select_crypto_backend }}) Generate empty file that will hold a public key (issue 33072)"
+ file:
+ path: '{{ output_dir }}/publickey4.pub'
+ state: touch
+
+- name: "({{ select_crypto_backend }}) Generate publickey in empty existing file (issue 33072)"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey4.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "({{ select_crypto_backend }}) Generate privatekey 5 (ECC)"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey5.pem'
+ type: ECC
+ curve: secp256r1
+ size: '{{ default_rsa_key_size }}'
+
+- name: "({{ select_crypto_backend }}) Generate publickey 5 - PEM format"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey5.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey5_1
+- name: "({{ select_crypto_backend }}) Generate publickey 5 - PEM format (idempotent)"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey5.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey5_2
+- name: "({{ select_crypto_backend }}) Generate publickey 5 - PEM format (different private key)"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey5.pub'
+ privatekey_path: '{{ output_dir }}/privatekey5.pem'
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: privatekey5_3
+
+- name: "({{ select_crypto_backend }}) Generate privatekey with password"
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: auto
+ select_crypto_backend: cryptography
+ size: '{{ default_rsa_key_size }}'
+
+- name: "({{ select_crypto_backend }}) Generate publickey - PEM format (failed passphrase 1)"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey_pw1.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ privatekey_passphrase: hunter2
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_1
+
+- name: "({{ select_crypto_backend }}) Generate publickey - PEM format (failed passphrase 2)"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey_pw2.pub'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ privatekey_passphrase: wrong_password
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_2
+
+- name: "({{ select_crypto_backend }}) Generate publickey - PEM format (failed passphrase 3)"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey_pw3.pub'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_3
+
+- name: "({{ select_crypto_backend }}) Create broken key"
+ copy:
+ dest: "{{ output_dir }}/publickeybroken.pub"
+ content: "broken"
+- name: "({{ select_crypto_backend }}) Regenerate broken key"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickeybroken.pub'
+ privatekey_path: '{{ output_dir }}/privatekey5.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: output_broken
+
+- name: "({{ select_crypto_backend }}) Generate publickey - PEM format (for removal)"
+ openssl_publickey:
+ path: '{{ output_dir }}/publickey_removal.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+- name: "({{ select_crypto_backend }}) Generate publickey - PEM format (removal)"
+ openssl_publickey:
+ state: absent
+ path: '{{ output_dir }}/publickey_removal.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: remove_1
+- name: "({{ select_crypto_backend }}) Generate publickey - PEM format (removal, idempotent)"
+ openssl_publickey:
+ state: absent
+ path: '{{ output_dir }}/publickey_removal.pub'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: remove_2
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tasks/main.yml
new file mode 100644
index 00000000..eb423054
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tasks/main.yml
@@ -0,0 +1,54 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- block:
+ - name: Generate privatekey1 - standard
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_autodetect.pem'
+ size: '{{ default_rsa_key_size }}'
+
+ - name: Run module with backend autodetection
+ openssl_publickey:
+ path: '{{ output_dir }}/privatekey_autodetect_public.pem'
+ privatekey_path: '{{ output_dir }}/privatekey_autodetect.pem'
+
+ when: |
+ pyopenssl_version.stdout is version('16.0.0', '>=') or
+ cryptography_version.stdout is version('1.2.3', '>=')
+
+- block:
+ - name: Running tests with pyOpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: pyopenssl
+
+ - import_tasks: ../tests/validate.yml
+ vars:
+ select_crypto_backend: pyopenssl
+
+ when: pyopenssl_version.stdout is version('16.0.0', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ - import_tasks: ../tests/validate.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ when: cryptography_version.stdout is version('1.2.3', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tests/validate.yml
new file mode 100644
index 00000000..34e67b54
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_publickey/tests/validate.yml
@@ -0,0 +1,146 @@
+---
+- name: "({{ select_crypto_backend }}) Validate publickey 1 idempotence and result behavior"
+ assert:
+ that:
+ - publickey is changed
+ - publickey_idempotence is not changed
+ - publickey.publickey == lookup('file', output_dir ~ '/publickey.pub', rstrip=False)
+ - publickey.publickey == publickey_idempotence.publickey
+
+- name: "({{ select_crypto_backend }}) Validate public key (test - privatekey modulus)"
+ shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ output_dir }}/privatekey.pem'
+ register: privatekey_modulus
+
+- name: "({{ select_crypto_backend }}) Validate public key (test - publickey modulus)"
+ shell: '{{ openssl_binary }} rsa -pubin -noout -modulus < {{ output_dir }}/publickey.pub'
+ register: publickey_modulus
+
+- name: "({{ select_crypto_backend }}) Validate public key (assert)"
+ assert:
+ that:
+ - publickey_modulus.stdout == privatekey_modulus.stdout
+
+- name: "({{ select_crypto_backend }}) Validate public key - OpenSSH format (test - privatekey's publickey)"
+ shell: 'ssh-keygen -y -f {{ output_dir }}/privatekey.pem'
+ register: privatekey_publickey
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate public key - OpenSSH format (test - publickey)"
+ slurp:
+ src: '{{ output_dir }}/publickey-ssh.pub'
+ register: publickey
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate public key - OpenSSH format (assert)"
+ assert:
+ that:
+ - privatekey_publickey.stdout == '{{ publickey.content|b64decode }}'
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate public key - OpenSSH format - test idempotence (issue 33256)"
+ assert:
+ that:
+ - publickey_ssh_idempotence is not changed
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.4.0', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate publickey2 (test - Ensure key has been removed)"
+ stat:
+ path: '{{ output_dir }}/publickey2.pub'
+ register: publickey2
+
+- name: "({{ select_crypto_backend }}) Validate publickey2 (assert - Ensure key has been removed)"
+ assert:
+ that:
+ - publickey2.stat.exists == False
+
+- name: "({{ select_crypto_backend }}) Validate publickey2 removal behavior"
+ assert:
+ that:
+ - publickey2_absent is changed
+ - publickey2_absent_idempotence is not changed
+ - publickey2_absent.publickey is none
+
+
+- name: "({{ select_crypto_backend }}) Validate publickey3 (test - privatekey modulus)"
+ shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ output_dir }}/privatekey3.pem -passin pass:ansible'
+ register: privatekey3_modulus
+ when: openssl_version.stdout is version('0.9.8zh', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate publickey3 (test - publickey modulus)"
+ shell: '{{ openssl_binary }} rsa -pubin -noout -modulus < {{ output_dir }}/publickey3.pub'
+ register: publickey3_modulus
+ when: openssl_version.stdout is version('0.9.8zh', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate publickey3 (assert)"
+ assert:
+ that:
+ - publickey3_modulus.stdout == privatekey3_modulus.stdout
+ when: openssl_version.stdout is version('0.9.8zh', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate publickey3 idempotence (assert)"
+ assert:
+ that:
+ - publickey3_idempotence is not changed
+
+- name: "({{ select_crypto_backend }}) Validate publickey4 (test - privatekey modulus)"
+ shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ output_dir }}/privatekey.pem'
+ register: privatekey4_modulus
+ when: openssl_version.stdout is version('0.9.8zh', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate publickey4 (test - publickey modulus)"
+ shell: '{{ openssl_binary }} rsa -pubin -noout -modulus < {{ output_dir }}/publickey4.pub'
+ register: publickey4_modulus
+ when: openssl_version.stdout is version('0.9.8zh', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate publickey4 (assert)"
+ assert:
+ that:
+ - publickey4_modulus.stdout == privatekey4_modulus.stdout
+ when: openssl_version.stdout is version('0.9.8zh', '>=')
+
+- name: "({{ select_crypto_backend }}) Validate idempotency and backup"
+ assert:
+ that:
+ - privatekey5_1 is changed
+ - privatekey5_1.backup_file is undefined
+ - privatekey5_2 is not changed
+ - privatekey5_2.backup_file is undefined
+ - privatekey5_3 is changed
+ - privatekey5_3.backup_file is string
+
+- name: "({{ select_crypto_backend }}) Validate public key 5 (test - privatekey's pubkey)"
+ command: '{{ openssl_binary }} ec -in {{ output_dir }}/privatekey5.pem -pubout'
+ register: privatekey5_pubkey
+
+- name: "({{ select_crypto_backend }}) Validate public key 5 (test - publickey pubkey)"
+ # Fancy way of writing "cat {{ output_dir }}/publickey5.pub"
+ command: '{{ openssl_binary }} ec -pubin -in {{ output_dir }}/publickey5.pub -pubout'
+ register: publickey5_pubkey
+
+- name: "({{ select_crypto_backend }}) Validate public key 5 (assert)"
+ assert:
+ that:
+ - publickey5_pubkey.stdout == privatekey5_pubkey.stdout
+
+- name:
+ assert:
+ that:
+ - passphrase_error_1 is failed
+ - "'assphrase' in passphrase_error_1.msg or 'assword' in passphrase_error_1.msg"
+ - passphrase_error_2 is failed
+ - "'assphrase' in passphrase_error_2.msg or 'assword' in passphrase_error_2.msg or 'serializ' in passphrase_error_2.msg"
+ - passphrase_error_3 is failed
+ - "'assphrase' in passphrase_error_3.msg or 'assword' in passphrase_error_3.msg or 'serializ' in passphrase_error_3.msg"
+
+- name: "({{ select_crypto_backend }}) Verify that broken key will be regenerated"
+ assert:
+ that:
+ - output_broken is changed
+
+- name: "({{ select_crypto_backend }}) Validate remove"
+ assert:
+ that:
+ - remove_1 is changed
+ - remove_2 is not changed
+ - remove_1.backup_file is string
+ - remove_2.backup_file is undefined
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/aliases
new file mode 100644
index 00000000..5a35a4b5
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/aliases
@@ -0,0 +1,3 @@
+shippable/posix/group1
+openssl_signature_info
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/tasks/loop.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/tasks/loop.yml
new file mode 100644
index 00000000..c33a6091
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/tasks/loop.yml
@@ -0,0 +1,28 @@
+---
+# This file is intended to be included in a loop statement
+- name: Sign statement with {{ item.type }} key - {{ item.passwd }} using {{ item.backend }}
+ openssl_signature:
+ privatekey_path: '{{ output_dir }}/{{item.backend}}_privatekey_{{ item.type }}_{{ item.passwd }}.pem'
+ privatekey_passphrase: '{{ item.privatekey_passphrase | default(omit) }}'
+ path: '{{ output_dir }}/statement.txt'
+ select_crypto_backend: '{{ item.backend }}'
+ register: sign_result
+
+- debug:
+ var: sign_result
+
+- name: Verify {{ item.type }} signature - {{ item.passwd }} using {{ item.backend }}
+ openssl_signature_info:
+ certificate_path: '{{ output_dir }}/{{item.backend}}_certificate_{{ item.type }}_{{ item.passwd }}.pem'
+ path: '{{ output_dir }}/statement.txt'
+ signature: '{{ sign_result.signature }}'
+ select_crypto_backend: '{{ item.backend }}'
+ register: verify_result
+
+- name: Make sure the signature is valid
+ assert:
+ that:
+ - verify_result.valid
+
+- debug:
+ var: verify_result
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/tasks/main.yml
new file mode 100644
index 00000000..b0b97c89
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/openssl_signature/tasks/main.yml
@@ -0,0 +1,113 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+# Test matrix:
+# * pyopenssl or cryptography
+# * DSA or ECC or ...
+# * password protected private key or not
+
+- name: Set up test combinations
+ set_fact:
+ all_tests: []
+ backends: []
+ key_types: []
+ key_password:
+ - passwd: nopasswd
+ - passwd: passwd
+ privatekey_passphrase: hunter2
+ privatekey_cipher: auto
+
+- name: Add cryptography backend
+ set_fact:
+ backends: "{{ backends + [ { 'backend': 'cryptography' } ] }}"
+ when: cryptography_version.stdout is version('1.4', '>=')
+
+- name: Add pyopenssl backend
+ set_fact:
+ backends: "{{ backends + [ { 'backend': 'pyopenssl' } ] }}"
+ when: pyopenssl_version.stdout is version('0.11', '>=')
+
+- name: Add RSA tests
+ set_fact:
+ key_types: "{{ key_types + [ { 'type': 'RSA', 'size': default_rsa_key_size } ] }}"
+ when: cryptography_version.stdout is version('1.4', '>=')
+
+- name: Add DSA + ECDSA tests
+ set_fact:
+ key_types: "{{ key_types + [ { 'type': 'DSA', 'size': 2048 }, { 'type': 'ECC', 'curve': 'secp256r1' } ] }}"
+ when:
+ - cryptography_version.stdout is version('1.5', '>=')
+ # FreeBSD 11 fails on secp256r1 keys
+ - not ansible_os_family == 'FreeBSD'
+
+- name: Add Ed25519 + Ed448 tests
+ set_fact:
+ key_types: "{{ key_types + [ { 'type': 'Ed25519' }, { 'type': 'Ed448' } ] }}"
+ when:
+ # The module under tests works with >= 2.6, but we also need to be able to create a certificate which requires 2.8
+ - cryptography_version.stdout is version('2.8', '>=')
+ # FreeBSD doesn't have support for Ed448/25519
+ - not ansible_os_family == 'FreeBSD'
+
+- name: Create all test combinations
+ set_fact:
+ # Explanation: see https://serverfault.com/a/1004124
+ all_tests: >-
+ [
+ {% for b in backends %}
+ {% for kt in key_types %}
+ {% for kp in key_password %}
+ {# Exclude Ed25519 and Ed448 tests on pyopenssl #}
+ {% if not (b.backend == 'pyopenssl' and (kt.type == 'Ed25519' or kt.type == 'Ed448')) %}
+ {{ b | combine (kt) | combine(kp) }},
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+ {% endfor %}
+ ]
+
+- name: Generate private keys
+ openssl_privatekey:
+ path: '{{ output_dir }}/{{item.backend}}_privatekey_{{ item.type }}_{{ item.passwd }}.pem'
+ type: '{{ item.type }}'
+ curve: '{{ item.curve | default(omit) }}'
+ size: '{{ item.size | default(omit) }}'
+ passphrase: '{{ item.privatekey_passphrase | default(omit) }}'
+ cipher: '{{ item.privatekey_cipher | default(omit) }}'
+ select_crypto_backend: cryptography
+ loop: '{{ all_tests }}'
+
+- name: Generate public keys
+ openssl_publickey:
+ path: '{{ output_dir }}/{{item.backend}}_publickey_{{ item.type }}_{{ item.passwd }}.pem'
+ privatekey_path: '{{ output_dir }}/{{item.backend}}_privatekey_{{ item.type }}_{{ item.passwd }}.pem'
+ privatekey_passphrase: '{{ item.privatekey_passphrase | default(omit) }}'
+ loop: '{{ all_tests }}'
+
+- name: Generate CSRs
+ openssl_csr:
+ path: '{{ output_dir }}/{{item.backend}}_{{ item.type }}_{{ item.passwd }}.csr'
+ privatekey_path: '{{ output_dir }}/{{item.backend}}_privatekey_{{ item.type }}_{{ item.passwd }}.pem'
+ privatekey_passphrase: '{{ item.privatekey_passphrase | default(omit) }}'
+ loop: '{{ all_tests }}'
+
+- name: Generate selfsigned certificates
+ x509_certificate:
+ provider: selfsigned
+ path: '{{ output_dir }}/{{item.backend}}_certificate_{{ item.type }}_{{ item.passwd }}.pem'
+ privatekey_path: '{{ output_dir }}/{{item.backend}}_privatekey_{{ item.type }}_{{ item.passwd }}.pem'
+ privatekey_passphrase: '{{ item.privatekey_passphrase | default(omit) }}'
+ csr_path: '{{ output_dir }}/{{item.backend}}_{{ item.type }}_{{ item.passwd }}.csr'
+ loop: '{{ all_tests }}'
+
+- name: Create statement to be signed
+ copy:
+ content: "Erst wenn der Subwoofer die Katze inhaliert, fickt der Bass richtig übel. -- W.A. Mozart"
+ dest: '{{ output_dir }}/statement.txt'
+
+- name: Loop over all variants
+ include_tasks: loop.yml
+ loop: '{{ all_tests }}'
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/defaults/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/defaults/main.yml
new file mode 100644
index 00000000..a1e5b8d1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/defaults/main.yml
@@ -0,0 +1,4 @@
+badssl_host: wrong.host.badssl.com
+httpbin_host: httpbin.org
+sni_host: ci-files.testing.ansible.com
+badssl_host_substring: wrong.host.badssl.com
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/meta/main.yml
new file mode 100644
index 00000000..1810d4be
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_remote_tmp_dir
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/tasks/default.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/tasks/default.yml
new file mode 100644
index 00000000..bff90350
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/tasks/default.yml
@@ -0,0 +1,64 @@
+- name: RedHat - Enable the dynamic CA configuration feature
+ command: update-ca-trust force-enable
+ when: ansible_os_family == 'RedHat'
+
+- name: RedHat - Retrieve test cacert
+ get_url:
+ url: "http://ansible.http.tests/cacert.pem"
+ dest: "/etc/pki/ca-trust/source/anchors/ansible.pem"
+ when: ansible_os_family == 'RedHat'
+
+- name: Get client cert/key
+ get_url:
+ url: "http://ansible.http.tests/{{ item }}"
+ dest: "{{ remote_tmp_dir }}/{{ item }}"
+ with_items:
+ - client.pem
+ - client.key
+
+- name: Suse - Retrieve test cacert
+ get_url:
+ url: "http://ansible.http.tests/cacert.pem"
+ dest: "/etc/pki/trust/anchors/ansible.pem"
+ when: ansible_os_family == 'Suse'
+
+- name: Debian - Retrieve test cacert
+ get_url:
+ url: "http://ansible.http.tests/cacert.pem"
+ dest: "/usr/local/share/ca-certificates/ansible.crt"
+ when: ansible_os_family == 'Debian'
+
+- name: Redhat - Update ca trust
+ command: update-ca-trust extract
+ when: ansible_os_family == 'RedHat'
+
+- name: Debian/Suse - Update ca certificates
+ command: update-ca-certificates
+ when: ansible_os_family == 'Debian' or ansible_os_family == 'Suse'
+
+- name: FreeBSD - Retrieve test cacert
+ get_url:
+ url: "http://ansible.http.tests/cacert.pem"
+ dest: "/tmp/ansible.pem"
+ when: ansible_os_family == 'FreeBSD'
+
+- name: FreeBSD - Add cacert to root certificate store
+ blockinfile:
+ path: "/etc/ssl/cert.pem"
+ block: "{{ lookup('file', '/tmp/ansible.pem') }}"
+ when: ansible_os_family == 'FreeBSD'
+
+- name: MacOS - Retrieve test cacert
+ when: ansible_os_family == 'Darwin'
+ block:
+ - uri:
+ url: "http://ansible.http.tests/cacert.pem"
+ return_content: true
+ register: cacert_pem
+
+ - raw: '{{ ansible_python_interpreter }} -c "import ssl; print(ssl.get_default_verify_paths().cafile)"'
+ register: macos_cafile
+
+ - blockinfile:
+ path: "{{ macos_cafile.stdout_lines|first }}"
+ block: "{{ cacert_pem.content }}"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/tasks/main.yml
new file mode 100644
index 00000000..49e1fa20
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/tasks/main.yml
@@ -0,0 +1,27 @@
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+# The docker --link functionality gives us an ENV var we can key off of to see if we have access to
+# the httptester container
+- set_fact:
+ has_httptester: "{{ lookup('env', 'HTTPTESTER') != '' }}"
+
+- name: make sure we have the ansible_os_family and ansible_distribution_version facts
+ setup:
+ gather_subset: distribution
+ when: ansible_facts == {}
+
+# If we are running with access to a httptester container, grab it's cacert and install it
+- block:
+ # Override hostname defaults with httptester linked names
+ - include_vars: httptester.yml
+
+ - include_tasks: "{{ lookup('first_found', files)}}"
+ vars:
+ files:
+ - "{{ ansible_os_family | lower }}.yml"
+ - "default.yml"
+ when:
+ - has_httptester|bool
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/vars/httptester.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/vars/httptester.yml
new file mode 100644
index 00000000..0e23ae93
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_http_tests/vars/httptester.yml
@@ -0,0 +1,5 @@
+# these are fake hostnames provided by docker link for the httptester container
+badssl_host: fail.ansible.http.tests
+httpbin_host: ansible.http.tests
+sni_host: sni1.ansible.http.tests
+badssl_host_substring: HTTP Client Testing Service
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_tests/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_tests/tasks/main.yml
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/prepare_tests/tasks/main.yml
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/meta/main.yml
new file mode 100644
index 00000000..96d5b2b8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies: []
+# - setup_openssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/tasks/main.yml
new file mode 100644
index 00000000..b18e5872
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/tasks/main.yml
@@ -0,0 +1,22 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+# BEGIN HACK: remove whenever we know how to properly detect 'default' docker container !!!!!!!!!!!!!!!!!!!!!
+- name: Default value for OpenSSL binary path
+ set_fact:
+ openssl_binary: openssl
+
+- name: Register openssl version
+ shell: "{{ openssl_binary }} version | cut -d' ' -f2"
+ register: openssl_version
+
+- name: Register cryptography version
+ command: "{{ ansible_python.executable }} -c 'import cryptography; print(cryptography.__version__)'"
+ register: cryptography_version
+# END HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+- debug:
+ msg: "ACME test container IP is {{ acme_host }}; OpenSSL version is {{ openssl_version.stdout }}; cryptography version is {{ cryptography_version.stdout }}"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/tasks/obtain-cert.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/tasks/obtain-cert.yml
new file mode 100644
index 00000000..ec53510b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/tasks/obtain-cert.yml
@@ -0,0 +1,144 @@
+---
+## PRIVATE KEY ################################################################################
+- name: ({{ certgen_title }}) Create cert private key (RSA)
+ command: "{{ openssl_binary }} genrsa -out {{ output_dir }}/{{ certificate_name }}.key {{ rsa_bits if key_type == 'rsa' else default_rsa_key_size }}"
+ when: "key_type == 'rsa'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 256)
+ command: "{{ openssl_binary }} ecparam -name prime256v1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec256'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 384)
+ command: "{{ openssl_binary }} ecparam -name secp384r1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec384'"
+- name: ({{ certgen_title }}) Create cert private key (ECC 512)
+ command: "{{ openssl_binary }} ecparam -name secp521r1 -genkey -out {{ output_dir }}/{{ certificate_name }}.key"
+ when: "key_type == 'ec521'"
+## CSR ########################################################################################
+- name: ({{ certgen_title }}) Create cert CSR
+ openssl_csr:
+ path: "{{ output_dir }}/{{ certificate_name }}.csr"
+ privatekey_path: "{{ output_dir }}/{{ certificate_name }}.key"
+ subject_alt_name: "{{ subject_alt_name }}"
+ subject_alt_name_critical: "{{ subject_alt_name_critical }}"
+ return_content: true
+ register: csr_result
+## ACME STEP 1 ################################################################################
+- name: ({{ certgen_title }}) Obtain cert, step 1
+ acme_certificate:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_key: "{{ (output_dir ~ '/' ~ account_key ~ '.pem') if account_key_content is not defined else omit }}"
+ account_key_content: "{{ account_key_content | default(omit) }}"
+ modify_account: "{{ modify_account }}"
+ csr: "{{ omit if use_csr_content | default(false) else output_dir ~ '/' ~ certificate_name ~ '.csr' }}"
+ csr_content: "{{ csr_result.csr if use_csr_content | default(false) else omit }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}.pem"
+ fullchain_dest: "{{ output_dir }}/{{ certificate_name }}-fullchain.pem"
+ chain_dest: "{{ output_dir }}/{{ certificate_name }}-chain.pem"
+ challenge: "{{ challenge }}"
+ deactivate_authzs: "{{ deactivate_authzs }}"
+ force: "{{ force }}"
+ remaining_days: "{{ remaining_days }}"
+ terms_agreed: "{{ terms_agreed }}"
+ account_email: "{{ account_email }}"
+ register: challenge_data
+- name: ({{ certgen_title }}) Print challenge data
+ debug:
+ var: challenge_data
+- name: ({{ certgen_title }}) Create HTTP challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/http/{{ item.key }}/{{ item.value['http-01'].resource[('.well-known/acme-challenge/'|length):] }}"
+ method: PUT
+ body_format: raw
+ body: "{{ item.value['http-01'].resource_value }}"
+ headers:
+ content-type: "application/octet-stream"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'http-01'"
+- name: ({{ certgen_title }}) Create DNS challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/dns/{{ item.key }}"
+ method: PUT
+ body_format: json
+ body: "{{ item.value }}"
+ with_dict: "{{ challenge_data.challenge_data_dns }}"
+ when: "challenge_data is changed and challenge == 'dns-01'"
+- name: ({{ certgen_title }}) Create TLS ALPN challenges (acm_challenge_cert_helper)
+ acme_challenge_cert_helper:
+ challenge: tls-alpn-01
+ challenge_data: "{{ item.value['tls-alpn-01'] }}"
+ private_key_src: "{{ output_dir }}/{{ certificate_name }}.key"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ register: tls_alpn_challenges
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is defined and challenge_alpn_tls == 'acme_challenge_cert_helper')"
+- name: ({{ certgen_title }}) Set TLS ALPN challenges (acm_challenge_cert_helper)
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.domain }}/{{ item.identifier }}/certificate-and-key"
+ method: PUT
+ body_format: raw
+ body: "{{ item.challenge_certificate }}\n{{ lookup('file', output_dir ~ '/' ~ certificate_name ~ '.key') }}"
+ headers:
+ content-type: "application/pem-certificate-chain"
+ with_items: "{{ tls_alpn_challenges.results }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is defined and challenge_alpn_tls == 'acme_challenge_cert_helper')"
+- name: ({{ certgen_title }}) Create TLS ALPN challenges (der-value-b64)
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.value['tls-alpn-01'].resource }}/{{ item.value['tls-alpn-01'].resource_original }}/der-value-b64"
+ method: PUT
+ body_format: raw
+ body: "{{ item.value['tls-alpn-01'].resource_value }}"
+ headers:
+ content-type: "application/octet-stream"
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls is not defined or challenge_alpn_tls == 'der-value-b64')"
+## ACME STEP 2 ################################################################################
+- name: ({{ certgen_title }}) Obtain cert, step 2
+ acme_certificate:
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ acme_version: 2
+ acme_directory: https://{{ acme_host }}:14000/dir
+ validate_certs: no
+ account_key: "{{ (output_dir ~ '/' ~ account_key ~ '.pem') if account_key_content is not defined else omit }}"
+ account_key_content: "{{ account_key_content | default(omit) }}"
+ account_uri: "{{ challenge_data.account_uri }}"
+ modify_account: "{{ modify_account }}"
+ csr: "{{ omit if use_csr_content | default(false) else output_dir ~ '/' ~ certificate_name ~ '.csr' }}"
+ csr_content: "{{ csr_result.csr if use_csr_content | default(false) else omit }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}.pem"
+ fullchain_dest: "{{ output_dir }}/{{ certificate_name }}-fullchain.pem"
+ chain_dest: "{{ output_dir }}/{{ certificate_name }}-chain.pem"
+ challenge: "{{ challenge }}"
+ deactivate_authzs: "{{ deactivate_authzs }}"
+ force: "{{ force }}"
+ remaining_days: "{{ remaining_days }}"
+ terms_agreed: "{{ terms_agreed }}"
+ account_email: "{{ account_email }}"
+ data: "{{ challenge_data }}"
+ retrieve_all_alternates: "{{ retrieve_all_alternates | default(omit) }}"
+ select_chain: "{{ select_chain | default(omit) if select_crypto_backend == 'cryptography' else omit }}"
+ register: certificate_obtain_result
+ when: challenge_data is changed
+- name: ({{ certgen_title }}) Deleting HTTP challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/http/{{ item.key }}/{{ item.value['http-01'].resource[('.well-known/acme-challenge/'|length):] }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'http-01'"
+- name: ({{ certgen_title }}) Deleting DNS challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/dns/{{ item.key }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data_dns }}"
+ when: "challenge_data is changed and challenge == 'dns-01'"
+- name: ({{ certgen_title }}) Deleting TLS ALPN challenges
+ uri:
+ url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.value['tls-alpn-01'].resource }}"
+ method: DELETE
+ with_dict: "{{ challenge_data.challenge_data }}"
+ when: "challenge_data is changed and challenge == 'tls-alpn-01'"
+- name: ({{ certgen_title }}) Get root certificate
+ get_url:
+ url: "http://{{ acme_host }}:5000/root-certificate-for-ca/{{ acme_expected_root_number | default(0) if select_crypto_backend == 'cryptography' else 0 }}"
+ dest: "{{ output_dir }}/{{ certificate_name }}-root.pem"
+###############################################################################################
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/vars/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/vars/main.yml
new file mode 100644
index 00000000..f2b772af
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_acme/vars/main.yml
@@ -0,0 +1,9 @@
+---
+default_rsa_key_size: 1024
+default_rsa_key_size_certifiates: >-
+ {{
+ 2048 if
+ (ansible_os_family == "RedHat" and ansible_facts.distribution_major_version | int >= 8) or
+ (ansible_distribution == "Ubuntu" and ansible_facts.distribution_major_version | int >= 20)
+ else 1024
+ }}
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/meta/main.yml
new file mode 100644
index 00000000..2be15776
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_remote_constraints
+ - setup_pkg_mgr
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/tasks/main.yml
new file mode 100644
index 00000000..907f44b7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/tasks/main.yml
@@ -0,0 +1,102 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Register system environment
+ command: "{{ ansible_python.executable }} -c 'import os; print(dict(os.environ))'"
+ register: sys_environment
+
+- debug: var=sys_environment
+
+- name: Default value for OpenSSL binary path
+ set_fact:
+ openssl_binary: openssl
+
+- name: Include OS-specific variables
+ include_vars: '{{ ansible_os_family }}.yml'
+ when: not ansible_os_family == "Darwin"
+
+- name: Install OpenSSL
+ become: true
+ package:
+ name: '{{ openssl_package_name }}'
+ when: not ansible_os_family == 'Darwin'
+
+- name: Register openssl version (full)
+ shell: "{{ openssl_binary }} version"
+ register: openssl_version_full
+
+- name: Show openssl version (full)
+ debug:
+ var: openssl_version_full.stdout_lines
+
+- when: ansible_os_family == "Darwin" and "LibreSSL" in openssl_version_full.stdout
+ # In case LibreSSL is installed on macOS, we need to install a more modern OpenSSL
+ block:
+ - name: MACOS | Find brew binary
+ command: which brew
+ register: brew_which
+
+ - name: MACOS | Get owner of brew binary
+ stat:
+ path: "{{ brew_which.stdout }}"
+ register: brew_stat
+
+ - name: MACOS | Install openssl
+ homebrew:
+ name: openssl
+ state: present
+ become: yes
+ become_user: "{{ brew_stat.stat.pw_name }}"
+
+ - name: MACOS | Locale openssl binary
+ command: brew --prefix openssl
+ register: brew_openssl_prefix
+
+ - name: MACOS | Point to OpenSSL binary
+ set_fact:
+ openssl_binary: "{{ brew_openssl_prefix.stdout }}/bin/openssl"
+
+ - name: MACOS | Register openssl version (full)
+ shell: "{{ openssl_binary }} version"
+ register: openssl_version_full_again
+ # We must use a different variable to prevent the 'when' condition of the surrounding block to fail
+
+ - name: MACOS | Show openssl version (full)
+ debug:
+ var: openssl_version_full_again.stdout_lines
+
+- name: Register openssl version
+ shell: "{{ openssl_binary }} version | cut -d' ' -f2"
+ register: openssl_version
+
+- when: ansible_facts.distribution ~ ansible_facts.distribution_major_version not in ['CentOS6', 'RedHat6']
+ block:
+ - name: Install cryptography (Python 3)
+ become: true
+ package:
+ name: '{{ cryptography_package_name_python3 }}'
+ when: not ansible_os_family == 'Darwin' and ansible_python_version is version('3.0', '>=')
+
+ - name: Install cryptography (Python 2)
+ become: true
+ package:
+ name: '{{ cryptography_package_name }}'
+ when: not ansible_os_family == 'Darwin' and ansible_python_version is version('3.0', '<')
+
+ - name: Install cryptography (Darwin)
+ become: true
+ pip:
+ name: cryptography
+ extra_args: "-c {{ remote_constraints }}"
+ when: ansible_os_family == 'Darwin'
+
+- name: Register cryptography version
+ command: "{{ ansible_python.executable }} -c 'import cryptography; print(cryptography.__version__)'"
+ register: cryptography_version
+
+- name: Print default key sizes
+ debug:
+ msg: "Default RSA key size: {{ default_rsa_key_size }} (for certificates: {{ default_rsa_key_size_certifiates }})"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/Debian.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/Debian.yml
new file mode 100644
index 00000000..810d314c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/Debian.yml
@@ -0,0 +1,4 @@
+---
+openssl_package_name: openssl
+cryptography_package_name: python-cryptography
+cryptography_package_name_python3: python3-cryptography
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/FreeBSD.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/FreeBSD.yml
new file mode 100644
index 00000000..4040bda4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/FreeBSD.yml
@@ -0,0 +1,4 @@
+---
+openssl_package_name: openssl
+cryptography_package_name: py27-cryptography
+cryptography_package_name_python3: "py{{ ansible_python.version.major }}{{ ansible_python.version.minor }}-cryptography"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/RedHat.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/RedHat.yml
new file mode 100644
index 00000000..810d314c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/RedHat.yml
@@ -0,0 +1,4 @@
+---
+openssl_package_name: openssl
+cryptography_package_name: python-cryptography
+cryptography_package_name_python3: python3-cryptography
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/Suse.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/Suse.yml
new file mode 100644
index 00000000..810d314c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/Suse.yml
@@ -0,0 +1,4 @@
+---
+openssl_package_name: openssl
+cryptography_package_name: python-cryptography
+cryptography_package_name_python3: python3-cryptography
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/main.yml
new file mode 100644
index 00000000..f2b772af
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_openssl/vars/main.yml
@@ -0,0 +1,9 @@
+---
+default_rsa_key_size: 1024
+default_rsa_key_size_certifiates: >-
+ {{
+ 2048 if
+ (ansible_os_family == "RedHat" and ansible_facts.distribution_major_version | int >= 8) or
+ (ansible_distribution == "Ubuntu" and ansible_facts.distribution_major_version | int >= 20)
+ else 1024
+ }}
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pkg_mgr/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pkg_mgr/tasks/main.yml
new file mode 100644
index 00000000..eeecb835
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pkg_mgr/tasks/main.yml
@@ -0,0 +1,17 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- set_fact:
+ pkg_mgr: community.general.pkgng
+ ansible_pkg_mgr: community.general.pkgng
+ cacheable: yes
+ when: ansible_os_family == 'FreeBSD' and ansible_version.string is version('2.10', '>=')
+
+- set_fact:
+ pkg_mgr: community.general.zypper
+ ansible_pkg_mgr: community.general.zypper
+ cacheable: yes
+ when: ansible_os_family == 'Suse' and ansible_version.string is version('2.10', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/meta/main.yml
new file mode 100644
index 00000000..2be15776
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_remote_constraints
+ - setup_pkg_mgr
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/tasks/main.yml
new file mode 100644
index 00000000..2057f884
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/tasks/main.yml
@@ -0,0 +1,45 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Include OS-specific variables
+ include_vars: '{{ ansible_os_family }}.yml'
+ when: not ansible_os_family == "Darwin"
+
+- name: Install pyOpenSSL (Python 3)
+ become: true
+ package:
+ name: '{{ pyopenssl_package_name_python3 }}'
+ when: not ansible_os_family == 'Darwin' and ansible_python_version is version('3.0', '>=')
+
+- name: Install pyOpenSSL (Python 2)
+ become: true
+ package:
+ name: '{{ pyopenssl_package_name }}'
+ when: not ansible_os_family == 'Darwin' and ansible_python_version is version('3.0', '<')
+
+- name: Install pyOpenSSL (Darwin)
+ become: true
+ pip:
+ name: pyOpenSSL
+ extra_args: "-c {{ remote_constraints }}"
+ when: ansible_os_family == 'Darwin'
+
+- name: Register pyOpenSSL version
+ command: "{{ ansible_python.executable }} -c 'import OpenSSL; print(OpenSSL.__version__)'"
+ register: pyopenssl_version
+
+- name: Register pyOpenSSL debug details
+ command: "{{ ansible_python.executable }} -m OpenSSL.debug"
+ register: pyopenssl_debug_version
+ ignore_errors: yes
+
+# Depending on which pyOpenSSL version has been installed, it could be that cryptography has
+# been upgraded to a newer version. Make sure to register cryptography_version another time here
+# to avoid strange testing behavior due to wrong values of cryptography_version.
+- name: Register cryptography version
+ command: "{{ ansible_python.executable }} -c 'import cryptography; print(cryptography.__version__)'"
+ register: cryptography_version
+ ignore_errors: yes # in case cryptography was not installed, and setup_openssl hasn't been run before, ignore errors
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/Debian.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/Debian.yml
new file mode 100644
index 00000000..45c183e9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/Debian.yml
@@ -0,0 +1,3 @@
+---
+pyopenssl_package_name: python-openssl
+pyopenssl_package_name_python3: python3-openssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/FreeBSD.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/FreeBSD.yml
new file mode 100644
index 00000000..7deca97a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/FreeBSD.yml
@@ -0,0 +1,3 @@
+---
+pyopenssl_package_name: py27-openssl
+pyopenssl_package_name_python3: "py{{ ansible_python.version.major }}{{ ansible_python.version.minor }}-openssl"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/RedHat.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/RedHat.yml
new file mode 100644
index 00000000..ffe6cd9b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/RedHat.yml
@@ -0,0 +1,3 @@
+---
+pyopenssl_package_name: pyOpenSSL
+pyopenssl_package_name_python3: python3-pyOpenSSL
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/Suse.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/Suse.yml
new file mode 100644
index 00000000..a0f085c7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_pyopenssl/vars/Suse.yml
@@ -0,0 +1,3 @@
+---
+pyopenssl_package_name: python-pyOpenSSL
+pyopenssl_package_name_python3: python3-pyOpenSSL
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/aliases
new file mode 100644
index 00000000..1ad133ba
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/aliases
@@ -0,0 +1 @@
+needs/file/tests/utils/constraints.txt
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/meta/main.yml
new file mode 100644
index 00000000..1810d4be
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_remote_tmp_dir
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/tasks/main.yml
new file mode 100644
index 00000000..d4f8148c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_constraints/tasks/main.yml
@@ -0,0 +1,13 @@
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: record constraints.txt path on remote host
+ set_fact:
+ remote_constraints: "{{ remote_tmp_dir }}/constraints.txt"
+
+- name: copy constraints.txt to remote host
+ copy:
+ src: "{{ role_path }}/../../../utils/constraints.txt"
+ dest: "{{ remote_constraints }}"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/handlers/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/handlers/main.yml
new file mode 100644
index 00000000..e8099486
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/handlers/main.yml
@@ -0,0 +1,2 @@
+- name: delete temporary directory
+ include_tasks: default-cleanup.yml
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/default-cleanup.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/default-cleanup.yml
new file mode 100644
index 00000000..39872d74
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/default-cleanup.yml
@@ -0,0 +1,5 @@
+- name: delete temporary directory
+ file:
+ path: "{{ remote_tmp_dir }}"
+ state: absent
+ no_log: yes
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/default.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/default.yml
new file mode 100644
index 00000000..1e0f51b8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/default.yml
@@ -0,0 +1,11 @@
+- name: create temporary directory
+ tempfile:
+ state: directory
+ suffix: .test
+ register: remote_tmp_dir
+ notify:
+ - delete temporary directory
+
+- name: record temporary directory
+ set_fact:
+ remote_tmp_dir: "{{ remote_tmp_dir.path }}"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/main.yml
new file mode 100644
index 00000000..93d786f0
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_remote_tmp_dir/tasks/main.yml
@@ -0,0 +1,15 @@
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: make sure we have the ansible_os_family and ansible_distribution_version facts
+ setup:
+ gather_subset: distribution
+ when: ansible_facts == {}
+
+- include_tasks: "{{ lookup('first_found', files)}}"
+ vars:
+ files:
+ - "{{ ansible_os_family | lower }}.yml"
+ - "default.yml"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_agent/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_agent/meta/main.yml
new file mode 100644
index 00000000..dc973f4e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_agent/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_ssh_keygen
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_agent/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_agent/tasks/main.yml
new file mode 100644
index 00000000..fe552825
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_agent/tasks/main.yml
@@ -0,0 +1,43 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Start an ssh agent to use for tests
+ shell: eval $(ssh-agent)>/dev/null&&echo "${SSH_AGENT_PID};${SSH_AUTH_SOCK}"
+ register: openssh_agent_env_vars
+
+- name: Register ssh agent facts
+ set_fact:
+ openssh_agent_pid: "{{ openssh_agent_env_vars.stdout.split(';')[0] }}"
+ openssh_agent_sock: "{{ openssh_agent_env_vars.stdout.split(';')[1] }}"
+
+- name: stat agent socket
+ stat:
+ path: "{{ openssh_agent_sock }}"
+ register: openssh_agent_socket_stat
+
+- name: Assert agent socket file is a socket
+ assert:
+ that:
+ - openssh_agent_socket_stat.stat.issock is defined
+ - openssh_agent_socket_stat.stat.issock
+ fail_msg: "{{ openssh_agent_sock }} is not a socket"
+
+- name: Verify agent responds
+ command: ssh-add -l
+ register: rc_openssh_agent_ssh_add_check
+ environment:
+ SSH_AUTH_SOCK: "{{ openssh_agent_sock }}"
+ when: openssh_agent_socket_stat.stat.issock
+ failed_when: rc_openssh_agent_ssh_add_check.rc == 2
+
+- name: Get ssh version
+ shell: ssh -Vq 2>&1|sed 's/^.*OpenSSH_\([0-9]\{1,\}\.[0-9]\{1,\}\).*$/\1/'
+ register:
+ rc_openssh_version_output
+
+- name: Set ssh version facts
+ set_fact:
+ openssh_version: "{{ rc_openssh_version_output.stdout.strip() }}"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/meta/main.yml
new file mode 100644
index 00000000..5438ced5
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_pkg_mgr
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/tasks/main.yml
new file mode 100644
index 00000000..1c8a7143
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/tasks/main.yml
@@ -0,0 +1,14 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Include OS-specific variables
+ include_vars: '{{ ansible_os_family }}.yml'
+ when: not ansible_os_family == "Darwin" and not ansible_os_family == "FreeBSD"
+
+- name: Install ssh-keygen
+ package:
+ name: '{{ openssh_client_package_name }}'
+ when: not ansible_os_family == "Darwin" and not ansible_os_family == "FreeBSD"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/Debian.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/Debian.yml
new file mode 100644
index 00000000..d7ff0c73
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/Debian.yml
@@ -0,0 +1 @@
+openssh_client_package_name: openssh-client
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/RedHat.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/RedHat.yml
new file mode 100644
index 00000000..bc656edf
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/RedHat.yml
@@ -0,0 +1 @@
+openssh_client_package_name: openssh-clients
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/Suse.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/Suse.yml
new file mode 100644
index 00000000..4091fa7b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/setup_ssh_keygen/vars/Suse.yml
@@ -0,0 +1 @@
+openssh_client_package_name: openssh
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/aliases
new file mode 100644
index 00000000..d7936330
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/aliases
@@ -0,0 +1,2 @@
+shippable/cloud/group1
+cloud/acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/meta/main.yml
new file mode 100644
index 00000000..81d1e7e7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_acme
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/tasks/impl.yml
new file mode 100644
index 00000000..7de7da68
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/tasks/impl.yml
@@ -0,0 +1,69 @@
+---
+- name: Generate account key
+ openssl_privatekey:
+ path: '{{ output_dir }}/account.key'
+ size: '{{ default_rsa_key_size }}'
+
+- name: Generate privatekey
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey.pem'
+ size: '{{ default_rsa_key_size }}'
+
+- name: Generate CSRs
+ openssl_csr:
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ path: '{{ output_dir }}/{{ item.name }}.csr'
+ subject_alt_name: '{{ item.sans }}'
+ loop:
+ - name: cert-1
+ sans:
+ - DNS:example.com
+ - name: cert-2
+ sans:
+ - DNS:example.com
+ - DNS:example.org
+
+- name: Retrieve certificate 1
+ x509_certificate:
+ provider: acme
+ path: '{{ output_dir }}/cert-1.pem'
+ csr_path: '{{ output_dir }}/cert-1.csr'
+ acme_accountkey_path: '{{ output_dir }}/account.key'
+ acme_challenge_path: '{{ output_dir }}/challenges/'
+ acme_directory: https://{{ acme_host }}:14000/dir
+ environment:
+ PATH: '{{ lookup("env", "PATH") }}:{{ output_dir }}'
+
+- name: Get certificate information
+ x509_certificate_info:
+ path: '{{ output_dir }}/cert-1.pem'
+ register: result
+
+- name: Validate certificate information
+ assert:
+ that:
+ - result.subject_alt_name | length == 1
+ - "'DNS:example.com' in result.subject_alt_name"
+
+- name: Retrieve certificate 2
+ x509_certificate:
+ provider: acme
+ path: '{{ output_dir }}/cert-2.pem'
+ csr_path: '{{ output_dir }}/cert-2.csr'
+ acme_accountkey_path: '{{ output_dir }}/account.key'
+ acme_challenge_path: '{{ output_dir }}/challenges/'
+ acme_directory: https://{{ acme_host }}:14000/dir
+ environment:
+ PATH: '{{ lookup("env", "PATH") }}:{{ output_dir }}'
+
+- name: Get certificate information
+ x509_certificate_info:
+ path: '{{ output_dir }}/cert-2.pem'
+ register: result
+
+- name: Validate certificate information
+ assert:
+ that:
+ - result.subject_alt_name | length == 2
+ - "'DNS:example.com' in result.subject_alt_name"
+ - "'DNS:example.org' in result.subject_alt_name"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/tasks/main.yml
new file mode 100644
index 00000000..d0888de9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate-acme/tasks/main.yml
@@ -0,0 +1,121 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- block:
+ - name: Obtain root and intermediate certificates
+ get_url:
+ url: "http://{{ acme_host }}:5000/{{ item.0 }}-certificate-for-ca/{{ item.1 }}"
+ dest: "{{ output_dir }}/acme-{{ item.0 }}-{{ item.1 }}.pem"
+ loop: "{{ query('nested', types, root_numbers) }}"
+
+ - name: Analyze root certificates
+ x509_certificate_info:
+ path: "{{ output_dir }}/acme-root-{{ item }}.pem"
+ loop: "{{ root_numbers }}"
+ register: acme_roots
+
+ - name: Analyze intermediate certificates
+ x509_certificate_info:
+ path: "{{ output_dir }}/acme-intermediate-{{ item }}.pem"
+ loop: "{{ root_numbers }}"
+ register: acme_intermediates
+
+ - set_fact:
+ x__: "{{ item | dict2items | selectattr('key', 'in', interesting_keys) | list | items2dict }}"
+ y__: "{{ lookup('file', output_dir ~ '/acme-root-' ~ item.item ~ '.pem', rstrip=False) }}"
+ loop: "{{ acme_roots.results }}"
+ register: acme_roots_tmp
+
+ - set_fact:
+ x__: "{{ item | dict2items | selectattr('key', 'in', interesting_keys) | list | items2dict }}"
+ y__: "{{ lookup('file', output_dir ~ '/acme-intermediate-' ~ item.item ~ '.pem', rstrip=False) }}"
+ loop: "{{ acme_intermediates.results }}"
+ register: acme_intermediates_tmp
+
+ - set_fact:
+ acme_roots: "{{ acme_roots_tmp.results | map(attribute='ansible_facts.x__') | list }}"
+ acme_root_certs: "{{ acme_roots_tmp.results | map(attribute='ansible_facts.y__') | list }}"
+ acme_intermediates: "{{ acme_intermediates_tmp.results | map(attribute='ansible_facts.x__') | list }}"
+ acme_intermediate_certs: "{{ acme_intermediates_tmp.results | map(attribute='ansible_facts.y__') | list }}"
+
+ vars:
+ types:
+ - root
+ - intermediate
+ root_numbers:
+ - 0
+ interesting_keys:
+ - authority_key_identifier
+ - subject_key_identifier
+ - issuer
+ - subject
+
+- name: Get hold of acme-tiny executable
+ get_url:
+ url: https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py
+ dest: "{{ output_dir }}/acme-tiny"
+
+- name: Make sure acme-tiny is executable
+ file:
+ path: "{{ output_dir }}/acme-tiny"
+ mode: "0755"
+
+- name: "Monkey-patch acme-tiny: Disable certificate validation"
+ blockinfile:
+ path: "{{ output_dir }}/acme-tiny"
+ marker: "# {mark} ANSIBLE MANAGED BLOCK: DISABLE CERTIFICATE VALIDATION FOR HTTPS REQUESTS"
+ insertafter: '^#!.*'
+ block: |
+ import ssl
+ try:
+ ssl._create_default_https_context = ssl._create_unverified_context
+ except Exception:
+ # Python before 2.7.9 has no verification at all. So nothing to disable.
+ pass
+ # For later:
+ try:
+ from urllib.request import Request # Python 3
+ except ImportError:
+ from urllib2 import Request # Python 2
+
+- name: "Monkey-patch acme-tiny: Disable check that challenge file is reachable via HTTP"
+ replace:
+ path: "{{ output_dir }}/acme-tiny"
+ regexp: 'parser\.add_argument\("--disable-check", default=False,'
+ replace: 'parser.add_argument("--disable-check", default=True,'
+
+- name: "Monkey-patch acme-tiny: Instead of writing challenge files to disk, post them to challenge server"
+ replace:
+ path: "{{ output_dir }}/acme-tiny"
+ regexp: 'with open\(wellknown_path, "w"\) as [^:]+:\n\s+[^. ]+\.write\(([^)]+)\)'
+ replace: 'r = Request(url="http://{{ acme_host }}:5000/http/" + domain + "/" + token, data=\1.encode("utf8"), headers={"content-type": "application/octet-stream"}) ; r.get_method = lambda: "PUT" ; urlopen(r).close()'
+
+- name: "Monkey-patch acme-tiny: Remove file cleanup"
+ replace:
+ path: "{{ output_dir }}/acme-tiny"
+ regexp: 'os\.remove\(wellknown_path\)'
+ replace: 'pass'
+
+- name: "Monkey-patch acme-tiny: Avoid crash on already valid challenges (https://github.com/diafygi/acme-tiny/pull/254)"
+ blockinfile:
+ path: "{{ output_dir }}/acme-tiny"
+ marker: "# {mark} ANSIBLE MANAGED BLOCK: AVOID CRASH ON ALREADY VALID CHALLENGES"
+ insertbefore: '# find the http-01 challenge and write the challenge file'
+ block: |2
+ # skip if already valid
+ if authorization['status'] == "valid":
+ log.info("{0} already verified. Skipping.".format(domain))
+ continue
+
+- name: Create challenges directory
+ file:
+ path: '{{ output_dir }}/challenges'
+ state: directory
+
+- name: Running tests
+ include_tasks: impl.yml
+ # Make x509_certificate module happy
+ when: cryptography_version.stdout is version('1.6', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/assertonly.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/assertonly.yml
new file mode 100644
index 00000000..b6f355a7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/assertonly.yml
@@ -0,0 +1,154 @@
+---
+- name: (Assertonly, {{select_crypto_backend}}) - Generate privatekey
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: (Assertonly, {{select_crypto_backend}}) - Generate privatekey with password
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: auto
+ select_crypto_backend: cryptography
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: (Assertonly, {{select_crypto_backend}}) - Generate CSR (no extensions)
+ openssl_csr:
+ path: '{{ output_dir }}/csr_noext.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.example.com
+ useCommonNameForSAN: no
+
+- name: (Assertonly, {{select_crypto_backend}}) - Generate CSR (with SANs)
+ openssl_csr:
+ path: '{{ output_dir }}/csr_sans.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.example.com
+ subject_alt_name:
+ - "DNS:ansible.com"
+ - "IP:127.0.0.1"
+ - "IP:::1"
+ useCommonNameForSAN: no
+
+- name: (Assertonly, {{select_crypto_backend}}) - Generate selfsigned certificate (no extensions)
+ x509_certificate:
+ path: '{{ output_dir }}/cert_noext.pem'
+ csr_path: '{{ output_dir }}/csr_noext.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (Assertonly, {{select_crypto_backend}}) - Generate selfsigned certificate (with SANs)
+ x509_certificate:
+ path: '{{ output_dir }}/cert_sans.pem'
+ csr_path: '{{ output_dir }}/csr_sans.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (Assertonly, {{select_crypto_backend}}) - Assert that subject_alt_name is there (should fail)
+ x509_certificate:
+ path: '{{ output_dir }}/cert_noext.pem'
+ provider: assertonly
+ subject_alt_name:
+ - "DNS:example.com"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: extension_missing_san
+
+- name: (Assertonly, {{select_crypto_backend}}) - Assert that subject_alt_name is there
+ x509_certificate:
+ path: '{{ output_dir }}/cert_sans.pem'
+ provider: assertonly
+ subject_alt_name:
+ - "DNS:ansible.com"
+ - "IP:127.0.0.1"
+ - "IP:::1"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: extension_san
+
+- name: (Assertonly, {{select_crypto_backend}}) - Assert that subject_alt_name is there (strict)
+ x509_certificate:
+ path: '{{ output_dir }}/cert_sans.pem'
+ provider: assertonly
+ subject_alt_name:
+ - "DNS:ansible.com"
+ - "IP:127.0.0.1"
+ - "IP:::1"
+ subject_alt_name_strict: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: extension_san_strict
+
+- name: (Assertonly, {{select_crypto_backend}}) - Assert that key_usage is there (should fail)
+ x509_certificate:
+ path: '{{ output_dir }}/cert_noext.pem'
+ provider: assertonly
+ key_usage:
+ - digitalSignature
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: extension_missing_ku
+
+- name: (Assertonly, {{select_crypto_backend}}) - Assert that extended_key_usage is there (should fail)
+ x509_certificate:
+ path: '{{ output_dir }}/cert_noext.pem'
+ provider: assertonly
+ extended_key_usage:
+ - biometricInfo
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: extension_missing_eku
+
+- assert:
+ that:
+ - extension_missing_san is failed
+ - "'Found no subjectAltName extension' in extension_missing_san.msg"
+ - extension_san is succeeded
+ - extension_san_strict is succeeded
+ - extension_missing_ku is failed
+ - "'Found no keyUsage extension' in extension_missing_ku.msg"
+ - extension_missing_eku is failed
+ - "'Found no extendedKeyUsage extension' in extension_missing_eku.msg"
+
+- name: (Assertonly, {{select_crypto_backend}}) - Check private key passphrase fail 1
+ x509_certificate:
+ path: '{{ output_dir }}/cert_noext.pem'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ privatekey_passphrase: hunter2
+ provider: assertonly
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_1
+
+- name: (Assertonly, {{select_crypto_backend}}) - Check private key passphrase fail 2
+ x509_certificate:
+ path: '{{ output_dir }}/cert_noext.pem'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ privatekey_passphrase: wrong_password
+ provider: assertonly
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_2
+
+- name: (Assertonly, {{select_crypto_backend}}) - Check private key passphrase fail 3
+ x509_certificate:
+ path: '{{ output_dir }}/cert_noext.pem'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ provider: assertonly
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_3
+
+- name: (Assertonly, {{select_crypto_backend}}) -
+ assert:
+ that:
+ - passphrase_error_1 is failed
+ - "'assphrase' in passphrase_error_1.msg or 'assword' in passphrase_error_1.msg"
+ - passphrase_error_2 is failed
+ - "'assphrase' in passphrase_error_2.msg or 'assword' in passphrase_error_2.msg or 'serializ' in passphrase_error_2.msg"
+ - passphrase_error_3 is failed
+ - "'assphrase' in passphrase_error_3.msg or 'assword' in passphrase_error_3.msg or 'serializ' in passphrase_error_3.msg"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/expired.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/expired.yml
new file mode 100644
index 00000000..76e21c83
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/expired.yml
@@ -0,0 +1,49 @@
+---
+- name: (Expired, {{select_crypto_backend}}) Generate privatekey
+ openssl_privatekey:
+ path: '{{ output_dir }}/has_expired_privatekey.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: (Expired, {{select_crypto_backend}}) Generate CSR
+ openssl_csr:
+ path: '{{ output_dir }}/has_expired_csr.csr'
+ privatekey_path: '{{ output_dir }}/has_expired_privatekey.pem'
+ subject:
+ commonName: www.example.com
+
+- name: (Expired, {{select_crypto_backend}}) Generate expired selfsigned certificate
+ x509_certificate:
+ path: '{{ output_dir }}/has_expired_cert.pem'
+ csr_path: '{{ output_dir }}/has_expired_csr.csr'
+ privatekey_path: '{{ output_dir }}/has_expired_privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ selfsigned_not_after: "-1s"
+ selfsigned_not_before: "-100s"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend == 'pyopenssl' # cryptography won't allow creating expired certificates
+
+- name: (Expired, {{select_crypto_backend}}) Generate expired selfsigned certificate
+ command: "{{ openssl_binary }} x509 -req -days -1 -in {{ output_dir }}/has_expired_csr.csr -signkey {{ output_dir }}/has_expired_privatekey.pem -out {{ output_dir }}/has_expired_cert.pem"
+ when: select_crypto_backend == 'cryptography' # So we create it with 'command'
+
+- name: "(Expired) Check task fails because cert is expired (has_expired: false)"
+ x509_certificate:
+ provider: assertonly
+ path: "{{ output_dir }}/has_expired_cert.pem"
+ has_expired: false
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: true
+ register: expired_cert_check
+
+- name: (Expired, {{select_crypto_backend}}) Ensure previous task failed
+ assert:
+ that: expired_cert_check is failed
+
+- name: "(Expired) Check expired cert check is ignored (has_expired: true)"
+ x509_certificate:
+ provider: assertonly
+ path: "{{ output_dir }}/has_expired_cert.pem"
+ has_expired: true
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: expired_cert_skip
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/impl.yml
new file mode 100644
index 00000000..f215591f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/impl.yml
@@ -0,0 +1,8 @@
+---
+- debug:
+ msg: "Executing tests with backend {{ select_crypto_backend }}"
+- import_tasks: assertonly.yml
+- import_tasks: expired.yml
+- import_tasks: selfsigned.yml
+- import_tasks: ownca.yml
+- import_tasks: removal.yml
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/main.yml
new file mode 100644
index 00000000..36b5c280
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/main.yml
@@ -0,0 +1,27 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Running tests with pyOpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: pyopenssl
+ when: pyopenssl_version.stdout is version('0.15', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+ when: cryptography_version.stdout is version('1.6', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/ownca.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/ownca.yml
new file mode 100644
index 00000000..3feea15f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/ownca.yml
@@ -0,0 +1,580 @@
+---
+- name: (OwnCA, {{select_crypto_backend}}) Generate CA privatekey
+ openssl_privatekey:
+ path: '{{ output_dir }}/ca_privatekey.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate CA privatekey with passphrase
+ openssl_privatekey:
+ path: '{{ output_dir }}/ca_privatekey_pw.pem'
+ passphrase: hunter2
+ cipher: auto
+ select_crypto_backend: cryptography
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate CA CSR
+ openssl_csr:
+ path: '{{ output_dir }}/ca_csr.csr'
+ privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ subject:
+ commonName: Example CA
+ useCommonNameForSAN: no
+ basic_constraints:
+ - 'CA:TRUE'
+ basic_constraints_critical: yes
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate CA CSR (privatekey passphrase)
+ openssl_csr:
+ path: '{{ output_dir }}/ca_csr_pw.csr'
+ privatekey_path: '{{ output_dir }}/ca_privatekey_pw.pem'
+ privatekey_passphrase: hunter2
+ subject:
+ commonName: Example CA
+ useCommonNameForSAN: no
+ basic_constraints:
+ - 'CA:TRUE'
+ basic_constraints_critical: yes
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate selfsigned CA certificate
+ x509_certificate:
+ path: '{{ output_dir }}/ca_cert.pem'
+ csr_path: '{{ output_dir }}/ca_csr.csr'
+ privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate selfsigned CA certificate (privatekey passphrase)
+ x509_certificate:
+ path: '{{ output_dir }}/ca_cert_pw.pem'
+ csr_path: '{{ output_dir }}/ca_csr_pw.csr'
+ privatekey_path: '{{ output_dir }}/ca_privatekey_pw.pem'
+ privatekey_passphrase: hunter2
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: ownca_certificate
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (idempotent)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: ownca_certificate_idempotence
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (check mode)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+
+- name: (OwnCA, {{select_crypto_backend}}) Check ownca certificate
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert.pem'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: assertonly
+ has_expired: False
+ version: 3
+ signature_algorithms:
+ - sha256WithRSAEncryption
+ - sha256WithECDSAEncryption
+ subject:
+ commonName: www.example.com
+ issuer:
+ commonName: Example CA
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate ownca v2 certificate
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_v2.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ ownca_version: 2
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: ownca_v2_certificate
+ ignore_errors: true
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate2
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert2.pem'
+ csr_path: '{{ output_dir }}/csr2.csr'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (OwnCA, {{select_crypto_backend}}) Check ownca certificate2
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert2.pem'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ provider: assertonly
+ has_expired: False
+ version: 3
+ signature_algorithms:
+ - sha256WithRSAEncryption
+ - sha256WithECDSAEncryption
+ subject:
+ commonName: www.example.com
+ C: US
+ ST: California
+ L: Los Angeles
+ O: ACME Inc.
+ OU:
+ - Roadrunner pest control
+ - Pyrotechnics
+ keyUsage:
+ - digitalSignature
+ extendedKeyUsage:
+ - ipsecUser
+ - biometricInfo
+ issuer:
+ commonName: Example CA
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (OwnCA, {{select_crypto_backend}}) Create ownca certificate with notBefore and notAfter
+ x509_certificate:
+ provider: ownca
+ ownca_not_before: 20181023133742Z
+ ownca_not_after: 20191023133742Z
+ path: "{{ output_dir }}/ownca_cert3.pem"
+ csr_path: "{{ output_dir }}/csr.csr"
+ privatekey_path: "{{ output_dir }}/privatekey3.pem"
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (OwnCA, {{select_crypto_backend}}) Create ownca certificate with relative notBefore and notAfter
+ x509_certificate:
+ provider: ownca
+ ownca_not_before: +1s
+ ownca_not_after: +52w
+ path: "{{ output_dir }}/ownca_cert4.pem"
+ csr_path: "{{ output_dir }}/csr.csr"
+ privatekey_path: "{{ output_dir }}/privatekey3.pem"
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate ownca ECC certificate
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_ecc.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: ownca_certificate_ecc
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate selfsigned certificate (privatekey passphrase)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_ecc_2.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert_pw.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey_pw.pem'
+ ownca_privatekey_passphrase: hunter2
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: selfsigned_certificate_passphrase
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (failed passphrase 1)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_pw1.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ ownca_privatekey_passphrase: hunter2
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_1
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (failed passphrase 2)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_pw2.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ ownca_privatekey_passphrase: wrong_password
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_2
+
+- name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (failed passphrase 3)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_pw3.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_3
+
+- name: (OwnCA, {{select_crypto_backend}}) Create broken certificate
+ copy:
+ dest: "{{ output_dir }}/ownca_broken.pem"
+ content: "broken"
+- name: (OwnCA, {{select_crypto_backend}}) Regenerate broken cert
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_broken.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ register: ownca_broken
+
+- name: (OwnCA, {{select_crypto_backend}}) Backup test
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_backup.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: ownca_backup_1
+- name: (OwnCA, {{select_crypto_backend}}) Backup test (idempotent)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_backup.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: ownca_backup_2
+- name: (OwnCA, {{select_crypto_backend}}) Backup test (change)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_backup.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: ownca_backup_3
+- name: (OwnCA, {{select_crypto_backend}}) Backup test (remove)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_backup.pem'
+ state: absent
+ provider: ownca
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: ownca_backup_4
+- name: (OwnCA, {{select_crypto_backend}}) Backup test (remove, idempotent)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_backup.pem'
+ state: absent
+ provider: ownca
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: ownca_backup_5
+
+- name: (OwnCA, {{select_crypto_backend}}) Create subject key identifier
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_ski.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ ownca_create_subject_key_identifier: always_create
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: ownca_subject_key_identifier_1
+
+- name: (OwnCA, {{select_crypto_backend}}) Create subject key identifier (idempotency)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_ski.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ ownca_create_subject_key_identifier: always_create
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: ownca_subject_key_identifier_2
+
+- name: (OwnCA, {{select_crypto_backend}}) Create subject key identifier (remove)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_ski.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ ownca_create_subject_key_identifier: never_create
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: ownca_subject_key_identifier_3
+
+- name: (OwnCA, {{select_crypto_backend}}) Create subject key identifier (remove idempotency)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_ski.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ ownca_create_subject_key_identifier: never_create
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: ownca_subject_key_identifier_4
+
+- name: (OwnCA, {{select_crypto_backend}}) Create subject key identifier (re-enable)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_ski.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ ownca_create_subject_key_identifier: always_create
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: ownca_subject_key_identifier_5
+
+- name: (OwnCA, {{select_crypto_backend}}) Create authority key identifier
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_aki.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ ownca_create_authority_key_identifier: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: ownca_authority_key_identifier_1
+
+- name: (OwnCA, {{select_crypto_backend}}) Create authority key identifier (idempotency)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_aki.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ ownca_create_authority_key_identifier: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: ownca_authority_key_identifier_2
+
+- name: (OwnCA, {{select_crypto_backend}}) Create authority key identifier (remove)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_aki.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ ownca_create_authority_key_identifier: no
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: ownca_authority_key_identifier_3
+
+- name: (OwnCA, {{select_crypto_backend}}) Create authority key identifier (remove idempotency)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_aki.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ ownca_create_authority_key_identifier: no
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: ownca_authority_key_identifier_4
+
+- name: (OwnCA, {{select_crypto_backend}}) Create authority key identifier (re-add)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_aki.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ ownca_create_authority_key_identifier: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: ownca_authority_key_identifier_5
+
+- name: (OwnCA, {{select_crypto_backend}}) Ed25519 and Ed448 tests (for cryptography >= 2.6)
+ block:
+ - name: (OwnCA, {{select_crypto_backend}}) Generate privatekeys
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_{{ item }}.pem'
+ type: '{{ item }}'
+ loop:
+ - Ed25519
+ - Ed448
+ register: ownca_certificate_ed25519_ed448_privatekey
+ ignore_errors: yes
+
+ - name: (OwnCA, {{select_crypto_backend}}) Generate CSR etc. if private key generation succeeded
+ when: ownca_certificate_ed25519_ed448_privatekey is not failed
+ block:
+
+ - name: (OwnCA, {{select_crypto_backend}}) Generate CSR
+ openssl_csr:
+ path: '{{ output_dir }}/csr_{{ item }}.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - Ed25519
+ - Ed448
+ ignore_errors: yes
+
+ - name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_{{ item }}.pem'
+ csr_path: '{{ output_dir }}/csr_{{ item }}.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - Ed25519
+ - Ed448
+ register: ownca_certificate_ed25519_ed448
+ ignore_errors: yes
+
+ - name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (idempotent)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_{{ item }}.pem'
+ csr_path: '{{ output_dir }}/csr_{{ item }}.csr'
+ ownca_path: '{{ output_dir }}/ca_cert.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem'
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - Ed25519
+ - Ed448
+ register: ownca_certificate_ed25519_ed448_idempotence
+ ignore_errors: yes
+
+ - name: (OwnCA, {{select_crypto_backend}}) Generate CA privatekey
+ openssl_privatekey:
+ path: '{{ output_dir }}/ca_privatekey_{{ item }}.pem'
+ type: '{{ item }}'
+ cipher: auto
+ passphrase: Test123
+ ignore_errors: yes
+ loop:
+ - Ed25519
+ - Ed448
+
+ - name: (OwnCA, {{select_crypto_backend}}) Generate CA CSR
+ openssl_csr:
+ path: '{{ output_dir }}/ca_csr_{{ item }}.csr'
+ privatekey_path: '{{ output_dir }}/ca_privatekey_{{ item }}.pem'
+ privatekey_passphrase: Test123
+ subject:
+ commonName: Example CA
+ useCommonNameForSAN: no
+ basic_constraints:
+ - 'CA:TRUE'
+ basic_constraints_critical: yes
+ key_usage:
+ - cRLSign
+ - keyCertSign
+ loop:
+ - Ed25519
+ - Ed448
+ ignore_errors: yes
+
+ - name: (OwnCA, {{select_crypto_backend}}) Generate selfsigned CA certificate
+ x509_certificate:
+ path: '{{ output_dir }}/ca_cert_{{ item }}.pem'
+ csr_path: '{{ output_dir }}/ca_csr_{{ item }}.csr'
+ privatekey_path: '{{ output_dir }}/ca_privatekey_{{ item }}.pem'
+ privatekey_passphrase: Test123
+ provider: selfsigned
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - Ed25519
+ - Ed448
+ ignore_errors: yes
+
+ - name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_{{ item }}_2.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ ownca_path: '{{ output_dir }}/ca_cert_{{ item }}.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey_{{ item }}.pem'
+ ownca_privatekey_passphrase: Test123
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - Ed25519
+ - Ed448
+ register: ownca_certificate_ed25519_ed448_2
+ ignore_errors: yes
+
+ - name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (idempotent)
+ x509_certificate:
+ path: '{{ output_dir }}/ownca_cert_{{ item }}_2.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ ownca_path: '{{ output_dir }}/ca_cert_{{ item }}.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca_privatekey_{{ item }}.pem'
+ ownca_privatekey_passphrase: Test123
+ provider: ownca
+ ownca_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - Ed25519
+ - Ed448
+ register: ownca_certificate_ed25519_ed448_2_idempotence
+ ignore_errors: yes
+
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=')
+
+- import_tasks: ../tests/validate_ownca.yml
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/removal.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/removal.yml
new file mode 100644
index 00000000..581021c4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/removal.yml
@@ -0,0 +1,53 @@
+---
+- name: (Removal, {{select_crypto_backend}}) Generate privatekey
+ openssl_privatekey:
+ path: '{{ output_dir }}/removal_privatekey.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: (Removal, {{select_crypto_backend}}) Generate CSR
+ openssl_csr:
+ path: '{{ output_dir }}/removal_csr.csr'
+ privatekey_path: '{{ output_dir }}/removal_privatekey.pem'
+
+- name: (Removal, {{select_crypto_backend}}) Generate selfsigned certificate
+ x509_certificate:
+ path: '{{ output_dir }}/removal_cert.pem'
+ csr_path: '{{ output_dir }}/removal_csr.csr'
+ privatekey_path: '{{ output_dir }}/removal_privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: "(Removal, {{select_crypto_backend}}) Check that file is not gone"
+ stat:
+ path: "{{ output_dir }}/removal_cert.pem"
+ register: removal_1_prestat
+
+- name: "(Removal, {{select_crypto_backend}}) Remove certificate"
+ x509_certificate:
+ path: "{{ output_dir }}/removal_cert.pem"
+ state: absent
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: removal_1
+
+- name: "(Removal, {{select_crypto_backend}}) Check that file is gone"
+ stat:
+ path: "{{ output_dir }}/removal_cert.pem"
+ register: removal_1_poststat
+
+- name: "(Removal, {{select_crypto_backend}}) Remove certificate (idempotent)"
+ x509_certificate:
+ path: "{{ output_dir }}/removal_cert.pem"
+ state: absent
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: removal_2
+
+- name: (Removal, {{select_crypto_backend}}) Ensure removal worked
+ assert:
+ that:
+ - removal_1_prestat.stat.exists
+ - removal_1 is changed
+ - not removal_1_poststat.stat.exists
+ - removal_2 is not changed
+ - removal_1.certificate is none
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/selfsigned.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/selfsigned.yml
new file mode 100644
index 00000000..03c197aa
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tasks/selfsigned.yml
@@ -0,0 +1,465 @@
+---
+- name: (Selfsigned, {{select_crypto_backend}}) Generate privatekey
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate privatekey with password
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: auto
+ select_crypto_backend: cryptography
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate without CSR
+ x509_certificate:
+ path: '{{ output_dir }}/cert_no_csr.pem'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: selfsigned_certificate_no_csr
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate without CSR - idempotency
+ x509_certificate:
+ path: '{{ output_dir }}/cert_no_csr.pem'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: selfsigned_certificate_no_csr_idempotence
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate without CSR (check mode)
+ x509_certificate:
+ path: '{{ output_dir }}/cert_no_csr.pem'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: selfsigned_certificate_no_csr_idempotence_check
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate CSR
+ openssl_csr:
+ path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.example.com
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate CSR
+ openssl_csr:
+ path: '{{ output_dir }}/csr_minimal_change.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.example.org
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate
+ x509_certificate:
+ path: '{{ output_dir }}/cert.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: selfsigned_certificate
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate - idempotency
+ x509_certificate:
+ path: '{{ output_dir }}/cert.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ return_content: yes
+ register: selfsigned_certificate_idempotence
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate (check mode)
+ x509_certificate:
+ path: '{{ output_dir }}/cert.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate (check mode, other CSR)
+ x509_certificate:
+ path: '{{ output_dir }}/cert.pem'
+ csr_path: '{{ output_dir }}/csr_minimal_change.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: selfsigned_certificate_csr_minimal_change
+
+- name: (Selfsigned, {{select_crypto_backend}}) Check selfsigned certificate
+ x509_certificate:
+ path: '{{ output_dir }}/cert.pem'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: assertonly
+ has_expired: False
+ version: 3
+ signature_algorithms:
+ - sha256WithRSAEncryption
+ - sha256WithECDSAEncryption
+ subject:
+ commonName: www.example.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned v2 certificate
+ x509_certificate:
+ path: '{{ output_dir }}/cert_v2.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ selfsigned_version: 2
+ select_crypto_backend: "{{ select_crypto_backend }}"
+ register: selfsigned_v2_cert
+ ignore_errors: true
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate privatekey2
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey2.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate CSR2
+ openssl_csr:
+ subject:
+ CN: www.example.com
+ C: US
+ ST: California
+ L: Los Angeles
+ O: ACME Inc.
+ OU:
+ - Roadrunner pest control
+ - Pyrotechnics
+ path: '{{ output_dir }}/csr2.csr'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ keyUsage:
+ - digitalSignature
+ extendedKeyUsage:
+ - ipsecUser
+ - biometricInfo
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate2
+ x509_certificate:
+ path: '{{ output_dir }}/cert2.pem'
+ csr_path: '{{ output_dir }}/csr2.csr'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (Selfsigned, {{select_crypto_backend}}) Check selfsigned certificate2
+ x509_certificate:
+ path: '{{ output_dir }}/cert2.pem'
+ privatekey_path: '{{ output_dir }}/privatekey2.pem'
+ provider: assertonly
+ has_expired: False
+ version: 3
+ signature_algorithms:
+ - sha256WithRSAEncryption
+ - sha256WithECDSAEncryption
+ subject:
+ commonName: www.example.com
+ C: US
+ ST: California
+ L: Los Angeles
+ O: ACME Inc.
+ OU:
+ - Roadrunner pest control
+ - Pyrotechnics
+ keyUsage:
+ - digitalSignature
+ extendedKeyUsage:
+ - ipsecUser
+ - biometricInfo
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (Selfsigned, {{select_crypto_backend}}) Create private key 3
+ openssl_privatekey:
+ path: "{{ output_dir }}/privatekey3.pem"
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: (Selfsigned, {{select_crypto_backend}}) Create CSR 3
+ openssl_csr:
+ subject:
+ CN: www.example.com
+ privatekey_path: "{{ output_dir }}/privatekey3.pem"
+ path: "{{ output_dir }}/csr3.pem"
+
+- name: (Selfsigned, {{select_crypto_backend}}) Create certificate3 with notBefore and notAfter
+ x509_certificate:
+ provider: selfsigned
+ selfsigned_not_before: 20181023133742Z
+ selfsigned_not_after: 20191023133742Z
+ path: "{{ output_dir }}/cert3.pem"
+ csr_path: "{{ output_dir }}/csr3.pem"
+ privatekey_path: "{{ output_dir }}/privatekey3.pem"
+ select_crypto_backend: '{{ select_crypto_backend }}'
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate privatekey
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_ecc.pem'
+ type: ECC
+ curve: "{{ (ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6') | ternary('secp521r1', 'secp256k1') }}"
+ # ^ cryptography on CentOS6 doesn't support secp256k1, so we use secp521r1 instead
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate CSR
+ openssl_csr:
+ path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ subject:
+ commonName: www.example.com
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate
+ x509_certificate:
+ path: '{{ output_dir }}/cert_ecc.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: selfsigned_certificate_ecc
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate CSR (privatekey passphrase)
+ openssl_csr:
+ path: '{{ output_dir }}/csr_pass.csr'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ privatekey_passphrase: hunter2
+ subject:
+ commonName: www.example.com
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate (privatekey passphrase)
+ x509_certificate:
+ path: '{{ output_dir }}/cert_pass.pem'
+ csr_path: '{{ output_dir }}/csr_pass.csr'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ privatekey_passphrase: hunter2
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: selfsigned_certificate_passphrase
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate (failed passphrase 1)
+ x509_certificate:
+ path: '{{ output_dir }}/cert_pw1.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ privatekey_passphrase: hunter2
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_1
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate (failed passphrase 2)
+ x509_certificate:
+ path: '{{ output_dir }}/cert_pw2.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ privatekey_passphrase: wrong_password
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_2
+
+- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate (failed passphrase 3)
+ x509_certificate:
+ path: '{{ output_dir }}/cert_pw3.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ ignore_errors: yes
+ register: passphrase_error_3
+
+- name: (Selfsigned, {{select_crypto_backend}}) Create broken certificate
+ copy:
+ dest: "{{ output_dir }}/cert_broken.pem"
+ content: "broken"
+- name: (Selfsigned, {{select_crypto_backend}}) Regenerate broken cert
+ x509_certificate:
+ path: '{{ output_dir }}/cert_broken.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ register: selfsigned_broken
+
+- name: (Selfsigned, {{select_crypto_backend}}) Backup test
+ x509_certificate:
+ path: '{{ output_dir }}/selfsigned_cert_backup.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: selfsigned_backup_1
+- name: (Selfsigned, {{select_crypto_backend}}) Backup test (idempotent)
+ x509_certificate:
+ path: '{{ output_dir }}/selfsigned_cert_backup.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: selfsigned_backup_2
+- name: (Selfsigned, {{select_crypto_backend}}) Backup test (change)
+ x509_certificate:
+ path: '{{ output_dir }}/selfsigned_cert_backup.pem'
+ csr_path: '{{ output_dir }}/csr.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: selfsigned_backup_3
+- name: (Selfsigned, {{select_crypto_backend}}) Backup test (remove)
+ x509_certificate:
+ path: '{{ output_dir }}/selfsigned_cert_backup.pem'
+ state: absent
+ provider: selfsigned
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: selfsigned_backup_4
+- name: (Selfsigned, {{select_crypto_backend}}) Backup test (remove, idempotent)
+ x509_certificate:
+ path: '{{ output_dir }}/selfsigned_cert_backup.pem'
+ state: absent
+ provider: selfsigned
+ backup: yes
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: selfsigned_backup_5
+
+- name: (Selfsigned, {{select_crypto_backend}}) Create subject key identifier test
+ x509_certificate:
+ path: '{{ output_dir }}/selfsigned_cert_ski.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ selfsigned_create_subject_key_identifier: always_create
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: selfsigned_subject_key_identifier_1
+
+- name: (Selfsigned, {{select_crypto_backend}}) Create subject key identifier test (idempotency)
+ x509_certificate:
+ path: '{{ output_dir }}/selfsigned_cert_ski.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ selfsigned_create_subject_key_identifier: always_create
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: selfsigned_subject_key_identifier_2
+
+- name: (Selfsigned, {{select_crypto_backend}}) Create subject key identifier test (remove)
+ x509_certificate:
+ path: '{{ output_dir }}/selfsigned_cert_ski.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ selfsigned_create_subject_key_identifier: never_create
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: selfsigned_subject_key_identifier_3
+
+- name: (Selfsigned, {{select_crypto_backend}}) Create subject key identifier test (remove idempotency)
+ x509_certificate:
+ path: '{{ output_dir }}/selfsigned_cert_ski.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ selfsigned_create_subject_key_identifier: never_create
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: selfsigned_subject_key_identifier_4
+
+- name: (Selfsigned, {{select_crypto_backend}}) Create subject key identifier test (re-enable)
+ x509_certificate:
+ path: '{{ output_dir }}/selfsigned_cert_ski.pem'
+ csr_path: '{{ output_dir }}/csr_ecc.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ selfsigned_create_subject_key_identifier: always_create
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ when: select_crypto_backend != 'pyopenssl'
+ register: selfsigned_subject_key_identifier_5
+
+- name: (Selfsigned, {{select_crypto_backend}}) Ed25519 and Ed448 tests (for cryptography >= 2.6)
+ block:
+ - name: (Selfsigned, {{select_crypto_backend}}) Generate privatekeys
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_{{ item }}.pem'
+ type: '{{ item }}'
+ loop:
+ - Ed25519
+ - Ed448
+ register: selfsigned_certificate_ed25519_ed448_privatekey
+ ignore_errors: yes
+
+ - name: (Selfsigned, {{select_crypto_backend}}) Generate CSR etc. if private key generation succeeded
+ when: selfsigned_certificate_ed25519_ed448_privatekey is not failed
+ block:
+
+ - name: (Selfsigned, {{select_crypto_backend}}) Generate CSR
+ openssl_csr:
+ path: '{{ output_dir }}/csr_{{ item }}.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem'
+ subject:
+ commonName: www.ansible.com
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - Ed25519
+ - Ed448
+ ignore_errors: yes
+
+ - name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate
+ x509_certificate:
+ path: '{{ output_dir }}/cert_{{ item }}.pem'
+ csr_path: '{{ output_dir }}/csr_{{ item }}.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - Ed25519
+ - Ed448
+ register: selfsigned_certificate_ed25519_ed448
+ ignore_errors: yes
+
+ - name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate - idempotency
+ x509_certificate:
+ path: '{{ output_dir }}/cert_{{ item }}.pem'
+ csr_path: '{{ output_dir }}/csr_{{ item }}.csr'
+ privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - Ed25519
+ - Ed448
+ register: selfsigned_certificate_ed25519_ed448_idempotence
+ ignore_errors: yes
+
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=')
+
+- import_tasks: ../tests/validate_selfsigned.yml
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tests/validate_ownca.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tests/validate_ownca.yml
new file mode 100644
index 00000000..e8d23f46
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tests/validate_ownca.yml
@@ -0,0 +1,178 @@
+---
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate (test - verify CA)
+ shell: '{{ openssl_binary }} verify -CAfile {{ output_dir }}/ca_cert.pem {{ output_dir }}/ownca_cert.pem | sed "s/.*: \(.*\)/\1/g"'
+ register: ownca_verify_ca
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate (test - ownca certificate modulus)
+ shell: '{{ openssl_binary }} x509 -noout -modulus -in {{ output_dir }}/ownca_cert.pem'
+ register: ownca_cert_modulus
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate (test - ownca issuer value)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir}}/ownca_cert.pem -text | grep "Issuer" | sed "s/.*: \(.*\)/\1/g"'
+ register: ownca_cert_issuer
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate (test - ownca certficate version == default == 3)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir}}/ownca_cert.pem -text | grep "Version" | sed "s/.*: \(.*\) .*/\1/g"'
+ register: ownca_cert_version
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate (assert)
+ assert:
+ that:
+ - ownca_verify_ca.stdout == 'OK'
+ - ownca_cert_modulus.stdout == privatekey_modulus.stdout
+ - ownca_cert_version.stdout == '3'
+ # openssl 1.1.x adds a space between the output
+ - ownca_cert_issuer.stdout in ['CN=Example CA', 'CN = Example CA']
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate idempotence
+ assert:
+ that:
+ - ownca_certificate.serial_number == ownca_certificate_idempotence.serial_number
+ - ownca_certificate.notBefore == ownca_certificate_idempotence.notBefore
+ - ownca_certificate.notAfter == ownca_certificate_idempotence.notAfter
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca data return
+ assert:
+ that:
+ - ownca_certificate.certificate == lookup('file', output_dir ~ '/ownca_cert.pem', rstrip=False)
+ - ownca_certificate.certificate == ownca_certificate_idempotence.certificate
+
+- block:
+ - name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate v2 (test - ownca certificate version == 2)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir}}/ownca_cert_v2.pem -text | grep "Version" | sed "s/.*: \(.*\) .*/\1/g"'
+ register: ownca_cert_v2_version
+
+ - name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate version 2 (assert)
+ assert:
+ that:
+ - ownca_cert_v2_version.stdout == '2'
+ when: "select_crypto_backend != 'cryptography'"
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate v2 (test - ownca certificate version == 2)
+ assert:
+ that:
+ - ownca_v2_certificate is failed
+ - "'The cryptography backend does not support v2 certificates' in ownca_v2_certificate.msg"
+ when: "select_crypto_backend == 'cryptography'"
+
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate2 (test - ownca certificate modulus)
+ shell: '{{ openssl_binary }} x509 -noout -modulus -in {{ output_dir }}/ownca_cert2.pem'
+ register: ownca_cert2_modulus
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate2 (assert)
+ assert:
+ that:
+ - ownca_cert2_modulus.stdout == privatekey2_modulus.stdout
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate owncal certificate3 (test - notBefore)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir }}/ownca_cert3.pem -text | grep "Not Before" | sed "s/.*: \(.*\) .*/\1/g"'
+ register: ownca_cert3_notBefore
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate3 (test - notAfter)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir }}/ownca_cert3.pem -text | grep "Not After" | sed "s/.*: \(.*\) .*/\1/g"'
+ register: ownca_cert3_notAfter
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate3 (assert - notBefore)
+ assert:
+ that:
+ - ownca_cert3_notBefore.stdout == 'Oct 23 13:37:42 2018'
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate3 (assert - notAfter)
+ assert:
+ that:
+ - ownca_cert3_notAfter.stdout == 'Oct 23 13:37:42 2019'
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca ECC certificate (test - ownca certificate pubkey)
+ shell: '{{ openssl_binary }} x509 -noout -pubkey -in {{ output_dir }}/ownca_cert_ecc.pem'
+ register: ownca_cert_ecc_pubkey
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca ECC certificate (test - ownca issuer value)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir}}/ownca_cert_ecc.pem -text | grep "Issuer" | sed "s/.*: \(.*\)/\1/g"'
+ register: ownca_cert_ecc_issuer
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca ECC certificate (assert)
+ assert:
+ that:
+ - ownca_cert_ecc_pubkey.stdout == privatekey_ecc_pubkey.stdout
+ # openssl 1.1.x adds a space between the output
+ - ownca_cert_ecc_issuer.stdout in ['CN=Example CA', 'CN = Example CA']
+
+- name: (OwnCA validation, {{select_crypto_backend}})
+ assert:
+ that:
+ - passphrase_error_1 is failed
+ - "'assphrase' in passphrase_error_1.msg or 'assword' in passphrase_error_1.msg"
+ - passphrase_error_2 is failed
+ - "'assphrase' in passphrase_error_2.msg or 'assword' in passphrase_error_2.msg or 'serializ' in passphrase_error_2.msg"
+ - passphrase_error_3 is failed
+ - "'assphrase' in passphrase_error_3.msg or 'assword' in passphrase_error_3.msg or 'serializ' in passphrase_error_3.msg"
+
+- name: (OwnCA validation, {{select_crypto_backend}})Verify that broken certificate will be regenerated
+ assert:
+ that:
+ - ownca_broken is changed
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Check backup
+ assert:
+ that:
+ - ownca_backup_1 is changed
+ - ownca_backup_1.backup_file is undefined
+ - ownca_backup_2 is not changed
+ - ownca_backup_2.backup_file is undefined
+ - ownca_backup_3 is changed
+ - ownca_backup_3.backup_file is string
+ - ownca_backup_4 is changed
+ - ownca_backup_4.backup_file is string
+ - ownca_backup_5 is not changed
+ - ownca_backup_5.backup_file is undefined
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Check create subject key identifier
+ assert:
+ that:
+ - ownca_subject_key_identifier_1 is changed
+ - ownca_subject_key_identifier_2 is not changed
+ - ownca_subject_key_identifier_3 is changed
+ - ownca_subject_key_identifier_4 is not changed
+ - ownca_subject_key_identifier_5 is changed
+ when: select_crypto_backend != 'pyopenssl'
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Check create authority key identifier
+ assert:
+ that:
+ - ownca_authority_key_identifier_1 is changed
+ - ownca_authority_key_identifier_2 is not changed
+ - ownca_authority_key_identifier_3 is changed
+ - ownca_authority_key_identifier_4 is not changed
+ - ownca_authority_key_identifier_5 is changed
+ when: select_crypto_backend != 'pyopenssl'
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Verify Ed25519 and Ed448 tests (for cryptography >= 2.6, < 2.8)
+ assert:
+ that:
+ - ownca_certificate_ed25519_ed448.results[0] is failed
+ - ownca_certificate_ed25519_ed448.results[1] is failed
+ - ownca_certificate_ed25519_ed448_idempotence.results[0] is failed
+ - ownca_certificate_ed25519_ed448_idempotence.results[1] is failed
+ - ownca_certificate_ed25519_ed448_2.results[0] is failed
+ - ownca_certificate_ed25519_ed448_2.results[1] is failed
+ - ownca_certificate_ed25519_ed448_2_idempotence.results[0] is failed
+ - ownca_certificate_ed25519_ed448_2_idempotence.results[1] is failed
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=') and cryptography_version.stdout is version('2.8', '<') and ownca_certificate_ed25519_ed448_privatekey is not failed
+
+- name: (OwnCA validation, {{select_crypto_backend}}) Verify Ed25519 and Ed448 tests (for cryptography >= 2.8)
+ assert:
+ that:
+ - ownca_certificate_ed25519_ed448 is succeeded
+ - ownca_certificate_ed25519_ed448.results[0] is changed
+ - ownca_certificate_ed25519_ed448.results[1] is changed
+ - ownca_certificate_ed25519_ed448_idempotence is succeeded
+ - ownca_certificate_ed25519_ed448_idempotence.results[0] is not changed
+ - ownca_certificate_ed25519_ed448_idempotence.results[1] is not changed
+ - ownca_certificate_ed25519_ed448_2 is succeeded
+ - ownca_certificate_ed25519_ed448_2.results[0] is changed
+ - ownca_certificate_ed25519_ed448_2.results[1] is changed
+ - ownca_certificate_ed25519_ed448_2_idempotence is succeeded
+ - ownca_certificate_ed25519_ed448_2_idempotence.results[0] is not changed
+ - ownca_certificate_ed25519_ed448_2_idempotence.results[1] is not changed
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.8', '>=') and ownca_certificate_ed25519_ed448_privatekey is not failed
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tests/validate_selfsigned.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tests/validate_selfsigned.yml
new file mode 100644
index 00000000..03da84e6
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate/tests/validate_selfsigned.yml
@@ -0,0 +1,198 @@
+---
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate (test - privatekey modulus)
+ shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ output_dir }}/privatekey.pem'
+ register: privatekey_modulus
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate behavior for no CSR
+ assert:
+ that:
+ - selfsigned_certificate_no_csr is changed
+ - selfsigned_certificate_no_csr_idempotence is not changed
+ - selfsigned_certificate_no_csr_idempotence_check is not changed
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate with no CSR (test - certificate modulus)
+ shell: '{{ openssl_binary }} x509 -noout -modulus -in {{ output_dir }}/cert_no_csr.pem'
+ register: cert_modulus
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate with no CSR (test - certficate version == default == 3)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir}}/cert_no_csr.pem -text | grep "Version" | sed "s/.*: \(.*\) .*/\1/g"'
+ register: cert_version
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate with no CSR (assert)
+ assert:
+ that:
+ - cert_modulus.stdout == privatekey_modulus.stdout
+ - cert_version.stdout == '3'
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate with no CSR idempotence
+ assert:
+ that:
+ - selfsigned_certificate_no_csr.serial_number == selfsigned_certificate_no_csr_idempotence.serial_number
+ - selfsigned_certificate_no_csr.notBefore == selfsigned_certificate_no_csr_idempotence.notBefore
+ - selfsigned_certificate_no_csr.notAfter == selfsigned_certificate_no_csr_idempotence.notAfter
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate data retrieval with no CSR
+ assert:
+ that:
+ - selfsigned_certificate_no_csr.certificate == lookup('file', output_dir ~ '/cert_no_csr.pem', rstrip=False)
+ - selfsigned_certificate_no_csr.certificate == selfsigned_certificate_no_csr_idempotence.certificate
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate (test - certificate modulus)
+ shell: '{{ openssl_binary }} x509 -noout -modulus -in {{ output_dir }}/cert.pem'
+ register: cert_modulus
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate (test - issuer value)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir}}/cert.pem -text | grep "Issuer" | sed "s/.*: \(.*\)/\1/g; s/ //g;"'
+ register: cert_issuer
+
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate (test - certficate version == default == 3)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir}}/cert.pem -text | grep "Version" | sed "s/.*: \(.*\) .*/\1/g"'
+ register: cert_version
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate (assert)
+ assert:
+ that:
+ - cert_modulus.stdout == privatekey_modulus.stdout
+ - cert_version.stdout == '3'
+ - cert_issuer.stdout == 'CN=www.example.com'
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate idempotence
+ assert:
+ that:
+ - selfsigned_certificate.serial_number == selfsigned_certificate_idempotence.serial_number
+ - selfsigned_certificate.notBefore == selfsigned_certificate_idempotence.notBefore
+ - selfsigned_certificate.notAfter == selfsigned_certificate_idempotence.notAfter
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate data retrieval
+ assert:
+ that:
+ - selfsigned_certificate.certificate == lookup('file', output_dir ~ '/cert.pem', rstrip=False)
+ - selfsigned_certificate.certificate == selfsigned_certificate_idempotence.certificate
+
+- name: Make sure that changes in CSR are detected even if private key is specified
+ assert:
+ that:
+ - selfsigned_certificate_csr_minimal_change is changed
+
+- block:
+ - name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate v2 (test - certificate version == 2)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir}}/cert_v2.pem -text | grep "Version" | sed "s/.*: \(.*\) .*/\1/g"'
+ register: cert_v2_version
+
+ - name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate version 2 (assert)
+ assert:
+ that:
+ - cert_v2_version.stdout == '2'
+ when: select_crypto_backend != 'cryptography'
+
+- block:
+ - name: (Selfsigned validateion, {{ select_crypto_backend }} Validate certificate v2 is failed
+ assert:
+ that:
+ - selfsigned_v2_cert is failed
+ - "'The cryptography backend does not support v2 certificates' in selfsigned_v2_cert.msg"
+ when: select_crypto_backend == 'cryptography'
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate2 (test - privatekey modulus)
+ shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ output_dir }}/privatekey2.pem'
+ register: privatekey2_modulus
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate2 (test - certificate modulus)
+ shell: '{{ openssl_binary }} x509 -noout -modulus -in {{ output_dir }}/cert2.pem'
+ register: cert2_modulus
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate2 (assert)
+ assert:
+ that:
+ - cert2_modulus.stdout == privatekey2_modulus.stdout
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate3 (test - notBefore)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir }}/cert3.pem -text | grep "Not Before" | sed "s/.*: \(.*\) .*/\1/g"'
+ register: cert3_notBefore
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate3 (test - notAfter)
+ shell: '{{ openssl_binary }} x509 -noout -in {{ output_dir }}/cert3.pem -text | grep "Not After" | sed "s/.*: \(.*\) .*/\1/g"'
+ register: cert3_notAfter
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate3 (assert - notBefore)
+ assert:
+ that:
+ - cert3_notBefore.stdout == 'Oct 23 13:37:42 2018'
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate certificate3 (assert - notAfter)
+ assert:
+ that:
+ - cert3_notAfter.stdout == 'Oct 23 13:37:42 2019'
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate ECC certificate (test - privatekey's pubkey)
+ shell: '{{ openssl_binary }} ec -pubout -in {{ output_dir }}/privatekey_ecc.pem'
+ register: privatekey_ecc_pubkey
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate ECC certificate (test - certificate pubkey)
+ shell: '{{ openssl_binary }} x509 -noout -pubkey -in {{ output_dir }}/cert_ecc.pem'
+ register: cert_ecc_pubkey
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Validate ECC certificate (assert)
+ assert:
+ that:
+ - cert_ecc_pubkey.stdout == privatekey_ecc_pubkey.stdout
+
+- name: (Selfsigned validation, {{select_crypto_backend}})
+ assert:
+ that:
+ - passphrase_error_1 is failed
+ - "'assphrase' in passphrase_error_1.msg or 'assword' in passphrase_error_1.msg"
+ - passphrase_error_2 is failed
+ - "'assphrase' in passphrase_error_2.msg or 'assword' in passphrase_error_2.msg or 'serializ' in passphrase_error_2.msg"
+ - passphrase_error_3 is failed
+ - "'assphrase' in passphrase_error_3.msg or 'assword' in passphrase_error_3.msg or 'serializ' in passphrase_error_3.msg"
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Verify that broken certificate will be regenerated
+ assert:
+ that:
+ - selfsigned_broken is changed
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Check backup
+ assert:
+ that:
+ - selfsigned_backup_1 is changed
+ - selfsigned_backup_1.backup_file is undefined
+ - selfsigned_backup_2 is not changed
+ - selfsigned_backup_2.backup_file is undefined
+ - selfsigned_backup_3 is changed
+ - selfsigned_backup_3.backup_file is string
+ - selfsigned_backup_4 is changed
+ - selfsigned_backup_4.backup_file is string
+ - selfsigned_backup_5 is not changed
+ - selfsigned_backup_5.backup_file is undefined
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Check create subject key identifier
+ assert:
+ that:
+ - selfsigned_subject_key_identifier_1 is changed
+ - selfsigned_subject_key_identifier_2 is not changed
+ - selfsigned_subject_key_identifier_3 is changed
+ - selfsigned_subject_key_identifier_4 is not changed
+ - selfsigned_subject_key_identifier_5 is changed
+ when: select_crypto_backend != 'pyopenssl'
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Verify Ed25519 and Ed448 tests (for cryptography >= 2.6, < 2.8)
+ assert:
+ that:
+ - selfsigned_certificate_ed25519_ed448.results[0] is failed
+ - selfsigned_certificate_ed25519_ed448.results[1] is failed
+ - selfsigned_certificate_ed25519_ed448_idempotence.results[0] is failed
+ - selfsigned_certificate_ed25519_ed448_idempotence.results[1] is failed
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=') and cryptography_version.stdout is version('2.8', '<') and selfsigned_certificate_ed25519_ed448_privatekey is not failed
+
+- name: (Selfsigned validation, {{select_crypto_backend}}) Verify Ed25519 and Ed448 tests (for cryptography >= 2.8)
+ assert:
+ that:
+ - selfsigned_certificate_ed25519_ed448 is succeeded
+ - selfsigned_certificate_ed25519_ed448.results[0] is changed
+ - selfsigned_certificate_ed25519_ed448.results[1] is changed
+ - selfsigned_certificate_ed25519_ed448_idempotence is succeeded
+ - selfsigned_certificate_ed25519_ed448_idempotence.results[0] is not changed
+ - selfsigned_certificate_ed25519_ed448_idempotence.results[1] is not changed
+ when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.8', '>=') and selfsigned_certificate_ed25519_ed448_privatekey is not failed
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/files/cert1.pem b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/files/cert1.pem
new file mode 100644
index 00000000..834eedc4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/files/cert1.pem
@@ -0,0 +1,45 @@
+-----BEGIN CERTIFICATE-----
+MIIH5jCCBs6gAwIBAgISA2gSCm/BtvCR2e2bIap5YbXaMA0GCSqGSIb3DQEBCwUA
+MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
+ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODA3MjcxNzMxMjdaFw0x
+ODEwMjUxNzMxMjdaMB4xHDAaBgNVBAMTE3d3dy5sZXRzZW5jcnlwdC5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDpL8ZjVL0MUkUAIbYO9+ZCni+c
+ghGd9WhM2Ztaay6Wyh6lNoCdltdqTwUhE4O+d7UFModjM3G/KMyfuujr06c5iGKL
+3saPmIzLaRPIEOUlB2rKgasKhe8mDRyRLzQSXXgnsaKcTBBuhIHvtP51ZMr05nJJ
+sX/5FGjj96w+KJel6E/Ux1a1ZDOFkAYNSIrJJhA5jjIvUPr+Ri6Oc6UlhF9oueKI
+uWBILxQpC778tBWdHoZeBCNTHA1VvtwC53OeuHvdZm1jB/e30Mgf5DtVizYpFXVD
+mztkrd6z/3B6ZwPyfCE4KgzSf70/byOz971OJxNKTUVWedKHHDlrMxfsPclbAgMB
+AAGjggTwMIIE7DAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
+CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFG1w4j/KDrYSFu7m9DPE
+xRR0E5gzMB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUF
+BwEBBGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNy
+eXB0Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNy
+eXB0Lm9yZy8wggHxBgNVHREEggHoMIIB5IIbY2VydC5pbnQteDEubGV0c2VuY3J5
+cHQub3JnghtjZXJ0LmludC14Mi5sZXRzZW5jcnlwdC5vcmeCG2NlcnQuaW50LXgz
+LmxldHNlbmNyeXB0Lm9yZ4IbY2VydC5pbnQteDQubGV0c2VuY3J5cHQub3Jnghxj
+ZXJ0LnJvb3QteDEubGV0c2VuY3J5cHQub3Jngh9jZXJ0LnN0YWdpbmcteDEubGV0
+c2VuY3J5cHQub3Jngh9jZXJ0LnN0Zy1pbnQteDEubGV0c2VuY3J5cHQub3JngiBj
+ZXJ0LnN0Zy1yb290LXgxLmxldHNlbmNyeXB0Lm9yZ4ISY3AubGV0c2VuY3J5cHQu
+b3JnghpjcC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZ4ITY3BzLmxldHNlbmNyeXB0
+Lm9yZ4IbY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3Jnghtjcmwucm9vdC14MS5s
+ZXRzZW5jcnlwdC5vcmeCD2xldHNlbmNyeXB0Lm9yZ4IWb3JpZ2luLmxldHNlbmNy
+eXB0Lm9yZ4IXb3JpZ2luMi5sZXRzZW5jcnlwdC5vcmeCFnN0YXR1cy5sZXRzZW5j
+cnlwdC5vcmeCE3d3dy5sZXRzZW5jcnlwdC5vcmcwgf4GA1UdIASB9jCB8zAIBgZn
+gQwBAgEwgeYGCysGAQQBgt8TAQEBMIHWMCYGCCsGAQUFBwIBFhpodHRwOi8vY3Bz
+LmxldHNlbmNyeXB0Lm9yZzCBqwYIKwYBBQUHAgIwgZ4MgZtUaGlzIENlcnRpZmlj
+YXRlIG1heSBvbmx5IGJlIHJlbGllZCB1cG9uIGJ5IFJlbHlpbmcgUGFydGllcyBh
+bmQgb25seSBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIENlcnRpZmljYXRlIFBvbGlj
+eSBmb3VuZCBhdCBodHRwczovL2xldHNlbmNyeXB0Lm9yZy9yZXBvc2l0b3J5LzCC
+AQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AMEWSuCnctLUOS3ICsEHcNTwxJvemRpI
+QMH6B1Fk9jNgAAABZN0ChToAAAQDAEcwRQIgblal8oXnfoopr1+dWVhvBx+sqHT0
+eLYxJHBTaRp3j1QCIQDhFQqMk6DDXUgcU12K36zLVFwJTdAJI4RBisnX+g+W0AB2
+ACk8UZZUyDlluqpQ/FgH1Ldvv1h6KXLcpMMM9OVFR/R4AAABZN0Chz4AAAQDAEcw
+RQIhAImOjvkritUNKJZB7dcUtjoyIbfNwdCspvRiEzXuvVQoAiAZryoyg3TcMun5
+Gb2dEn1cttMnPW9u670/JdRjvjU/wTANBgkqhkiG9w0BAQsFAAOCAQEAGepCmckP
+Tn9Sz268FEwkdD+6wWaPfeYlh+9nacFh90nQ35EYQMOK8a+X7ixHGbRz19On3Wt4
+1fcbPa9SefocTjAintMwwreCxpRTmwGACYojd7vRWEmA6q7+/HO2BfZahWzclOjw
+mSDBycDEm8R0ZK52vYjzVno8x0mrsmSO0403S/6syYB/guH6P17kIBw+Tgx6/i/c
+I1C6MoFkuaAKUUcZmgGGBgE+L/7cWtWjbkVXyA3ZQQy9G7rcBT+N/RrDfBh4iZDq
+jAN5UIIYL8upBhjiMYVuoJrH2nklzEwr5SWKcccJX5eWkGLUwlcY9LGAA8+17l2I
+l1Ou20Dm9TxnNw==
+-----END CERTIFICATE-----
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/tasks/impl.yml
new file mode 100644
index 00000000..91838bd4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/tasks/impl.yml
@@ -0,0 +1,125 @@
+---
+- debug:
+ msg: "Executing tests with backend {{ select_crypto_backend }}"
+
+- name: ({{select_crypto_backend}}) Get certificate info
+ x509_certificate_info:
+ path: '{{ output_dir }}/cert_1.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: Check whether issuer and subject behave as expected
+ assert:
+ that:
+ - result.issuer.organizationalUnitName == 'ACME Department'
+ - "['organizationalUnitName', 'Crypto Department'] in result.issuer_ordered"
+ - "['organizationalUnitName', 'ACME Department'] in result.issuer_ordered"
+ - result.subject.organizationalUnitName == 'ACME Department'
+ - "['organizationalUnitName', 'Crypto Department'] in result.subject_ordered"
+ - "['organizationalUnitName', 'ACME Department'] in result.subject_ordered"
+
+- name: Check SubjectKeyIdentifier and AuthorityKeyIdentifier
+ assert:
+ that:
+ - result.subject_key_identifier == "00:11:22:33"
+ - result.authority_key_identifier == "44:55:66:77"
+ - result.authority_cert_issuer == expected_authority_cert_issuer
+ - result.authority_cert_serial_number == 12345
+ vars:
+ expected_authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+ when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
+
+- name: Update result list
+ set_fact:
+ info_results: "{{ info_results + [result] }}"
+
+- name: ({{select_crypto_backend}}) Get certificate info directly
+ x509_certificate_info:
+ content: '{{ lookup("file", output_dir ~ "/cert_1.pem") }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result_direct
+
+- name: ({{select_crypto_backend}}) Compare output of direct and loaded info
+ assert:
+ that:
+ - result == result_direct
+
+- name: ({{select_crypto_backend}}) Get certificate info
+ x509_certificate_info:
+ path: '{{ output_dir }}/cert_2.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ valid_at:
+ today: "+0d"
+ past: "20190101235901Z"
+ twentydays: "+20d"
+ register: result
+- assert:
+ that:
+ - result.valid_at.today
+ - not result.valid_at.past
+ - not result.valid_at.twentydays
+
+- name: Update result list
+ set_fact:
+ info_results: "{{ info_results + [result] }}"
+
+- name: ({{select_crypto_backend}}) Get certificate info
+ x509_certificate_info:
+ path: '{{ output_dir }}/cert_3.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: Check AuthorityKeyIdentifier
+ assert:
+ that:
+ - result.authority_key_identifier is none
+ - result.authority_cert_issuer == expected_authority_cert_issuer
+ - result.authority_cert_serial_number == 12345
+ vars:
+ expected_authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+ when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
+
+- name: Update result list
+ set_fact:
+ info_results: "{{ info_results + [result] }}"
+
+- name: ({{select_crypto_backend}}) Get certificate info
+ x509_certificate_info:
+ path: '{{ output_dir }}/cert_4.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+
+- name: Check AuthorityKeyIdentifier
+ assert:
+ that:
+ - result.authority_key_identifier == "44:55:66:77"
+ - result.authority_cert_issuer is none
+ - result.authority_cert_serial_number is none
+ when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
+
+- name: Update result list
+ set_fact:
+ info_results: "{{ info_results + [result] }}"
+
+- name: ({{select_crypto_backend}}) Get certificate info for packaged cert 1
+ x509_certificate_info:
+ path: '{{ role_path }}/files/cert1.pem'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: result
+- assert:
+ that:
+ - "'ocsp_uri' in result"
+ - "result.ocsp_uri == 'http://ocsp.int-x3.letsencrypt.org'"
+- name: Check fingerprints
+ assert:
+ that:
+ - (result.fingerprints.sha256 == '57:7c:f1:f5:dd:cc:6e:e9:f3:17:28:73:17:e4:25:c7:69:74:3e:f7:9a:df:58:20:7a:5a:e4:aa:de:bf:24:5b' if result.fingerprints.sha256 is defined else true)
+ - (result.fingerprints.sha1 == 'b7:79:64:f4:2b:e0:ae:45:74:d4:f3:08:f6:53:cb:39:26:fa:52:6b' if result.fingerprints.sha1 is defined else true)
+
+- name: Update result list
+ set_fact:
+ info_results: "{{ info_results + [result] }}"
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/tasks/main.yml
new file mode 100644
index 00000000..44da12e2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/tasks/main.yml
@@ -0,0 +1,183 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Generate privatekey
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: Generate privatekey with password
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekeypw.pem'
+ passphrase: hunter2
+ cipher: auto
+ select_crypto_backend: cryptography
+ size: '{{ default_rsa_key_size_certifiates }}'
+
+- name: Generate CSR 1
+ openssl_csr:
+ path: '{{ output_dir }}/csr_1.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ subject:
+ commonName: www.example.com
+ C: de
+ L: Somewhere
+ ST: Zurich
+ streetAddress: Welcome Street
+ O: Ansible
+ organizationalUnitName:
+ - Crypto Department
+ - ACME Department
+ serialNumber: "1234"
+ SN: Last Name
+ GN: First Name
+ title: Chief
+ pseudonym: test
+ UID: asdf
+ emailAddress: test@example.com
+ postalAddress: 1234 Somewhere
+ postalCode: "1234"
+ useCommonNameForSAN: no
+ key_usage:
+ - digitalSignature
+ - keyAgreement
+ - Non Repudiation
+ - Key Encipherment
+ - dataEncipherment
+ - Certificate Sign
+ - cRLSign
+ - Encipher Only
+ - decipherOnly
+ key_usage_critical: yes
+ extended_key_usage:
+ - serverAuth # the same as "TLS Web Server Authentication"
+ - TLS Web Server Authentication
+ - TLS Web Client Authentication
+ - Code Signing
+ - E-mail Protection
+ - timeStamping
+ - OCSPSigning
+ - Any Extended Key Usage
+ - qcStatements
+ - DVCS
+ - IPSec User
+ - biometricInfo
+ subject_alt_name:
+ - "DNS:www.ansible.com"
+ - "IP:1.2.3.4"
+ - "IP:::1"
+ - "email:test@example.org"
+ - "URI:https://example.org/test/index.html"
+ basic_constraints:
+ - "CA:TRUE"
+ - "pathlen:23"
+ basic_constraints_critical: yes
+ ocsp_must_staple: yes
+ subject_key_identifier: '{{ "00:11:22:33" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ vars:
+ value_for_authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+
+- name: Generate CSR 2
+ openssl_csr:
+ path: '{{ output_dir }}/csr_2.csr'
+ privatekey_path: '{{ output_dir }}/privatekeypw.pem'
+ privatekey_passphrase: hunter2
+ useCommonNameForSAN: no
+ basic_constraints:
+ - "CA:TRUE"
+
+- name: Generate CSR 3
+ openssl_csr:
+ path: '{{ output_dir }}/csr_3.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ useCommonNameForSAN: no
+ subject_alt_name:
+ - "DNS:*.ansible.com"
+ - "DNS:*.example.org"
+ - "IP:DEAD:BEEF::1"
+ basic_constraints:
+ - "CA:FALSE"
+ authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+ vars:
+ value_for_authority_cert_issuer:
+ - "DNS:ca.example.org"
+ - "IP:1.2.3.4"
+
+- name: Generate CSR 4
+ openssl_csr:
+ path: '{{ output_dir }}/csr_4.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ useCommonNameForSAN: no
+ authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
+
+- name: Generate selfsigned certificates
+ x509_certificate:
+ path: '{{ output_dir }}/cert_{{ item }}.pem'
+ csr_path: '{{ output_dir }}/csr_{{ item }}.csr'
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ provider: selfsigned
+ selfsigned_digest: sha256
+ selfsigned_not_after: "+10d"
+ selfsigned_not_before: "-3d"
+ loop:
+ - 1
+ - 2
+ - 3
+ - 4
+
+- name: Prepare result list
+ set_fact:
+ info_results: []
+
+- name: Running tests with pyOpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: pyopenssl
+ when: pyopenssl_version.stdout is version('0.15', '>=')
+
+- name: Prepare result list
+ set_fact:
+ pyopenssl_info_results: "{{ info_results }}"
+ info_results: []
+
+- name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+ when: cryptography_version.stdout is version('1.6', '>=')
+
+- name: Prepare result list
+ set_fact:
+ cryptography_info_results: "{{ info_results }}"
+
+- block:
+ - name: Dump pyOpenSSL results
+ debug:
+ var: pyopenssl_info_results
+ - name: Dump cryptography results
+ debug:
+ var: cryptography_info_results
+ - name: Compare results
+ assert:
+ that:
+ - ' (item.0 | dict2items | rejectattr("key", "in", keys_to_ignore) | list | items2dict)
+ == (item.1 | dict2items | rejectattr("key", "in", keys_to_ignore) | list | items2dict)'
+ quiet: yes
+ loop: "{{ pyopenssl_info_results | zip(cryptography_info_results) | list }}"
+ when: pyopenssl_version.stdout is version('0.15', '>=') and cryptography_version.stdout is version('1.6', '>=')
+ vars:
+ keys_to_ignore:
+ - deprecations
+ - subject_key_identifier
+ - authority_key_identifier
+ - authority_cert_issuer
+ - authority_cert_serial_number
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/test_plugins/jinja_compatibility.py b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/test_plugins/jinja_compatibility.py
new file mode 100644
index 00000000..fc2b5f0f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_info/test_plugins/jinja_compatibility.py
@@ -0,0 +1,15 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+def compatibility_in_test(a, b):
+ return a in b
+
+
+class TestModule:
+ ''' Ansible math jinja2 tests '''
+
+ def tests(self):
+ return {
+ 'in': compatibility_in_test,
+ }
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/aliases
new file mode 100644
index 00000000..6eae8bd8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/aliases
@@ -0,0 +1,2 @@
+shippable/posix/group1
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/meta/main.yml
new file mode 100644
index 00000000..d1a318db
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/meta/main.yml
@@ -0,0 +1,3 @@
+dependencies:
+ - setup_openssl
+ - setup_pyopenssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/tasks/impl.yml
new file mode 100644
index 00000000..854ae5d6
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/tasks/impl.yml
@@ -0,0 +1,237 @@
+---
+- name: "({{ select_crypto_backend }}) Generate privatekey"
+ openssl_privatekey:
+ path: '{{ output_dir }}/{{ item }}.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+ loop:
+ - privatekey
+ - privatekey2
+
+- name: "({{ select_crypto_backend }}) Generate CSRs"
+ openssl_csr:
+ privatekey_path: '{{ output_dir }}/{{ item.key }}.pem'
+ path: '{{ output_dir }}/{{ item.name }}.csr'
+ subject:
+ commonName: '{{ item.cn }}'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ loop:
+ - name: cert
+ key: privatekey
+ cn: www.ansible.com
+ - name: cert-2
+ key: privatekey
+ cn: ansible.com
+ - name: cert-3
+ key: privatekey2
+ cn: example.com
+ - name: cert-4
+ key: privatekey2
+ cn: example.org
+
+## Self Signed
+
+- name: "({{ select_crypto_backend }}) Generate self-signed certificate (check mode)"
+ x509_certificate_pipe:
+ provider: selfsigned
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ selfsigned_not_before: 20181023133742Z
+ selfsigned_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: generate_certificate_check
+
+- name: "({{ select_crypto_backend }}) Generate self-signed certificate"
+ x509_certificate_pipe:
+ provider: selfsigned
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ selfsigned_not_before: 20181023133742Z
+ selfsigned_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: generate_certificate
+
+- name: "({{ select_crypto_backend }}) Generate self-signed certificate (idempotent)"
+ x509_certificate_pipe:
+ provider: selfsigned
+ content: "{{ generate_certificate.certificate }}"
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ selfsigned_not_before: 20181023133742Z
+ selfsigned_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: generate_certificate_idempotent
+
+- name: "({{ select_crypto_backend }}) Generate self-signed certificate (idempotent, check mode)"
+ x509_certificate_pipe:
+ provider: selfsigned
+ content: "{{ generate_certificate.certificate }}"
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ selfsigned_not_before: 20181023133742Z
+ selfsigned_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: generate_certificate_idempotent_check
+
+- name: "({{ select_crypto_backend }}) Generate self-signed certificate (changed)"
+ x509_certificate_pipe:
+ provider: selfsigned
+ content: "{{ generate_certificate.certificate }}"
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ selfsigned_not_before: 20181023133742Z
+ selfsigned_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert-2.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: generate_certificate_changed
+
+- name: "({{ select_crypto_backend }}) Generate self-signed certificate (changed, check mode)"
+ x509_certificate_pipe:
+ provider: selfsigned
+ content: "{{ generate_certificate.certificate }}"
+ privatekey_path: '{{ output_dir }}/privatekey.pem'
+ selfsigned_not_before: 20181023133742Z
+ selfsigned_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert-2.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: generate_certificate_changed_check
+
+- name: "({{ select_crypto_backend }}) Validate certificate (test - privatekey modulus)"
+ shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ output_dir }}/privatekey.pem'
+ register: privatekey_modulus
+
+- name: "({{ select_crypto_backend }}) Validate certificate (test - Common Name)"
+ shell: "{{ openssl_binary }} x509 -noout -subject -in /dev/stdin -nameopt oneline,-space_eq"
+ args:
+ stdin: "{{ generate_certificate.certificate }}"
+ register: certificate_cn
+
+- name: "({{ select_crypto_backend }}) Validate certificate (test - certificate modulus)"
+ shell: '{{ openssl_binary }} x509 -noout -modulus -in /dev/stdin'
+ args:
+ stdin: "{{ generate_certificate.certificate }}"
+ register: certificate_modulus
+
+- name: "({{ select_crypto_backend }}) Validate certificate (assert)"
+ assert:
+ that:
+ - certificate_cn.stdout.split('=')[-1] == 'www.ansible.com'
+ - certificate_modulus.stdout == privatekey_modulus.stdout
+
+- name: "({{ select_crypto_backend }}) Validate certificate (check mode, idempotency)"
+ assert:
+ that:
+ - generate_certificate_check is changed
+ - generate_certificate is changed
+ - generate_certificate_idempotent is not changed
+ - generate_certificate_idempotent_check is not changed
+ - generate_certificate_changed is changed
+ - generate_certificate_changed_check is changed
+
+## Own CA
+
+- name: "({{ select_crypto_backend }}) Generate own CA certificate (check mode)"
+ x509_certificate_pipe:
+ provider: ownca
+ ownca_content: '{{ generate_certificate.certificate }}'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ ownca_not_before: 20181023133742Z
+ ownca_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert-3.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: ownca_generate_certificate_check
+
+- name: "({{ select_crypto_backend }}) Generate own CA certificate"
+ x509_certificate_pipe:
+ provider: ownca
+ ownca_content: '{{ generate_certificate.certificate }}'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ ownca_not_before: 20181023133742Z
+ ownca_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert-3.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: ownca_generate_certificate
+
+- name: "({{ select_crypto_backend }}) Generate own CA certificate (idempotent)"
+ x509_certificate_pipe:
+ provider: ownca
+ content: "{{ ownca_generate_certificate.certificate }}"
+ ownca_content: '{{ generate_certificate.certificate }}'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ ownca_not_before: 20181023133742Z
+ ownca_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert-3.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: ownca_generate_certificate_idempotent
+
+- name: "({{ select_crypto_backend }}) Generate own CA certificate (idempotent, check mode)"
+ x509_certificate_pipe:
+ provider: ownca
+ content: "{{ ownca_generate_certificate.certificate }}"
+ ownca_content: '{{ generate_certificate.certificate }}'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ ownca_not_before: 20181023133742Z
+ ownca_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert-3.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: ownca_generate_certificate_idempotent_check
+
+- name: "({{ select_crypto_backend }}) Generate own CA certificate (changed)"
+ x509_certificate_pipe:
+ provider: ownca
+ content: "{{ ownca_generate_certificate.certificate }}"
+ ownca_content: '{{ generate_certificate.certificate }}'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ ownca_not_before: 20181023133742Z
+ ownca_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert-4.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ register: ownca_generate_certificate_changed
+
+- name: "({{ select_crypto_backend }}) Generate own CA certificate (changed, check mode)"
+ x509_certificate_pipe:
+ provider: ownca
+ content: "{{ ownca_generate_certificate.certificate }}"
+ ownca_content: '{{ generate_certificate.certificate }}'
+ ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
+ ownca_not_before: 20181023133742Z
+ ownca_not_after: 20191023133742Z
+ csr_path: '{{ output_dir }}/cert-4.csr'
+ select_crypto_backend: '{{ select_crypto_backend }}'
+ check_mode: yes
+ register: ownca_generate_certificate_changed_check
+
+- name: "({{ select_crypto_backend }}) Validate certificate (test - privatekey modulus)"
+ shell: '{{ openssl_binary }} rsa -noout -modulus -in {{ output_dir }}/privatekey2.pem'
+ register: privatekey_modulus
+
+- name: "({{ select_crypto_backend }}) Validate certificate (test - Common Name)"
+ shell: "{{ openssl_binary }} x509 -noout -subject -in /dev/stdin -nameopt oneline,-space_eq"
+ args:
+ stdin: "{{ ownca_generate_certificate.certificate }}"
+ register: certificate_cn
+
+- name: "({{ select_crypto_backend }}) Validate certificate (test - certificate modulus)"
+ shell: '{{ openssl_binary }} x509 -noout -modulus -in /dev/stdin'
+ args:
+ stdin: "{{ ownca_generate_certificate.certificate }}"
+ register: certificate_modulus
+
+- name: "({{ select_crypto_backend }}) Validate certificate (assert)"
+ assert:
+ that:
+ - certificate_cn.stdout.split('=')[-1] == 'example.com'
+ - certificate_modulus.stdout == privatekey_modulus.stdout
+
+- name: "({{ select_crypto_backend }}) Validate certificate (check mode, idempotency)"
+ assert:
+ that:
+ - ownca_generate_certificate_check is changed
+ - ownca_generate_certificate is changed
+ - ownca_generate_certificate_idempotent is not changed
+ - ownca_generate_certificate_idempotent_check is not changed
+ - ownca_generate_certificate_changed is changed
+ - ownca_generate_certificate_changed_check is changed
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/tasks/main.yml
new file mode 100644
index 00000000..6cb76213
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_certificate_pipe/tasks/main.yml
@@ -0,0 +1,40 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- name: Prepare private key for backend autodetection test
+ openssl_privatekey:
+ path: '{{ output_dir }}/privatekey_backend_selection.pem'
+ size: '{{ default_rsa_key_size_certifiates }}'
+- name: Run module with backend autodetection
+ x509_certificate_pipe:
+ provider: selfsigned
+ privatekey_path: '{{ output_dir }}/privatekey_backend_selection.pem'
+
+- block:
+ - name: Running tests with pyOpenSSL backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: pyopenssl
+
+ when: pyopenssl_version.stdout is version('0.15', '>=')
+
+- name: Remove output directory
+ file:
+ path: "{{ output_dir }}"
+ state: absent
+
+- name: Re-create output directory
+ file:
+ path: "{{ output_dir }}"
+ state: directory
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ when: cryptography_version.stdout is version('1.6', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/aliases b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/aliases
new file mode 100644
index 00000000..96537bac
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/aliases
@@ -0,0 +1,3 @@
+shippable/posix/group1
+x509_crl_info
+destructive
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/meta/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/meta/main.yml
new file mode 100644
index 00000000..800aff64
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - setup_openssl
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tasks/impl.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tasks/impl.yml
new file mode 100644
index 00000000..68ed2fc7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tasks/impl.yml
@@ -0,0 +1,388 @@
+---
+- name: Create CRL 1 (check mode)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: 20191013000000Z
+ next_update: 20191113000000Z
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ revocation_date: 20191013000000Z
+ - path: '{{ output_dir }}/cert-2.pem'
+ revocation_date: 20191013000000Z
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ revocation_date: 20191001000000Z
+ check_mode: yes
+ register: crl_1_check
+- name: Create CRL 1
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: 20191013000000Z
+ next_update: 20191113000000Z
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ revocation_date: 20191013000000Z
+ - path: '{{ output_dir }}/cert-2.pem'
+ revocation_date: 20191013000000Z
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ revocation_date: 20191001000000Z
+ register: crl_1
+- name: Retrieve CRL 1 infos
+ x509_crl_info:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ register: crl_1_info_1
+- name: Retrieve CRL 1 infos via file content
+ x509_crl_info:
+ content: '{{ lookup("file", output_dir ~ "/ca-crl1.crl") }}'
+ register: crl_1_info_2
+- name: Retrieve CRL 1 infos via file content (Base64)
+ x509_crl_info:
+ content: '{{ lookup("file", output_dir ~ "/ca-crl1.crl") | b64encode }}'
+ register: crl_1_info_3
+- name: Create CRL 1 (idempotent, check mode)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: 20191013000000Z
+ next_update: 20191113000000Z
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ revocation_date: 20191013000000Z
+ - path: '{{ output_dir }}/cert-2.pem'
+ revocation_date: 20191013000000Z
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ revocation_date: 20191001000000Z
+ check_mode: yes
+ register: crl_1_idem_check
+- name: Create CRL 1 (idempotent)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: 20191013000000Z
+ next_update: 20191113000000Z
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ revocation_date: 20191013000000Z
+ - path: '{{ output_dir }}/cert-2.pem'
+ revocation_date: 20191013000000Z
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ revocation_date: 20191001000000Z
+ register: crl_1_idem
+- name: Create CRL 1 (idempotent with content, check mode)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ privatekey_content: "{{ lookup('file', output_dir ~ '/ca.key') }}"
+ issuer:
+ CN: Ansible
+ last_update: 20191013000000Z
+ next_update: 20191113000000Z
+ revoked_certificates:
+ - content: "{{ lookup('file', output_dir ~ '/cert-1.pem') }}"
+ revocation_date: 20191013000000Z
+ - content: "{{ lookup('file', output_dir ~ '/cert-2.pem') }}"
+ revocation_date: 20191013000000Z
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ revocation_date: 20191001000000Z
+ check_mode: yes
+ register: crl_1_idem_content_check
+- name: Create CRL 1 (idempotent with content)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ privatekey_content: "{{ lookup('file', output_dir ~ '/ca.key') }}"
+ issuer:
+ CN: Ansible
+ last_update: 20191013000000Z
+ next_update: 20191113000000Z
+ revoked_certificates:
+ - content: "{{ lookup('file', output_dir ~ '/cert-1.pem') }}"
+ revocation_date: 20191013000000Z
+ - content: "{{ lookup('file', output_dir ~ '/cert-2.pem') }}"
+ revocation_date: 20191013000000Z
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ revocation_date: 20191001000000Z
+ register: crl_1_idem_content
+- name: Create CRL 1 (format, check mode)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ format: der
+ issuer:
+ CN: Ansible
+ last_update: 20191013000000Z
+ next_update: 20191113000000Z
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ revocation_date: 20191013000000Z
+ - path: '{{ output_dir }}/cert-2.pem'
+ revocation_date: 20191013000000Z
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ revocation_date: 20191001000000Z
+ check_mode: yes
+ register: crl_1_format_check
+- name: Create CRL 1 (format)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ format: der
+ issuer:
+ CN: Ansible
+ last_update: 20191013000000Z
+ next_update: 20191113000000Z
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ revocation_date: 20191013000000Z
+ - path: '{{ output_dir }}/cert-2.pem'
+ revocation_date: 20191013000000Z
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ revocation_date: 20191001000000Z
+ register: crl_1_format
+- name: Create CRL 1 (format, idempotent, check mode)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ format: der
+ issuer:
+ CN: Ansible
+ last_update: 20191013000000Z
+ next_update: 20191113000000Z
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ revocation_date: 20191013000000Z
+ - path: '{{ output_dir }}/cert-2.pem'
+ revocation_date: 20191013000000Z
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ revocation_date: 20191001000000Z
+ check_mode: yes
+ register: crl_1_format_idem_check
+- name: Create CRL 1 (format, idempotent)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ format: der
+ issuer:
+ CN: Ansible
+ last_update: 20191013000000Z
+ next_update: 20191113000000Z
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ revocation_date: 20191013000000Z
+ - path: '{{ output_dir }}/cert-2.pem'
+ revocation_date: 20191013000000Z
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ revocation_date: 20191001000000Z
+ return_content: yes
+ register: crl_1_format_idem
+- name: Retrieve CRL 1 infos via file
+ x509_crl_info:
+ path: '{{ output_dir }}/ca-crl1.crl'
+ register: crl_1_info_4
+- name: Read ca-crl1.crl
+ slurp:
+ src: "{{ output_dir }}/ca-crl1.crl"
+ register: content
+- name: Retrieve CRL 1 infos via file content (Base64)
+ x509_crl_info:
+ content: '{{ content.content }}'
+ register: crl_1_info_5
+
+- name: Create CRL 2 (check mode)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl2.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: +0d
+ next_update: +0d
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ - path: '{{ output_dir }}/cert-2.pem'
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ check_mode: yes
+ register: crl_2_check
+- name: Create CRL 2
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl2.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: +0d
+ next_update: +0d
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ - path: '{{ output_dir }}/cert-2.pem'
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ register: crl_2
+- name: Create CRL 2 (idempotent, check mode)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl2.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: +0d
+ next_update: +0d
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ - path: '{{ output_dir }}/cert-2.pem'
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ ignore_timestamps: yes
+ check_mode: yes
+ register: crl_2_idem_check
+- name: Create CRL 2 (idempotent)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl2.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: +0d
+ next_update: +0d
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-1.pem'
+ - path: '{{ output_dir }}/cert-2.pem'
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ - serial_number: 1234
+ ignore_timestamps: yes
+ register: crl_2_idem
+- name: Create CRL 2 (idempotent update, check mode)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl2.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: +0d
+ next_update: +0d
+ revoked_certificates:
+ - serial_number: 1235
+ ignore_timestamps: yes
+ mode: update
+ check_mode: yes
+ register: crl_2_idem_update_change_check
+- name: Create CRL 2 (idempotent update)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl2.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: +0d
+ next_update: +0d
+ revoked_certificates:
+ - serial_number: 1235
+ ignore_timestamps: yes
+ mode: update
+ register: crl_2_idem_update_change
+- name: Create CRL 2 (idempotent update, check mode)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl2.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: +0d
+ next_update: +0d
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-2.pem'
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ ignore_timestamps: yes
+ mode: update
+ check_mode: yes
+ register: crl_2_idem_update_check
+- name: Create CRL 2 (idempotent update)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl2.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: +0d
+ next_update: +0d
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-2.pem'
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ ignore_timestamps: yes
+ mode: update
+ register: crl_2_idem_update
+- name: Create CRL 2 (changed timestamps, check mode)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl2.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: +0d
+ next_update: +0d
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-2.pem'
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ ignore_timestamps: no
+ mode: update
+ check_mode: yes
+ register: crl_2_change_check
+- name: Create CRL 2 (changed timestamps)
+ x509_crl:
+ path: '{{ output_dir }}/ca-crl2.crl'
+ privatekey_path: '{{ output_dir }}/ca.key'
+ issuer:
+ CN: Ansible
+ last_update: +0d
+ next_update: +0d
+ revoked_certificates:
+ - path: '{{ output_dir }}/cert-2.pem'
+ reason: key_compromise
+ reason_critical: yes
+ invalidity_date: 20191012000000Z
+ ignore_timestamps: no
+ mode: update
+ return_content: yes
+ register: crl_2_change
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tasks/main.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tasks/main.yml
new file mode 100644
index 00000000..c2467213
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tasks/main.yml
@@ -0,0 +1,88 @@
+---
+####################################################################
+# WARNING: These are designed specifically for Ansible tests #
+# and should not be used as examples of how to write Ansible roles #
+####################################################################
+
+- set_fact:
+ certificates:
+ - name: ca
+ subject:
+ commonName: Ansible
+ is_ca: yes
+ - name: ca-2
+ subject:
+ commonName: Ansible Other CA
+ is_ca: yes
+ - name: cert-1
+ subject_alt_name:
+ - DNS:ansible.com
+ - name: cert-2
+ subject_alt_name:
+ - DNS:example.com
+ - name: cert-3
+ subject_alt_name:
+ - DNS:example.org
+ - IP:1.2.3.4
+ - name: cert-4
+ subject_alt_name:
+ - DNS:test.ansible.com
+ - DNS:b64.ansible.com
+
+- name: Generate private keys
+ openssl_privatekey:
+ path: '{{ output_dir }}/{{ item.name }}.key'
+ type: ECC
+ curve: secp256r1
+ loop: "{{ certificates }}"
+
+- name: Generate CSRs
+ openssl_csr:
+ path: '{{ output_dir }}/{{ item.name }}.csr'
+ privatekey_path: '{{ output_dir }}/{{ item.name }}.key'
+ subject: "{{ item.subject | default(omit) }}"
+ subject_alt_name: "{{ item.subject_alt_name | default(omit) }}"
+ basic_constraints: "{{ 'CA:TRUE' if item.is_ca | default(false) else omit }}"
+ use_common_name_for_san: no
+ loop: "{{ certificates }}"
+
+- name: Generate CA certificates
+ x509_certificate:
+ path: '{{ output_dir }}/{{ item.name }}.pem'
+ csr_path: '{{ output_dir }}/{{ item.name }}.csr'
+ privatekey_path: '{{ output_dir }}/{{ item.name }}.key'
+ provider: selfsigned
+ loop: "{{ certificates }}"
+ when: item.is_ca | default(false)
+
+- name: Generate other certificates
+ x509_certificate:
+ path: '{{ output_dir }}/{{ item.name }}.pem'
+ csr_path: '{{ output_dir }}/{{ item.name }}.csr'
+ provider: ownca
+ ownca_path: '{{ output_dir }}/ca.pem'
+ ownca_privatekey_path: '{{ output_dir }}/ca.key'
+ loop: "{{ certificates }}"
+ when: not (item.is_ca | default(false))
+
+- name: Get certificate infos
+ x509_certificate_info:
+ path: '{{ output_dir }}/{{ item }}.pem'
+ loop:
+ - cert-1
+ - cert-2
+ - cert-3
+ - cert-4
+ register: certificate_infos
+
+- block:
+ - name: Running tests with cryptography backend
+ include_tasks: impl.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ - import_tasks: ../tests/validate.yml
+ vars:
+ select_crypto_backend: cryptography
+
+ when: cryptography_version.stdout is version('1.2', '>=')
diff --git a/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tests/validate.yml b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tests/validate.yml
new file mode 100644
index 00000000..c31fa942
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/community/crypto/tests/integration/targets/x509_crl/tests/validate.yml
@@ -0,0 +1,82 @@
+---
+- name: Validate CRL 1
+ assert:
+ that:
+ - crl_1_check is changed
+ - crl_1 is changed
+ - crl_1_idem_check is not changed
+ - crl_1_idem is not changed
+ - crl_1_idem_content_check is not changed
+ - crl_1_idem_content is not changed
+
+- name: Validate CRL 1 info
+ assert:
+ that:
+ - crl_1_info_1.format == 'pem'
+ - crl_1_info_1.digest == 'ecdsa-with-SHA256'
+ - crl_1_info_1.issuer | length == 1
+ - crl_1_info_1.issuer.commonName == 'Ansible'
+ - crl_1_info_1.issuer_ordered | length == 1
+ - crl_1_info_1.last_update == '20191013000000Z'
+ - crl_1_info_1.next_update == '20191113000000Z'
+ - crl_1_info_1.revoked_certificates | length == 3
+ - crl_1_info_1.revoked_certificates[0].invalidity_date is none
+ - crl_1_info_1.revoked_certificates[0].invalidity_date_critical == false
+ - crl_1_info_1.revoked_certificates[0].issuer is none
+ - crl_1_info_1.revoked_certificates[0].issuer_critical == false
+ - crl_1_info_1.revoked_certificates[0].reason is none
+ - crl_1_info_1.revoked_certificates[0].reason_critical == false
+ - crl_1_info_1.revoked_certificates[0].revocation_date == '20191013000000Z'
+ - crl_1_info_1.revoked_certificates[0].serial_number == certificate_infos.results[0].serial_number
+ - crl_1_info_1.revoked_certificates[1].invalidity_date == '20191012000000Z'
+ - crl_1_info_1.revoked_certificates[1].invalidity_date_critical == false
+ - crl_1_info_1.revoked_certificates[1].issuer is none
+ - crl_1_info_1.revoked_certificates[1].issuer_critical == false
+ - crl_1_info_1.revoked_certificates[1].reason == 'key_compromise'
+ - crl_1_info_1.revoked_certificates[1].reason_critical == true
+ - crl_1_info_1.revoked_certificates[1].revocation_date == '20191013000000Z'
+ - crl_1_info_1.revoked_certificates[1].serial_number == certificate_infos.results[1].serial_number
+ - crl_1_info_1.revoked_certificates[2].invalidity_date is none
+ - crl_1_info_1.revoked_certificates[2].invalidity_date_critical == false
+ - crl_1_info_1.revoked_certificates[2].issuer is none
+ - crl_1_info_1.revoked_certificates[2].issuer_critical == false
+ - crl_1_info_1.revoked_certificates[2].reason is none
+ - crl_1_info_1.revoked_certificates[2].reason_critical == false
+ - crl_1_info_1.revoked_certificates[2].revocation_date == '20191001000000Z'
+ - crl_1_info_1.revoked_certificates[2].serial_number == 1234
+ - crl_1_info_1 == crl_1_info_2
+ - crl_1_info_1 == crl_1_info_3
+
+- name: Validate CRL 1
+ assert:
+ that:
+ - crl_1_format_check is changed
+ - crl_1_format is changed
+ - crl_1_format_idem_check is not changed
+ - crl_1_format_idem is not changed
+ - crl_1_info_4.format == 'der'
+ - crl_1_info_5.format == 'der'
+
+- name: Read ca-crl1.crl
+ slurp:
+ src: "{{ output_dir }}/ca-crl1.crl"
+ register: content
+- name: Validate CRL 1 Base64 content
+ assert:
+ that:
+ - crl_1_format_idem.crl | b64decode == content.content | b64decode
+
+- name: Validate CRL 2
+ assert:
+ that:
+ - crl_2_check is changed
+ - crl_2 is changed
+ - crl_2_idem_check is not changed
+ - crl_2_idem is not changed
+ - crl_2_idem_update_change_check is changed
+ - crl_2_idem_update_change is changed
+ - crl_2_idem_update_check is not changed
+ - crl_2_idem_update is not changed
+ - crl_2_change_check is changed
+ - crl_2_change is changed
+ - crl_2_change.crl == lookup('file', output_dir ~ '/ca-crl2.crl', rstrip=False)