Updated proxy-server.conf-sample with the correct default. Also updated the note on the overview-auth doc page. Change-Id: I5cd62a7a118a28f7b58f47b8d8d4d963f6bc7347
11 KiB
The Auth System
TempAuth
The auth system for Swift is loosely based on the auth system from the existing Rackspace architecture -- actually from a few existing auth systems -- and is therefore a bit disjointed. The distilled points about it are:
- The authentication/authorization part can be an external system or a subsystem run within Swift as WSGI middleware
- The user of Swift passes in an auth token with each request
- Swift validates each token with the external auth system or auth subsystem and caches the result
- The token does not change from request to request, but does expire
The token can be passed into Swift using the X-Auth-Token or the X-Storage-Token header. Both have the same format: just a simple string representing the token. Some auth systems use UUID tokens, some an MD5 hash of something unique, some use "something else" but the salient point is that the token is a string which can be sent as-is back to the auth system for validation.
Swift will make calls to the auth system, giving the auth token to be validated. For a valid token, the auth system responds with an overall expiration in seconds from now. Swift will cache the token up to the expiration time.
The included TempAuth also has the concept of admin and non-admin
users within an account. Admin users can do anything within the account.
Non-admin users can only perform operations per container based on the
container's X-Container-Read and X-Container-Write ACLs. Container ACLs
use the "V1" ACL syntax, which looks like this:
name1, name2, .r:referrer1.com, .r:-bad.referrer1.com, .rlistings
For more information on ACLs, see swift.common.middleware.acl
.
Additionally, if the auth system sets the request environ's swift_owner key to True, the proxy will return additional header information in some requests, such as the X-Container-Sync-Key for a container GET or HEAD.
In addition to container ACLs, TempAuth allows account-level ACLs.
Any auth system may use the special header
X-Account-Access-Control
to specify account-level ACLs in a
format specific to that auth system. (Following the TempAuth format is
strongly recommended.) These headers are visible and settable only by
account owners (those for whom swift_owner
is true).
Behavior of account ACLs is auth-system-dependent. In the case of
TempAuth, if an authenticated user has membership in a group which is
listed in the ACL, then the user is allowed the access level of that
ACL.
Account ACLs use the "V2" ACL syntax, which is a JSON dictionary with
keys named "admin", "read-write", and "read-only". (Note the case
sensitivity.) An example value for the
X-Account-Access-Control
header looks like this:
{"admin":["a","b"],"read-only":["c"]}
Keys may be absent
(as shown). The recommended way to generate ACL strings is as
follows:
from swift.common.middleware.acl import format_acl
acl_data = { 'admin': ['alice'], 'read-write': ['bob', 'carol'] }
acl_string = format_acl(version=2, acl_dict=acl_data)
Using the format_acl
method will ensure that JSON is encoded as
ASCII (using e.g. 'u1234' for Unicode). While it's permissible to
manually send curl
commands containing
X-Account-Access-Control
headers, you should exercise
caution when doing so, due to the potential for human error.
Within the JSON dictionary stored in
X-Account-Access-Control
, the keys have the following
meanings:
Access Level | Description |
---|---|
read-only |
These identities can read everything (except privileged headers) in the account. Specifically, a user with read-only account access can get a list of containers in the account, list the contents of any container, retrieve any object, and see the (non-privileged) headers of the account, any container, or any object. |
read-write |
These identities can read or write (or create) any container. A user with read-write account access can create new containers, set any unprivileged container headers, overwrite objects, delete containers, etc. A read-write user can NOT set account headers (or perform any PUT/POST/DELETE requests on the account). |
admin |
These identities have "swift_owner" privileges. A user with admin account access can do anything the account owner can, including setting account headers and any privileged headers -- and thus granting read-only, read-write, or admin access to other users. |
For more details, see swift.common.middleware.tempauth
. For details on the
ACL format, see swift.common.middleware.acl
.
Users with the special group .reseller_admin
can operate
on any account. For an example usage please see swift.common.middleware.tempauth
. If a request is
coming from a reseller the auth system sets the request environ
reseller_request to True. This can be used by other middlewares.
TempAuth will now allow OPTIONS requests to go through without a token.
The user starts a session by sending a ReST request to the auth system to receive the auth token and a URL to the Swift system.
Keystone Auth
Swift is able to authenticate against OpenStack Keystone via
the keystoneauth
middleware.
In order to use the keystoneauth
middleware the
auth_token
middleware from KeystoneMiddleware
will need to be configured.
The authtoken
middleware performs the authentication
token validation and retrieves actual user authentication information.
It can be found in the KeystoneMiddleware
distribution.
The keystoneauth
middleware performs authorization and mapping the Keystone roles to
Swift's ACLs.
Configuring Swift to use Keystone
Configuring Swift to use Keystone is
relatively straight forward. The first step is to ensure that you have
the auth_token
middleware installed. It can either be
dropped in your python path or installed via the KeystoneMiddleware
package.
You need at first make sure you have a service endpoint of type
object-store
in Keystone pointing to your Swift proxy. For
example having this in your
/etc/keystone/default_catalog.templates
:
catalog.RegionOne.object_store.name = Swift Service
catalog.RegionOne.object_store.publicURL = http://swiftproxy:8080/v1/AUTH_$(tenant_id)s
catalog.RegionOne.object_store.adminURL = http://swiftproxy:8080/
catalog.RegionOne.object_store.internalURL = http://swiftproxy:8080/v1/AUTH_$(tenant_id)s
On your Swift Proxy server you will want to adjust your main pipeline
and add auth_token and keystoneauth in your
/etc/swift/proxy-server.conf
like this :
[pipeline:main]
pipeline = [....] authtoken keystoneauth proxy-logging proxy-server
add the configuration for the authtoken middleware:
[filter:authtoken]
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
identity_uri = http://keystonehost:35357/
admin_tenant_name = service
admin_user = swift
admin_password = password
auth_uri = http://keystonehost:5000/
cache = swift.cache
include_service_catalog = False
delay_auth_decision = True
The actual values for these variables will need to be set depending on your situation, but in short:
identity_uri
points to the Keystone Admin service. This information is used by the middleware to actually query Keystone about the validity of the authentication tokens. It is not necessary to append any Keystone API version number to this URI.- The admin auth credentials (
admin_user
,admin_tenant_name
,admin_password
) will be used to retrieve an admin token. That token will be used to authorize user tokens behind the scenes. auth_uri
should point to a Keystone service from which users may retrieve tokens. This value is used in the WWW-Authenticate header that auth_token sends with any denial response.cache
is set toswift.cache
. This means that the middleware will get the Swift memcache from the request environment.include_service_catalog
defaults toTrue
if not set. This means that when validating a token, the service catalog is retrieved and stored in theX-Service-Catalog
header. Since Swift does not use theX-Service-Catalog
header, there is no point in getting the service catalog. We recommend you setinclude_service_catalog
toFalse
.
Note
The authtoken config variable delay_auth_decision
must
be set to True
. The default is False
, but that
breaks public access, staticweb
, formpost
, tempurl
, and authenticated capabilities requests
(using discoverability
).
and you can finally add the keystoneauth configuration:
[filter:keystoneauth]
use = egg:swift#keystoneauth
operator_roles = admin, swiftoperator
Access control using keystoneauth
By default the only users able to perform operations (e.g. create a
container) on an account are those having a Keystone role for the
corresponding Keystone project that matches one of the roles specified
in the operator_roles
option.
Users who have one of the operator_roles
will be able to
set container ACLs to grant other users permission to read and/or write
objects in specific containers, using X-Container-Read
and
X-Container-Write
headers respectively. In addition to the
ACL formats described here <swift.common.middleware.acl>
, keystoneauth
supports ACLs using the format:
other_project_id:other_user_id.
where other_project_id
is the UUID of a Keystone project
and other_user_id
is the UUID of a Keystone user. This will
allow the other user to access a container provided their token is
scoped on the other project. Both other_project_id
and
other_user_id
may be replaced with the wildcard character
*
which will match any project or user respectively.
Be sure to use Keystone UUIDs rather than names in container ACLs.
Note
For backwards compatibility, keystoneauth will by default grant
container ACLs expressed as
other_project_name:other_user_name
(i.e. using Keystone
names rather than UUIDs) in the special case when both the other project
and the other user are in Keystone's default domain and the project
being accessed is also in the default domain.
For further information see keystoneauth
Users with the Keystone role defined in
reseller_admin_role
(ResellerAdmin
by default)
can operate on any account. The auth system sets the request environ
reseller_request to True if a request is coming from a user with this
role. This can be used by other middlewares.
Extending Auth
TempAuth is written as wsgi middleware, so implementing your own auth is as easy as writing new wsgi middleware, and plugging it in to the proxy server. The KeyStone project and the Swauth project are examples of additional auth services.
Also, see development_auth
.