From fc4580b4cc9b2c5bbc41f4a04e59e6c812801c62 Mon Sep 17 00:00:00 2001 From: Tim Rupp Date: Tue, 31 Oct 2017 21:17:07 -0700 Subject: [PATCH] Removes bigip ssl certificate from skip file (#32424) --- .../network/f5/bigip_ssl_certificate.py | 163 ++++++++++-------- test/sanity/import/skip.txt | 1 - .../modules/network/f5/fixtures/chain1.crt | 68 ++++++++ .../network/f5/test_bigip_ssl_certificate.py | 36 ++-- 4 files changed, 169 insertions(+), 99 deletions(-) create mode 100644 test/units/modules/network/f5/fixtures/chain1.crt diff --git a/lib/ansible/modules/network/f5/bigip_ssl_certificate.py b/lib/ansible/modules/network/f5/bigip_ssl_certificate.py index 5c9f443f8de..ae60bb00ece 100644 --- a/lib/ansible/modules/network/f5/bigip_ssl_certificate.py +++ b/lib/ansible/modules/network/f5/bigip_ssl_certificate.py @@ -4,13 +4,17 @@ # Copyright (c) 2017 F5 Networks Inc. # GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} -DOCUMENTATION = ''' +DOCUMENTATION = r''' module: bigip_ssl_certificate -short_description: Import/Delete certificates from BIG-IP. +short_description: Import/Delete certificates from BIG-IP description: - This module will import/delete SSL certificates on BIG-IP LTM. Certificates can be imported from certificate and key files on the local @@ -41,7 +45,7 @@ options: - absent name: description: - - SSL Certificate Name. This is the cert/key pair name used + - SSL Certificate Name. This is the cert/key pair name used when importing a certificate/key into the F5. It also determines the filenames of the objects on the LTM (:Partition:name.cer_11111_1 and :Partition_name.key_11111_1). @@ -69,87 +73,97 @@ notes: a role context. extends_documentation_fragment: f5 requirements: - - f5-sdk >= 1.5.0 - - BIG-IP >= v12 + - f5-sdk >= 3.0.3 + - BIG-IP >= v12 author: - - Tim Rupp (@caphrim007) + - Tim Rupp (@caphrim007) ''' -EXAMPLES = ''' +EXAMPLES = r''' - name: Import PEM Certificate from local disk bigip_ssl_certificate: - name: "certificate-name" - server: "lb.mydomain.com" - user: "admin" - password: "secret" - state: "present" - cert_src: "/path/to/cert.crt" - key_src: "/path/to/key.key" + name: certificate-name + server: lb.mydomain.com + user: admin + password: secret + state: present + cert_src: /path/to/cert.crt + key_src: /path/to/key.key delegate_to: localhost - name: Use a file lookup to import PEM Certificate bigip_ssl_certificate: - name: "certificate-name" - server: "lb.mydomain.com" - user: "admin" - password: "secret" - state: "present" - cert_content: "{{ lookup('file', '/path/to/cert.crt') }}" - key_content: "{{ lookup('file', '/path/to/key.key') }}" + name: certificate-name + server: lb.mydomain.com + user: admin + password: secret + state: present + cert_content: "{{ lookup('file', '/path/to/cert.crt') }}" + key_content: "{{ lookup('file', '/path/to/key.key') }}" + delegate_to: localhost + +- name: Use a file lookup to import CA certificate chain + bigip_ssl_certificate: + name: ca-chain-name + server: lb.mydomain.com + user: admin + password: secret + state: present + cert_content: "{{ lookup('file', '/path/to/ca-chain.crt') }}" delegate_to: localhost - name: "Delete Certificate" bigip_ssl_certificate: - name: "certificate-name" - server: "lb.mydomain.com" - user: "admin" - password: "secret" - state: "absent" + name: certificate-name + server: lb.mydomain.com + user: admin + password: secret + state: absent delegate_to: localhost ''' -RETURN = ''' +RETURN = r''' cert_name: - description: The name of the certificate that the user provided - returned: created - type: string - sample: "cert1" + description: The name of the certificate that the user provided + returned: created + type: string + sample: cert1 key_filename: - description: - - The name of the SSL certificate key. The C(key_filename) and - C(cert_filename) will be similar to each other, however the - C(key_filename) will have a C(.key) extension. - returned: created - type: string - sample: "cert1.key" + description: + - The name of the SSL certificate key. The C(key_filename) and + C(cert_filename) will be similar to each other, however the + C(key_filename) will have a C(.key) extension. + returned: created + type: string + sample: cert1.key key_checksum: - description: SHA1 checksum of the key that was provided. - returned: changed and created - type: string - sample: "cf23df2207d99a74fbe169e3eba035e633b65d94" + description: SHA1 checksum of the key that was provided. + returned: changed and created + type: string + sample: cf23df2207d99a74fbe169e3eba035e633b65d94 key_source_path: - description: Path on BIG-IP where the source of the key is stored - returned: created - type: string - sample: "/var/config/rest/downloads/cert1.key" + description: Path on BIG-IP where the source of the key is stored + returned: created + type: string + sample: /var/config/rest/downloads/cert1.key cert_filename: - description: - - The name of the SSL certificate. The C(cert_filename) and - C(key_filename) will be similar to each other, however the - C(cert_filename) will have a C(.crt) extension. - returned: created - type: string - sample: "cert1.crt" + description: + - The name of the SSL certificate. The C(cert_filename) and + C(key_filename) will be similar to each other, however the + C(cert_filename) will have a C(.crt) extension. + returned: created + type: string + sample: cert1.crt cert_checksum: - description: SHA1 checksum of the cert that was provided. - returned: changed and created - type: string - sample: "f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0" + description: SHA1 checksum of the cert that was provided. + returned: changed and created + type: string + sample: f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0 cert_source_path: - description: Path on BIG-IP where the source of the certificate is stored. - returned: created - type: string - sample: "/var/config/rest/downloads/cert1.crt" + description: Path on BIG-IP where the source of the certificate is stored. + returned: created + type: string + sample: /var/config/rest/downloads/cert1.crt ''' @@ -162,14 +176,16 @@ try: except ImportError: from io import StringIO -from ansible.module_utils.f5_utils import ( - AnsibleF5Client, - AnsibleF5Parameters, - HAS_F5SDK, - F5ModuleError, - iControlUnexpectedHTTPError, - iteritems -) +from ansible.module_utils.f5_utils import AnsibleF5Client +from ansible.module_utils.f5_utils import AnsibleF5Parameters +from ansible.module_utils.f5_utils import HAS_F5SDK +from ansible.module_utils.f5_utils import F5ModuleError +from ansible.module_utils.f5_utils import iteritems + +try: + from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError +except ImportError: + HAS_F5SDK = False class Parameters(AnsibleF5Parameters): @@ -544,14 +560,14 @@ class KeyManager(BaseManager): if getattr(self.want, key) is not None: changed[key] = getattr(self.want, key) if changed: - self.changes = Parameters(changed) + self.changes = KeyParameters(changed) except Exception: pass def _update_changed_options(self): changed = {} try: - for key in CertParameters.updatables: + for key in KeyParameters.updatables: if getattr(self.want, key) is not None: attr1 = getattr(self.want, key) attr2 = getattr(self.have, key) @@ -560,7 +576,7 @@ class KeyManager(BaseManager): if self.want.key_checksum != self.have.checksum: changed['key_checksum'] = self.want.key_checksum if changed: - self.changes = CertParameters(changed) + self.changes = KeyParameters(changed) return True except Exception: pass @@ -635,7 +651,7 @@ class ArgumentSpec(object): name=dict( required=True ), - cert_content=dict(), + cert_content=dict(aliases=['content']), cert_src=dict( type='path', removed_in_version='2.4' @@ -649,7 +665,6 @@ class ArgumentSpec(object): no_log=True ), state=dict( - required=False, default='present', choices=['absent', 'present'] ) diff --git a/test/sanity/import/skip.txt b/test/sanity/import/skip.txt index c20250b9a15..d9620bd0cb1 100644 --- a/test/sanity/import/skip.txt +++ b/test/sanity/import/skip.txt @@ -23,7 +23,6 @@ lib/ansible/modules/network/f5/bigip_provision.py lib/ansible/modules/network/f5/bigip_qkview.py lib/ansible/modules/network/f5/bigip_snmp.py lib/ansible/modules/network/f5/bigip_snmp_trap.py -lib/ansible/modules/network/f5/bigip_ssl_certificate.py lib/ansible/modules/network/f5/bigip_ucs.py lib/ansible/modules/network/f5/bigip_user.py lib/ansible/modules/network/f5/bigip_virtual_address.py diff --git a/test/units/modules/network/f5/fixtures/chain1.crt b/test/units/modules/network/f5/fixtures/chain1.crt new file mode 100644 index 00000000000..38dd8dc9cf0 --- /dev/null +++ b/test/units/modules/network/f5/fixtures/chain1.crt @@ -0,0 +1,68 @@ +-----BEGIN CERTIFICATE----- +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 +0Qn4FWp63AaOBNrC +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAweTELMAkGA1UEBhMCR0Ix +EDAOBgNVBAgMB0VuZ2xhbmQxEjAQBgNVBAoMCUFsaWNlIEx0ZDEoMCYGA1UECwwf +QWxpY2UgTHRkIENlcnRpZmljYXRlIEF1dGhvcml0eTEaMBgGA1UEAwwRQWxpY2Ug +THRkIFJvb3QgQ0EwHhcNMTcwNzI1MDMxNzE0WhcNMjcwNzIzMDMxNzE0WjCBgTEL +MAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxEjAQBgNVBAoMCUFsaWNlIEx0 +ZDEoMCYGA1UECwwfQWxpY2UgTHRkIENlcnRpZmljYXRlIEF1dGhvcml0eTEiMCAG +A1UEAwwZQWxpY2UgTHRkIEludGVybWVkaWF0ZSBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAL1whyll1+/qWhAUdy6U5vtopX0wzJrg3dk8tIlpDChh +khTEK779aQNapRKpZmJ6hnCkg7buVOSBP2WqqGQ1s9cakBSFkDyy5hrqeSzIR93w +9n2sTc4EBD0b8QWn5D0hdoWLT3+OwFHCBf/vb+qA9Vz0P/PRPYUnKttQH6nXTj9C ++AzegfS4SbfDJ4XdhbzCewgUvr3rqP61AQuEwZq7qoVCA3bFSASUfbJgMBxJgfBG +KynueJ62L+wbZLXUDq9G3T0KIUlxgGIcPQ0tu2kW7uSeY5wZazuvNJCHM9HKsjUf +wb8GgavQRlgunE9zXAEr+iP2DQrmZXdhJkkb4EyG1vuTMK3DtGjlpXAVGsiuuZ1o +PVYZDVKhfKFN9tyop/dppxDTHyJlp2prtsudhtqwzYDqrUsMu4/LMWvxgUcTK4U7 +mPSBcvOb4fTqXirNRYsqi8BK/nxt/hUBVG0vEnoIH0ppzqWvMcsMtMi3535sErUJ +k8IVKYIGB9OKb9SzpERYT6+BH9sUURZ/xyhRd2pj7EiVAEVxrrVoedZJzLRuXH99 +qhFG2HnDAaDC9LX09GveTzgUVUfif5fJgGBkzslpM3z8t3THz9RjrqtrzKOCHcZF +cgt46oQByT0UjhIPCz3/6h04XzSszue8aTAwi1JaYhHoXEPolgJRoLeuFdsJtfyt +AgMBAAGjZjBkMB0GA1UdDgQWBBSiTrrHxly7SsSV+MqprYstABOIjDAfBgNVHSME +GDAWgBSTaHXZxq7+zWT8gZHQ4BRZlt/xrzASBgNVHRMBAf8ECDAGAQH/AgEAMA4G +A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAakyu4lsOWz2+VHI0S6xb +M/afSDgnmI+i/1lSQ7UHM1XIvuINIzAcWndU1XuHyFjT7p9ZDPZ52gcseIenrKOD +EsJWKO3u33to3YUMfBCJi9VbTCtd6rkjuFggN6EKM1esqs0kgenWmvEQSv73OOii +UCAbif4fSva6C5PhgK7X0zE+hTsPxRZnN8baRlL01IHEraG+PfYCEpjvzExzoaW6 +aLNS0DAS1escb9K5u6Cf4KIxkdqpcYIW7v7tehj5KS3E0cRv3QAaMUBkMWTWlSP3 +irzC0OB8BFuYZ1OxDYnxhSY1mfwfI8kWrvA83okS8qwfjq/rty53VG3tON9GzGXg +P1SQ3xB/6yxSvskcbN1blfHJfJRpOIxBvAydhdBCh7PO0WJzTP8kmffMhOiT5AdE +jcJVxWSjwqUetomlNiErEvo7ZmxEwQZQE5wnuGM4eAbV87zLVrnj+viRo1dP7RFN +iRUwjrxKpozUY5AGY2hZdFrWObBe1AvLDQcNDUc+oMwgnIBC2YtO1cTKJ3IFru0f +Av48lyJ88AfO2W7pEfoVqAAZszu2s0VZB5W9fBOQLizvkjK8s5YeUPdhW3epEYF9 +I1PsTSNdN+abV5qNdIjgRVtNlV63+1y0Ez7J7RvO847ZYTuqHnfaRG03p10YnxBs +WcSe5ozInV3EZ9TxFcGQR+E= +-----END CERTIFICATE----- diff --git a/test/units/modules/network/f5/test_bigip_ssl_certificate.py b/test/units/modules/network/f5/test_bigip_ssl_certificate.py index 5a34ae2cef4..2eb33d9ea68 100644 --- a/test/units/modules/network/f5/test_bigip_ssl_certificate.py +++ b/test/units/modules/network/f5/test_bigip_ssl_certificate.py @@ -1,21 +1,7 @@ # -*- coding: utf-8 -*- # -# Copyright 2017 F5 Networks Inc. -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . +# Copyright (c) 2017 F5 Networks Inc. +# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import (absolute_import, division, print_function) __metaclass__ = type @@ -39,14 +25,18 @@ try: from library.bigip_ssl_certificate import KeyParameters from library.bigip_ssl_certificate import CertParameters from library.bigip_ssl_certificate import CertificateManager + from library.bigip_ssl_certificate import HAS_F5SDK from library.bigip_ssl_certificate import KeyManager + from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError except ImportError: try: from ansible.modules.network.f5.bigip_ssl_certificate import ArgumentSpec from ansible.modules.network.f5.bigip_ssl_certificate import KeyParameters from ansible.modules.network.f5.bigip_ssl_certificate import CertParameters from ansible.modules.network.f5.bigip_ssl_certificate import CertificateManager + from ansible.modules.network.f5.bigip_ssl_certificate import HAS_F5SDK from ansible.modules.network.f5.bigip_ssl_certificate import KeyManager + from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError except ImportError: raise SkipTest("F5 Ansible modules require the f5-sdk Python library") @@ -139,7 +129,7 @@ class TestCertificateManager(unittest.TestCase): cert_content=load_fixture('cert1.crt'), key_content=load_fixture('cert1.key'), state='present', - password='passsword', + password='password', server='localhost', user='admin' )) @@ -159,14 +149,12 @@ class TestCertificateManager(unittest.TestCase): assert results['changed'] is True - def test_update_certificate_new_certificate_and_key_password_protected_key(self, *args): + def test_import_certificate_chain(self, *args): set_module_args(dict( name='foo', - cert_content=load_fixture('cert2.crt'), - key_content=load_fixture('cert2.key'), + cert_content=load_fixture('chain1.crt'), state='present', - passphrase='keypass', - password='passsword', + password='password', server='localhost', user='admin' )) @@ -200,7 +188,7 @@ class TestKeyManager(unittest.TestCase): cert_content=load_fixture('cert1.crt'), key_content=load_fixture('cert1.key'), state='present', - password='passsword', + password='password', server='localhost', user='admin' )) @@ -227,7 +215,7 @@ class TestKeyManager(unittest.TestCase): key_content=load_fixture('cert2.key'), state='present', passphrase='keypass', - password='passsword', + password='password', server='localhost', user='admin' ))