Permalink
Browse files

Use TENANT_ID if it exists, but still support X_TENANT.

This continues support for middleware that is using the older data model where tenantId and tenantName were the same thing. X_TENANT is what is in the URL in Keystoe.

Added documentation on Middleware headers and HTTP API interactions.

Change-Id: I65a31ab07eb18d6882977acc64679c873b951bfb
  • Loading branch information...
ziadsawalha authored and dolph committed Nov 7, 2011
1 parent c325643 commit df6e1c9640c29ba6a32ff92b438a41fde34d4400
View
@@ -81,6 +81,7 @@ Developer Docs
developing
architecture
+ middleware
sourcecode/autoindex
Indices and tables
View
@@ -0,0 +1,65 @@
+..
+ Copyright 2011 OpenStack, LLC
+ All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License"); you may
+ not use this file except in compliance with the License. You may obtain
+ a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ License for the specific language governing permissions and limitations
+ under the License.
+
+==========
+Middleware
+==========
+
+The Keystone middleware sits in front of an OpenStack service and handles authenticating
+incoming requests. The middleware was designed according to `this spec`.
+
+The middleware is found in source under Keystone/middleware.
+
+The middleware supports two interfaces; WSGI and REST/HTTP.
+
+.. _`this spec`: http://wiki.openstack.org/openstack-authn
+
+REST & HTTP API
+===============
+
+If an unauthenticated call comes in, the middleware will respond with a 401 Unauthorized error. As per
+HTTP standards, it will also return a WWW-Authenticate header informing the caller
+of what protocols are supported. For Keystone authentication, the response syntax will be::
+
+ WWW-Authenticate: Keystone uri="url to Keystone server"
+
+The client can then make the necessary calls to the Keystone server, obtain a token, and retry the call with the token.
+
+The token is passed in using ther X-Auth-Token header.
+
+WSGI API (Headers)
+==================
+
+Upon successful authentication the middleware sends the following
+headers to the downstream WSGI app:
+
+X-Identity-Status
+ Provides information on whether the request was authenticated or not.
+
+X-Tenant
+ Provides the tenant ID (as it appears in the URL in Keystone). This is to support any legacy implementations before Keystone switched to an ID/Name schema for tenants.
+
+X-Tenant-Id
+ The unique, immutable tenant Id
+
+X-Tenant-Name
+ The unique, but mutable (it can change) tenant name.
+
+X-User
+ The username used to log in
+
+X-Roles
+ The roles associated with that user
@@ -200,11 +200,18 @@ def __call__(self, env, start_response):
if claims:
self._decorate_request('X_AUTHORIZATION', "Proxy %s" %
claims['user'], env, proxy_headers)
+
+ # For legacy compatibility before we had ID and Name
self._decorate_request('X_TENANT',
+ claims['tenant'], env, proxy_headers)
+
+ # Services should use these
+ self._decorate_request('X_TENANT_NAME',
claims.get('tenant_name', claims['tenant']),
env, proxy_headers)
self._decorate_request('X_TENANT_ID',
claims['tenant'], env, proxy_headers)
+
self._decorate_request('X_USER',
claims['user'], env, proxy_headers)
if 'roles' in claims and len(claims['roles']) > 0:
@@ -74,7 +74,13 @@ def __call__(self, req):
self.auth.modify_user(user_ref, admin=is_admin)
# create a project for tenant
- project_id = req.headers['X_TENANT']
+ if 'X_TENANT_ID' in req.headers:
+ # This is the new header since Keystone went to ID/Name
+ project_id = req.headers['X_TENANT_ID']
+ else:
+ # This is for legacy compatibility
+ project_id = req.headers['X_TENANT']
+
if project_id:
try:
project_ref = self.auth.get_project(project_id)
@@ -41,7 +41,13 @@ def __call__(self, req):
return webob.exc.HTTPUnauthorized()
# get the roles
roles = [r.strip() for r in req.headers.get('X_ROLE', '').split(',')]
- project_id = req.headers['X_TENANT_ID']
+ if 'X_TENANT_ID' in req.headers:
+ # This is the new header since Keystone went to ID/Name
+ project_id = req.headers['X_TENANT_ID']
+ else:
+ # This is for legacy compatibility
+ project_id = req.headers['X_TENANT']
+
# Get the auth token
auth_token = req.headers.get('X_AUTH_TOKEN',
req.headers.get('X_STORAGE_TOKEN'))

0 comments on commit df6e1c9

Please sign in to comment.