Keystone Middleware
Keystonemiddleware provides WSGI middleware components for OpenStack Identity (Keystone) integration. It enables services to authenticate requests against Keystone, handle tokens, and authorize access based on user roles and projects. The current stable version is 12.0.0, and it follows the OpenStack release cycle, typically releasing new versions with each OpenStack cycle, leading to several major releases per year.
Common errors
-
AuthToken did not receive a value for 'memcached_servers'
cause The AuthToken middleware was initialized without specifying any Memcached servers, which is now a required configuration for token caching.fixAdd `memcached_servers = <ip>:<port>` to your AuthToken configuration. For example, `memcached_servers = 127.0.0.1:11211`. -
raise DiscoveryException('Could not discover appropriate URL for identity service')cause Keystonemiddleware could not reach or properly discover the Keystone identity service based on the provided `auth_url` or `www_authenticate_uri`.fixVerify that `auth_url` (e.g., `http://localhost:5000/v3`) is correct and that the Keystone service is running and network accessible from where your application is running. Check firewall rules or DNS issues. -
ValueError: Auth token is not an rstrip safe type (it's unicode)
cause This error can occur in older Python 2 environments or with misconfigured `oslo.config` due to incompatible string handling when parsing configuration values.fixUpgrade to Python 3.10+ as keystonemiddleware 12.0.0 requires it. If on an older version of `keystonemiddleware` and Python 3, ensure `oslo.config` is updated and config values are consistently handled as strings.
Warnings
- breaking Python 3.10 or higher is now required for keystonemiddleware 12.0.0. Older Python versions are no longer supported.
- gotcha The `AuthToken` middleware now strictly requires `memcached_servers` to be configured for efficient token caching. If not set, token validation can be slow or fail under load.
- deprecated The `keystonemiddleware.multiformats` module has been deprecated and its functionality has been moved to `oslo_middleware.base.RequestBodySizeLimiter`.
- gotcha Incorrect or missing `auth_url`, `www_authenticate_uri`, or service catalog type/name can lead to authentication failures or delays during discovery.
Install
-
pip install keystonemiddleware
Imports
- AuthToken
from keystonemiddleware.auth_token import AuthToken
- AuditMiddleware
from keystonemiddleware.audit import AuditMiddleware
- CORS
from keystonemiddleware.cors import CORS
Quickstart
import os
from wsgiref.simple_server import make_server
from keystonemiddleware.auth_token import AuthToken
def simple_app(environ, start_response):
"""Simplest possible WSGI application"""
status = '200 OK'
headers = [('Content-type', 'text/plain; charset=utf-8')]
start_response(status, headers)
# AuthToken populates these if a valid token is provided
user_id = environ.get('HTTP_X_USER_ID', 'Unknown User ID')
project_id = environ.get('HTTP_X_PROJECT_ID', 'Unknown Project ID')
return [f"Hello, user '{user_id}' from project '{project_id}' via keystonemiddleware!\n".encode('utf-8')]
# Configuration for AuthToken (simplified, typically from paste.ini or configuration files)
# IMPORTANT: Replace with your actual Keystone endpoint and user/project details.
# For production, avoid 'insecure=True' and set 'memcached_servers'.
auth_config = {
'auth_url': os.environ.get('OS_AUTH_URL', 'http://localhost:5000/v3'),
'username': os.environ.get('OS_USERNAME', 'admin'),
'password': os.environ.get('OS_PASSWORD', 'secret'),
'project_name': os.environ.get('OS_PROJECT_NAME', 'admin'),
'user_domain_name': os.environ.get('OS_USER_DOMAIN_NAME', 'Default'),
'project_domain_name': os.environ.get('OS_PROJECT_DOMAIN_NAME', 'Default'),
'memcached_servers': os.environ.get('MEMCACHED_SERVERS', '127.0.0.1:11211'), # Required for caching
'insecure': 'True' if os.environ.get('OS_INSECURE') else 'False', # Use only for testing/development
'delay_auth_decision': 'True' # Allows app to handle unauthenticated requests if needed
}
# Wrap the application with AuthToken middleware
application = AuthToken(simple_app, auth_config)
if __name__ == '__main__':
httpd = make_server('', 8000, application)
print("Serving on port 8000...")
print("Access with a valid X-Auth-Token header to see user info:")
print(" curl -H \"X-Auth-Token: <your-keystone-token>\" http://localhost:8000/")
print("Or with no token (if 'delay_auth_decision' is True):")
print(" curl http://localhost:8000/")
print("Ensure memcached is running if configured, e.g., 'sudo apt install memcached' and 'systemctl start memcached'.")
print("Configure environment variables like OS_AUTH_URL, OS_USERNAME, OS_PASSWORD, etc. for actual Keystone integration.")
httpd.serve_forever()