2010-07-12 17:03:45 -05:00
|
|
|
===============
|
|
|
|
The Auth System
|
|
|
|
===============
|
|
|
|
|
2011-05-26 02:17:42 +00:00
|
|
|
--------
|
2011-05-26 02:24:12 +00:00
|
|
|
TempAuth
|
2011-05-26 02:17:42 +00:00
|
|
|
--------
|
2010-07-23 17:15:29 -05:00
|
|
|
|
2010-09-05 20:30:09 -07:00
|
|
|
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:
|
2010-07-12 17:03:45 -05:00
|
|
|
|
2011-03-14 02:56:37 +00:00
|
|
|
* The authentication/authorization part can be an external system or a
|
|
|
|
subsystem run within Swift as WSGI middleware
|
2010-07-12 17:03:45 -05:00
|
|
|
* The user of Swift passes in an auth token with each request
|
2011-03-14 02:56:37 +00:00
|
|
|
* Swift validates each token with the external auth system or auth subsystem
|
|
|
|
and caches the result
|
2010-07-12 17:03:45 -05:00
|
|
|
* 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
|
2011-03-14 02:56:37 +00:00
|
|
|
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
|
2010-07-12 17:03:45 -05:00
|
|
|
validation.
|
|
|
|
|
2011-03-14 02:56:37 +00:00
|
|
|
Swift will make calls to the auth system, giving the auth token to be
|
2010-09-05 20:30:09 -07:00
|
|
|
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
|
2011-07-08 19:57:45 +00:00
|
|
|
time.
|
|
|
|
|
Privileged acct ACL header, new ACL syntax, TempAuth impl.
* Introduce a new privileged account header: X-Account-Access-Control
* Introduce JSON-based version 2 ACL syntax -- see below for discussion
* Implement account ACL authorization in TempAuth
X-Account-Access-Control Header
-------------------------------
Accounts now have a new privileged header to represent ACLs or any other
form of account-level access control. The value of the header is an opaque
string to be interpreted by the auth system, but it must be a JSON-encoded
dictionary. A reference implementation is given in TempAuth, with the
knowledge that historically other auth systems often use TempAuth as a
starting point.
The reference implementation describes three levels of account access:
"admin", "read-write", and "read-only". Adding new access control
features in a future patch (e.g. "write-only" account access) will
automatically be forward- and backward-compatible, due to the JSON
dictionary header format.
The privileged X-Account-Access-Control header may only be read or written
by a user with "swift_owner" status, traditionally the account owner but
now also any user on the "admin" ACL.
Access Levels:
Read-only access is intended to indicate to the auth system that this
list of 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 access is intended to indicate to the auth system that this
list of 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 access is intended to indicate to the auth system that this list of
identities has "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 changing the value of
X-Account-Access-Control and thereby granting read-only, read-write, or
admin access to other users.
The auth system is responsible for making decisions based on this header,
if it chooses to support its use. Therefore the above access level
descriptions are necessarily advisory only for other auth systems.
When setting the value of the header, callers are urged to use the new
format_acl() method, described below.
New ACL Format
--------------
The account ACLs introduce a new format for ACLs, rather than reusing the
existing format from X-Container-Read/X-Container-Write. There are several
reasons for this:
* Container ACL format does not support Unicode
* Container ACLs have a different structure than account ACLs
+ account ACLs have no concept of referrers or rlistings
+ accounts have additional "admin" access level
+ account access levels are structured as admin > rw > ro, which seems more
appropriate for how people access accounts, rather than reusing
container ACLs' orthogonal read and write access
In addition, the container ACL syntax is a bit arbitrary and highly custom,
so instead of parsing additional custom syntax, I'd rather propose a next
version and introduce a means for migration. The V2 ACL syntax has the
following benefits:
* JSON is a well-known standard syntax with parsers in all languages
* no artificial value restrictions (you can grant access to a user named
".rlistings" if you want)
* forward and backward compatibility: you may have extraneous keys, but
your attempt to parse the header won't raise an exception
I've introduced hooks in parse_acl and format_acl which currently default
to the old V1 syntax but tolerate the V2 syntax and can easily be flipped
to default to V2. I'm not changing the default or adding code to rewrite
V1 ACLs to V2, because this patch has suffered a lot of scope creep already,
but this seems like a sensible milestone in the migration.
TempAuth Account ACL Implementation
-----------------------------------
As stated above, core Swift is responsible for privileging the
X-Account-Access-Control header (making it only accessible to swift_owners),
for translating it to -sysmeta-* headers to trigger persistence by the
account server, and for including the header in the responses to requests
by privileged users. Core Swift puts no expectation on the *content* of
this header. Auth systems (including TempAuth) are responsible for
defining the content of the header and taking action based on it.
In addition to the changes described above, this patch defines a format
to be used by TempAuth for these headers in the common.middleware.acl
module, in the methods format_v2_acl() and parse_v2_acl(). This patch
also teaches TempAuth to take action based on the header contents. TempAuth
now sets swift_owner=True if the user is on the Admin ACL, authorizes
GET/HEAD/OPTIONS requests if the user is on any ACL, authorizes
PUT/POST/DELETE requests if the user is on the admin or read-write ACL, etc.
Note that the action of setting swift_owner=True triggers core Swift to
add or strip the privileged headers from the responses. Core Swift (not
the auth system) is responsible for that.
DocImpact: Documentation for the new ACL usage and format appears in
summary form in doc/source/overview_auth.rst, and in more detail in
swift/common/middleware/tempauth.py in the TempAuth class docstring.
I leave it to the Swift doc team to determine whether more is needed.
Change-Id: I836a99eaaa6bb0e92dc03e1ca46a474522e6e826
2013-11-13 20:55:14 +00:00
|
|
|
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 :mod:`swift.common.middleware.acl`.
|
2011-07-08 19:57:45 +00:00
|
|
|
|
|
|
|
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.
|
2010-07-23 17:15:29 -05:00
|
|
|
|
Privileged acct ACL header, new ACL syntax, TempAuth impl.
* Introduce a new privileged account header: X-Account-Access-Control
* Introduce JSON-based version 2 ACL syntax -- see below for discussion
* Implement account ACL authorization in TempAuth
X-Account-Access-Control Header
-------------------------------
Accounts now have a new privileged header to represent ACLs or any other
form of account-level access control. The value of the header is an opaque
string to be interpreted by the auth system, but it must be a JSON-encoded
dictionary. A reference implementation is given in TempAuth, with the
knowledge that historically other auth systems often use TempAuth as a
starting point.
The reference implementation describes three levels of account access:
"admin", "read-write", and "read-only". Adding new access control
features in a future patch (e.g. "write-only" account access) will
automatically be forward- and backward-compatible, due to the JSON
dictionary header format.
The privileged X-Account-Access-Control header may only be read or written
by a user with "swift_owner" status, traditionally the account owner but
now also any user on the "admin" ACL.
Access Levels:
Read-only access is intended to indicate to the auth system that this
list of 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 access is intended to indicate to the auth system that this
list of 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 access is intended to indicate to the auth system that this list of
identities has "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 changing the value of
X-Account-Access-Control and thereby granting read-only, read-write, or
admin access to other users.
The auth system is responsible for making decisions based on this header,
if it chooses to support its use. Therefore the above access level
descriptions are necessarily advisory only for other auth systems.
When setting the value of the header, callers are urged to use the new
format_acl() method, described below.
New ACL Format
--------------
The account ACLs introduce a new format for ACLs, rather than reusing the
existing format from X-Container-Read/X-Container-Write. There are several
reasons for this:
* Container ACL format does not support Unicode
* Container ACLs have a different structure than account ACLs
+ account ACLs have no concept of referrers or rlistings
+ accounts have additional "admin" access level
+ account access levels are structured as admin > rw > ro, which seems more
appropriate for how people access accounts, rather than reusing
container ACLs' orthogonal read and write access
In addition, the container ACL syntax is a bit arbitrary and highly custom,
so instead of parsing additional custom syntax, I'd rather propose a next
version and introduce a means for migration. The V2 ACL syntax has the
following benefits:
* JSON is a well-known standard syntax with parsers in all languages
* no artificial value restrictions (you can grant access to a user named
".rlistings" if you want)
* forward and backward compatibility: you may have extraneous keys, but
your attempt to parse the header won't raise an exception
I've introduced hooks in parse_acl and format_acl which currently default
to the old V1 syntax but tolerate the V2 syntax and can easily be flipped
to default to V2. I'm not changing the default or adding code to rewrite
V1 ACLs to V2, because this patch has suffered a lot of scope creep already,
but this seems like a sensible milestone in the migration.
TempAuth Account ACL Implementation
-----------------------------------
As stated above, core Swift is responsible for privileging the
X-Account-Access-Control header (making it only accessible to swift_owners),
for translating it to -sysmeta-* headers to trigger persistence by the
account server, and for including the header in the responses to requests
by privileged users. Core Swift puts no expectation on the *content* of
this header. Auth systems (including TempAuth) are responsible for
defining the content of the header and taking action based on it.
In addition to the changes described above, this patch defines a format
to be used by TempAuth for these headers in the common.middleware.acl
module, in the methods format_v2_acl() and parse_v2_acl(). This patch
also teaches TempAuth to take action based on the header contents. TempAuth
now sets swift_owner=True if the user is on the Admin ACL, authorizes
GET/HEAD/OPTIONS requests if the user is on any ACL, authorizes
PUT/POST/DELETE requests if the user is on the admin or read-write ACL, etc.
Note that the action of setting swift_owner=True triggers core Swift to
add or strip the privileged headers from the responses. Core Swift (not
the auth system) is responsible for that.
DocImpact: Documentation for the new ACL usage and format appears in
summary form in doc/source/overview_auth.rst, and in more detail in
swift/common/middleware/tempauth.py in the TempAuth class docstring.
I leave it to the Swift doc team to determine whether more is needed.
Change-Id: I836a99eaaa6bb0e92dc03e1ca46a474522e6e826
2013-11-13 20:55:14 +00:00
|
|
|
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 :func:`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
|
2014-02-23 10:22:34 -08:00
|
|
|
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.
|
Privileged acct ACL header, new ACL syntax, TempAuth impl.
* Introduce a new privileged account header: X-Account-Access-Control
* Introduce JSON-based version 2 ACL syntax -- see below for discussion
* Implement account ACL authorization in TempAuth
X-Account-Access-Control Header
-------------------------------
Accounts now have a new privileged header to represent ACLs or any other
form of account-level access control. The value of the header is an opaque
string to be interpreted by the auth system, but it must be a JSON-encoded
dictionary. A reference implementation is given in TempAuth, with the
knowledge that historically other auth systems often use TempAuth as a
starting point.
The reference implementation describes three levels of account access:
"admin", "read-write", and "read-only". Adding new access control
features in a future patch (e.g. "write-only" account access) will
automatically be forward- and backward-compatible, due to the JSON
dictionary header format.
The privileged X-Account-Access-Control header may only be read or written
by a user with "swift_owner" status, traditionally the account owner but
now also any user on the "admin" ACL.
Access Levels:
Read-only access is intended to indicate to the auth system that this
list of 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 access is intended to indicate to the auth system that this
list of 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 access is intended to indicate to the auth system that this list of
identities has "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 changing the value of
X-Account-Access-Control and thereby granting read-only, read-write, or
admin access to other users.
The auth system is responsible for making decisions based on this header,
if it chooses to support its use. Therefore the above access level
descriptions are necessarily advisory only for other auth systems.
When setting the value of the header, callers are urged to use the new
format_acl() method, described below.
New ACL Format
--------------
The account ACLs introduce a new format for ACLs, rather than reusing the
existing format from X-Container-Read/X-Container-Write. There are several
reasons for this:
* Container ACL format does not support Unicode
* Container ACLs have a different structure than account ACLs
+ account ACLs have no concept of referrers or rlistings
+ accounts have additional "admin" access level
+ account access levels are structured as admin > rw > ro, which seems more
appropriate for how people access accounts, rather than reusing
container ACLs' orthogonal read and write access
In addition, the container ACL syntax is a bit arbitrary and highly custom,
so instead of parsing additional custom syntax, I'd rather propose a next
version and introduce a means for migration. The V2 ACL syntax has the
following benefits:
* JSON is a well-known standard syntax with parsers in all languages
* no artificial value restrictions (you can grant access to a user named
".rlistings" if you want)
* forward and backward compatibility: you may have extraneous keys, but
your attempt to parse the header won't raise an exception
I've introduced hooks in parse_acl and format_acl which currently default
to the old V1 syntax but tolerate the V2 syntax and can easily be flipped
to default to V2. I'm not changing the default or adding code to rewrite
V1 ACLs to V2, because this patch has suffered a lot of scope creep already,
but this seems like a sensible milestone in the migration.
TempAuth Account ACL Implementation
-----------------------------------
As stated above, core Swift is responsible for privileging the
X-Account-Access-Control header (making it only accessible to swift_owners),
for translating it to -sysmeta-* headers to trigger persistence by the
account server, and for including the header in the responses to requests
by privileged users. Core Swift puts no expectation on the *content* of
this header. Auth systems (including TempAuth) are responsible for
defining the content of the header and taking action based on it.
In addition to the changes described above, this patch defines a format
to be used by TempAuth for these headers in the common.middleware.acl
module, in the methods format_v2_acl() and parse_v2_acl(). This patch
also teaches TempAuth to take action based on the header contents. TempAuth
now sets swift_owner=True if the user is on the Admin ACL, authorizes
GET/HEAD/OPTIONS requests if the user is on any ACL, authorizes
PUT/POST/DELETE requests if the user is on the admin or read-write ACL, etc.
Note that the action of setting swift_owner=True triggers core Swift to
add or strip the privileged headers from the responses. Core Swift (not
the auth system) is responsible for that.
DocImpact: Documentation for the new ACL usage and format appears in
summary form in doc/source/overview_auth.rst, and in more detail in
swift/common/middleware/tempauth.py in the TempAuth class docstring.
I leave it to the Swift doc team to determine whether more is needed.
Change-Id: I836a99eaaa6bb0e92dc03e1ca46a474522e6e826
2013-11-13 20:55:14 +00:00
|
|
|
read-write These identities can read or write (or create) any container.
|
|
|
|
A user with read-write account access can create new
|
2014-02-23 10:22:34 -08:00
|
|
|
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).
|
Privileged acct ACL header, new ACL syntax, TempAuth impl.
* Introduce a new privileged account header: X-Account-Access-Control
* Introduce JSON-based version 2 ACL syntax -- see below for discussion
* Implement account ACL authorization in TempAuth
X-Account-Access-Control Header
-------------------------------
Accounts now have a new privileged header to represent ACLs or any other
form of account-level access control. The value of the header is an opaque
string to be interpreted by the auth system, but it must be a JSON-encoded
dictionary. A reference implementation is given in TempAuth, with the
knowledge that historically other auth systems often use TempAuth as a
starting point.
The reference implementation describes three levels of account access:
"admin", "read-write", and "read-only". Adding new access control
features in a future patch (e.g. "write-only" account access) will
automatically be forward- and backward-compatible, due to the JSON
dictionary header format.
The privileged X-Account-Access-Control header may only be read or written
by a user with "swift_owner" status, traditionally the account owner but
now also any user on the "admin" ACL.
Access Levels:
Read-only access is intended to indicate to the auth system that this
list of 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 access is intended to indicate to the auth system that this
list of 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 access is intended to indicate to the auth system that this list of
identities has "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 changing the value of
X-Account-Access-Control and thereby granting read-only, read-write, or
admin access to other users.
The auth system is responsible for making decisions based on this header,
if it chooses to support its use. Therefore the above access level
descriptions are necessarily advisory only for other auth systems.
When setting the value of the header, callers are urged to use the new
format_acl() method, described below.
New ACL Format
--------------
The account ACLs introduce a new format for ACLs, rather than reusing the
existing format from X-Container-Read/X-Container-Write. There are several
reasons for this:
* Container ACL format does not support Unicode
* Container ACLs have a different structure than account ACLs
+ account ACLs have no concept of referrers or rlistings
+ accounts have additional "admin" access level
+ account access levels are structured as admin > rw > ro, which seems more
appropriate for how people access accounts, rather than reusing
container ACLs' orthogonal read and write access
In addition, the container ACL syntax is a bit arbitrary and highly custom,
so instead of parsing additional custom syntax, I'd rather propose a next
version and introduce a means for migration. The V2 ACL syntax has the
following benefits:
* JSON is a well-known standard syntax with parsers in all languages
* no artificial value restrictions (you can grant access to a user named
".rlistings" if you want)
* forward and backward compatibility: you may have extraneous keys, but
your attempt to parse the header won't raise an exception
I've introduced hooks in parse_acl and format_acl which currently default
to the old V1 syntax but tolerate the V2 syntax and can easily be flipped
to default to V2. I'm not changing the default or adding code to rewrite
V1 ACLs to V2, because this patch has suffered a lot of scope creep already,
but this seems like a sensible milestone in the migration.
TempAuth Account ACL Implementation
-----------------------------------
As stated above, core Swift is responsible for privileging the
X-Account-Access-Control header (making it only accessible to swift_owners),
for translating it to -sysmeta-* headers to trigger persistence by the
account server, and for including the header in the responses to requests
by privileged users. Core Swift puts no expectation on the *content* of
this header. Auth systems (including TempAuth) are responsible for
defining the content of the header and taking action based on it.
In addition to the changes described above, this patch defines a format
to be used by TempAuth for these headers in the common.middleware.acl
module, in the methods format_v2_acl() and parse_v2_acl(). This patch
also teaches TempAuth to take action based on the header contents. TempAuth
now sets swift_owner=True if the user is on the Admin ACL, authorizes
GET/HEAD/OPTIONS requests if the user is on any ACL, authorizes
PUT/POST/DELETE requests if the user is on the admin or read-write ACL, etc.
Note that the action of setting swift_owner=True triggers core Swift to
add or strip the privileged headers from the responses. Core Swift (not
the auth system) is responsible for that.
DocImpact: Documentation for the new ACL usage and format appears in
summary form in doc/source/overview_auth.rst, and in more detail in
swift/common/middleware/tempauth.py in the TempAuth class docstring.
I leave it to the Swift doc team to determine whether more is needed.
Change-Id: I836a99eaaa6bb0e92dc03e1ca46a474522e6e826
2013-11-13 20:55:14 +00:00
|
|
|
admin These identities have "swift_owner" privileges. A user with
|
|
|
|
admin account access can do anything the account owner can,
|
2014-02-23 10:22:34 -08:00
|
|
|
including setting account headers and any privileged headers
|
|
|
|
-- and thus granting read-only, read-write, or admin access
|
|
|
|
to other users.
|
Privileged acct ACL header, new ACL syntax, TempAuth impl.
* Introduce a new privileged account header: X-Account-Access-Control
* Introduce JSON-based version 2 ACL syntax -- see below for discussion
* Implement account ACL authorization in TempAuth
X-Account-Access-Control Header
-------------------------------
Accounts now have a new privileged header to represent ACLs or any other
form of account-level access control. The value of the header is an opaque
string to be interpreted by the auth system, but it must be a JSON-encoded
dictionary. A reference implementation is given in TempAuth, with the
knowledge that historically other auth systems often use TempAuth as a
starting point.
The reference implementation describes three levels of account access:
"admin", "read-write", and "read-only". Adding new access control
features in a future patch (e.g. "write-only" account access) will
automatically be forward- and backward-compatible, due to the JSON
dictionary header format.
The privileged X-Account-Access-Control header may only be read or written
by a user with "swift_owner" status, traditionally the account owner but
now also any user on the "admin" ACL.
Access Levels:
Read-only access is intended to indicate to the auth system that this
list of 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 access is intended to indicate to the auth system that this
list of 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 access is intended to indicate to the auth system that this list of
identities has "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 changing the value of
X-Account-Access-Control and thereby granting read-only, read-write, or
admin access to other users.
The auth system is responsible for making decisions based on this header,
if it chooses to support its use. Therefore the above access level
descriptions are necessarily advisory only for other auth systems.
When setting the value of the header, callers are urged to use the new
format_acl() method, described below.
New ACL Format
--------------
The account ACLs introduce a new format for ACLs, rather than reusing the
existing format from X-Container-Read/X-Container-Write. There are several
reasons for this:
* Container ACL format does not support Unicode
* Container ACLs have a different structure than account ACLs
+ account ACLs have no concept of referrers or rlistings
+ accounts have additional "admin" access level
+ account access levels are structured as admin > rw > ro, which seems more
appropriate for how people access accounts, rather than reusing
container ACLs' orthogonal read and write access
In addition, the container ACL syntax is a bit arbitrary and highly custom,
so instead of parsing additional custom syntax, I'd rather propose a next
version and introduce a means for migration. The V2 ACL syntax has the
following benefits:
* JSON is a well-known standard syntax with parsers in all languages
* no artificial value restrictions (you can grant access to a user named
".rlistings" if you want)
* forward and backward compatibility: you may have extraneous keys, but
your attempt to parse the header won't raise an exception
I've introduced hooks in parse_acl and format_acl which currently default
to the old V1 syntax but tolerate the V2 syntax and can easily be flipped
to default to V2. I'm not changing the default or adding code to rewrite
V1 ACLs to V2, because this patch has suffered a lot of scope creep already,
but this seems like a sensible milestone in the migration.
TempAuth Account ACL Implementation
-----------------------------------
As stated above, core Swift is responsible for privileging the
X-Account-Access-Control header (making it only accessible to swift_owners),
for translating it to -sysmeta-* headers to trigger persistence by the
account server, and for including the header in the responses to requests
by privileged users. Core Swift puts no expectation on the *content* of
this header. Auth systems (including TempAuth) are responsible for
defining the content of the header and taking action based on it.
In addition to the changes described above, this patch defines a format
to be used by TempAuth for these headers in the common.middleware.acl
module, in the methods format_v2_acl() and parse_v2_acl(). This patch
also teaches TempAuth to take action based on the header contents. TempAuth
now sets swift_owner=True if the user is on the Admin ACL, authorizes
GET/HEAD/OPTIONS requests if the user is on any ACL, authorizes
PUT/POST/DELETE requests if the user is on the admin or read-write ACL, etc.
Note that the action of setting swift_owner=True triggers core Swift to
add or strip the privileged headers from the responses. Core Swift (not
the auth system) is responsible for that.
DocImpact: Documentation for the new ACL usage and format appears in
summary form in doc/source/overview_auth.rst, and in more detail in
swift/common/middleware/tempauth.py in the TempAuth class docstring.
I leave it to the Swift doc team to determine whether more is needed.
Change-Id: I836a99eaaa6bb0e92dc03e1ca46a474522e6e826
2013-11-13 20:55:14 +00:00
|
|
|
============ ==============================================================
|
|
|
|
|
|
|
|
|
|
|
|
For more details, see :mod:`swift.common.middleware.tempauth`. For details
|
|
|
|
on the ACL format, see :mod:`swift.common.middleware.acl`.
|
|
|
|
|
2013-03-08 19:33:27 +01:00
|
|
|
Users with the special group ``.reseller_admin`` can operate on any account.
|
|
|
|
For an example usage please see :mod:`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.
|
|
|
|
|
2012-10-11 16:52:26 -05:00
|
|
|
TempAuth will now allow OPTIONS requests to go through without a token.
|
|
|
|
|
2011-03-14 02:56:37 +00:00
|
|
|
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.
|
2010-07-23 17:15:29 -05:00
|
|
|
|
2012-06-20 16:37:30 +01:00
|
|
|
-------------
|
|
|
|
Keystone Auth
|
|
|
|
-------------
|
|
|
|
|
2014-09-10 16:09:13 +01:00
|
|
|
Swift is able to authenticate against OpenStack Keystone_ via the
|
|
|
|
:ref:`keystoneauth` middleware.
|
2012-06-20 16:37:30 +01:00
|
|
|
|
2014-09-10 16:09:13 +01:00
|
|
|
In order to use the ``keystoneauth`` middleware the ``auth_token``
|
|
|
|
middleware from KeystoneMiddleware_ will need to be configured.
|
2012-06-20 16:37:30 +01:00
|
|
|
|
|
|
|
The ``authtoken`` middleware performs the authentication token
|
|
|
|
validation and retrieves actual user authentication information. It
|
2014-09-10 16:09:13 +01:00
|
|
|
can be found in the KeystoneMiddleware_ distribution.
|
2012-06-20 16:37:30 +01:00
|
|
|
|
2014-09-10 16:09:13 +01:00
|
|
|
The :ref:`keystoneauth` middleware performs authorization and mapping the
|
|
|
|
Keystone roles to Swift's ACLs.
|
|
|
|
|
|
|
|
.. _KeystoneMiddleware: http://docs.openstack.org/developer/keystonemiddleware/
|
|
|
|
.. _Keystone: http://docs.openstack.org/developer/keystone/
|
2012-06-20 16:37:30 +01:00
|
|
|
|
|
|
|
Configuring Swift to use Keystone
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2014-09-10 16:09:13 +01:00
|
|
|
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.
|
2012-06-20 16:37:30 +01:00
|
|
|
|
|
|
|
You need at first make sure you have a service endpoint of type
|
2014-09-10 16:09:13 +01:00
|
|
|
``object-store`` in Keystone pointing to your Swift proxy. For example
|
2012-06-20 16:37:30 +01:00
|
|
|
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]
|
2014-07-23 10:27:40 -07:00
|
|
|
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
|
2015-02-03 11:57:06 +00:00
|
|
|
identity_uri = http://keystonehost:35357/
|
2012-06-20 16:37:30 +01:00
|
|
|
admin_tenant_name = service
|
|
|
|
admin_user = swift
|
|
|
|
admin_password = password
|
2015-02-03 11:57:06 +00:00
|
|
|
auth_uri = http://keystonehost:5000/
|
2013-02-21 22:58:27 +01:00
|
|
|
cache = swift.cache
|
2013-12-02 13:40:01 +00:00
|
|
|
include_service_catalog = False
|
2015-02-05 11:01:02 -08:00
|
|
|
delay_auth_decision = True
|
2012-06-20 16:37:30 +01:00
|
|
|
|
|
|
|
The actual values for these variables will need to be set depending on
|
2015-02-03 11:57:06 +00:00
|
|
|
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.
|
2012-06-20 16:37:30 +01:00
|
|
|
* 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.
|
2015-02-03 11:57:06 +00:00
|
|
|
* ``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.
|
2014-09-10 16:09:13 +01:00
|
|
|
* ``cache`` is set to ``swift.cache``. This means that the middleware
|
2013-12-02 13:40:01 +00:00
|
|
|
will get the Swift memcache from the request environment.
|
2014-09-10 16:09:13 +01:00
|
|
|
* ``include_service_catalog`` defaults to ``True`` if not set. This means
|
2013-12-02 13:40:01 +00:00
|
|
|
that when validating a token, the service catalog is retrieved
|
2014-09-10 16:09:13 +01:00
|
|
|
and stored in the ``X-Service-Catalog`` header. Since Swift does not
|
|
|
|
use the ``X-Service-Catalog`` header, there is no point in getting
|
|
|
|
the service catalog. We recommend you set ``include_service_catalog``
|
|
|
|
to ``False``.
|
2013-12-02 13:40:01 +00:00
|
|
|
|
2012-06-20 16:37:30 +01:00
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
2015-02-05 11:01:02 -08:00
|
|
|
The authtoken config variable ``delay_auth_decision`` must be set to
|
|
|
|
``True``. The default is ``False``, but that breaks public access,
|
|
|
|
:ref:`staticweb`, :ref:`formpost`, :ref:`tempurl`, and authenticated
|
|
|
|
capabilities requests (using :ref:`discoverability`).
|
2012-06-20 16:37:30 +01:00
|
|
|
|
2014-11-25 14:42:42 +00:00
|
|
|
and you can finally add the keystoneauth configuration. Here is a simple
|
|
|
|
configuration::
|
2012-06-20 16:37:30 +01:00
|
|
|
|
|
|
|
[filter:keystoneauth]
|
|
|
|
use = egg:swift#keystoneauth
|
|
|
|
operator_roles = admin, swiftoperator
|
|
|
|
|
2014-11-25 14:42:42 +00:00
|
|
|
Use an appropriate list of roles in operator_roles. For example, in
|
|
|
|
some systems, the role ``_member_`` or ``Member`` is used to indicate
|
|
|
|
that the user is allowed to operate on project resources.
|
|
|
|
|
|
|
|
OpenStack Service Using Composite Tokens
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
Some Openstack services such as Cinder and Glance may use
|
|
|
|
a "service account". In this mode, you configure a separate account where
|
|
|
|
the service stores project data that it manages. This account is not used
|
|
|
|
directly by the end-user. Instead, all access is done through the service.
|
|
|
|
|
|
|
|
To access the "service" account, the service must present two tokens: one from
|
|
|
|
the end-user and another from its own service user. Only when both tokens are
|
|
|
|
present can the account be accessed. This section describes how to set the
|
|
|
|
configuration options to correctly control access to both the "normal" and
|
|
|
|
"service" accounts.
|
|
|
|
|
|
|
|
In this example, end users use the ``AUTH_`` prefix in account names,
|
|
|
|
whereas services use the ``SERVICE_`` prefix::
|
|
|
|
|
|
|
|
[filter:keystoneauth]
|
|
|
|
use = egg:swift#keystoneauth
|
|
|
|
reseller_prefix = AUTH, SERVICE
|
|
|
|
operator_roles = admin, swiftoperator
|
|
|
|
SERVICE_service_roles = service
|
|
|
|
|
|
|
|
The actual values for these variable will need to be set depending on your
|
|
|
|
situation as follows:
|
|
|
|
|
|
|
|
* The first item in the reseller_prefix list must match Keystone's endpoint
|
|
|
|
(see ``/etc/keystone/default_catalog.templates`` above). Normally
|
|
|
|
this is ``AUTH``.
|
|
|
|
* The second item in the reseller_prefix list is the prefix used by the
|
|
|
|
Openstack services(s). You must configure this value (``SERVICE`` in the
|
|
|
|
example) with whatever the other Openstack service(s) use.
|
|
|
|
* Set the operator_roles option to contain a role or roles that end-user's
|
|
|
|
have on project's they use.
|
|
|
|
* Set the SERVICE_service_roles value to a role or roles that only the
|
|
|
|
Openstack service user has. Do not use a role that is assigned to
|
|
|
|
"normal" end users. In this example, the role ``service`` is used.
|
|
|
|
The service user is granted this role to a *single* project only. You do
|
|
|
|
not need to make the service user a member of every project.
|
|
|
|
|
|
|
|
This configuration works as follows:
|
|
|
|
|
|
|
|
* The end-user presents a user token to an Openstack service. The service
|
|
|
|
then makes a Swift request to the account with the ``SERVICE`` prefix.
|
|
|
|
* The service forwards the original user token with the request. It also
|
|
|
|
adds it's own service token.
|
|
|
|
* Swift validates both tokens. When validated, the user token gives the
|
|
|
|
``admin`` or ``swiftoperator`` role(s). When validated, the service token
|
|
|
|
gives the ``service`` role.
|
|
|
|
* Swift interprets the above configuration as follows:
|
2015-10-19 13:55:02 +01:00
|
|
|
|
2014-11-25 14:42:42 +00:00
|
|
|
* Did the user token provide one of the roles listed in operator_roles?
|
|
|
|
* Did the service token have the ``service`` role as described by the
|
|
|
|
``SERVICE_service_roles`` options.
|
2015-10-19 13:55:02 +01:00
|
|
|
|
2014-11-25 14:42:42 +00:00
|
|
|
* If both conditions are met, the request is granted. Otherwise, Swift
|
|
|
|
rejects the request.
|
|
|
|
|
|
|
|
In the above example, all services share the same account. You can separate
|
|
|
|
each service into its own account. For example, the following provides a
|
|
|
|
dedicated account for each of the Glance and Cinder services. In addition,
|
|
|
|
you must assign the ``glance_service`` and ``cinder_service`` to the
|
|
|
|
appropriate service users::
|
|
|
|
|
|
|
|
[filter:keystoneauth]
|
|
|
|
use = egg:swift#keystoneauth
|
|
|
|
reseller_prefix = AUTH, IMAGE, VOLUME
|
|
|
|
operator_roles = admin, swiftoperator
|
|
|
|
IMAGE_service_roles = glance_service
|
|
|
|
VOLUME_service_roles = cinder_service
|
|
|
|
|
|
|
|
|
2014-09-10 16:09:13 +01:00
|
|
|
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
|
|
|
|
:mod:`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.
|
2012-06-20 16:37:30 +01:00
|
|
|
|
2014-09-10 16:09:13 +01:00
|
|
|
For further information see :ref:`keystoneauth`
|
2012-06-20 16:37:30 +01:00
|
|
|
|
2013-03-08 19:33:27 +01:00
|
|
|
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
|
2014-05-26 16:05:42 -05:00
|
|
|
from a user with this role. This can be used by other middlewares.
|
2013-03-08 19:33:27 +01:00
|
|
|
|
2010-07-23 17:15:29 -05:00
|
|
|
--------------
|
|
|
|
Extending Auth
|
|
|
|
--------------
|
|
|
|
|
2011-05-26 02:24:12 +00:00
|
|
|
TempAuth is written as wsgi middleware, so implementing your own auth is as
|
2011-05-26 02:17:42 +00:00
|
|
|
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.
|
2010-07-23 17:15:29 -05:00
|
|
|
|
2010-09-05 20:30:09 -07:00
|
|
|
Also, see :doc:`development_auth`.
|