Blame SOURCES/0003-ONTAP-plugin-SSL-fix.patch

35f900
From f6122f1bbfa6e79f3e014a4ba65ffef7e1c113c1 Mon Sep 17 00:00:00 2001
35f900
From: Gris Ge <fge@redhat.com>
35f900
Date: Thu, 30 Mar 2017 21:03:26 +0800
35f900
Subject: [PATCH] ONTAP plugin: SSL fix.
35f900
35f900
Issue:
35f900
    lsmcli  -u "ontap+ssl://root@na3170b.lab.bos.redhat.com" ls
35f900
    NETWORK_ERROR(142): 
35f900
    unsupported protocol
35f900
35f900
Root cause:
35f900
    Some OS are removing openssl the support of SSLv2 and SSLv3.
35f900
35f900
Fix:
35f900
    * When ONTAP filer is using SSLv2 or SSLv3, raise NO_SUPPORT error
35f900
      and suggest user to enable TLS.
35f900
    * New URI parameter 'ssl_verify=yes' to enable full SSL
35f900
      verification, by default, we still ignore hostname check and
35f900
      certification check.
35f900
    * Updated manpage with guide to enable TLS on ONTAP filer and
35f900
      explanation of new URI parameter 'ssl_verify=yes'.
35f900
    * Use uri_parse() from lsm instead of urlparse().
35f900
35f900
Signed-off-by: Gris Ge <fge@redhat.com>
35f900
---
35f900
 doc/man/ontap_lsmplugin.1.in | 11 +++++++++--
35f900
 plugin/ontap/na.py           | 44 +++++++++++++++++++++++++++++++++-----------
35f900
 plugin/ontap/ontap.py        | 21 +++++++++++----------
35f900
 3 files changed, 53 insertions(+), 23 deletions(-)
35f900
35f900
diff --git a/doc/man/ontap_lsmplugin.1.in b/doc/man/ontap_lsmplugin.1.in
35f900
index ef0cd12..3d6cc70 100644
35f900
--- a/doc/man/ontap_lsmplugin.1.in
35f900
+++ b/doc/man/ontap_lsmplugin.1.in
35f900
@@ -12,9 +12,10 @@ This plugin requires NetApp ONTAP storage array to enable these options:
35f900
     \fBoptions httpd.enable on\fR
35f900
     \fBoptions httpd.admin.enable on\fR
35f900
 
35f900
-This options is required for HTTPS connection:
35f900
+These options are required for HTTPS connection:
35f900
 
35f900
     \fBoptions httpd.admin.ssl.enable on\fR
35f900
+    \fBoptions tls.enable on\fR
35f900
 
35f900
 .SH URI
35f900
 To use this plugin, users should set their URI to this format:
35f900
@@ -40,7 +41,13 @@ The \fBontap_filer_ip\fR is the NetApp ONTAP filer IP address or DNS name.
35f900
 .TP
35f900
 \fBURI parameters\fR
35f900
 
35f900
-No additional URI parameters are supported by this plugin.
35f900
+This URI parameter is supported by this plugin:
35f900
+
35f900
+.RS 7
35f900
+.TP
35f900
+\fBssl_verify=yes\fR
35f900
+By default, SSL connection does not verify hostname and certification.
35f900
+If this URI parameter is defined, all SSL verifications will be performed.
35f900
 
35f900
 .SH Supported Hardware
35f900
 NetApp ONTAP 8.x is supported.
35f900
diff --git a/plugin/ontap/na.py b/plugin/ontap/na.py
35f900
index a16e884..26c0ff6 100644
35f900
--- a/plugin/ontap/na.py
35f900
+++ b/plugin/ontap/na.py
35f900
@@ -20,10 +20,9 @@
35f900
 from xml.etree import ElementTree
35f900
 import time
35f900
 from binascii import hexlify
35f900
-from ssl import SSLError
35f900
+import ssl
35f900
 from lsm.external.xmltodict import convert_xml_to_dict
35f900
-from lsm import (ErrorNumber)
35f900
-
35f900
+from lsm import (LsmError, ErrorNumber)
35f900
 
35f900
 if six.PY3:
35f900
     long = int
35f900
@@ -33,6 +32,7 @@
35f900
                                 urlopen,
35f900
                                 HTTPPasswordMgrWithDefaultRealm,
35f900
                                 HTTPBasicAuthHandler,
35f900
+                                HTTPSHandler,
35f900
                                 build_opener,
35f900
                                 install_opener)
35f900
     from urllib.error import (URLError, HTTPError)
35f900
@@ -42,6 +42,7 @@
35f900
                          urlopen,
35f900
                          HTTPPasswordMgrWithDefaultRealm,
35f900
                          HTTPBasicAuthHandler,
35f900
+                         HTTPSHandler,
35f900
                          build_opener,
35f900
                          install_opener,
35f900
                          URLError,
35f900
@@ -79,13 +80,13 @@ def param_value(val):
35f900
 
35f900
 
35f900
 def netapp_filer(host, username, password, timeout, command, parameters=None,
35f900
-                 ssl=False):
35f900
+                 use_ssl=False, ssl_verify=False):
35f900
     """
35f900
     Issue a command to the NetApp filer.
35f900
-    Note: Change to default ssl on before we ship a release version.
35f900
+    Note: Change to default use_ssl on before we ship a release version.
35f900
     """
35f900
     proto = 'http'
35f900
-    if ssl:
35f900
+    if use_ssl:
35f900
         proto = 'https'
35f900
 
35f900
     url = "%s://%s/servlets/netapp.servlets.admin.XMLrequest_filer" % \
35f900
@@ -98,7 +99,15 @@ def netapp_filer(host, username, password, timeout, command, parameters=None,
35f900
     password_manager.add_password(None, url, username, password)
35f900
     auth_manager = HTTPBasicAuthHandler(password_manager)
35f900
 
35f900
-    opener = build_opener(auth_manager)
35f900
+    if use_ssl:
35f900
+        ssl._DEFAULT_CIPHERS += ':RC4-SHA'
35f900
+        ssl_ctx = ssl.create_default_context()
35f900
+        if ssl_verify == False:
35f900
+            ssl_ctx.check_hostname = False
35f900
+            ssl_ctx.verify_mode = ssl.CERT_NONE
35f900
+        opener = build_opener(HTTPSHandler(context=ssl_ctx), auth_manager)
35f900
+    else:
35f900
+        opener = build_opener(auth_manager)
35f900
     install_opener(opener)
35f900
 
35f900
     # build the command and the arguments for it
35f900
@@ -127,13 +136,23 @@ def netapp_filer(host, username, password, timeout, command, parameters=None,
35f900
     except HTTPError:
35f900
         raise
35f900
     except URLError as ue:
35f900
+        err_msg = str(ue)
35f900
         if isinstance(ue.reason, socket.timeout):
35f900
             raise FilerError(Filer.ETIMEOUT, "Connection timeout")
35f900
+        elif "UNSUPPORTED_PROTOCOL" in err_msg or \
35f900
+           "EOF occurred in violation of protocol" in err_msg :
35f900
+            raise LsmError(ErrorNumber.NO_SUPPORT,
35f900
+                           "ONTAP SSL version is not supported, "
35f900
+                           "please enable TLS on ONTAP filer, "
35f900
+                           "check 'man 1 ontap_lsmplugin'")
35f900
+        elif "CERTIFICATE_VERIFY_FAILED" in err_msg:
35f900
+            raise LsmError(ErrorNumber.NETWORK_CONNREFUSED,
35f900
+                           "SSL certification verification failed")
35f900
         else:
35f900
             raise
35f900
     except socket.timeout:
35f900
         raise FilerError(Filer.ETIMEOUT, "Connection timeout")
35f900
-    except SSLError as sse:
35f900
+    except ssl.SSLError as sse:
35f900
         # The ssl library doesn't give a good way to find specific reason.
35f900
         # We are doing a string contains which is not ideal, but other than
35f900
         # throwing a generic error in this case there isn't much we can do
35f900
@@ -262,7 +281,8 @@ class Filer(object):
35f900
     def _invoke(self, command, parameters=None):
35f900
 
35f900
         rc = netapp_filer(self.host, self.username, self.password,
35f900
-                          self.timeout, command, parameters, self.ssl)
35f900
+                          self.timeout, command, parameters, self.use_ssl,
35f900
+                          self.ssl_verify)
35f900
 
35f900
         t = rc['netapp']['results']['attrib']
35f900
 
35f900
@@ -271,12 +291,14 @@ def _invoke(self, command, parameters=None):
35f900
 
35f900
         return rc['netapp']['results']
35f900
 
35f900
-    def __init__(self, host, username, password, timeout, ssl=True):
35f900
+    def __init__(self, host, username, password, timeout, use_ssl=True,
35f900
+                 ssl_verify=False):
35f900
         self.host = host
35f900
         self.username = username
35f900
         self.password = password
35f900
         self.timeout = timeout
35f900
-        self.ssl = ssl
35f900
+        self.use_ssl = use_ssl
35f900
+        self.ssl_verify = ssl_verify
35f900
 
35f900
     def system_info(self):
35f900
         rc = self._invoke('system-get-info')
35f900
diff --git a/plugin/ontap/ontap.py b/plugin/ontap/ontap.py
35f900
index 7fd5dc3..186a57a 100644
35f900
--- a/plugin/ontap/ontap.py
35f900
+++ b/plugin/ontap/ontap.py
35f900
@@ -22,15 +22,10 @@
35f900
                  AccessGroup, System, Capabilities, Disk, Pool,
35f900
                  IStorageAreaNetwork, INfs, LsmError, ErrorNumber, JobStatus,
35f900
                  md5, VERSION, common_urllib2_error_handler,
35f900
-                 search_property, TargetPort, int_div)
35f900
+                 search_property, TargetPort, int_div, uri_parse)
35f900
 
35f900
 import lsm.plugin.ontap.na as na
35f900
 
35f900
-try:
35f900
-    from urllib.parse import urlparse
35f900
-except ImportError:
35f900
-    from urlparse import urlparse
35f900
-
35f900
 # Maps na to lsm, this is expected to expand over time.
35f900
 e_map = {
35f900
     na.Filer.ENOSPC: ErrorNumber.NOT_ENOUGH_SPACE,
35f900
@@ -135,13 +130,19 @@ def __init__(self):
35f900
     @handle_ontap_errors
35f900
     def plugin_register(self, uri, password, timeout, flags=0):
35f900
         ssl = False
35f900
-        u = urlparse(uri)
35f900
+        u = uri_parse(uri)
35f900
 
35f900
-        if u.scheme.lower() == 'ontap+ssl':
35f900
+        if u['scheme'].lower() == 'ontap+ssl':
35f900
             ssl = True
35f900
+        if 'parameters' in u and 'ssl_verify' in u['parameters'] and \
35f900
+           u['parameters']['ssl_verify'] == 'yes':
35f900
+            ssl_verify = True
35f900
+        else:
35f900
+            ssl_verify = False
35f900
 
35f900
-        self.f = na.Filer(u.hostname, u.username, password,
35f900
-                          int_div(timeout, Ontap.TMO_CONV), ssl)
35f900
+        self.f = na.Filer(u['host'], u['username'], password,
35f900
+                          int_div(timeout, Ontap.TMO_CONV), ssl,
35f900
+                          ssl_verify)
35f900
         # Smoke test
35f900
         i = self.f.system_info()
35f900
         # TODO Get real filer status
35f900
-- 
35f900
2.12.1
35f900