From 6a02b17a2eb18196b3b9fd8bccf34cbe588bc911 Mon Sep 17 00:00:00 2001
From: Toshio Kuratomi <toshio@fedoraproject.org>
Date: Thu, 24 Dec 2015 11:57:15 -0800
Subject: [PATCH] Update f5 validate_certs functionality to do the right thing
 on multiple python versions

This requires the implementation in the module_utils code here
https://github.com/ansible/ansible/pull/13667 to funciton
---
 .../modules/extras/network/f5/bigip_facts.py  | 27 +++++++++----------
 .../extras/network/f5/bigip_monitor_http.py   |  5 ++--
 .../extras/network/f5/bigip_monitor_tcp.py    |  5 ++--
 .../modules/extras/network/f5/bigip_node.py   |  5 ++--
 .../modules/extras/network/f5/bigip_pool.py   |  8 +++---
 .../extras/network/f5/bigip_pool_member.py    |  5 ++--
 6 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/lib/ansible/modules/extras/network/f5/bigip_facts.py b/lib/ansible/modules/extras/network/f5/bigip_facts.py
index 215a2cfe679..9f30397ea17 100644
--- a/lib/ansible/modules/extras/network/f5/bigip_facts.py
+++ b/lib/ansible/modules/extras/network/f5/bigip_facts.py
@@ -59,7 +59,8 @@ options:
     validate_certs:
         description:
             - If C(no), SSL certificates will not be validated. This should only be used
-              on personally controlled sites using self-signed certificates.
+              on personally controlled sites.  Prior to 2.0, this module would always
+              validate on python >= 2.7.9 and never validate on python <= 2.7.8
         required: false
         default: 'yes'
         choices: ['yes', 'no']
@@ -136,8 +137,8 @@ class F5(object):
         api: iControl API instance.
     """
 
-    def __init__(self, host, user, password, session=False):
-        self.api = bigsuds.BIGIP(hostname=host, username=user, password=password)
+    def __init__(self, host, user, password, session=False, validate_certs=True):
+        self.api = bigip_api(host, user, password, validate_certs)
         if session:
             self.start_session()
 
@@ -1574,12 +1575,6 @@ def generate_software_list(f5):
     software_list = software.get_all_software_status()
     return software_list
 
-def disable_ssl_cert_validation():
-    # You probably only want to do this for testing and never in production.
-    # From https://www.python.org/dev/peps/pep-0476/#id29
-    import ssl
-    ssl._create_default_https_context = ssl._create_unverified_context
-
 
 def main():
     module = AnsibleModule(
@@ -1595,7 +1590,7 @@ def main():
     )
 
     if not bigsuds_found:
-        module.fail_json(msg="the python suds and bigsuds modules is required")
+        module.fail_json(msg="the python suds and bigsuds modules are required")
 
     server = module.params['server']
     user = module.params['user']
@@ -1603,6 +1598,12 @@ def main():
     validate_certs = module.params['validate_certs']
     session = module.params['session']
     fact_filter = module.params['filter']
+
+    if validate_certs:
+        import ssl
+        if not hasattr(ssl, 'SSLContext'):
+            module.fail_json(msg='bigsuds does not support verifying certificates with python < 2.7.9.  Either update python or set validate_certs=False on the task')
+
     if fact_filter:
         regex = fnmatch.translate(fact_filter)
     else:
@@ -1617,14 +1618,11 @@ def main():
     if not all(include_test):
         module.fail_json(msg="value of include must be one or more of: %s, got: %s" % (",".join(valid_includes), ",".join(include)))
 
-    if not validate_certs:
-        disable_ssl_cert_validation()
-
     try:
         facts = {}
 
         if len(include) > 0:
-            f5 = F5(server, user, password, session)
+            f5 = F5(server, user, password, session, validate_certs)
             saved_active_folder = f5.get_active_folder()
             saved_recursive_query_state = f5.get_recursive_query_state()
             if saved_active_folder != "/":
@@ -1685,6 +1683,7 @@ def main():
 
 # include magic from lib/ansible/module_common.py
 from ansible.module_utils.basic import *
+from ansible.module_utils.f5 import *
 
 if __name__ == '__main__':
     main()
diff --git a/lib/ansible/modules/extras/network/f5/bigip_monitor_http.py b/lib/ansible/modules/extras/network/f5/bigip_monitor_http.py
index c2f6a87172e..e79463181ac 100644
--- a/lib/ansible/modules/extras/network/f5/bigip_monitor_http.py
+++ b/lib/ansible/modules/extras/network/f5/bigip_monitor_http.py
@@ -54,7 +54,8 @@ options:
     validate_certs:
         description:
             - If C(no), SSL certificates will not be validated. This should only be used
-              on personally controlled sites using self-signed certificates.
+              on personally controlled sites.  Prior to 2.0, this module would always
+              validate on python >= 2.7.9 and never validate on python <= 2.7.8
         required: false
         default: 'yes'
         choices: ['yes', 'no']
@@ -333,7 +334,7 @@ def main():
 
     # end monitor specific stuff
 
-    api = bigip_api(server, user, password)
+    api = bigip_api(server, user, password, validate_certs)
     monitor_exists = check_monitor_exists(module, api, monitor, parent)
 
 
diff --git a/lib/ansible/modules/extras/network/f5/bigip_monitor_tcp.py b/lib/ansible/modules/extras/network/f5/bigip_monitor_tcp.py
index 9a08418563c..815de7462a4 100644
--- a/lib/ansible/modules/extras/network/f5/bigip_monitor_tcp.py
+++ b/lib/ansible/modules/extras/network/f5/bigip_monitor_tcp.py
@@ -52,7 +52,8 @@ options:
     validate_certs:
         description:
             - If C(no), SSL certificates will not be validated. This should only be used
-              on personally controlled sites using self-signed certificates.
+              on personally controlled sites.  Prior to 2.0, this module would always
+              validate on python >= 2.7.9 and never validate on python <= 2.7.8
         required: false
         default: 'yes'
         choices: ['yes', 'no']
@@ -356,7 +357,7 @@ def main():
 
     # end monitor specific stuff
 
-    api = bigip_api(server, user, password)
+    api = bigip_api(server, user, password, validate_certs)
     monitor_exists = check_monitor_exists(module, api, monitor, parent)
 
 
diff --git a/lib/ansible/modules/extras/network/f5/bigip_node.py b/lib/ansible/modules/extras/network/f5/bigip_node.py
index 7db197839f7..b6a44b81d0a 100644
--- a/lib/ansible/modules/extras/network/f5/bigip_node.py
+++ b/lib/ansible/modules/extras/network/f5/bigip_node.py
@@ -57,7 +57,8 @@ options:
     validate_certs:
         description:
             - If C(no), SSL certificates will not be validated. This should only be used
-              on personally controlled sites using self-signed certificates.
+              on personally controlled sites.  Prior to 2.0, this module would always
+              validate on python >= 2.7.9 and never validate on python <= 2.7.8
         required: false
         default: 'yes'
         choices: ['yes', 'no']
@@ -290,7 +291,7 @@ def main():
         module.fail_json(msg="host parameter invalid when state=absent")
 
     try:
-        api = bigip_api(server, user, password)
+        api = bigip_api(server, user, password, validate_certs)
         result = {'changed': False}  # default
 
         if state == 'absent':
diff --git a/lib/ansible/modules/extras/network/f5/bigip_pool.py b/lib/ansible/modules/extras/network/f5/bigip_pool.py
index 5330b0d4302..9860b9f2df6 100644
--- a/lib/ansible/modules/extras/network/f5/bigip_pool.py
+++ b/lib/ansible/modules/extras/network/f5/bigip_pool.py
@@ -57,7 +57,8 @@ options:
     validate_certs:
         description:
             - If C(no), SSL certificates will not be validated. This should only be used
-              on personally controlled sites using self-signed certificates.
+              on personally controlled sites.  Prior to 2.0, this module would always
+              validate on python >= 2.7.9 and never validate on python <= 2.7.8
         required: false
         default: 'yes'
         choices: ['yes', 'no']
@@ -390,9 +391,6 @@ def main():
     address = fq_name(partition,host)
     port = module.params['port']
 
-    if not validate_certs:
-        disable_ssl_cert_validation()
-
     # sanity check user supplied values
 
     if (host and not port) or (port and not host):
@@ -421,7 +419,7 @@ def main():
         module.fail_json(msg="quorum requires monitors parameter")
 
     try:
-        api = bigip_api(server, user, password)
+        api = bigip_api(server, user, password, validate_certs)
         result = {'changed': False}  # default
 
         if state == 'absent':
diff --git a/lib/ansible/modules/extras/network/f5/bigip_pool_member.py b/lib/ansible/modules/extras/network/f5/bigip_pool_member.py
index f98c647c618..865478206c6 100644
--- a/lib/ansible/modules/extras/network/f5/bigip_pool_member.py
+++ b/lib/ansible/modules/extras/network/f5/bigip_pool_member.py
@@ -59,7 +59,8 @@ options:
     validate_certs:
         description:
             - If C(no), SSL certificates will not be validated. This should only be used
-              on personally controlled sites using self-signed certificates.
+              on personally controlled sites.  Prior to 2.0, this module would always
+              validate on python >= 2.7.9 and never validate on python <= 2.7.8
         required: false
         default: 'yes'
         choices: ['yes', 'no']
@@ -377,7 +378,7 @@ def main():
         module.fail_json(msg="valid ports must be in range 1 - 65535")
 
     try:
-        api = bigip_api(server, user, password)
+        api = bigip_api(server, user, password, validate_certs)
         if not pool_exists(api, pool):
             module.fail_json(msg="pool %s does not exist" % pool)
         result = {'changed': False}  # default