summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2017-12-06 15:01:05 +0000
committerGerrit Code Review <review@openstack.org>2017-12-06 15:01:05 +0000
commit6c3e444a61d6e7f3ff6618b209e3303865d4ea3a (patch)
tree91e38683bfb941f5ed51141c407c7f659f2918b0
parent51d5b63a083450468cec474b9b6400df5d977091 (diff)
parentf71a78db86632dccb391782e62da69a4627c7cad (diff)
Merge "Enforce policy on oslo-context"
-rw-r--r--keystone/middleware/auth.py81
-rw-r--r--keystone/tests/unit/test_v3.py10
2 files changed, 52 insertions, 39 deletions
diff --git a/keystone/middleware/auth.py b/keystone/middleware/auth.py
index ccf5980..6f8b7d4 100644
--- a/keystone/middleware/auth.py
+++ b/keystone/middleware/auth.py
@@ -156,6 +156,8 @@ class AuthContextMiddleware(auth_token.BaseAuthProtocol):
156 156
157 if resp: 157 if resp:
158 return resp 158 return resp
159 if request.token_auth.user is not None:
160 request.set_user_headers(request.token_auth.user)
159 161
160 # NOTE(jamielennox): function is split so testing can check errors from 162 # NOTE(jamielennox): function is split so testing can check errors from
161 # fill_context. There is no actual reason for fill_context to raise 163 # fill_context. There is no actual reason for fill_context to raise
@@ -164,13 +166,28 @@ class AuthContextMiddleware(auth_token.BaseAuthProtocol):
164 # and the middleware_exceptions helper removed. 166 # and the middleware_exceptions helper removed.
165 self.fill_context(request) 167 self.fill_context(request)
166 168
169 def _keystone_specific_values(self, token, request_context):
170 if token.domain_scoped:
171 # Domain scoped tokens should never have is_admin_project set
172 # Even if KSA defaults it otherwise. The two mechanisms are
173 # parallel; only ione or the other should be used for access.
174 request_context.is_admin_project = False
175 request_context.domain_id = token.domain_id
176 request_context.domain_name = token.domain_name
177 if token.oauth_scoped:
178 request_context.is_delegated_auth = True
179 request_context.oauth_consumer_id = token.oauth_consumer_id
180 request_context.oauth_access_token_id = token.oauth_access_token_id
181 if token.trust_scoped:
182 request_context.is_delegated_auth = True
183 request_context.trust_id = token.trust_id
184 if token.is_federated_user:
185 request_context.group_ids = token.federation_group_ids
186 else:
187 request_context.group_ids = []
188
167 def fill_context(self, request): 189 def fill_context(self, request):
168 # The request context stores itself in thread-local memory for logging. 190 # The request context stores itself in thread-local memory for logging.
169 request_context = context.RequestContext(
170 request_id=request.environ.get('openstack.request_id'),
171 authenticated=False,
172 overwrite=True)
173 request.environ[context.REQUEST_CONTEXT_ENV] = request_context
174 191
175 if authorization.AUTH_CONTEXT_ENV in request.environ: 192 if authorization.AUTH_CONTEXT_ENV in request.environ:
176 msg = ('Auth context already exists in the request ' 193 msg = ('Auth context already exists in the request '
@@ -179,6 +196,13 @@ class AuthContextMiddleware(auth_token.BaseAuthProtocol):
179 LOG.warning(msg) 196 LOG.warning(msg)
180 return 197 return
181 198
199 kwargs = {
200 'authenticated': False,
201 'overwrite': True}
202 request_context = context.RequestContext.from_environ(
203 request.environ, **kwargs)
204 request.environ[context.REQUEST_CONTEXT_ENV] = request_context
205
182 # NOTE(gyee): token takes precedence over SSL client certificates. 206 # NOTE(gyee): token takes precedence over SSL client certificates.
183 # This will preserve backward compatibility with the existing 207 # This will preserve backward compatibility with the existing
184 # behavior. Tokenless authorization with X.509 SSL client 208 # behavior. Tokenless authorization with X.509 SSL client
@@ -190,10 +214,23 @@ class AuthContextMiddleware(auth_token.BaseAuthProtocol):
190 auth_context = {} 214 auth_context = {}
191 215
192 elif request.token_auth.has_user_token: 216 elif request.token_auth.has_user_token:
217 # Keystone enforces policy on some values that other services
218 # do not, and should not, use. This adds them in to the context.
219 token = token_model.KeystoneToken(token_id=request.user_token,
220 token_data=request.token_info)
221 self._keystone_specific_values(token, request_context)
193 request_context.auth_token = request.user_token 222 request_context.auth_token = request.user_token
194 ref = token_model.KeystoneToken(token_id=request.user_token, 223 auth_context = request_context.to_policy_values()
195 token_data=request.token_info) 224 additional = {
196 auth_context = authorization.token_to_auth_context(ref) 225 'trust_id': request_context.trust_id,
226 'trustor_id': request_context.trustor_id,
227 'trustee_id': request_context.trustee_id,
228 'domain_id': request_context._domain_id,
229 'domain_name': request_context.domain_name,
230 'group_ids': request_context.group_ids,
231 'token': token
232 }
233 auth_context.update(additional)
197 234
198 elif self._validate_trusted_issuer(request): 235 elif self._validate_trusted_issuer(request):
199 auth_context = self._build_tokenless_auth_context(request) 236 auth_context = self._build_tokenless_auth_context(request)
@@ -207,34 +244,6 @@ class AuthContextMiddleware(auth_token.BaseAuthProtocol):
207 # set authenticated to flag to keystone that a token has been validated 244 # set authenticated to flag to keystone that a token has been validated
208 request_context.authenticated = True 245 request_context.authenticated = True
209 246
210 # The attributes of request_context are put into the logs. This is a
211 # common pattern for all the OpenStack services. In all the other
212 # projects these are IDs, so set the attributes to IDs here rather than
213 # the name.
214 request_context.user_id = auth_context.get('user_id')
215 request_context.project_id = auth_context.get('project_id')
216 request_context.domain_id = auth_context.get('domain_id')
217 request_context.domain_name = auth_context.get('domain_name')
218 request_context.user_domain_id = auth_context.get('user_domain_id')
219 request_context.roles = auth_context.get('roles')
220
221 is_admin_project = auth_context.get('is_admin_project', True)
222 request_context.is_admin_project = is_admin_project
223
224 project_domain_id = auth_context.get('project_domain_id')
225 request_context.project_domain_id = project_domain_id
226
227 is_delegated_auth = auth_context.get('is_delegated_auth', False)
228 request_context.is_delegated_auth = is_delegated_auth
229
230 request_context.trust_id = auth_context.get('trust_id')
231 request_context.trustor_id = auth_context.get('trustor_id')
232 request_context.trustee_id = auth_context.get('trustee_id')
233
234 access_token_id = auth_context.get('access_token_id')
235 request_context.oauth_consumer_id = auth_context.get('consumer_id')
236 request_context.oauth_acess_token_id = access_token_id
237
238 LOG.debug('RBAC: auth_context: %s', auth_context) 247 LOG.debug('RBAC: auth_context: %s', auth_context)
239 request.environ[authorization.AUTH_CONTEXT_ENV] = auth_context 248 request.environ[authorization.AUTH_CONTEXT_ENV] = auth_context
240 249
diff --git a/keystone/tests/unit/test_v3.py b/keystone/tests/unit/test_v3.py
index 64a074e..bffe311 100644
--- a/keystone/tests/unit/test_v3.py
+++ b/keystone/tests/unit/test_v3.py
@@ -1300,10 +1300,14 @@ class AuthContextMiddlewareTestCase(RestfulTestCase):
1300 def test_unscoped_token_auth_context(self): 1300 def test_unscoped_token_auth_context(self):
1301 unscoped_token = self.get_unscoped_token() 1301 unscoped_token = self.get_unscoped_token()
1302 req = self._middleware_request(unscoped_token) 1302 req = self._middleware_request(unscoped_token)
1303 # This check originally looked that the value was unset
1304 # but that was an artifact of the custom context keystone
1305 # used to create. Oslo-context will always provide the
1306 # same set of keys, but the values will be None in an
1307 # unscoped token
1303 for key in ['project_id', 'domain_id', 'domain_name']: 1308 for key in ['project_id', 'domain_id', 'domain_name']:
1304 self.assertNotIn( 1309 self.assertIsNone(
1305 key, 1310 req.environ.get(authorization.AUTH_CONTEXT_ENV)[key])
1306 req.environ.get(authorization.AUTH_CONTEXT_ENV))
1307 1311
1308 def test_project_scoped_token_auth_context(self): 1312 def test_project_scoped_token_auth_context(self):
1309 project_scoped_token = self.get_scoped_token() 1313 project_scoped_token = self.get_scoped_token()