Blob Blame History Raw
From c40a11439c738b67471da01ebfbc3d3d66db6311 Mon Sep 17 00:00:00 2001
From: Marek 'marx' Grac <mgrac@redhat.com>
Date: Fri, 7 Mar 2014 15:13:44 +0100
Subject: [PATCH] fence_vmware_soap: Add new options --ssl-secure and
 --ssl-insecure

These new options extends current --ssl (same as --ssl-secure). Until now certificate of the fence device
was not validated what can possibly lead to attack on infrastructe. With this patch, user can decide
if certificate should (--ssl-secure) or should not (--ssl-insecure) be verified.

python-suds do not validates SSL certificates at all. It is required to change underlying library to
one that can support that what results in new dependency on python-requests.
---
 fence/agents/vmware_soap/fence_vmware_soap.py |   35 +++++++++++++++++++++---
 1 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/fence/agents/vmware_soap/fence_vmware_soap.py b/fence/agents/vmware_soap/fence_vmware_soap.py
index bbac1c5..a578662 100644
--- a/fence/agents/vmware_soap/fence_vmware_soap.py
+++ b/fence/agents/vmware_soap/fence_vmware_soap.py
@@ -2,11 +2,13 @@
 
 import sys, exceptions, time
 import shutil, tempfile, suds
-import logging
+import logging, requests
 sys.path.append("@FENCEAGENTSLIBDIR@")
 
 from suds.client import Client
 from suds.sudsobject import Property
+from suds.transport.http import HttpAuthenticated
+from suds.transport import Reply, TransportError
 from fencing import *
 
 #BEGIN_VERSION_GENERATION
@@ -15,13 +17,32 @@ REDHAT_COPYRIGHT=""
 BUILD_DATE="April, 2011"
 #END_VERSION_GENERATION
 
+class RequestsTransport(HttpAuthenticated):
+	def __init__(self, **kwargs):
+		self.cert = kwargs.pop('cert', None)
+		self.verify = kwargs.pop('verify', True)
+		self.session = requests.Session()
+		# super won't work because not using new style class
+		HttpAuthenticated.__init__(self, **kwargs)
+
+	def send(self, request):
+		self.addcredentials(request)
+		resp = self.session.post(request.url, data = request.message, headers = request.headers, cert = self.cert, verify = self.verify)
+		result = Reply(resp.status_code, resp.headers, resp.content)
+		return result
+
 def soap_login(options):
 	if options["--action"] in ["off", "reboot"]:
 		time.sleep(int(options["--delay"]))
 
-	if options.has_key("--ssl"):
+	if options.has_key("--ssl") or options.has_key("--ssl-secure") or options.has_key("--ssl-insecure"):
+		if options.has_key("--ssl-insecure"):
+			verify = False
+		else:
+			verify = True
 		url = "https://"
 	else:
+		verify = False
 		url = "http://"
 	
 	url += options["--ip"] + ":" + str(options["--ipport"]) + "/sdk"
@@ -29,10 +50,10 @@ def soap_login(options):
 	tmp_dir = tempfile.mkdtemp()
 	tempfile.tempdir = tmp_dir
 	atexit.register(remove_tmp_dir, tmp_dir)
-	
+
 	try:
-		conn = Client(url + "/vimService.wsdl")
-		conn.set_options(location = url)
+		headers = {"Content-Type" : "text/xml;charset=UTF-8", "SOAPAction" : ""}
+		conn = Client(url + "/vimService.wsdl", location = url, transport = RequestsTransport(verify = verify), headers = headers)
 
 		mo_ServiceInstance = Property('ServiceInstance')
 		mo_ServiceInstance._type = 'ServiceInstance'
@@ -41,6 +62,8 @@ def soap_login(options):
 		mo_SessionManager._type = 'SessionManager'
 
 		SessionManager = conn.service.Login(mo_SessionManager, options["--username"], options["--password"])
+	except requests.exceptions.SSLError, ex:
+		fail_usage("Server side certificate verification failed")
 	except Exception, ex:
 		fail(EC_LOGIN_DENIED)	
 
@@ -202,6 +225,8 @@ Alternatively you can always use UUID to access virtual machine."
 
 	logging.basicConfig(level=logging.INFO)
 	logging.getLogger('suds.client').setLevel(logging.CRITICAL)
+	logging.getLogger("requests").setLevel(logging.CRITICAL)
+	logging.getLogger("urllib3").setLevel(logging.CRITICAL)
 
 	##
 	## Operate the fencing device
-- 
1.7.7.6