From 8b22c45a454789abdc5b9a3bd8f3c0525be0a8b5 Mon Sep 17 00:00:00 2001 From: Yanis Guenane Date: Tue, 25 Jul 2017 13:18:18 +0200 Subject: [PATCH] Enable integration tests for the crypto/ namespace (#26684) Crypto namespace contains the openssl modules. It has no integration testing as of now. This commits aims to add integration tests for the crypto namespace. This will make it easier to spot breaking changes in the future. This tests currently apply to: * openssl_privatekey * openssl_publickey * openssl_csr --- lib/ansible/module_utils/crypto.py | 19 +++++++------ lib/ansible/modules/crypto/openssl_csr.py | 10 ++++--- .../modules/crypto/openssl_publickey.py | 2 +- test/integration/targets/openssl_csr/aliases | 1 + .../targets/openssl_csr/meta/main.yml | 2 ++ .../targets/openssl_csr/tasks/main.yml | 11 ++++++++ .../targets/openssl_csr/tests/validate.yml | 17 +++++++++++ .../targets/openssl_privatekey/aliases | 1 + .../targets/openssl_privatekey/meta/main.yml | 2 ++ .../targets/openssl_privatekey/tasks/main.yml | 15 ++++++++++ .../openssl_privatekey/tests/validate.yml | 28 +++++++++++++++++++ .../targets/openssl_publickey/aliases | 1 + .../targets/openssl_publickey/meta/main.yml | 2 ++ .../targets/openssl_publickey/tasks/main.yml | 13 +++++++++ .../openssl_publickey/tests/validate.yml | 12 ++++++++ .../targets/setup_openssl/tasks/main.yml | 25 +++++++++++++++++ .../targets/setup_openssl/vars/Debian.yml | 2 ++ .../targets/setup_openssl/vars/FreeBSD.yml | 1 + .../targets/setup_openssl/vars/RedHat.yml | 1 + .../targets/setup_openssl/vars/Suse.yml | 1 + 20 files changed, 152 insertions(+), 14 deletions(-) create mode 100644 test/integration/targets/openssl_csr/aliases create mode 100644 test/integration/targets/openssl_csr/meta/main.yml create mode 100644 test/integration/targets/openssl_csr/tasks/main.yml create mode 100644 test/integration/targets/openssl_csr/tests/validate.yml create mode 100644 test/integration/targets/openssl_privatekey/aliases create mode 100644 test/integration/targets/openssl_privatekey/meta/main.yml create mode 100644 test/integration/targets/openssl_privatekey/tasks/main.yml create mode 100644 test/integration/targets/openssl_privatekey/tests/validate.yml create mode 100644 test/integration/targets/openssl_publickey/aliases create mode 100644 test/integration/targets/openssl_publickey/meta/main.yml create mode 100644 test/integration/targets/openssl_publickey/tasks/main.yml create mode 100644 test/integration/targets/openssl_publickey/tests/validate.yml create mode 100644 test/integration/targets/setup_openssl/tasks/main.yml create mode 100644 test/integration/targets/setup_openssl/vars/Debian.yml create mode 100644 test/integration/targets/setup_openssl/vars/FreeBSD.yml create mode 100644 test/integration/targets/setup_openssl/vars/RedHat.yml create mode 100644 test/integration/targets/setup_openssl/vars/Suse.yml diff --git a/lib/ansible/module_utils/crypto.py b/lib/ansible/module_utils/crypto.py index 4f2b770cd48..0ee1f67a151 100644 --- a/lib/ansible/module_utils/crypto.py +++ b/lib/ansible/module_utils/crypto.py @@ -35,15 +35,12 @@ class OpenSSLObjectError(Exception): pass -def get_fingerprint(path, passphrase): +def get_fingerprint(path, passphrase=None): """Generate the fingerprint of the public key. """ fingerprint = {} - privatekey = crypto.load_privatekey(crypto.FILETYPE_PEM, - open(path, 'rb').read(), - passphrase) - + privatekey = load_privatekey(path, passphrase) try: publickey = crypto.dump_publickey(crypto.FILETYPE_ASN1, privatekey) for algo in hashlib.algorithms: @@ -63,10 +60,14 @@ def load_privatekey(path, passphrase=None): """Load the specified OpenSSL private key.""" try: - privatekey_content = open(path, 'rb').read() - privatekey = crypto.load_privatekey(crypto.FILETYPE_PEM, - privatekey_content, - passphrase) + if passphrase: + privatekey = crypto.load_privatekey(crypto.FILETYPE_PEM, + open(path, 'rb').read(), + passphrase) + else: + privatekey = crypto.load_privatekey(crypto.FILETYPE_PEM, + open(path, 'rb').read()) + return privatekey except (IOError, OSError) as exc: raise OpenSSLObjectError(exc) diff --git a/lib/ansible/modules/crypto/openssl_csr.py b/lib/ansible/modules/crypto/openssl_csr.py index 217e40ce1dd..1a25c3cdc42 100644 --- a/lib/ansible/modules/crypto/openssl_csr.py +++ b/lib/ansible/modules/crypto/openssl_csr.py @@ -179,6 +179,7 @@ except ImportError: else: pyopenssl_found = True +from ansible.module_utils import crypto as crypto_utils from ansible.module_utils.basic import AnsibleModule from ansible.module_utils._text import to_native @@ -231,10 +232,11 @@ class CertificateSigningRequest(object): if self.subjectAltName is not None: req.add_extensions([crypto.X509Extension(b"subjectAltName", False, self.subjectAltName.encode('ascii'))]) - privatekey_content = open(self.privatekey_path).read() - self.privatekey = crypto.load_privatekey(crypto.FILETYPE_PEM, - privatekey_content, - self.privatekey_passphrase) + self.privatekey = crypto_utils.load_privatekey( + self.privatekey_path, + self.privatekey_passphrase + ) + req.set_pubkey(self.privatekey) req.sign(self.privatekey, self.digest) self.request = req diff --git a/lib/ansible/modules/crypto/openssl_publickey.py b/lib/ansible/modules/crypto/openssl_publickey.py index fe7cfdd8352..b8d1bd2f118 100644 --- a/lib/ansible/modules/crypto/openssl_publickey.py +++ b/lib/ansible/modules/crypto/openssl_publickey.py @@ -187,7 +187,7 @@ class PublicKey(object): self.privatekey = crypto.load_privatekey(crypto.FILETYPE_PEM, privatekey_content) publickey_content = crypto.dump_publickey(crypto.FILETYPE_PEM, self.privatekey) - publickey_file = open(self.path, 'w') + publickey_file = open(self.path, 'wb') publickey_file.write(publickey_content) publickey_file.close() diff --git a/test/integration/targets/openssl_csr/aliases b/test/integration/targets/openssl_csr/aliases new file mode 100644 index 00000000000..4485d761629 --- /dev/null +++ b/test/integration/targets/openssl_csr/aliases @@ -0,0 +1 @@ +posix/ci/group1 diff --git a/test/integration/targets/openssl_csr/meta/main.yml b/test/integration/targets/openssl_csr/meta/main.yml new file mode 100644 index 00000000000..800aff64284 --- /dev/null +++ b/test/integration/targets/openssl_csr/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_openssl diff --git a/test/integration/targets/openssl_csr/tasks/main.yml b/test/integration/targets/openssl_csr/tasks/main.yml new file mode 100644 index 00000000000..48f3a489efa --- /dev/null +++ b/test/integration/targets/openssl_csr/tasks/main.yml @@ -0,0 +1,11 @@ +- name: Generate privatekey + openssl_privatekey: + path: '{{ output_dir }}/privatekey.pem' + +- name: Generate CSR + openssl_csr: + path: '{{ output_dir }}/csr.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + commonName: 'www.ansible.com' + +- import_tasks: ../tests/validate.yml diff --git a/test/integration/targets/openssl_csr/tests/validate.yml b/test/integration/targets/openssl_csr/tests/validate.yml new file mode 100644 index 00000000000..b24f61a2bbf --- /dev/null +++ b/test/integration/targets/openssl_csr/tests/validate.yml @@ -0,0 +1,17 @@ +- name: Validate CSR (test - privatekey modulus) + shell: 'openssl rsa -noout -modulus -in {{ output_dir }}/privatekey.pem | openssl md5' + register: privatekey_modulus + +- name: Validate CSR (test - Common Name) + shell: "openssl req -noout -subject -in {{ output_dir }}/csr.csr -nameopt oneline,-space_eq" + register: csr_cn + +- name: Validate CSR (test - csr modulus) + shell: 'openssl req -noout -modulus -in {{ output_dir }}/csr.csr | openssl md5' + register: csr_modulus + +- name: Validate CSR (assert) + assert: + that: + - csr_cn.stdout.split('=')[-1] == 'www.ansible.com' + - csr_modulus.stdout == privatekey_modulus.stdout diff --git a/test/integration/targets/openssl_privatekey/aliases b/test/integration/targets/openssl_privatekey/aliases new file mode 100644 index 00000000000..4485d761629 --- /dev/null +++ b/test/integration/targets/openssl_privatekey/aliases @@ -0,0 +1 @@ +posix/ci/group1 diff --git a/test/integration/targets/openssl_privatekey/meta/main.yml b/test/integration/targets/openssl_privatekey/meta/main.yml new file mode 100644 index 00000000000..800aff64284 --- /dev/null +++ b/test/integration/targets/openssl_privatekey/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_openssl diff --git a/test/integration/targets/openssl_privatekey/tasks/main.yml b/test/integration/targets/openssl_privatekey/tasks/main.yml new file mode 100644 index 00000000000..464f56e17e3 --- /dev/null +++ b/test/integration/targets/openssl_privatekey/tasks/main.yml @@ -0,0 +1,15 @@ +- name: Generate privatekey1 - standard + openssl_privatekey: + path: '{{ output_dir }}/privatekey1.pem' + +- name: Generate privatekey2 - size 2048 + openssl_privatekey: + path: '{{ output_dir }}/privatekey2.pem' + size: 2048 + +- name: Generate privatekey3 - type DSA + openssl_privatekey: + path: '{{ output_dir }}/privatekey3.pem' + type: DSA + +- import_tasks: ../tests/validate.yml diff --git a/test/integration/targets/openssl_privatekey/tests/validate.yml b/test/integration/targets/openssl_privatekey/tests/validate.yml new file mode 100644 index 00000000000..ccbce924e55 --- /dev/null +++ b/test/integration/targets/openssl_privatekey/tests/validate.yml @@ -0,0 +1,28 @@ +- name: Validate privatekey1 (test) + shell: "openssl rsa -noout -text -in {{ output_dir }}/privatekey1.pem | grep Private | sed 's/Private-Key: (\\(.*\\) bit)/\\1/'" + register: privatekey1 + +- name: Validate privatekey1 (assert) + assert: + that: + - privatekey1.stdout == '4096' + + +- name: Validate privatekey2 (test) + shell: "openssl rsa -noout -text -in {{ output_dir }}/privatekey2.pem | grep Private | sed 's/Private-Key: (\\(.*\\) bit)/\\1/'" + register: privatekey2 + +- name: Validate privatekey2 (assert) + assert: + that: + - privatekey2.stdout == '2048' + + +- name: Validate privatekey3 (test) + shell: "openssl dsa -noout -text -in {{ output_dir }}/privatekey3.pem | grep Private | sed 's/Private-Key: (\\(.*\\) bit)/\\1/'" + register: privatekey3 + +- name: Validate privatekey3 (assert) + assert: + that: + - privatekey1.stdout == '4096' diff --git a/test/integration/targets/openssl_publickey/aliases b/test/integration/targets/openssl_publickey/aliases new file mode 100644 index 00000000000..4485d761629 --- /dev/null +++ b/test/integration/targets/openssl_publickey/aliases @@ -0,0 +1 @@ +posix/ci/group1 diff --git a/test/integration/targets/openssl_publickey/meta/main.yml b/test/integration/targets/openssl_publickey/meta/main.yml new file mode 100644 index 00000000000..800aff64284 --- /dev/null +++ b/test/integration/targets/openssl_publickey/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_openssl diff --git a/test/integration/targets/openssl_publickey/tasks/main.yml b/test/integration/targets/openssl_publickey/tasks/main.yml new file mode 100644 index 00000000000..8f8a7a34526 --- /dev/null +++ b/test/integration/targets/openssl_publickey/tasks/main.yml @@ -0,0 +1,13 @@ +- block: + - name: Generate privatekey + openssl_privatekey: + path: '{{ output_dir }}/privatekey.pem' + + - name: Generate publickey + openssl_publickey: + path: '{{ output_dir }}/publickey.pub' + privatekey_path: '{{ output_dir }}/privatekey.pem' + + - import_tasks: ../tests/validate.yml + + when: pyopenssl_version.stdout|version_compare('16.0.0', '>=') diff --git a/test/integration/targets/openssl_publickey/tests/validate.yml b/test/integration/targets/openssl_publickey/tests/validate.yml new file mode 100644 index 00000000000..8bf34c6d138 --- /dev/null +++ b/test/integration/targets/openssl_publickey/tests/validate.yml @@ -0,0 +1,12 @@ +- name: Validate public key (test - privatekey modulus) + shell: 'openssl rsa -noout -modulus -in {{ output_dir }}/privatekey.pem | openssl md5' + register: privatekey_modulus + +- name: Validate public key (test - publickey modulus) + shell: 'openssl rsa -pubin -noout -modulus < {{ output_dir }}/publickey.pub | openssl md5' + register: publickey_modulus + +- name: Validate public key (assert) + assert: + that: + - publickey_modulus.stdout == privatekey_modulus.stdout diff --git a/test/integration/targets/setup_openssl/tasks/main.yml b/test/integration/targets/setup_openssl/tasks/main.yml new file mode 100644 index 00000000000..282ee43dd49 --- /dev/null +++ b/test/integration/targets/setup_openssl/tasks/main.yml @@ -0,0 +1,25 @@ +- name: Incluse OS-specific variables + include_vars: '{{ ansible_os_family }}.yml' + when: not ansible_os_family == "Darwin" + +- name: Install pyOpenSSL + become: True + package: + name: '{{ pyopenssl_package_name_python3 }}' + when: not ansible_os_family == 'Darwin' and ansible_python_version|version_compare('3.0', '>=') + +- name: Install pyOpenSSL + become: True + package: + name: '{{ pyopenssl_package_name }}' + when: not ansible_os_family == 'Darwin' and ansible_python_version|version_compare('3.0', '<') + +- name: Install pyOpenSSL + become: True + pip: + name: pyOpenSSL + when: ansible_os_family == 'Darwin' + +- name: register openssl version + command: python -c 'import OpenSSL; print(OpenSSL.__version__)' + register: pyopenssl_version diff --git a/test/integration/targets/setup_openssl/vars/Debian.yml b/test/integration/targets/setup_openssl/vars/Debian.yml new file mode 100644 index 00000000000..44d0aab0b3b --- /dev/null +++ b/test/integration/targets/setup_openssl/vars/Debian.yml @@ -0,0 +1,2 @@ +pyopenssl_package_name: python-openssl +pyopenssl_package_name_python3: python3-openssl diff --git a/test/integration/targets/setup_openssl/vars/FreeBSD.yml b/test/integration/targets/setup_openssl/vars/FreeBSD.yml new file mode 100644 index 00000000000..a2064a7d062 --- /dev/null +++ b/test/integration/targets/setup_openssl/vars/FreeBSD.yml @@ -0,0 +1 @@ +pyopenssl_package_name: py27-openssl diff --git a/test/integration/targets/setup_openssl/vars/RedHat.yml b/test/integration/targets/setup_openssl/vars/RedHat.yml new file mode 100644 index 00000000000..5631e74433d --- /dev/null +++ b/test/integration/targets/setup_openssl/vars/RedHat.yml @@ -0,0 +1 @@ +pyopenssl_package_name: pyOpenSSL diff --git a/test/integration/targets/setup_openssl/vars/Suse.yml b/test/integration/targets/setup_openssl/vars/Suse.yml new file mode 100644 index 00000000000..4816a9f645b --- /dev/null +++ b/test/integration/targets/setup_openssl/vars/Suse.yml @@ -0,0 +1 @@ +pyopenssl_package_name: python-pyOpenSSL