diff options
| author | Guang Yee <guang.yee@hp.com> | 2012-12-19 15:50:34 -0800 |
|---|---|---|
| committer | Guang Yee <guang.yee@hp.com> | 2013-01-15 22:06:56 -0800 |
| commit | 3dfb8437fc9135465f2b66b2c420bf20899fcf10 (patch) | |
| tree | c5e0524df91c2e64729ce74dcb0d6bb32f015b2b /doc/source | |
| parent | 4851cc175180e7803a693e556c92611de5c0ced8 (diff) | |
| download | python-keystoneclient-3dfb8437fc9135465f2b66b2c420bf20899fcf10.tar.gz | |
Blueprint memcache-protection: enable memcache value encryption/integrity check
DocImpact
Change-Id: I8b733256a3c2cdcf7c2ec5edac491ac4739aa847
Diffstat (limited to 'doc/source')
| -rw-r--r-- | doc/source/images/graphs_authComp.svg | 48 | ||||
| -rw-r--r-- | doc/source/images/graphs_authCompDelegate.svg | 53 | ||||
| -rw-r--r-- | doc/source/middlewarearchitecture.rst | 309 |
3 files changed, 410 insertions, 0 deletions
diff --git a/doc/source/images/graphs_authComp.svg b/doc/source/images/graphs_authComp.svg new file mode 100644 index 0000000..6be629c --- /dev/null +++ b/doc/source/images/graphs_authComp.svg @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<!-- Generated by graphviz version 2.27.20101213.0545 (20101213.0545) + --> +<!-- Title: AuthComp Pages: 1 --> +<svg width="510pt" height="118pt" + viewBox="0.00 0.00 510.00 118.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 114)"> +<title>AuthComp</title> +<polygon fill="white" stroke="white" points="-4,5 -4,-114 507,-114 507,5 -4,5"/> +<!-- AuthComp --> +<g id="node2" class="node"><title>AuthComp</title> +<polygon fill="#fdefe3" stroke="#c00000" points="292,-65 194,-65 194,-25 292,-25 292,-65"/> +<text text-anchor="middle" x="243" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">Auth</text> +<text text-anchor="middle" x="243" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Component</text> +</g> +<!-- Reject --> +<!-- AuthComp->Reject --> +<g id="edge3" class="edge"><title>AuthComp->Reject</title> +<path fill="none" stroke="black" d="M193.933,-51.2787C157.514,-55.939 108.38,-62.2263 73.8172,-66.649"/> +<polygon fill="black" stroke="black" points="73.0637,-63.2168 63.5888,-67.9578 73.9522,-70.1602 73.0637,-63.2168"/> +<text text-anchor="middle" x="129" y="-97.4" font-family="Times,serif" font-size="14.00">Reject</text> +<text text-anchor="middle" x="129" y="-82.4" font-family="Times,serif" font-size="14.00">Unauthenticated</text> +<text text-anchor="middle" x="129" y="-67.4" font-family="Times,serif" font-size="14.00">Requests</text> +</g> +<!-- Service --> +<g id="node6" class="node"><title>Service</title> +<polygon fill="#d1ebf1" stroke="#1f477d" points="502,-65 408,-65 408,-25 502,-25 502,-65"/> +<text text-anchor="middle" x="455" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">OpenStack</text> +<text text-anchor="middle" x="455" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Service</text> +</g> +<!-- AuthComp->Service --> +<g id="edge5" class="edge"><title>AuthComp->Service</title> +<path fill="none" stroke="black" d="M292.17,-45C323.626,-45 364.563,-45 397.52,-45"/> +<polygon fill="black" stroke="black" points="397.917,-48.5001 407.917,-45 397.917,-41.5001 397.917,-48.5001"/> +<text text-anchor="middle" x="350" y="-77.4" font-family="Times,serif" font-size="14.00">Forward</text> +<text text-anchor="middle" x="350" y="-62.4" font-family="Times,serif" font-size="14.00">Authenticated</text> +<text text-anchor="middle" x="350" y="-47.4" font-family="Times,serif" font-size="14.00">Requests</text> +</g> +<!-- Start --> +<!-- Start->AuthComp --> +<g id="edge7" class="edge"><title>Start->AuthComp</title> +<path fill="none" stroke="black" d="M59.1526,-21.4745C90.4482,-25.4792 142.816,-32.1802 183.673,-37.4084"/> +<polygon fill="black" stroke="black" points="183.43,-40.9057 193.793,-38.7034 184.318,-33.9623 183.43,-40.9057"/> +</g> +</g> +</svg> diff --git a/doc/source/images/graphs_authCompDelegate.svg b/doc/source/images/graphs_authCompDelegate.svg new file mode 100644 index 0000000..4788829 --- /dev/null +++ b/doc/source/images/graphs_authCompDelegate.svg @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<!-- Generated by graphviz version 2.27.20101213.0545 (20101213.0545) + --> +<!-- Title: AuthCompDelegate Pages: 1 --> +<svg width="588pt" height="104pt" + viewBox="0.00 0.00 588.00 104.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 100)"> +<title>AuthCompDelegate</title> +<polygon fill="white" stroke="white" points="-4,5 -4,-100 585,-100 585,5 -4,5"/> +<!-- AuthComp --> +<g id="node2" class="node"><title>AuthComp</title> +<polygon fill="#fdefe3" stroke="#c00000" points="338,-65 240,-65 240,-25 338,-25 338,-65"/> +<text text-anchor="middle" x="289" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">Auth</text> +<text text-anchor="middle" x="289" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Component</text> +</g> +<!-- Reject --> +<!-- AuthComp->Reject --> +<g id="edge3" class="edge"><title>AuthComp->Reject</title> +<path fill="none" stroke="black" d="M239.6,-50.1899C191.406,-55.2531 118.917,-62.8686 73.5875,-67.6309"/> +<polygon fill="black" stroke="black" points="73.0928,-64.1635 63.5132,-68.6893 73.8242,-71.1252 73.0928,-64.1635"/> +<text text-anchor="middle" x="152" y="-83.4" font-family="Times,serif" font-size="14.00">Reject Requests</text> +<text text-anchor="middle" x="152" y="-68.4" font-family="Times,serif" font-size="14.00">Indicated by the Service</text> +</g> +<!-- Service --> +<g id="node6" class="node"><title>Service</title> +<polygon fill="#d1ebf1" stroke="#1f477d" points="580,-65 486,-65 486,-25 580,-25 580,-65"/> +<text text-anchor="middle" x="533" y="-48.4" font-family="Helvetica,sans-Serif" font-size="14.00">OpenStack</text> +<text text-anchor="middle" x="533" y="-32.4" font-family="Helvetica,sans-Serif" font-size="14.00">Service</text> +</g> +<!-- AuthComp->Service --> +<g id="edge5" class="edge"><title>AuthComp->Service</title> +<path fill="none" stroke="black" d="M338.009,-49.0804C344.065,-49.4598 350.172,-49.7828 356,-50 405.743,-51.8535 418.259,-51.9103 468,-50 470.523,-49.9031 473.101,-49.7851 475.704,-49.6504"/> +<polygon fill="black" stroke="black" points="476.03,-53.1374 485.807,-49.0576 475.62,-46.1494 476.03,-53.1374"/> +<text text-anchor="middle" x="412" y="-68.4" font-family="Times,serif" font-size="14.00">Forward Requests</text> +<text text-anchor="middle" x="412" y="-53.4" font-family="Times,serif" font-size="14.00">with Identiy Status</text> +</g> +<!-- Service->AuthComp --> +<g id="edge7" class="edge"><title>Service->AuthComp</title> +<path fill="none" stroke="black" d="M495.062,-24.9037C486.397,-21.2187 477.064,-17.9304 468,-16 419.314,-5.63183 404.743,-5.9037 356,-16 349.891,-17.2653 343.655,-19.116 337.566,-21.2803"/> +<polygon fill="black" stroke="black" points="336.234,-18.0426 328.158,-24.9003 338.748,-24.5757 336.234,-18.0426"/> +<text text-anchor="middle" x="412" y="-33.4" font-family="Times,serif" font-size="14.00">Send Response OR</text> +<text text-anchor="middle" x="412" y="-18.4" font-family="Times,serif" font-size="14.00">Reject Message</text> +</g> +<!-- Start --> +<!-- Start->AuthComp --> +<g id="edge9" class="edge"><title>Start->AuthComp</title> +<path fill="none" stroke="black" d="M59.0178,-20.8384C99.2135,-25.0613 175.782,-33.1055 229.492,-38.7482"/> +<polygon fill="black" stroke="black" points="229.265,-42.2435 239.576,-39.8076 229.997,-35.2818 229.265,-42.2435"/> +</g> +</g> +</svg> diff --git a/doc/source/middlewarearchitecture.rst b/doc/source/middlewarearchitecture.rst new file mode 100644 index 0000000..59a6db0 --- /dev/null +++ b/doc/source/middlewarearchitecture.rst @@ -0,0 +1,309 @@ +.. + Copyright 2011-2012 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 Architecture +======================= + +Abstract +======== + +The Keystone middleware architecture supports a common authentication protocol +in use between the OpenStack projects. By using keystone as a common +authentication and authorization mechanisms, the OpenStack project can plug in +to existing authentication and authorization systems in use by existing +environments. + +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. + +For the architecture of keystone and its services, please see +:doc:`architecture`. This documentation primarily describes the implementation +in ``keystoneclient/middleware/auth_token.py`` +(:py:class:`keystoneclient.middleware.auth_token.AuthProtocol`) + +Specification Overview +====================== + +'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. OpenStack is +using a token based mechanism to represent authentication and authorization. + +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 + * in invalid, or not 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. + +.. _authComponent: + +Authentication Component +------------------------ + +Figure 1. Authentication Component + +.. image:: images/graphs_authComp.svg + :width: 100% + :height: 180 + :alt: An Authentication Component + +The middleware may also be configured to operated in a 'delegated mode'. +In this mode, the decision reject an unauthenticated client is delegated to +the OpenStack service, as illustrated in :ref:`authComponentDelegated`. + +Here, requests are forwarded to the OpenStack service with an identity status +message that indicates whether the client's identity has been confirmed or is +indeterminate. It is the OpenStack service that decides whether or not a reject +message should be sent to the client. + +.. _authComponentDelegated: + +Authentication Component (Delegated Mode) +----------------------------------------- + +Figure 2. Authentication Component (Delegated Mode) + +.. image:: images/graphs_authCompDelegate.svg + :width: 100% + :height: 180 + :alt: An Authentication Component (Delegated Mode) + +.. _deployStrategies: + +Deployment Strategy +=================== + +The middleware is intended to be used inline with OpenStack wsgi components, +based on the openstack-common 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. + +Configuration +------------- + +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 = tokenauth myService + + [filter:tokenauth] + paste.filter_factory = keystone.middleware.auth_token:filter_factory + auth_host = 127.0.0.1 + auth_port = 35357 + auth_protocol = http + auth_uri = http://127.0.0.1:5000/ + admin_token = Super999Sekret888Password777 + admin_user = admin + admin_password = SuperSekretPassword + admin_tenant_name = service + ;Uncomment next line to use Swift MemcacheRing + ;cache = swift.cache + ;Uncomment next line and check ip:port to use memcached to cache tokens + ;memcache_servers = 127.0.0.1:11211 + ;Uncomment next 2 lines to turn on memcache protection + ;memcache_security_strategy = ENCRYPT + ;memcache_secret_key = change_me + ;Uncomment next 2 lines if Keystone server is validating client cert + ;certfile = <path to middleware public cert> + ;keyfile = <path to middleware private cert> + +For services which have 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 +from api-paste.ini:: + + [filter:authtoken] + paste.filter_factory = keystone.middleware.auth_token:filter_factory + +and set in nova.conf:: + + [DEFAULT] + ... + auth_strategy=keystone + + [keystone_authtoken] + auth_host = 127.0.0.1 + auth_port = 35357 + auth_protocol = http + auth_uri = http://127.0.0.1:5000/ + admin_user = admin + admin_password = SuperSekretPassword + admin_tenant_name = service + +Note that middleware parameters in paste config take priority, they must be +removed to use values in [keystone_authtoken] section. + +Configuration Options +--------------------- + +* ``auth_host``: (required) the host providing the keystone service API endpoint + for validating and requesting tokens +* ``admin_token``: either this or the following three options are required. If + set, this is a single shared secret with the keystone configuration used to + validate tokens. +* ``admin_user``, ``admin_password``, ``admin_tenant_name``: if ``admin_token`` + is not set, or invalid, then admin_user, admin_password, and + admin_tenant_name are defined as a service account which is expected to have + been previously configured in Keystone to validate user tokens. + +* ``delay_auth_decision``: (optional, default `0`) (off). If on, the middleware + will not reject invalid auth requests, but will delegate that decision to + downstream WSGI components. +* ``auth_port``: (optional, default `35357`) the port used to validate tokens +* ``auth_protocol``: (optional, default `https`) +* ``auth_uri``: (optional, defaults to `auth_protocol`://`auth_host`:`auth_port`) +* ``certfile``: (required, if Keystone server requires client cert) +* ``keyfile``: (required, if Keystone server requires client cert) This can be + the same as the certfile if the certfile includes the private key. + +Caching for improved response +----------------------------- + +In order to prevent every service request, the middleware may be configured +to utilize a cache, and the keystone API returns the tokens with an +expiration (configurable in duration on the keystone service). The middleware +supports memcache based caching. + +* ``memcache_servers``: (optonal) if defined, the memcache server(s) to use for + cacheing. It will be ignored if Swift MemcacheRing is used instead. +* ``token_cache_time``: (optional, default 300 seconds) Only valid if + memcache_servers is defined. + +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 +provide the ``cache`` option. + +* ``cache``: (optional) if defined, the environment key where the Swift + MemcacheRing object is stored. + +Memcached and System Time +========================= + +When using `memcached`_ with ``auth_token`` middleware, ensure that the system +time of memcached hosts is set to UTC. Memcached uses the host's system +time in determining whether a key has expired, whereas Keystone sets +key expiry in UTC. The timezone used by Keystone and memcached must +match if key expiry is to behave as expected. + +.. _`memcached`: http://memcached.org/ + +Memcache Protection +=================== + +When using memcached, we are storing user tokens and token validation +information into the cache as raw data. Which means anyone who have access +to the memcache servers can read and modify data stored there. To mitigate +this risk, ``auth_token`` middleware provides an option to either encrypt +or authenticate the token data stored in the cache. + +* ``memcache_security_strategy``: (optional) if defined, indicate whether token + data should be encrypted or authenticated. Acceptable values are ``ENCRYPT`` + or ``MAC``. If ``ENCRYPT``, token data is encrypted in the cache. If + ``MAC``, token data is authenticated (with HMAC) in the cache. If its value + is neither ``MAC`` nor ``ENCRYPT``, ``auth_token`` will raise an exception + on initialization. +* ``memcache_secret_key``: (optional, mandatory if + ``memcache_security_strategy`` is defined) if defined, + a random string to be used for key derivation. If + ``memcache_security_strategy`` is defined and ``memcache_secret_key`` is + absent, ``auth_token`` will raise an exception on initialization. + +Exchanging User Information +=========================== + +The middleware expects to find a token representing the user with the header +``X-Auth-Token`` or ``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 auth_uri returned is configured with the middleware. + +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 +unsuccessful. + +Extended the request with additional User Information +----------------------------------------------------- + +:py:class:`keystone.middleware.auth_token.AuthProtocol` extends the request +with additional information if the user has been authenticated. + + +X-Identity-Status + Provides information on whether the request was authenticated or not. + +X-Tenant-Id + The unique, immutable tenant Id + +X-Tenant-Name + The unique, but mutable (it can change) tenant name. + +X-User-Id + The user id of the user used to log in + +X-User-Name + The username used to log in + +X-Roles + The roles associated with that user + +Deprecated additions +-------------------- + +X-Tenant + Provides the tenant name. This is to support any legacy implementations + before Keystone switched to an ID/Name schema for tenants. + +X-User + The username used to log in. This is to support any legacy implementations + before Keystone switched to an ID/Name schema for tenants. + +X-Role + The roles associated with that user + +References +========== + +.. [PEP-333] pep0333 Phillip J Eby. 'Python Web Server Gateway Interface + v1.0.'' http://www.python.org/dev/peps/pep-0333/. |
