~ubuntu-branches/ubuntu/precise/keystone/precise-security

« back to all changes in this revision

Viewing changes to doc/source/middleware_architecture.rst

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-03-09 12:26:12 UTC
  • mto: (25.1.1 precise-proposed)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: package-import@ubuntu.com-20120309122612-t4zqpaytkiptezsa
Tags: upstream-2012.1~rc1~20120308.2103
ImportĀ upstreamĀ versionĀ 2012.1~rc1~20120308.2103

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
..
 
2
      Copyright 2011-2012 OpenStack, LLC
 
3
      All Rights Reserved.
 
4
 
 
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
 
8
 
 
9
          http://www.apache.org/licenses/LICENSE-2.0
 
10
 
 
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
 
15
      under the License.
 
16
 
 
17
=======================
 
18
Middleware Architecture
 
19
=======================
 
20
 
 
21
Abstract
 
22
========
 
23
 
 
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.
 
30
 
 
31
Rationale and Goals
 
32
===================
 
33
 
 
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
 
39
as WSGI middleware.
 
40
 
 
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.
 
47
 
 
48
Specification Overview
 
49
======================
 
50
 
 
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.
 
56
 
 
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`.
 
63
 
 
64
.. _authComponent:
 
65
 
 
66
Authentication Component
 
67
------------------------
 
68
 
 
69
Figure 1. Authentication Component
 
70
 
 
71
.. image:: images/graphs_authComp.svg
 
72
   :width: 100%
 
73
   :height: 180
 
74
   :alt: An Authentication Component
 
75
 
 
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`.
 
79
 
 
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.
 
85
 
 
86
.. _authComponentDelegated:
 
87
 
 
88
Authentication Component (Delegated Mode)
 
89
-----------------------------------------
 
90
 
 
91
Figure 2. Authentication Component (Delegated Mode)
 
92
 
 
93
.. image:: images/graphs_authCompDelegate.svg
 
94
   :width: 100%
 
95
   :height: 180
 
96
   :alt: An Authentication Component (Delegated Mode)
 
97
 
 
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.
 
104
 
 
105
.. _deployStrategies:
 
106
 
 
107
Deployment Strategies
 
108
=====================
 
109
 
 
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).
 
114
 
 
115
.. _deployment:
 
116
 
 
117
Authentication Component Deployments Options
 
118
--------------------------------------------
 
119
 
 
120
Figure 3. Authentication Component Deployments Options
 
121
 
 
122
.. image:: images/images_layouts.svg
 
123
   :width: 100%
 
124
   :height: 180
 
125
   :alt: Authentication Component Deployments Options
 
126
 
 
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.
 
133
 
 
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.
 
143
 
 
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]_.
 
150
 
 
151
Additionally, services should support the ability to swap between different
 
152
embedded or external authentication components via configuration options.
 
153
 
 
154
Exchanging User Information
 
155
===========================
 
156
 
 
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`.
 
160
 
 
161
.. _xAuthHeader:
 
162
 
 
163
X-Authorization Header
 
164
----------------------
 
165
 
 
166
Example 1. X-Authorization Header::
 
167
 
 
168
    X-Authorization: Proxy JoeUser
 
169
 
 
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
 
172
issued the request.
 
173
 
 
174
.. note:
 
175
 
 
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.
 
181
 
 
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
 
188
unmodified.
 
189
 
 
190
Reverse Proxy Authentication
 
191
----------------------------
 
192
 
 
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.
 
200
 
 
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
 
204
[RFC-2617]_.
 
205
 
 
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.
 
211
 
 
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.
 
223
 
 
224
.. _proxyAuth:
 
225
 
 
226
Reverse Proxy Authentication
 
227
----------------------------
 
228
 
 
229
Figure 4. Reverse Proxy Authentication
 
230
 
 
231
.. image:: images/graphs_proxyAuth.svg
 
232
   :width: 100%
 
233
   :height: 180
 
234
   :alt: Reverse Proxy Authentication
 
235
 
 
236
.. _proxyAuthDelegated:
 
237
 
 
238
Reverse Proxy Authentication (Delegated Mode)
 
239
---------------------------------------------
 
240
 
 
241
Figure 5. Reverse Proxy Authentication (Delegated Mode)
 
242
 
 
243
.. image:: images/graphs_delegate_forbiden_proxy.svg
 
244
   :width: 100%
 
245
   :height: 180
 
246
   :alt: Reverse Proxy Authentication (Delegated Mode)
 
247
 
 
248
Delegated Mode
 
249
==============
 
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:
 
260
 
 
261
Identity Status Values
 
262
----------------------
 
263
 
 
264
Confirmed
 
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.
 
268
 
 
269
Indeterminate
 
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`.
 
274
 
 
275
.. _xauth-header-indeterminate:
 
276
 
 
277
Indeterminate Identity Headers
 
278
------------------------------
 
279
 
 
280
Example 2. Indeterminate Identity Headers::
 
281
 
 
282
    X-Identity-Status: Indeterminate
 
283
    X-Authorization: Proxy
 
284
 
 
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`.
 
289
 
 
290
X-Identity-Status
 
291
    Provides information on whether the request was authenticated or not.
 
292
 
 
293
X-Tenant
 
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.
 
295
 
 
296
X-Tenant-Id
 
297
    The unique, immutable tenant Id
 
298
 
 
299
X-Tenant-Name
 
300
    The unique, but mutable (it can change) tenant name.
 
301
 
 
302
X-User-Id
 
303
    The user id of the user used to log in
 
304
 
 
305
X-User-Name
 
306
    The username used to log in
 
307
 
 
308
X-User
 
309
    The username used to log in. This is to support any legacy implementations before Keystone switched to an ID/Name schema for tenants.
 
310
 
 
311
X-Roles
 
312
    The roles associated with that user
 
313
 
 
314
.. _unauthHeaders:
 
315
 
 
316
Delegated WWW-Authenticate Header
 
317
---------------------------------
 
318
 
 
319
::
 
320
 
 
321
    WWW-Authenticate: Delegated
 
322
 
 
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.
 
327
 
 
328
.. _delegateRejectBasic:
 
329
 
 
330
Delegated Reject Basic Auth
 
331
---------------------------
 
332
 
 
333
.. image:: images/graphs_delegate_reject_basic.svg
 
334
   :width: 100%
 
335
   :height: 180
 
336
   :alt: Delegated Reject Basic Auth
 
337
 
 
338
.. _delegateRejectOAuth:
 
339
 
 
340
Delegated Reject OAuth
 
341
----------------------
 
342
 
 
343
.. image:: images/graphs_delegate_reject_oauth.svg
 
344
   :width: 100%
 
345
   :height: 180
 
346
   :alt: Delegated Reject OAuth
 
347
 
 
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
 
353
unauthorized.
 
354
 
 
355
.. _delegateForbidden:
 
356
 
 
357
Delegated Reject Forbidden
 
358
--------------------------
 
359
 
 
360
Figure 8. Delegated Reject Forbidden
 
361
 
 
362
.. image:: images/graphs_delegate_forbiden_basic.svg
 
363
   :width: 100%
 
364
   :height: 180
 
365
   :alt: Delegated Reject Forbidden
 
366
 
 
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.
 
370
 
 
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.
 
380
 
 
381
.. _delegateUnimplemented:
 
382
 
 
383
Unimplemented Delegated Mode
 
384
----------------------------
 
385
 
 
386
.. image:: images/graphs_delegate_unimplemented.svg
 
387
   :width: 100%
 
388
   :height: 180
 
389
   :alt: Unimplemented Delegated Mode
 
390
 
 
391
Handling Direct Client Connections
 
392
==================================
 
393
 
 
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`.
 
402
 
 
403
.. _redirect:
 
404
 
 
405
Auth Component Redirect
 
406
-----------------------
 
407
 
 
408
.. image:: images/graphs_305.svg
 
409
   :width: 100%
 
410
   :height: 280
 
411
   :alt: Auth Component Redirect
 
412
 
 
413
.. _redirect-response:
 
414
 
 
415
Auth Component Redirect Response
 
416
--------------------------------
 
417
 
 
418
::
 
419
 
 
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
 
423
 
 
424
Using Multiple Authentication Components
 
425
========================================
 
426
 
 
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`.
 
433
 
 
434
.. _multiAuth:
 
435
 
 
436
Multiple Authentication Components
 
437
----------------------------------
 
438
 
 
439
.. image:: images/graphs_mapper.svg
 
440
   :width: 100%
 
441
   :height: 320
 
442
   :alt: Multiple Authentication Components
 
443
 
 
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.
 
450
 
 
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.
 
456
 
 
457
The Default Component
 
458
=====================
 
459
 
 
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.
 
472
 
 
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.
 
482
 
 
483
We will discuss the design of the default component in an upcoming blueprint.
 
484
 
 
485
.. _both:
 
486
 
 
487
Disabled Embedded Component
 
488
---------------------------
 
489
 
 
490
.. image:: images/graphs_both.svg
 
491
   :width: 100%
 
492
   :height: 250
 
493
   :alt: Disabled Embedded Component
 
494
 
 
495
Questions and Answers
 
496
=====================
 
497
 
 
498
#. Why do authentication components send reject messages? Why not have
 
499
   OpenStack services reject requests themselves?
 
500
 
 
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
 
505
   components.
 
506
 
 
507
#. Why require support for deploying authentication components in separate
 
508
   nodes?
 
509
 
 
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.
 
514
 
 
515
References
 
516
==========
 
517
 
 
518
.. [PEP-333] pep0333 Phillip J Eby.  'Python Web Server Gateway Interface
 
519
    v1.0.''  http://www.python.org/dev/peps/pep-0333/.
 
520
 
 
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.
 
524
 
 
525
.. |must| replace:: must must
 
526
.. |should| replace:: should should
 
527
.. |may| replace:: may may
 
528
.. |must not| replace:: "must not" "must not"
 
529