|
|
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 |
|