summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keystonemiddleware/auth_token/__init__.py5
-rw-r--r--keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py66
-rw-r--r--releasenotes/notes/delay_auth_instead_of_503-f9b46bf4fbc11455.yaml9
3 files changed, 80 insertions, 0 deletions
diff --git a/keystonemiddleware/auth_token/__init__.py b/keystonemiddleware/auth_token/__init__.py
index 4ac7388..003f14e 100644
--- a/keystonemiddleware/auth_token/__init__.py
+++ b/keystonemiddleware/auth_token/__init__.py
@@ -768,6 +768,11 @@ class AuthProtocol(BaseAuthProtocol):
768 ksm_exceptions.RevocationListError, 768 ksm_exceptions.RevocationListError,
769 ksm_exceptions.ServiceError) as e: 769 ksm_exceptions.ServiceError) as e:
770 self.log.critical('Unable to validate token: %s', e) 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 raise webob.exc.HTTPServiceUnavailable( 776 raise webob.exc.HTTPServiceUnavailable(
772 'The Keystone service is temporarily unavailable.') 777 'The Keystone service is temporarily unavailable.')
773 except ksm_exceptions.InvalidToken: 778 except ksm_exceptions.InvalidToken:
diff --git a/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py b/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py
index f9916cc..9051d71 100644
--- a/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py
+++ b/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py
@@ -2043,6 +2043,18 @@ class v3AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
2043 2043
2044class DelayedAuthTests(BaseAuthTokenMiddlewareTest): 2044class 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 def test_header_in_401(self): 2058 def test_header_in_401(self):
2047 body = uuid.uuid4().hex 2059 body = uuid.uuid4().hex
2048 www_authenticate_uri = 'http://local.test' 2060 www_authenticate_uri = 'http://local.test'
@@ -2101,6 +2113,60 @@ class DelayedAuthTests(BaseAuthTokenMiddlewareTest):
2101 self.assertFalse(token_auth.has_service_token) 2113 self.assertFalse(token_auth.has_service_token)
2102 self.assertIsNone(token_auth.service) 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
2105class CommonCompositeAuthTests(object): 2171class CommonCompositeAuthTests(object):
2106 """Test Composite authentication. 2172 """Test Composite authentication.
diff --git a/releasenotes/notes/delay_auth_instead_of_503-f9b46bf4fbc11455.yaml b/releasenotes/notes/delay_auth_instead_of_503-f9b46bf4fbc11455.yaml
new file mode 100644
index 0000000..11ce28a
--- /dev/null
+++ b/releasenotes/notes/delay_auth_instead_of_503-f9b46bf4fbc11455.yaml
@@ -0,0 +1,9 @@
1---
2fixes:
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.