Tenant role conflicts/overlaps can be a security issue

Bug #890411 reported by Jason Rouault
22
This bug affects 2 people
Affects Status Importance Assigned to Milestone
OpenStack Identity (keystone)
Invalid
Medium
Arvind Tiwari

Bug Description

During the validate token call all the tenant roles (associated with the tenant scoped token) are returned to the middle-ware component and then passed along in the X_ROLES header to the OS service for consumption. In the case were more than one OS service are bound to the same tenant (e.g. Swift and Nova, or Nova 1 and Nova 2), a user with particular role for one service, lets just say the 'Admin' role will now also have the 'Admin' role in the second service. This is because roles are currently only scoped to the tenant level. The middle-ware just takes all returned tenant roles and stuffs them into the X_ROLES header regardless of the actual service the middle-ware is protecting. A quick fix to this problem would be to change the validate token interfaces (GET/HEAD /tokens/{tokenId}) to require a {serviceId} filter... so something like GET /tokens/{tokenId}?serviceId={serviceId}. The Keystone service would then only return roles in the response that are tied to that specific serviceId. If the serviceId was not provided, or was invalid, or no roles where found for that serviceId, then a 401 would be returned. Future Keystone work could consider allowing to filter down to the {endpointId}, but for such a change it would require a data model change to allow serviceIds to be defined on endpoint references.... Not to mention more API changes.

Tags: security
Changed in keystone:
assignee: nobody → HP Cloud Engineering (hp-cloud-engineering)
Revision history for this message
Thierry Carrez (ttx) wrote :

Subscribed Ziad, as PTL for Keystone.

If I understand correctly, this is more an unfortunate design choice (roles being scoped to tenants) than a security flaw ? If you confirm that the current behavior is by design, I agree that this design should be improved to allow roles scoped to tenant + service, but I see no reason to keep this private.

If this is not by design and roles should actually be scoped to tenant + service, then this is a vulnerability and we should keep the bug private until this is fixed. And if this affect stable/diablo as well, I suggest we delay 2011.3.1 to include the fix...

Revision history for this message
Jason Rouault (jason.rouault) wrote :

Designs can induce security defects... I think this should stay private until HP introduces the changes

Revision history for this message
Thierry Carrez (ttx) wrote :

Jason: oh, I agree with you -- my question stems from my ignorance of Keystone stuff. If Keystone roles are supposed to be universal rather than service-specific, then this is not a security issue. The admin of one is supposed to be the admin of the other. If roles are supposed to be service-specific, then this is definitely a serious security issue.

Revision history for this message
Jason Rouault (jason.rouault) wrote :

Thierry: roles are supposed to be service specific

Thierry Carrez (ttx)
Changed in keystone:
importance: Undecided → High
status: New → Confirmed
Revision history for this message
Thierry Carrez (ttx) wrote :

Dolph, Ziad, please ack/comment

Revision history for this message
Dolph Mathews (dolph) wrote :

While this *was* by design, we definitely recognize that the design should be re-thought (especially with the introduction of Capabilities on the horizon).

Other than additional query parameters for ?service/endpoint, I don't see this as a change of spec, but rather just implementation behavior.

Revision history for this message
Thierry Carrez (ttx) wrote :

So Dolph, if I understand correctly, this was by design but could definitely evolve in the future towards service-specific rights ? That means it will probably be improved in Essex but should not be fixed in stable/diablo ?

If that interpretation is correct, I tend to not consider this a security hole but rather an architectural limitation that should be lifted in future releases... and would advocate for this bug being made public (but not before the original reporter is ok with it).

@Jason: let me know if you agree with Dolph's position, and when you're comfortable opening this up (which can be after HP evolves its implementation).

Revision history for this message
Jason Rouault (jason.rouault) wrote :

I think this needs to be addressed in diablo/stable for the servidId filter. HP is looking at committing the fix

Revision history for this message
Thierry Carrez (ttx) wrote :

Adding members of the stable maintenance team.

All: Should we delay 2011.3.1 to include that fix ?

Revision history for this message
Dolph Mathews (dolph) wrote :

As long as it's backwards compatible (i.e. optional) in stable/diablo, I don't see why we couldn't/shouldn't include it.

Revision history for this message
Ziad Sawalha (ziad-sawalha) wrote :

We did not consider the use case of having multiple instances of services or services that don't trust each other sharing one instance of Keystone. That was not an oversight, but a conscious decision to focus on exiting incubation and integrating with existing OpenStack services in known, common deployments.

That is not to negate the concern Jason brings up, which is valid.

We did, however, blueprint a mechanism to separate services so they can own their own endpoints and roles. That mechanism was not fully implemented until today (https://review.openstack.org/1864). Using the enforced ownership over service names, you can have services own their role prefixes (ex. nova:admin is owned by nova and glance cannot edit it. Similarly, glance:admin is created and owned by glance).

While all roles are still returned to the middleware, the service can identify the roles it owns by the prefix.

But I still look forward to the patch from HP. Meanwhile, I would consider this workaround a mitigation for the above risk. I will work on documenting it.

Changed in keystone:
status: Confirmed → Fix Committed
Revision history for this message
Jason Rouault (jason.rouault) wrote :

Ziad, the change to add a service prefix will only work if the service (e.g. Nova) knows how to consume the concatenated servicename:rolename. Today services do not know how to consume this (e.g. they just look for 'admin'). I assume this change is for Essex, and in the Essex work stream all the other services will change to understand the prefix?

Thierry Carrez (ttx)
Changed in keystone:
importance: High → Undecided
Revision history for this message
Guang Yee (guang-yee) wrote :

Proposed Solution:

We'll be changing the validate token APIs to look for the mandatory request
parameter "serviceId" for scoped token validation. Specifically,

GET/HEAD /tokens/{tokenId}?[belongsTo=<tenantID>&][serviceId=<comma-separated service IDs>]

"serviceId" is a comma-separated list of service IDs.

The Keystone service will filter the roles with the given service IDs. If the serviceId
was not provided, or was invalid, or no roles were found for that serviceId, then a
401 would be returned.

Global roles (roles without any tenant association) will only be returned if
the global service ID is included in "serviceId". For example,

serviceId=<service ID>,<global service ID>

Keep in mind that the global service ID is just an special string denoting the need to return
the global roles. It is configurable in keystone.conf. For example,

global_service_id = global

The global service ID in middleware must match the one specified in keystone.conf inorder for
the global roles to return. Any mismatch will result in 401 since the global service ID does
not match any valid service in the backend.

MAKE NO MISTAKE, THIS CHANGE WILL NOT BE BACKWARD COMPATIBLE.

As mentioned above, If the serviceId was not provided, or was invalid, or no roles were found
for that serviceId, then a 401 would be returned.

Furthermore, we will be modifying the middleware and keystone-manage CLI to facilitate
service IDs.

Affected Middleware Components: auth_token.py, swift_auth.py, and quantum_auth_token.py.

auth_token.py and quantum_auth_token.py:

Users are required to specify the "service_ids" property in the auth_token section of the conf file.
"service_ids" is a comma-separated list if service IDs.

For example, if this is a Nova service instance and its service ID is 888, user will need to set it
in api-paste.ini.

[filter:authtoken]
...
service_ids = 888
...

To specify multiple service IDs.

[filter:authtoken]
...
service_ids = 888,999
...

By default, global roles (roles without tenant association) will not be return on validate token call.
To ask Keystone to return the global roles, user must specify the global service ID. For example,

[filter:authtoken]
...
service_ids = 888,999,global
...

As mentioned above, the global service ID is also configurable in keystone.conf. The global service ID
in middleware must match the one specified in keystone.conf inorder for the global roles to return.

swift_auth.py:

Same as auth_token.py exception it is using the "keystone_service_ids" property instead of "service_ids".

Affected CLI: keystone-manage

"keystone-manage role add" will not accept an optional service name parameter. For example,

keystone-manage role add nova_role nova_service

However, service name can be part of the role name. For example,

keystone-manage role add nove_service:nova_role

Though redundant, but user may also specify service name and prefix the role name with the service name.
For example,

keystone-manage role add nova_service:nova_role nova_service

However, if both service name and serive_name prefix are specified, they must match. Otherwise, ValueError
will be raised.

Revision history for this message
Thierry Carrez (ttx) wrote :

Reopening since there is no consensus on the fix yet

Changed in keystone:
status: Fix Committed → Incomplete
Revision history for this message
Guang Yee (guang-yee) wrote :

Please let me know if there are problems with the proposed solution. Otherwise, I'll be pushing the changes for review shortly.

Revision history for this message
Jason Rouault (jason.rouault) wrote :

yep, I like

Revision history for this message
Guang Yee (guang-yee) wrote :

After much consideration, we've decided to make the serviceId parameter "optional" in order to fulfill backward compatible requirement.

GET/HEAD /tokens/{tokenId}?[belongsTo=<tenantID>&][serviceId=<comma-separated service IDs>]

Keep in mind that the absence of serviceId, if one chooses to, means we still have tenant role conflicts/overlaps security problems as described in the bug.

Please let me know if there are objections. Otherwise, I'll start implementing the changes.

Revision history for this message
Thierry Carrez (ttx) wrote :

Ziad, Dolph: please comment !

Revision history for this message
Dolph Mathews (dolph) wrote :

The discussion has continued in the code review: https://review.openstack.org/#change,publish,2018

Recommend we mark this bug public now, as it is referenced by the commit message under review. The optional/required debate could use community feedback.

Thierry Carrez (ttx)
Changed in keystone:
importance: Undecided → Medium
status: Incomplete → In Progress
visibility: private → public
Changed in keystone:
milestone: none → essex-3
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix proposed to keystone (master)

Fix proposed to branch: master
Review: https://review.openstack.org/2623

Revision history for this message
OpenStack Infra (hudson-openstack) wrote :

Fix proposed to branch: master
Review: https://review.openstack.org/2624

Revision history for this message
OpenStack Infra (hudson-openstack) wrote :

Fix proposed to branch: master
Review: https://review.openstack.org/2640

Revision history for this message
OpenStack Infra (hudson-openstack) wrote :

Fix proposed to branch: master
Review: https://review.openstack.org/2654

Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix merged to keystone (master)

Reviewed: https://review.openstack.org/2654
Committed: http://github.com/openstack/keystone/commit/fafc25b3b1d6f0610d31819d55c6c480cfd5bb5a
Submitter: Jenkins
Branch: master

commit fafc25b3b1d6f0610d31819d55c6c480cfd5bb5a
Author: Guang Yee <email address hidden>
Date: Mon Dec 26 15:44:56 2011 -0800

    Add HP-IDM extension to fix Bug 890411

    See

    https://github.com/openstack/keystone/raw/master/keystone/content/admin/HP-IDM-admin-devguide.pdf
    https://github.com/openstack/keystone/raw/master/keystone/content/admin/HP-IDM-admin.wadl

    and

    https://bugs.launchpad.net/keystone/+bug/890411

    for more details.

    incorporated feedbacks from https://review.openstack.org/#change,2624

    Change-Id: Ied659b3c010ac4efa04c073388bdf3f3a67a51f0

Changed in keystone:
status: In Progress → Fix Committed
Thierry Carrez (ttx)
Changed in keystone:
status: Fix Committed → Fix Released
Thierry Carrez (ttx)
Changed in keystone:
milestone: essex-3 → 2012.1
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix proposed to keystone (master)

Fix proposed to branch: master
Review: https://review.openstack.org/7010

Changed in keystone:
assignee: HP Cloud Engineering (hp-cloud-engineering) → Guang Yee (guang-yee)
status: Fix Released → In Progress
Joseph Heck (heckj)
Changed in keystone:
milestone: 2012.1 → folsom-2
Joseph Heck (heckj)
Changed in keystone:
milestone: folsom-2 → none
Revision history for this message
Thierry Carrez (ttx) wrote :

Obviously not being worked on

information type: Public Security → Public
tags: added: security
Changed in keystone:
assignee: Guang Yee (guang-yee) → nobody
status: In Progress → Confirmed
Revision history for this message
Kurt Seifried (kseifried) wrote :

This sounds like it might need a CVE id. Can anyone confirm yes/no if this needs a CVE?

Revision history for this message
Dolph Mathews (dolph) wrote :

The high level ask here was basically the subject of this Havana summit session: https://etherpad.openstack.org/havana-endpoint-filtering

It's being worked on, but not as a "bug."

Changed in keystone:
assignee: nobody → Arvind Tiwari (arvind-tiwari)
Revision history for this message
Kurt Seifried (kseifried) wrote :

Ping, I assume this is not being treated as security flaw, can anyone confirm that? thanks.

Revision history for this message
Morgan Fainberg (mdrnstm) wrote :

This stems from a design decision, and isn't really a bug. This is more of a lack of a feature. This should be written up as a specification: https://git.openstack.org/cgit/openstack/keystone-specs and treated like a new feature. Marking this bug as "wont fix"

Changed in keystone:
status: Confirmed → Invalid
Revision history for this message
Morgan Fainberg (mdrnstm) wrote :

Correction, marked as Invalid.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.