Skip to content

Commit

Permalink
Use TENANT_ID if it exists, but still support X_TENANT.
Browse files Browse the repository at this point in the history
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 10, 2011
1 parent c325643 commit df6e1c9
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 2 deletions.
1 change: 1 addition & 0 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Developer Docs

developing
architecture
middleware
sourcecode/autoindex

Indices and tables
Expand Down
65 changes: 65 additions & 0 deletions doc/source/middleware.rst
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions keystone/middleware/auth_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 7 additions & 1 deletion keystone/middleware/nova_auth_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 7 additions & 1 deletion keystone/middleware/nova_keystone_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'))
Expand Down

0 comments on commit df6e1c9

Please sign in to comment.