Michael Pasternak has uploaded a new change for review.

Change subject: sdk: session based authentication for /localhost is broken 
#916285
......................................................................

sdk: session based authentication for /localhost is broken #916285

detailed explanation:
=====================

REST-API introduced new functionality at #876641 to JSESSION
based authentication,

if HTTP header Prefer:persistent-auth is set and client sends
the Authorization header as well, - will be re-initiated new
JSESSION, what is made all clients sending both Prefer and
Authorization headers to get authorised again using Authorization
header and not JSESSION,

correct behaviour is:
====================

1. send Authorization & Prefer headers
2. store JSESSION returned in cookie
3. use for authorization Prefer header & JSESSION cookie

disabling session based authentication:
======================================

1. omit from request Prefer header
2. add Authorization header

https://bugzilla.redhat.com/show_bug.cgi?id=916285

Change-Id: Ief0ed86c26c2e74b8cc8f46d68b01f904c50d0e2
Signed-off-by: Michael Pasternak <[email protected]>
---
M src/ovirtsdk/infrastructure/proxy.py
M src/ovirtsdk/web/connection.py
2 files changed, 68 insertions(+), 12 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine-sdk refs/changes/78/12578/1

diff --git a/src/ovirtsdk/infrastructure/proxy.py 
b/src/ovirtsdk/infrastructure/proxy.py
index 4dd5188..c15a927 100644
--- a/src/ovirtsdk/infrastructure/proxy.py
+++ b/src/ovirtsdk/infrastructure/proxy.py
@@ -90,6 +90,7 @@
     '''
     The proxy to web connection
     '''
+
     def __init__(self, connections_pool, persistent_auth=True):
         '''
         @param connections_pool: connections pool
@@ -101,11 +102,26 @@
         # In order to create the cookies adapter we need to extract from the
         # URL the host name, so that we can accept cookies only from that host:
         self._url = self.__connections_pool.get_url()
-        parsed_url = urlparse.urlparse(self._url)
 
         # Create the cookies policy and jar:
-        cookies_policy = 
cookielib.DefaultCookiePolicy(allowed_domains=[parsed_url.hostname])
+        cookies_policy = cookielib.DefaultCookiePolicy(
+                   strict_ns_domain=DefaultCookiePolicy.DomainStrictNoDots,
+                   allowed_domains=self.__getAllowedDomains(self._url))
         self._cookies_jar = cookielib.CookieJar(policy=cookies_policy)
+
+    def __getAllowedDomains(self, url):
+        '''
+        fetches allowed domains for cookie
+        '''
+
+        LOCAL_HOST = 'localhost'
+        parsed_url = urlparse.urlparse(url)
+        domains = [parsed_url.hostname]
+
+        if parsed_url.hostname == LOCAL_HOST:
+            return domains.append(LOCAL_HOST + '.local')
+
+        return domains
 
     def getConnectionsPool(self):
         '''
@@ -196,10 +212,7 @@
         '''
         try:
             # Add cookie headers as needed:
-            request_adapter = CookieJarAdapter(self._url, headers)
-            self._cookies_jar.set_policy(
-                     cookielib.DefaultCookiePolicy(
-                           
strict_ns_domain=DefaultCookiePolicy.DomainStrictNoDots))
+            request_adapter = CookieJarAdapter(self._url + url, headers)
             self._cookies_jar.add_cookie_header(request_adapter)
 
             # Every request except the last one should indicate that we prefer
@@ -208,7 +221,14 @@
                 headers["Prefer"] = "persistent-auth"
 
             # Send the request and wait for the response:
-            conn.doRequest(method=method, url=url, body=body, headers=headers)
+            conn.doRequest(
+                   method=method,
+                   url=url,
+                   body=body,
+                   headers=headers,
+                   no_auth=self._persistent_auth and \
+                        self.__isSetJsessionCookie(self._cookies_jar)
+            )
 
             response = conn.getResponse()
 
@@ -242,6 +262,19 @@
         finally:
             conn.close()
 
+    def __isSetJsessionCookie(self, cookies_jar):
+        '''
+        Checks if JSESSIONID cookie is set
+
+        @param cookies_jar: cookies container
+        '''
+        if cookies_jar and len(cookies_jar._cookies) > 0:
+            for key in cookies_jar._cookies.keys():
+                if cookies_jar._cookies[key].has_key('/api') and \
+                    cookies_jar._cookies[key]['/api'].has_key('JSESSIONID'):
+                    return True
+        return False
+
     def __xml2py(self, obj):
         '''
         Parse XML in to python entity
diff --git a/src/ovirtsdk/web/connection.py b/src/ovirtsdk/web/connection.py
index d17eebf..fa30fc4 100644
--- a/src/ovirtsdk/web/connection.py
+++ b/src/ovirtsdk/web/connection.py
@@ -54,16 +54,38 @@
     def getConnection(self):
         return self.__connection
 
-    def getDefaultHeaders(self):
+    def getDefaultHeaders(self, no_auth=False):
+        '''
+        Fetches headers to be used on request
+
+        @param no_auth: do not authorize request (authorization is done via 
cookie)
+        '''
+
+        AUTH_HEADER = 'Authorization'
+
         headers = self.__headers.copy()
         headers.update(self.__createDynamicHeaders())
+
+        # remove AUTH_HEADER
+        if no_auth and headers.has_key(AUTH_HEADER):
+            headers.pop(AUTH_HEADER)
+
         return headers
 
-    def doRequest(self, method, url, body=urllib.urlencode({}), headers={}):
-        return self.__connection.request(method, url, body, 
self.getHeaders(headers))
+    def doRequest(self, method, url, body=urllib.urlencode({}), headers={}, 
no_auth=False):
+        '''
+        Performs HTTP request
 
-    def getHeaders(self, headers):
-        extended_headers = self.getDefaultHeaders()
+        @param method: HTTP method
+        @param url: URL to invoke the request on
+        @param body: request body
+        @param headers: request headers
+        @param no_auth: do not authorize request (authorization is done via 
cookie)
+        '''
+        return self.__connection.request(method, url, body, 
self.getHeaders(headers, no_auth))
+
+    def getHeaders(self, headers, no_auth=False):
+        extended_headers = self.getDefaultHeaders(no_auth)
         for k in headers.keys():
             if (headers[k] is None and extended_headers.has_key(k)):
                 extended_headers.pop(k)
@@ -72,6 +94,7 @@
                     extended_headers[k] = str(headers[k])
                 else:
                     extended_headers[k] = headers[k]
+
         return extended_headers
 
     def getResponse(self):


--
To view, visit http://gerrit.ovirt.org/12578
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ief0ed86c26c2e74b8cc8f46d68b01f904c50d0e2
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine-sdk
Gerrit-Branch: sdk_3.2
Gerrit-Owner: Michael Pasternak <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to