The keystonemiddleware architecture supports a common authentication protocol in use between the OpenStack projects. By using keystone as a common authentication and authorization mechanism, various OpenStack projects can leverage the existing authentication and authorization systems in use.
In this document, we describe the architecture and responsibilities of the authentication middleware which acts as the internal API mechanism for OpenStack projects based on the WSGI standard.
This documentation describes the implementation in
‘Authentication’ is the process of determining that users are who they say they are. Typically, ‘authentication protocols’ such as HTTP Basic Auth, Digest Access, public key, token, etc, are used to verify a user’s identity. In this document, we define an ‘authentication component’ as a software module that implements an authentication protocol for an OpenStack service. Bearer tokens are currently the most common authentication protocol used within OpenStack.
At a high level, an authentication middleware component is a proxy that intercepts HTTP calls from clients and populates HTTP headers in the request context for other WSGI middleware or applications to use. The general flow of the middleware processing is:
clear any existing authorization headers to prevent forgery
collect the token from the existing HTTP request headers
validate the token
if valid, populate additional headers representing the identity that has been authenticated and authorized
if invalid, or no token present, reject the request (HTTPUnauthorized) or pass along a header indicating the request is unauthorized (configurable in the middleware)
if the keystone service is unavailable to validate the token, reject the request with HTTPServiceUnavailable.
The following shows the default behavior of an Authentication Component deployed in front of an OpenStack service.
The Authentication Component, or middleware, will reject any unauthenticated requests, only allowing authenticated requests through to the OpenStack service.
Authentication Component (Delegated Mode)¶
The Authentication Component may be configured to operate in a ‘delegated mode’. In this mode, the decision to reject or accept an unauthenticated client is delegated to the OpenStack service.
Here, requests are forwarded to the OpenStack service with an identity status message that indicates whether the identity of the client has been confirmed or is indeterminate. The consuming OpenStack service decides whether or not a rejection message should be sent to the client.
The middleware is intended to be used inline with OpenStack WSGI components, based on the Oslo WSGI middleware class. It is typically deployed as a configuration element in a paste configuration pipeline of other middleware components, with the pipeline terminating in the service application. The middleware conforms to the python WSGI standard [PEP-333]. In initializing the middleware, a configuration item (which acts like a python dictionary) is passed to the middleware with relevant configuration options.
The middleware is configured within the config file of the main application as a WSGI component. Example for the auth_token middleware:
[app:myService] paste.app_factory = myService:app_factory [pipeline:main] pipeline = authtoken myService [filter:authtoken] paste.filter_factory = keystonemiddleware.auth_token:filter_factory
[DEFAULT] [keystone_authtoken] # # From keystonemiddleware.auth_token # # Complete "public" Identity API endpoint. This endpoint should not be an # "admin" endpoint, as it should be accessible by all end users. # Unauthenticated clients are redirected to this endpoint to authenticate. # Although this endpoint should ideally be unversioned, client support in the # wild varies. If you're using a versioned v2 endpoint here, then this should # *not* be the same endpoint the service user utilizes for validating tokens, # because normal end users may not be able to reach that endpoint. (string # value) # Deprecated group/name - [keystone_authtoken]/auth_uri #www_authenticate_uri = <None> # DEPRECATED: Complete "public" Identity API endpoint. This endpoint should not # be an "admin" endpoint, as it should be accessible by all end users. # Unauthenticated clients are redirected to this endpoint to authenticate. # Although this endpoint should ideally be unversioned, client support in the # wild varies. If you're using a versioned v2 endpoint here, then this should # *not* be the same endpoint the service user utilizes for validating tokens, # because normal end users may not be able to reach that endpoint. This option # is deprecated in favor of www_authenticate_uri and will be removed in the S # release. (string value) # This option is deprecated for removal since Queens. # Its value may be silently ignored in the future. # Reason: The auth_uri option is deprecated in favor of www_authenticate_uri # and will be removed in the S release. #auth_uri = <None> # API version of the Identity API endpoint. (string value) #auth_version = <None> # Interface to use for the Identity API endpoint. Valid values are "public", # "internal" (default) or "admin". (string value) #interface = internal # Do not handle authorization requests within the middleware, but delegate the # authorization decision to downstream WSGI components. (boolean value) #delay_auth_decision = false # Request timeout value for communicating with Identity API server. (integer # value) #http_connect_timeout = <None> # How many times are we trying to reconnect when communicating with Identity # API Server. (integer value) #http_request_max_retries = 3 # Request environment key where the Swift cache object is stored. When # auth_token middleware is deployed with a Swift cache, use this option to have # the middleware share a caching backend with swift. Otherwise, use the # ``memcached_servers`` option instead. (string value) #cache = <None> # Required if identity server requires client certificate (string value) #certfile = <None> # Required if identity server requires client certificate (string value) #keyfile = <None> # A PEM encoded Certificate Authority to use when verifying HTTPs connections. # Defaults to system CAs. (string value) #cafile = <None> # Verify HTTPS connections. (boolean value) #insecure = false # The region in which the identity server can be found. (string value) #region_name = <None> # Optionally specify a list of memcached server(s) to use for caching. If left # undefined, tokens will instead be cached in-process. (list value) # Deprecated group/name - [keystone_authtoken]/memcache_servers #memcached_servers = <None> # In order to prevent excessive effort spent validating tokens, the middleware # caches previously-seen tokens for a configurable duration (in seconds). Set # to -1 to disable caching completely. (integer value) #token_cache_time = 300 # (Optional) If defined, indicate whether token data should be authenticated or # authenticated and encrypted. If MAC, token data is authenticated (with HMAC) # in the cache. If ENCRYPT, token data is encrypted and authenticated in the # cache. If the value is not one of these options or empty, auth_token will # raise an exception on initialization. (string value) # Possible values: # None - <No description provided> # MAC - <No description provided> # ENCRYPT - <No description provided> #memcache_security_strategy = None # (Optional, mandatory if memcache_security_strategy is defined) This string is # used for key derivation. (string value) #memcache_secret_key = <None> # (Optional) Number of seconds memcached server is considered dead before it is # tried again. (integer value) #memcache_pool_dead_retry = 300 # (Optional) Maximum total number of open connections to every memcached # server. (integer value) #memcache_pool_maxsize = 10 # (Optional) Socket timeout in seconds for communicating with a memcached # server. (integer value) #memcache_pool_socket_timeout = 3 # (Optional) Number of seconds a connection to memcached is held unused in the # pool before it is closed. (integer value) #memcache_pool_unused_timeout = 60 # (Optional) Number of seconds that an operation will wait to get a memcached # client connection from the pool. (integer value) #memcache_pool_conn_get_timeout = 10 # (Optional) Use the advanced (eventlet safe) memcached client pool. (boolean # value) #memcache_use_advanced_pool = true # (Optional) Indicate whether to set the X-Service-Catalog header. If False, # middleware will not ask for service catalog on token validation and will not # set the X-Service-Catalog header. (boolean value) #include_service_catalog = true # Used to control the use and type of token binding. Can be set to: "disabled" # to not check token binding. "permissive" (default) to validate binding # information if the bind type is of a form known to the server and ignore it # if not. "strict" like "permissive" but if the bind type is unknown the token # will be rejected. "required" any form of token binding is needed to be # allowed. Finally the name of a binding method that must be present in tokens. # (string value) #enforce_token_bind = permissive # A choice of roles that must be present in a service token. Service tokens are # allowed to request that an expired token can be used and so this check should # tightly control that only actual services should be sending this token. Roles # here are applied as an ANY check so any role in this list must be present. # For backwards compatibility reasons this currently only affects the # allow_expired check. (list value) #service_token_roles = service # For backwards compatibility reasons we must let valid service tokens pass # that don't pass the service_token_roles check as valid. Setting this true # will become the default in a future release and should be enabled if # possible. (boolean value) #service_token_roles_required = false # The name or type of the service as it appears in the service catalog. This is # used to validate tokens that have restricted access rules. (string value) #service_type = <None> # Authentication type to load (string value) # Deprecated group/name - [keystone_authtoken]/auth_plugin #auth_type = <None> # Config Section from which to load plugin specific options (string value) #auth_section = <None>
auth_type configuration option is set, you may need to refer to
the Authentication Plugins document for how to configure the auth_token
For services which have a separate paste-deploy ini file, auth_token middleware
can be alternatively configured in [keystone_authtoken] section in the main
config file. For example in nova, all middleware parameters can be removed
[filter:authtoken] paste.filter_factory = keystonemiddleware.auth_token:filter_factory
and set in
[DEFAULT] auth_strategy=keystone [keystone_authtoken] identity_uri = http://127.0.0.1:5000 admin_user = admin admin_password = SuperSekretPassword admin_tenant_name = service # Any of the options that could be set in api-paste.ini can be set here.
Middleware parameters in paste config take priority and must be removed to use options in the [keystone_authtoken] section.
The following is an example of a service’s auth_token middleware configuration
auth_type is set to
[keystone_authtoken] auth_type = password project_domain_name = Default project_name = service user_domain_name = Default username = nova password = ServicePassword interface = public auth_url = http://127.0.0.1:5000 # Any of the options that could be set in api-paste.ini can be set here.
If using an
auth_type, connection to the Identity service will be
established on the
interface as registered in the service catalog.
In the case where you are using an
auth_type and have multiple regions,
also specify the
region_name option to fetch the correct endpoint.
If the service doesn’t use the global oslo.config object (CONF), then the oslo config project name can be set it in paste config and keystonemiddleware will load the project configuration itself. Optionally the location of the configuration file can be set if oslo.config is not able to discover it.
[filter:authtoken] paste.filter_factory = keystonemiddleware.auth_token:filter_factory oslo_config_project = nova # oslo_config_file = /not_discoverable_location/nova.conf
Improving response time¶
Validating the identity of every client on every request can impact performance for both the OpenStack service and the identity service. As a result, keystonemiddleware is configurable to cache authentication responses from the identity service in-memory. It is worth noting that tokens invalidated after they’ve been stored in the cache may continue to work. Deployments using memcached may use the following keystonemiddleware configuration options instead of an in-memory cache.
memcached_servers: (optional) if defined, the memcached server(s) to use for caching. It will be ignored if Swift MemcacheRing is used instead.
token_cache_time: (optional, default 300 seconds) Set to -1 to disable caching completely.
When deploying auth_token middleware with Swift, user may elect
to use Swift MemcacheRing instead of the local Keystone memcache.
The Swift MemcacheRing object is passed in from the request environment
and it defaults to ‘swift.cache’. However it could be
different, depending on deployment. To use Swift MemcacheRing, you must
cache: (optional) if defined, the environment key where the Swift MemcacheRing object is stored.
In order to use memcached it is necessary to install the python-memcached library. If data stored in memcached will need to be encrypted it is also necessary to install the pycrypto library. These libs are not listed in the requirements.txt file.
When using memcached, tokens and authentication responses are stored in the
cache as raw data. In the event the cache is compromised, all token and
authentication responses will be readable. To mitigate this risk,
auth_token middleware provides an option to authenticate and optionally
encrypt the token data stored in the cache.
memcache_security_strategy: (optional) if defined, indicate whether token data should be authenticated or authenticated and encrypted. Acceptable values are
MAC, token data is authenticated (with HMAC) in the cache. If
ENCRYPT, token data is encrypted and authenticated in the cache. If the value is not one of these options or empty,
auth_tokenwill raise an exception on initialization.
memcache_secret_key: (optional, mandatory if
memcache_security_strategyis defined) this string is used for key derivation. If
memcache_security_strategyis defined and
auth_tokenwill raise an exception on initialization.
Exchanging User Information¶
The middleware expects to find a token representing the user with the header
X-Storage-Token. X-Storage-Token is supported for
swift/cloud files and for legacy Rackspace use. If the token isn’t present and
the middleware is configured to not delegate auth responsibility, it will
respond to the HTTP request with HTTPUnauthorized, returning the header
WWW-Authenticate with the value Keystone uri=’…’ to indicate where to
request a token. The URI returned is configured with the
The authentication middleware extends the HTTP request with the header
X-Identity-Status. If a request is successfully authenticated, the value
is set to Confirmed. If the middleware is delegating the auth decision to the
service, then the status is set to Invalid if the auth request was
X-Service-Token header may also be included with a request. If present,
and the value of
X-Storage-Token has not caused the
request to be denied, then the middleware will attempt to validate the value of
X-Service-Token. If valid, the authentication middleware extends the HTTP
request with the header
X-Service-Identity-Status having value Confirmed
and also extends the request with additional headers representing the identity
authenticated and authorised by the token.
X-Service-Token is present and its value is invalid and the
delay_auth_decision option is True then the value of
X-Service-Identity-Status is set to Invalid and no further headers are
added. Otherwise if
X-Service-Token is present and its value is invalid
then the middleware will respond to the HTTP request with HTTPUnauthorized,
regardless of the validity of the
Extended the request with additional User Information¶
keystonemiddleware.auth_token.AuthProtocol extends the
request with additional information if the user has been authenticated. See the
“What we add to the request for use by the OpenStack service” section in
keystonemiddleware.auth_token for the list of fields set by
the auth_token middleware.