Browse Source

Merge "Respect delay_auth_decision when Keystone is unavailable"

Zuul 6 months ago
parent
commit
fc51082ef4

+ 5
- 0
keystonemiddleware/auth_token/__init__.py View File

@@ -768,6 +768,11 @@ class AuthProtocol(BaseAuthProtocol):
768 768
                 ksm_exceptions.RevocationListError,
769 769
                 ksm_exceptions.ServiceError) as e:
770 770
             self.log.critical('Unable to validate token: %s', e)
771
+            if self._delay_auth_decision:
772
+                self.log.debug('Keystone unavailable; marking token as '
773
+                               'invalid and deferring auth decision.')
774
+                raise ksm_exceptions.InvalidToken(
775
+                    'Keystone unavailable: %s' % e)
771 776
             raise webob.exc.HTTPServiceUnavailable(
772 777
                 'The Keystone service is temporarily unavailable.')
773 778
         except ksm_exceptions.InvalidToken:

+ 66
- 0
keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py View File

@@ -2043,6 +2043,18 @@ class v3AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
2043 2043
 
2044 2044
 class DelayedAuthTests(BaseAuthTokenMiddlewareTest):
2045 2045
 
2046
+    def token_response(self, request, context):
2047
+        auth_id = request.headers.get('X-Auth-Token')
2048
+        self.assertEqual(auth_id, FAKE_ADMIN_TOKEN_ID)
2049
+
2050
+        if request.headers.get('X-Subject-Token') == ERROR_TOKEN:
2051
+            msg = 'Network connection refused.'
2052
+            raise ksc_exceptions.ConnectionRefused(msg)
2053
+
2054
+        # All others just fail
2055
+        context.status_code = 404
2056
+        return ''
2057
+
2046 2058
     def test_header_in_401(self):
2047 2059
         body = uuid.uuid4().hex
2048 2060
         www_authenticate_uri = 'http://local.test'
@@ -2101,6 +2113,60 @@ class DelayedAuthTests(BaseAuthTokenMiddlewareTest):
2101 2113
         self.assertFalse(token_auth.has_service_token)
2102 2114
         self.assertIsNone(token_auth.service)
2103 2115
 
2116
+    def test_auth_plugin_with_token(self):
2117
+        self.requests_mock.get('%s/v3/auth/tokens' % BASE_URI,
2118
+                               text=self.token_response,
2119
+                               headers={'X-Subject-Token': uuid.uuid4().hex})
2120
+
2121
+        body = uuid.uuid4().hex
2122
+        www_authenticate_uri = 'http://local.test'
2123
+        conf = {
2124
+            'delay_auth_decision': 'True',
2125
+            'www_authenticate_uri': www_authenticate_uri,
2126
+            'auth_type': 'admin_token',
2127
+            'endpoint': '%s/v3' % BASE_URI,
2128
+            'token': FAKE_ADMIN_TOKEN_ID,
2129
+        }
2130
+
2131
+        middleware = self.create_simple_middleware(body=body, conf=conf)
2132
+        resp = self.call(middleware, headers={
2133
+            'X-Auth-Token': 'non-keystone-token'})
2134
+        self.assertEqual(six.b(body), resp.body)
2135
+
2136
+        token_auth = resp.request.environ['keystone.token_auth']
2137
+
2138
+        self.assertFalse(token_auth.has_user_token)
2139
+        self.assertIsNone(token_auth.user)
2140
+        self.assertFalse(token_auth.has_service_token)
2141
+        self.assertIsNone(token_auth.service)
2142
+
2143
+    def test_auth_plugin_with_token_keystone_down(self):
2144
+        self.requests_mock.get('%s/v3/auth/tokens' % BASE_URI,
2145
+                               text=self.token_response,
2146
+                               headers={'X-Subject-Token': ERROR_TOKEN})
2147
+
2148
+        body = uuid.uuid4().hex
2149
+        www_authenticate_uri = 'http://local.test'
2150
+        conf = {
2151
+            'delay_auth_decision': 'True',
2152
+            'www_authenticate_uri': www_authenticate_uri,
2153
+            'auth_type': 'admin_token',
2154
+            'endpoint': '%s/v3' % BASE_URI,
2155
+            'token': FAKE_ADMIN_TOKEN_ID,
2156
+            'http_request_max_retries': '0'
2157
+        }
2158
+
2159
+        middleware = self.create_simple_middleware(body=body, conf=conf)
2160
+        resp = self.call(middleware, headers={'X-Auth-Token': ERROR_TOKEN})
2161
+        self.assertEqual(six.b(body), resp.body)
2162
+
2163
+        token_auth = resp.request.environ['keystone.token_auth']
2164
+
2165
+        self.assertFalse(token_auth.has_user_token)
2166
+        self.assertIsNone(token_auth.user)
2167
+        self.assertFalse(token_auth.has_service_token)
2168
+        self.assertIsNone(token_auth.service)
2169
+
2104 2170
 
2105 2171
 class CommonCompositeAuthTests(object):
2106 2172
     """Test Composite authentication.

+ 9
- 0
releasenotes/notes/delay_auth_instead_of_503-f9b46bf4fbc11455.yaml View File

@@ -0,0 +1,9 @@
1
+---
2
+fixes:
3
+  - |
4
+    When ``delay_auth_decision`` is enabled and a Keystone failure prevents
5
+    a final decision about whether a token is valid or invalid, it will be
6
+    marked invalid and the application will be responsible for a final auth
7
+    decision. This is similar to what happens when a token is confirmed *not*
8
+    valid. This allows a Keystone outage to only affect Keystone users in a
9
+    multi-auth system.

Loading…
Cancel
Save