This work is licensed under a Creative Commons Attribution 3.0 Unported License. http://creativecommons.org/licenses/by/3.0/legalcode
This is a proposal for how Composite Tokens can be used by services such as Glance and Cinder to store objects in project-specific accounts yet retain control over how those objects are accessed.
This proposal uses the “Service Token Composite Authorization” support in the auth_token Keystone middleware (http://git.openstack.org/cgit/openstack/keystone-specs/plain/specs/keystonemiddleware/service-tokens.rst).
Swift is used by many OpenStack services to store data on behalf of users. There are typically two approaches to where the data is stored:
There are advantages and limitations with both approaches as described in the following table:
|Item||Feature/Topic||Single- Project||Multi- Project|
|1||Fragile to password leak (CVE-2013-1840)||Yes||No|
|2||Fragile to token leak||Yes||No|
|3||Fragile to container deletion||Yes||No|
|4||Fragile to service user deletion||Yes||No|
|5||“Noise” in Swift account||No||Yes|
|6||Namespace collisions (user and service picking same name)||No||Yes|
|7||Guarantee of consistency (service database vs swift account)||Yes||No|
|8||Policy enforcement (e.g., Image Download)||Yes||No|
It is proposed to put service data into a separate account to the end-user’s “normal” account. Although the account has a different name, the account is linked to the end-user’s project. This solves issues with noise and namespace collisions. To remove fragility and improve consistency guarantees, it is proposed to use the composite token feature to manage access to this account.
In summary, there are three related changes:
The effect is that access to the data must be made through the service. In addition, the service can only access the data when it is processing a request from the end-user (i.e, when it has an end-user’s token).
The changes are described one by one in this document. The impatient can skip to “Composite Tokens in the OpenStack Environment” for a complete, example.
The authentication system will validate a second token. The token is stored in the X-Service-Token header so is known as the service token (name chosen by Keystone).
The core functions of the token authentication scheme is to determine who the user is, what account is being accessed and what roles apply. Keystoneauth and Tempauth have slightly different semantics, so the tokens are combined in slightly different ways as explained in the following sections.
The following rules are used when a service token is present:
In this example, the <token-two> is scoped to a different project than the account/project being accessed:
Client | <user-token>: project-id: 1234 | user-id: 9876 | roles: admin | X-Auth-Token: <user-token> | X-Service-Token: <token-two> | | <token-two>: project-id: 5678 v user-id: 5432 Swift roles: service | v Combined identity information: user_id: 9876 project_id: 1234 roles: admin service_roles: service
The user groups from both tokens are simply combined into one list. The following diagram gives an example of this:
Client | <user-token>: from "joe" | | | X-Auth-Token: <user-token> | X-Service-Token: <token-two> | | <token-two>: from "glance" v Swift | | [filter:tempauth] | user_joesaccount_joe: joespassword .admin | user_glanceaccount_glance: glancepassword servicegroup | v Combined Groups: .admin servicegroup
The reseller_prefix will now support a list of prefixes. For example, the following supports both AUTH_ and SERVICE_ in keystoneauth:
[filter:keystoneauth] reseller_prefix = AUTH_, SERVICE_
For backward compatibility, the default remains as AUTH_.
All existing configuration options are assumed to apply to the first item in the list. However, to indicate which prefix an option applies to, put the prefix in front of the option name. This applies to the following options:
Other options (logging, storage_url_scheme, etc.) are not specific to the reseller prefix.
For example, this shows two prefixes and some options:
[filter:keystoneauth] reseller_prefix = AUTH_, SERVICE_ reseller_admin_role = ResellerAdmin <= global, applies to all AUTH_operator_roles = admin <= new style SERVICE_operator_roles = admin allow_overrides = false
This section presents a simple configuration showing the flow from client through an OpenStack Service to Swift. We use Glance in this example, but the principal is the same for all services. See later for a more complex service-specific setup.
The flow is as follows:
Client | <user-token>: project-id: 1234 | user-id: 9876 | (request) roles: admin | X-Auth-Token: <user-token> | v Glance | | PUT /v1/SERVICE_1234/container/object | X-Auth-Token: <user-token> | X-Service-Token: <glance-token> | | <glance-token>: project-id: 5678 v user-id: 5432 Swift roles: service | v Combined identity information: user_id: 9876 project-id: 1234 roles: admin service_roles: service [filter:keystoneauth] reseller_prefix = AUTH_, SERVICE_ AUTH_operator_roles = admin AUTH_reseller_admin_roles = ResellerAdmin SERVICE_operator_roles = admin SERVICE_service_roles = service SERVICE_reseller_admin_roles = ResellerAdmin
The authorization logic is as follows:
/v1/SERVICE_1234/container/object ------- | in? | reseller_prefix = AUTH_, SERVICE_ \ Yes \ Use SERVICE_* configuration | | /v1/SERVICE_1234/container/object ---- | same as? project-id: 1234 \ Yes \ roles: admin | in? SERVICE_operator_roles = admin \ Yes \ service_roles: service | in? SERVICE_service_roles = service \ Yes \ ----> swift_owner = True
These work on the principal that the secret key is stored in a privileged header. No change is proposed as the account controls described in this document continue to use this concept. However, an additional use-case becomes possible: it should be possible to use temporary URLs to allow a client to upload or download objects to or from a service account.
Using a common SERVICE_ namespace means that all OpenStack Services share the same account. A simple alternative is to use multiple accounts – with corresponding reseller_prefixes and service catalog entries. For example, Glance could use IMAGE_ and Cinder could use VOLUME_. There is nothing in this proposal that limits this option. Here is an example of a possible configuration:
[filter:keystoneauth] reseller_prefix = AUTH_, IMAGE_, VOLUME_ IMAGE_service_roles glance_service VOLUME_service_roles = cinder_service
No changes are needed in python-swiftclient to support this feature.
Services (such as Glance, Cinder) need to be enhanced as follows to use the SERVICE_ namespace:
The Swift software must be upgraded before Services attempt to use the SERVICE_ namespace. Since Services use configurable options to decide how they use Swift, this should be easy to sequence (i.e., upgrade software first, then change the Service’s configuration options).
How Services handle existing legacy data is beyond the scope of this proposal.
An earlier draft proposed extending the account ACL. It also proposed to add a default account ACL concept. On review, it was decided that this was unnecessary for this use-case (though that work might happen in it’s own right).
An earlier draft proposed new sysmeta that established “co-ownership” rules for containers.
The Keystone Composite Authorization scheme has use cases for other Openstack projects. The OSLO incubator policy checker module may be extended to support roles acquired from X-Service-Token. However, this will only be used in Swift if keystoneauth already uses a policy.xml file.
If policy files are adapted by keystoneauth, it should be easy to apply. In effect, a different policy.xml file would be supplied for each reseller prefix.
The proxy-logging middleware logs the value of X-Auth-Token. No change is proposed.
To be fully effective, changes are needed in other projects:
No new git repositories will be created.
No new servers are created. The keystoneauth middleware is used by the proxy-server.
No DNS entries will to be created or updated.