Hello community,

here is the log from the commit of package openstack-keystone for 
openSUSE:Factory checked in at 2013-03-08 09:29:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openstack-keystone (Old)
 and      /work/SRC/openSUSE:Factory/.openstack-keystone.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openstack-keystone", Maintainer is "radma...@suse.com"

Changes:
--------
--- /work/SRC/openSUSE:Factory/openstack-keystone/openstack-keystone.changes    
2013-02-22 16:55:56.000000000 +0100
+++ 
/work/SRC/openSUSE:Factory/.openstack-keystone.new/openstack-keystone.changes   
    2013-03-08 09:29:08.000000000 +0100
@@ -1,0 +2,7 @@
+Tue Mar  5 16:51:28 UTC 2013 - cloud-de...@suse.de
+
+- Update to version 2012.2.4+git.1362502288.8690166:
+  + Sync timeutils to pick up normalize fix.
+  + Backport of fix for 24-hour failure of pki.
+
+--------------------------------------------------------------------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ openstack-keystone-doc.spec ++++++
--- /var/tmp/diff_new_pack.GJMiEy/_old  2013-03-08 09:29:09.000000000 +0100
+++ /var/tmp/diff_new_pack.GJMiEy/_new  2013-03-08 09:29:09.000000000 +0100
@@ -19,7 +19,7 @@
 %define component keystone
 
 Name:           openstack-%{component}-doc
-Version:        2012.2.4+git.1361527873.37b3532
+Version:        2012.2.4+git.1362502288.8690166
 Release:        0
 License:        Apache-2.0
 Summary:        OpenStack Identity Service (Keystone) - Documentation

++++++ openstack-keystone.spec ++++++
--- /var/tmp/diff_new_pack.GJMiEy/_old  2013-03-08 09:29:09.000000000 +0100
+++ /var/tmp/diff_new_pack.GJMiEy/_new  2013-03-08 09:29:09.000000000 +0100
@@ -23,7 +23,7 @@
 %define hybrid keystone-hybrid-backend-folsom
 
 Name:           openstack-%{component}
-Version:        2012.2.4+git.1361527873.37b3532
+Version:        2012.2.4+git.1362502288.8690166
 Release:        0
 License:        Apache-2.0
 Summary:        OpenStack Identity Service (Keystone)

++++++ keystone-hybrid-backend-folsom.tar.gz ++++++

++++++ keystone-stable-folsom.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystone-2012.2.4/ChangeLog 
new/keystone-2012.2.4/ChangeLog
--- old/keystone-2012.2.4/ChangeLog     2013-02-20 02:12:22.000000000 +0100
+++ new/keystone-2012.2.4/ChangeLog     2013-03-05 15:24:55.000000000 +0100
@@ -1,3 +1,44 @@
+commit 86901664189c62fce6f8f81619da0896cce469a1
+Author: Joe Heck <he...@mac.com>
+Date:   Thu Nov 1 15:36:31 2012 -0700
+
+    Backport of fix for 24-hour failure of pki.
+    
+    A 401 from the admin token was being treated as an invalid user token
+    and the admin token was never re-requested. This would cause all
+    services to incorrectly report all tokens as invalid after the service
+    had been running for 24 hours. This change re-requests the admin token
+    and attempts to revalidate instead of returning 401.
+    
+    Original commit message follows:
+    
+    fixes bug 1074172
+    
+    updated diablo token based on output from diablo/stable keystone
+    added expiry to example tokens for test_auth_middleware
+    added a stack based HTTP response to test_auth_middleware to verify
+    sequencing
+    
+    Change-Id: I738b0e9c1a0e62ad86adb95ec0b73f621513f7d4
+    (cherry picked from commit 7cc02c80cfb1976271fa8b6271091fcd35c1cb34)
+
+ keystone/middleware/auth_token.py   |   38 ++++++++++++++--
+ tests/test_auth_token_middleware.py |   85 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 120 insertions(+), 3 deletions(-)
+
+commit 790c87e8bc401ef202e715a324a6053aaa9e2d5e
+Author: Vishvananda Ishaya <vishvana...@gmail.com>
+Date:   Mon Mar 4 13:37:46 2013 -0800
+
+    Sync timeutils to pick up normalize fix.
+    
+    Required to backport fix for bug 1074172.
+    
+    Change-Id: I6003abedcfc6ba9d287cabda35c0bbc821519008
+
+ keystone/openstack/common/timeutils.py |   15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
 commit 37b3532884f30fc979f633abe9be2b694d16887a
 Merge: 8a22745 f0b4d30
 Author: Jenkins <jenk...@review.openstack.org>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keystone-2012.2.4/keystone/middleware/auth_token.py 
new/keystone-2012.2.4/keystone/middleware/auth_token.py
--- old/keystone-2012.2.4/keystone/middleware/auth_token.py     2013-02-20 
02:08:12.000000000 +0100
+++ new/keystone-2012.2.4/keystone/middleware/auth_token.py     2013-03-05 
15:22:06.000000000 +0100
@@ -159,6 +159,16 @@
 CONF.register_opts(opts, group='keystone_authtoken')
 
 
+def will_expire_soon(expiry):
+    """ Determines if expiration is about to occur.
+
+    :param expiry: a datetime of the expected expiration
+    :returns: boolean : true if expiration is within 30 seconds
+    """
+    soon = (timeutils.utcnow() + datetime.timedelta(seconds=30))
+    return expiry < soon
+
+
 class InvalidUserToken(Exception):
     pass
 
@@ -230,6 +240,7 @@
         # Credentials used to verify this component with the Auth service since
         # validating tokens is a privileged call
         self.admin_token = self._conf_get('admin_token')
+        self.admin_token_expiry = None
         self.admin_user = self._conf_get('admin_user')
         self.admin_password = self._conf_get('admin_password')
         self.admin_tenant_name = self._conf_get('admin_tenant_name')
@@ -345,12 +356,21 @@
     def get_admin_token(self):
         """Return admin token, possibly fetching a new one.
 
+        if self.admin_token_expiry is set from fetching an admin token, check
+        it for expiration, and request a new token is the existing token
+        is about to expire.
+
         :return admin token id
         :raise ServiceError when unable to retrieve token from keystone
 
         """
+        if self.admin_token_expiry:
+            if will_expire_soon(self.admin_token_expiry):
+                self.admin_token = None
+
         if not self.admin_token:
-            self.admin_token = self._request_admin_token()
+            (self.admin_token,
+             self.admin_token_expiry) = self._request_admin_token()
 
         return self.admin_token
 
@@ -455,11 +475,17 @@
 
         try:
             token = data['access']['token']['id']
+            expiry = data['access']['token']['expires']
             assert token
-            return token
+            assert expiry
+            datetime_expiry = timeutils.parse_isotime(expiry)
+            return (token, timeutils.normalize_time(datetime_expiry))
         except (AssertionError, KeyError):
             LOG.warn("Unexpected response from keystone service: %s", data)
             raise ServiceError('invalid json response')
+        except (ValueError):
+            LOG.warn("Unable to parse expiration time from token: %s", data)
+            raise ServiceError('invalid json response')
 
     def _validate_user_token(self, user_token, retry=True):
         """Authenticate user using PKI
@@ -771,10 +797,16 @@
         with open(self.revoked_file_name, 'w') as f:
             f.write(value)
 
-    def fetch_revocation_list(self):
+    def fetch_revocation_list(self, retry=True):
         headers = {'X-Auth-Token': self.get_admin_token()}
         response, data = self._json_request('GET', '/v2.0/tokens/revoked',
                                             additional_headers=headers)
+        if response.status == 401:
+            if retry:
+                LOG.info('Keystone rejected admin token %s, resetting admin '
+                         'token', headers)
+                self.admin_token = None
+                return self.fetch_revocation_list(retry=False)
         if response.status != 200:
             raise ServiceError('Unable to fetch token revocation list.')
         if (not 'signed' in data):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystone-2012.2.4/keystone/openstack/common/timeutils.py 
new/keystone-2012.2.4/keystone/openstack/common/timeutils.py
--- old/keystone-2012.2.4/keystone/openstack/common/timeutils.py        
2013-02-20 02:08:12.000000000 +0100
+++ new/keystone-2012.2.4/keystone/openstack/common/timeutils.py        
2013-03-05 15:22:06.000000000 +0100
@@ -62,9 +62,11 @@
 
 
 def normalize_time(timestamp):
-    """Normalize time in arbitrary timezone to UTC"""
+    """Normalize time in arbitrary timezone to UTC naive object"""
     offset = timestamp.utcoffset()
-    return timestamp.replace(tzinfo=None) - offset if offset else timestamp
+    if offset is None:
+        return timestamp
+    return timestamp.replace(tzinfo=None) - offset
 
 
 def is_older_than(before, seconds):
@@ -121,7 +123,10 @@
 
 def unmarshall_time(tyme):
     """Unmarshall a datetime dict."""
-    return datetime.datetime(day=tyme['day'], month=tyme['month'],
-                             year=tyme['year'], hour=tyme['hour'],
-                             minute=tyme['minute'], second=tyme['second'],
+    return datetime.datetime(day=tyme['day'],
+                             month=tyme['month'],
+                             year=tyme['year'],
+                             hour=tyme['hour'],
+                             minute=tyme['minute'],
+                             second=tyme['second'],
                              microsecond=tyme['microsecond'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keystone-2012.2.4/tests/test_auth_token_middleware.py 
new/keystone-2012.2.4/tests/test_auth_token_middleware.py
--- old/keystone-2012.2.4/tests/test_auth_token_middleware.py   2013-02-20 
02:08:12.000000000 +0100
+++ new/keystone-2012.2.4/tests/test_auth_token_middleware.py   2013-03-05 
15:22:06.000000000 +0100
@@ -69,6 +69,7 @@
         'access': {
             'token': {
                 'id': UUID_TOKEN_DEFAULT,
+                'expires': '2999-01-01T00:00:10Z',
                 'tenant': {
                     'id': 'tenant_id1',
                     'name': 'tenant_name1',
@@ -89,6 +90,7 @@
         'access': {
             'token': {
                 'id': VALID_DIABLO_TOKEN,
+                'expires': '2999-01-01T00:00:10',
                 'tenantId': 'tenant_id1',
             },
             'user': {
@@ -105,6 +107,7 @@
         'access': {
             'token': {
                 'id': UUID_TOKEN_UNSCOPED,
+                'expires': '2999-01-01T00:00:10Z',
             },
             'user': {
                 'id': 'user_id1',
@@ -120,6 +123,7 @@
         'access': {
             'token': {
                 'id': 'valid-token',
+                'expires': '2999-01-01T00:00:10Z',
                 'tenant': {
                     'id': 'tenant_id1',
                     'name': 'tenant_name1',
@@ -137,6 +141,8 @@
     },
 }
 
+FAKE_RESPONSE_STACK = []
+
 
 # The data for these tests are signed using openssl and are stored in files
 # in the signing subdirectory.  In order to keep the values consistent between
@@ -223,6 +229,23 @@
         return self.body
 
 
+class FakeStackHTTPConnection(object):
+
+    def __init__(self, *args, **kwargs):
+        pass
+
+    def getresponse(self):
+        if len(FAKE_RESPONSE_STACK):
+            return FAKE_RESPONSE_STACK.pop()
+        return FakeHTTPResponse(500, jsonutils.dumps('UNEXPECTED RESPONSE'))
+
+    def request(self, *_args, **_kwargs):
+        pass
+
+    def close(self):
+        pass
+
+
 class FakeHTTPConnection(object):
 
     last_requested_url = ''
@@ -339,6 +362,60 @@
         self.response_headers = dict(headers)
 
 
+class StackResponseAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest):
+    """Auth Token middleware test setup that allows the tests to define
+    a stack of responses to HTTP requests in the test and get those
+    responses back in sequence for testing.
+
+    Example::
+
+        resp1 = FakeHTTPResponse(401, jsonutils.dumps(''))
+        resp2 = FakeHTTPResponse(200, jsonutils.dumps({
+            'access': {
+                'token': {'id': 'admin_token2'},
+            },
+            })
+        FAKE_RESPONSE_STACK.append(resp1)
+        FAKE_RESPONSE_STACK.append(resp2)
+
+        ... do your testing code here ...
+
+    """
+
+    def setUp(self, expected_env=None):
+        super(StackResponseAuthTokenMiddlewareTest, self).setUp(expected_env)
+        self.middleware.http_client_class = FakeStackHTTPConnection
+
+    def test_fetch_revocation_list_with_expire(self):
+        # first response to revocation list should return 401 Unauthorized
+        # to pretend to be an expired token
+        resp1 = FakeHTTPResponse(200, jsonutils.dumps({
+            'access': {
+                'token': {'id': 'admin_token2'},
+            },
+        }))
+        resp2 = FakeHTTPResponse(401, jsonutils.dumps(''))
+        resp3 = FakeHTTPResponse(200, jsonutils.dumps({
+            'access': {
+                'token': {'id': 'admin_token2'},
+            },
+        }))
+        resp4 = FakeHTTPResponse(200, SIGNED_REVOCATION_LIST)
+
+        # first get_admin_token() call
+        FAKE_RESPONSE_STACK.append(resp1)
+        # request revocation list, get "unauthorized" due to simulated expired
+        # token
+        FAKE_RESPONSE_STACK.append(resp2)
+        # request a new admin_token
+        FAKE_RESPONSE_STACK.append(resp3)
+        # request revocation list, get the revocation list properly
+        FAKE_RESPONSE_STACK.append(resp4)
+
+        fetched_list = jsonutils.loads(self.middleware.fetch_revocation_list())
+        self.assertEqual(fetched_list, REVOCATION_LIST)
+
+
 class DiabloAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest):
     """Auth Token middleware should understand Diablo keystone responses."""
     def setUp(self):
@@ -564,3 +641,11 @@
         self.assertEqual(self.response_status, 200)
         self.assertFalse(req.headers.get('X-Service-Catalog'))
         self.assertEqual(body, ['SUCCESS'])
+
+    def test_will_expire_soon(self):
+        tenseconds = datetime.datetime.utcnow() + datetime.timedelta(
+            seconds=10)
+        self.assertTrue(auth_token.will_expire_soon(tenseconds))
+        fortyseconds = datetime.datetime.utcnow() + datetime.timedelta(
+            seconds=40)
+        self.assertFalse(auth_token.will_expire_soon(fortyseconds))

-- 
To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org
For additional commands, e-mail: opensuse-commit+h...@opensuse.org

Reply via email to