2
Copyright 2011-2012 OpenStack, LLC
5
Licensed under the Apache License, Version 2.0 (the "License"); you may
6
not use this file except in compliance with the License. You may obtain
7
a copy of the License at
9
http://www.apache.org/licenses/LICENSE-2.0
11
Unless required by applicable law or agreed to in writing, software
12
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
License for the specific language governing permissions and limitations
17
=======================
18
Middleware Architecture
19
=======================
24
The Keystone middleware architecture supports multiple authentication protocols
25
in a pluggable manner in OpenStack. By providing support for authentication via
26
pluggable authentication components, this architecture allows OpenStack
27
services to be integrated easily into existing deployment environments. It also
28
provides a path by which to implement support for emerging authentication
29
standards such as OAUTH.
34
Keystone is the Identity service for OpenStack. To support the easy integrating
35
of OpenStack with existing authentication and identity management systems,
36
Keystone supports talking to multiple backends like LDAP.
37
And to support different deployment needs, it can support multiple
38
authentication protocols via pluggable 'authentication components' implemented
41
In this document, we describe the responsibilities of the authentication
42
middleware. We describe how these interact with underlying OpenStack services
43
and how existing services can be modified to take advantage of pluggable
44
authentication. The goal is to allow OpenStack services to be integrated easily
45
into existing deployment environments and to provide a path by which to
46
implement support for emerging authentication standards such as OAUTH.
48
Specification Overview
49
======================
51
'Authentication' is the process of determining that users are who they say they
52
are. Typically, 'authentication protocols' such as HTTP Basic Auth, Digest
53
Access, public key, token, etc, are used to verify a user's identity. In this
54
document, we define an ''authentication component'' as a software module that
55
implements an authentication protocol for an OpenStack service.
57
At a high level, an authentication component is simply a reverse proxy that
58
intercepts HTTP calls from clients. Once it has verified a user's identity, the
59
authentication component extends the call with information about the current
60
user and forwards the request to the OpenStack service. Otherwise, if a user's
61
identity is not verified, the message is rejected before it gets to the
62
service. This is illustrated in :ref:`authComponent`.
66
Authentication Component
67
------------------------
69
Figure 1. Authentication Component
71
.. image:: images/graphs_authComp.svg
74
:alt: An Authentication Component
76
Authentication components may operate in 'delegated mode'. In this mode, the
77
decision reject an unauthenticated client is delegated to the OpenStack
78
service. Delegated mode is illustrated in :ref:`authComponentDelegated`.
80
Here, requests are forwarded to the OpenStack service with an identity status
81
message that indicates whether the client's identity has been confirmed or is
82
indeterminate. It is the OpenStack service that decides whether or not a reject
83
message should be sent to the client. Note that it is always the responsibility
84
of the Authentication Component to transmit reject messages to the client.
86
.. _authComponentDelegated:
88
Authentication Component (Delegated Mode)
89
-----------------------------------------
91
Figure 2. Authentication Component (Delegated Mode)
93
.. image:: images/graphs_authCompDelegate.svg
96
:alt: An Authentication Component (Delegated Mode)
98
In this architecture, we define interactions between the authentication component
99
and the OpenStack service. Interactions between the client and the
100
authentication component are defined only for exceptional cases. For example,
101
we define the message that should be returned when the OpenStack service is
102
down. Other interactions, however, are defined by the underlying authentication
103
protocol and the OpenStack service and are considered out of scope.
105
.. _deployStrategies:
107
Deployment Strategies
108
=====================
110
An authentication component may be integrated directly into the service
111
implementation, or it may be deployed separately as an HTTP reverse proxy. This
112
is illustrated in :ref:`deployment`, showing both approaches to
113
authentication, labeled Option (a) and Option (b).
117
Authentication Component Deployments Options
118
--------------------------------------------
120
Figure 3. Authentication Component Deployments Options
122
.. image:: images/images_layouts.svg
125
:alt: Authentication Component Deployments Options
127
In Option (a), the component is integrated into the service implementation. In
128
this case, communication between the authentication component and the service
129
can be efficiently implemented via a method call. In Option (b), the component
130
is deployed separately and communication between the service and the component
131
involves an HTTP request. In both cases, unauthenticated requests are filtered
132
before they reach the service.
134
Each approach offers some benefits. Option (a) offers low latency and ease of
135
initial implementation, making it possibly most appropriate as a starting point
136
for simple configurations. Option (b) offers several key advantages that may be
137
of particular value in complex and dynamic configurations. It offers the
138
ability to scale horizontally in cases where authentication is computationally
139
expensive, such as when verifying digital signatures. Option (b) also allows
140
authentication components to be written in different programming languages.
141
Finally, Option (b) allows multiple authentication components to be deployed in
142
front of the same service.
144
OpenStack services can support both embedded (Option (a)) and external (Option
145
(b)) deployment strategies. Individual authentication components should support
146
either strategy or they |may| support both strategies. In order to support
147
option (a), authentication components written in the Python programming
148
language should be written as WSGI middleware components (in accordance with
149
the Web Server Gateway Interface (WSGI) standard [PEP-333]_.
151
Additionally, services should support the ability to swap between different
152
embedded or external authentication components via configuration options.
154
Exchanging User Information
155
===========================
157
If a request is successfully authenticated, the authentication component must
158
extend the request by adding an ``X-Authorization`` header. The header |must|
159
be formatted as illustrated in :ref:`xAuthHeader`.
163
X-Authorization Header
164
----------------------
166
Example 1. X-Authorization Header::
168
X-Authorization: Proxy JoeUser
170
Here, `Proxy` denotes that the authentication occurred via a proxy (in this
171
case authentication component) and ''JoeUser'' is the name of the user who
176
We considered using an ``Authorization`` header rather than an
177
``X-Authorization``, thereby following normal HTTP semantics. There are some
178
cases, however, where multiple ``Authorization`` headers need to be transmitted
179
in a single request. We want to assure ourselves that this will not break
180
common clients before we recommend the approach.
182
Authentication components |may| extend the request with additional
183
information. For example, an authentication system may add additional headers
184
or modify the target URI to pass authentication information to the back-end
185
service. Additionally, an authentication component |may| strip sensitive
186
information ā a plain text password, for example ā from the request. That said,
187
an authentication component |should| pass the majority of the request
190
Reverse Proxy Authentication
191
----------------------------
193
An OpenStack service |should| verify that it is receiving requests from a
194
trusted authentication component. This is particularly important in cases where
195
the authentication component and the OpenStack service are deployed separately.
196
In order to trust incoming requests, the OpenStack service should therefore
197
authenticate the authentication component. To avoid confusion, we call this
198
'reverse proxy authentication', since in this case the authentication
199
component is acting as an HTTP reverse proxy.
201
Any HTTP-based authentication scheme may be used for reverse proxy
202
authentication; however, all OpenStack services and all authentication
203
components |must| support HTTP Basic Authentication as defined in
206
Whether or not reverse proxy authentication is required is strictly a
207
deployment concern. For example, an operations team may opt to utilize firewall
208
rules instead of an authentication protocol to verify the integrity of incoming
209
request. Because of this, both OpenStack services and authentication components
210
|must| also allow for unauthenticated communication.
212
In cases where reverse proxy authentication is used, the authorization
213
component may receive an HTTP 401 authentication error or an HTTP 403
214
authorization error. These errors indicate that the component does not have
215
access to the underlying OpenStack service. The authentication component
216
|must not| return these errors to the client application. Instead, the
217
component |must| return a 500 internal error. This is illustrated in
218
:ref:`proxyAuth` and :ref:`proxyAuthDelegated` below. The component
219
|should| format the errors in a manner that does not break the service
220
contract defined by the OpenStack service. :ref:`proxyAuthDelegated`
221
illustrates proxy authorization in delegated mode. Delegated mode is discussed
222
in detail in the next section.
226
Reverse Proxy Authentication
227
----------------------------
229
Figure 4. Reverse Proxy Authentication
231
.. image:: images/graphs_proxyAuth.svg
234
:alt: Reverse Proxy Authentication
236
.. _proxyAuthDelegated:
238
Reverse Proxy Authentication (Delegated Mode)
239
---------------------------------------------
241
Figure 5. Reverse Proxy Authentication (Delegated Mode)
243
.. image:: images/graphs_delegate_forbiden_proxy.svg
246
:alt: Reverse Proxy Authentication (Delegated Mode)
250
In some cases, the decision to reject an unauthenticated request should be
251
delegated to the OpenStack service. An unauthenticated request may be
252
appropriate in cases when anonymous access is allowed. In order to support
253
these cases, an authentication component may be placed in Delegated Mode. In
254
this mode, the component forwards requests to the OpenStack service when the
255
client's identity has been confirmed or is indeterminate ā that is when
256
credentials are missing. The authentication component directly rejects requests
257
with invalid credentials. Authentication components |must| extend the
258
request by adding an `X-Identity-Status` header. The identity status header
259
|must| contain one of the following values:
261
Identity Status Values
262
----------------------
265
A `confirmed` value indicates that valid credentials were sent and identity
266
has been confirmed. The service can trust that the request has been sent on
267
behalf of the user specified in the `X-Authorization` header.
270
An `indeterminate` value indicates that no credentials were sent and
271
identity has not been confirmed. In this case, the service will receive an
272
`X-Authorization` header with no user entry as illustrated in
273
:ref:`xauth-header-indeterminate`.
275
.. _xauth-header-indeterminate:
277
Indeterminate Identity Headers
278
------------------------------
280
Example 2. Indeterminate Identity Headers::
282
X-Identity-Status: Indeterminate
283
X-Authorization: Proxy
285
Services |may| reject a delegated request by issuing an HTTP 401
286
authentication error or an HTTP 403 authorization error. These responses
287
|must| contain an ``WWW-Authenticate`` header with a value of ``Delegated`` as
288
illustrated in :ref:`unauthHeaders`.
291
Provides information on whether the request was authenticated or not.
294
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.
297
The unique, immutable tenant Id
300
The unique, but mutable (it can change) tenant name.
303
The user id of the user used to log in
306
The username used to log in
309
The username used to log in. This is to support any legacy implementations before Keystone switched to an ID/Name schema for tenants.
312
The roles associated with that user
316
Delegated WWW-Authenticate Header
317
---------------------------------
321
WWW-Authenticate: Delegated
323
It is important to note that the actual reject message will likely be modified
324
by the authentication component in order to comply with the authentication
325
scheme it is implementing. This is illustrated in :ref:`delegateRejectBasic` and
326
:ref:`delegateRejectOAuth` below.
328
.. _delegateRejectBasic:
330
Delegated Reject Basic Auth
331
---------------------------
333
.. image:: images/graphs_delegate_reject_basic.svg
336
:alt: Delegated Reject Basic Auth
338
.. _delegateRejectOAuth:
340
Delegated Reject OAuth
341
----------------------
343
.. image:: images/graphs_delegate_reject_oauth.svg
346
:alt: Delegated Reject OAuth
348
The presence of the `WWW-Authenticate` header with a value of `Delegated`
349
distinguishes a client authentication/authorization failure from a component
350
failure. For example, compare :ref:`delegateForbidden` with :ref:`proxyAuthDelegated`. In
351
:ref:`delegateForbidden`, the client is not allowed to access the OpenStack service.
352
In :ref:`proxyAuthDelegated`, it is the authentication component itself which is
355
.. _delegateForbidden:
357
Delegated Reject Forbidden
358
--------------------------
360
Figure 8. Delegated Reject Forbidden
362
.. image:: images/graphs_delegate_forbiden_basic.svg
365
:alt: Delegated Reject Forbidden
367
Authentication components |must| support both delegated and undelegated
368
(standard) modes. Delegated mode |should| be configured via a configuration
369
option. Delegated mode |should| be disabled by default.
371
OpenStack services are not required to support delegated mode. If a service
372
does not support delegated mode, it |must| respond with a 501 not implemented
373
error and an `WWW-Authenticate` header with a value of `Delegated`. The
374
authentication component |must not| return the error to the client
375
application. Instead, the component |must| return a 500 internal error; this is
376
illustrated in :ref:`delegateUnimplemented`. The component |should|
377
format the error in a manner that does not break the service contract defined
378
by the OpenStack service. The component should also log the error such that it
379
that will inform operators of the misconfiguration.
381
.. _delegateUnimplemented:
383
Unimplemented Delegated Mode
384
----------------------------
386
.. image:: images/graphs_delegate_unimplemented.svg
389
:alt: Unimplemented Delegated Mode
391
Handling Direct Client Connections
392
==================================
394
Requests from the authentication component to an OpenStack service |must|
395
contain an ``X-Authorization`` header. If the header is missing, and reverse
396
proxy authentication fails or is switched off, the OpenStack service |may|
397
assume that the request is coming directly from a client application. In this
398
case, the OpenStack service |must| redirect the request to the authentication
399
component by issuing an HTTP 305 User Proxy redirect. This is illustrated in
400
:ref:`redirect`. Note that the redirect response |must| include a ``Location`` header
401
specifying the authentication component's URL as shown in :ref:`redirect-response`.
405
Auth Component Redirect
406
-----------------------
408
.. image:: images/graphs_305.svg
411
:alt: Auth Component Redirect
413
.. _redirect-response:
415
Auth Component Redirect Response
416
--------------------------------
420
HTTP/1.1 305 Use Proxy
421
Date: Thu, 28 Oct 2011 07:41:16 GMT
422
Location: http://sample.auth.openstack.com/path/to/resource
424
Using Multiple Authentication Components
425
========================================
427
There are some use cases when a service provider might want to consider using
428
multiple authentication components for different purposes. For instance, a
429
service provider may have one authentication scheme to authenticate the users
430
of the service and another one to authenticate the administrators or operations
431
personnel that maintain the service. For such scenarios, we propose using a
432
mapper as illustrated in :ref:`multiAuth`.
436
Multiple Authentication Components
437
----------------------------------
439
.. image:: images/graphs_mapper.svg
442
:alt: Multiple Authentication Components
444
At a high level, a mapper is a simple reverse proxy that intercepts HTTP calls
445
from clients and routes the request to the appropriate authentication
446
component. A mapper can make the routing decisions based on a number of routing
447
rules that map a resource to a specific authentication component. For example,
448
a request URI may determine whether a call should be authenticated via one
449
authentication component or another.
451
Note that neither the authentication component nor the OpenStack service need
452
be aware of the mapper. Any external authentication component can be used
453
alongside others. Mappers may provide a means by which to offer support for
454
anonymous or guest access to a subset of service resources. A mapper may be
455
implemented via a traditional reverse proxy server such as Pound or Zeus.
457
The Default Component
458
=====================
460
Individual services |must| be distributed with a simple integrated
461
authentication component by default. Providing such a component lowers barriers
462
to the deployment of individual services. This is especially important to]
463
developers who may want to deploy OpenStack services on their own machines.
464
Also, since there is no direct dependency on an external authentication system,
465
OpenStack services can be deployed individually, without the need to stand up
466
and configure additional services. Finally, having a standard authentication
467
component that all services share promotes a separation of concerns. That is,
468
as a community we are explicitly stating that services should not develop their
469
own authentication mechanisms. Additional authentication components may be
470
developed, of course, but these components should not be intimately coupled to
471
any one particular service.
473
As discussed in :ref:`deployStrategies`, an authentication component may be
474
integrated directly into the service implementation (Option (a)), or it may be
475
deployed separately as an HTTP reverse proxy (Option (b)). The default
476
component should be implemented to support Option (a) and services should
477
maintain support for Option (b). One way to achieve this is to provide a
478
method that allows the disabling of the default authentication component via
479
configuration. This is illustrated in :ref:`both`. Here, requests are
480
sent directly to the OpenStack service when the default authentication
481
component is disabled.
483
We will discuss the design of the default component in an upcoming blueprint.
487
Disabled Embedded Component
488
---------------------------
490
.. image:: images/graphs_both.svg
493
:alt: Disabled Embedded Component
495
Questions and Answers
496
=====================
498
#. Why do authentication components send reject messages? Why not have
499
OpenStack services reject requests themselves?
501
The content and format of an authentication failed message is determined by
502
the authentication scheme (or protocol). For the service to respond
503
appropriately, it would have to be aware of the authentication scheme in
504
which it participates; this defeats the purpose of pluggable authentication
507
#. Why require support for deploying authentication components in separate
510
The deployment strategy is very flexible. It allows for authentication
511
components to be horizontally scalable. It allows for components to be written
512
in different languages. Finally, it allows different authentication components
513
to be deployed simultaneously as described above.
518
.. [PEP-333] pep0333 Phillip J Eby. 'Python Web Server Gateway Interface
519
v1.0.'' http://www.python.org/dev/peps/pep-0333/.
521
.. [RFC-2617] rfc2617 J Franks. P Hallam-Baker. J Hostetler. S Lawrence.
522
P Leach. A Luotonen. L Stewart. ''HTTP Authentication: Basic and Digest
523
Access Authentication.'' http://tools.ietf.org/html/rfc2617.
525
.. |must| replace:: must must
526
.. |should| replace:: should should
527
.. |may| replace:: may may
528
.. |must not| replace:: "must not" "must not"