RESOURCE GROUPS ---> ROLES <--- USERS ^ | permissions
User Deploying Another User's Bundle To Specific Resource Group
Team Leader Creates Bundles, Team Members Deploy Those Bundles
Deployment Manager Gives Teams Bundles Which They Can Deploy
Allow A User To See All Bundles In the System And Deploy Them Anywhere Accessible To User
Allow A User To See All Bundles In the System But Only Deploy Them To Specific Resource Groups
Allow a User To Only Delete Certain Bundles The User Can See
We need a more fine-grained security model surrounding bundle deployments. This design page explains how we can do it.
To apply fine grained security permissions to the bundle subsystem will require adding a new concept to the security subsystem - bundle groups. Similar to resource groups, bundle groups will allow RHQ to apply user permissions to a set of bundles.
Today's RHQ security model surrounding resources looks like this:
RESOURCE GROUPS ---> ROLES <--- USERS ^ | permissions
An RHQ admin can define a role (which has certain permissions enabled, like MANAGE_INVENTORY, CONTROL, CONFIGURE_WRITE, et. al.). If a permission is a global permission, it does not involve resource groups; rather, it takes affect globally (e.g. MANAGE_INVENTORY). If a permission is a resource permission (e.g. CONTROL), it is restricted in that it applies only for resources found in resource groups assigned to the role that provides the permission.
What this means for the newly proposed DEPLOY_BUNDLES permission (which will be described below) is that it restricts the user to only deploy bundles to resource groups that that user has access to.
If we want to allow for a user to deploy a bundle to an allowed resource group, not only does the resource group need to be assigned to a role that is assigned to the user, but the bundle to be deployed must be in a bundle group that is attached to a role that is assigned to a user (note: the role doesn't have to be the same as the one the resource group is attached to). Today, we do not have this concept of a bundle group. We would have to add a new relationship between role and bundle - this is where bundle groups come in:
BUNDLE GROUPS | v RESOURCE GROUPS ---> ROLES <--- USERS ^ | permissions
WARNING! Any change to the security model involves large amounts of risk. Not only because it involves security, but also because it is used in so many places. We have role queries in every subsystem. Even if we only add to the model (and leave alone what already exists), we would need to carefully study the changes and perform some quality testing to ensure we don't break existing queries and security checks.
If we have that new bundle group relationship to roles, then this would allow things like having an admin user create a new role with permission DEPLOY_BUNDLES, assign resource groups to that role, assign bundle groups to that role, then give that role to any user. That user would then be able to deploy those bundles that are members of the bundle group but only to those resource groups assigned roles that the user is assigned. More examples will be explained below in the Use Cases section of this document.
Implies all other bundle-related permissions.
This is for backward compatibility - it can do EVERYTHING bundle-wise.
We may want to rename this during a db upgrade to something else - to indicate it may be deprecated.
This permission is required to CRUD bundle groups (bundle groups are a new entity introduced in order to implement these new features).
Currently, this means it can add and remove members of the group.
This implies Global.VIEW_ALL_BUNDLES - user can see all bundles.
This seems analogous to INVENTORY_MANAGER permission for resources/resource groups.
This is to allow a user to deploy bundles the user can see to any resource group the user can see.
This should be renamed to avoid duplicating the resource group level permission name - what is a good name?
You can view all bundles, no matter what group, if any, a bundle is in.
This permission is useful for a user that wants to add bundles to bundle groups.
Use case: this can be used to allow users to see all bundles but with the restriction of only allowing the user to deploy to those resource groups that he has access to (DEPLOY_BUNDLES permission)
A user can create bundles (which also means uploading bundle versions).
At create time, the new bundle MUST BE assigned to bundle group(s) the user can see.
A newly created bundle must be assigned to at least one of the bundle groups the user can see (note: if the user has Global.VIEW_ALL_BUNDLES permission, he can see all bundles). The bundle group assignment is not done when the bundle being uploaded is merely a new version of a previously existing bundle since all bundle versions have the same group membership as the bundle they belong to.
If the new bundle is really a bundle version for an EXISTING bundle, the user MUST have permission to see that bundle in order to update it.
This means that there must exist at least one bundle group that the bundle is assigned to and that the user can see. Notice that the bundle can be part of other bundle groups that the user cannot see and this will still be allowed. As long as there is at least one user-visible bundle group that the bundle is assigned, you can update the bundle with a new bundle version.
IFF the user has Global.VIEW_ALL_BUNDLES, the user can opt to not put the bundle in any group
IFF the user has Global.VIEW_ALL_BUNDLES, the user can opt to put the bundle version in any existing bundle.
CREATE_BUNDLES is a global permission because we need to support the use-case of someone being able to create a bundle (or bundle version) and not assign it immediately to a bundle group. Since this use case does not involve a bundle group, obviously, a bundle-group-level permission will not work. Therefore, this global permission exists.
A user can delete any bundle (or bundle version) he can view.
A user with this permission will also need Global.VIEW_ALL_BUNDLES in order to delete bundles that are not in any group.
If you delete a bundle version, nothing has to be done with groups. If you delete the bundle itself, all of its versions will be deleted and that bundle will be removed from any groups it was a member of.
DELETE_BUNDLES is a global permission because we need to support the use-case of someone being able to delete a bundle (or bundle versions) that are not currently associated with any bundle group. Since this use case does not involve a bundle group, obviously, a bundle-group-level permission will not work. Therefore, this global permission exists.
A user can add any bundle he can see to the bundle group (allowing him to "copy" bundles from one bundle group to another).
The user needs Global.VIEW_ALL_BUNDLES permission to add bundles that are not in any group.
A user can remove bundles from the bundle group (this does not delete the bundles, it only removes them from a bundle group).
This is an implied permission. If you are in a role that has a bundle group associated with it, you are immediately allowed to view the bundles assigned to that bundle group.
The user can deploy bundles he can see to the resource group. This includes bundles in the user's bundle groups. If the user has VIEW_ALL_BUNDLES, the user can deploy any bundle.
Note that a bundle group and a resource group need NOT be associated with the same role. If bundle group A is associated with role A and resource group B is associated with role B, as long as DEPLOY_BUNDLES is enabled for role B, you can deploy any bundle in bundle group A to resource group B.
There is a distinction to be made when creating an initial bundle (that is, creating bundle version "1.0" where the bundle itself is also created) and when uploading a new bundle version for an existing bundle (e.g. uploading bundle verison "2.0"). Here are tables to show what is allowed and disallowed when creating or updating bundles when certain permissions are assigned to a given user.
In both the tables below, the VIEW_BUNDLES column represents the bundle group permission and the CREATE_BUNDLES and VIEW_ALL_BUNDLES columns represent the global permissions. If a permission column is checked, that means the user is granted those permissions.
The "In No Groups" column means if the bundle is to be created but not assigned to any group (or, for the "Updating" table, if the bundle to be updated with a new bundle version already exists but is not assigned in any group). If this column is checked, it means the operation is allowed if the checked permissions are effective for the given user.
The "In At Least 1 Group" column means if the bundle is to be created and assigned to at least one group (or, for the "Updating" table, if the bundle to be updated with a new bundle version already exists and is assigned to at least one bundle group). If this column is checked, it means the operation is allowed if the checked permissions are effective for the given user.
Initial Bundle Creation
CREATE_BUNDLES |
VIEW_ALL_BUNDLES |
VIEW_BUNDLES |
→ |
In No Groups |
In At Least 1 Group |
|
|
|
→ |
|
|
|
|
|
→ |
|
|
|
|
|
→ |
|
|
|
|
|
→ |
|
|
Updating Bundle By Creating New Bundle Version For Existing Bundle
CREATE_BUNDLES |
VIEW_ALL_BUNDLES |
VIEW_BUNDLES |
→ |
In No Groups |
In At Least 1 Group |
|
|
|
→ |
|
|
|
|
|
→ |
|
|
|
|
|
→ |
|
|
|
|
|
→ |
|
|
Analogous to creating bundles, this table shows the permissions needed to delete bundles:
DELETE_BUNDLES |
VIEW_ALL_BUNDLES |
VIEW_BUNDLES |
→ |
In No Groups |
In At Least 1 Group |
|
|
|
→ |
|
|
|
|
|
→ |
|
|
|
|
|
→ |
|
|
|
|
|
→ |
|
|
Today, there is a coarse-grained, "uber-permission" MANAGE_BUNDLE. If you have this global permission, you can create, delete, deploy and pretty much do anything in the bundle subsystem. We would leave this in the code for backward compatibility. If a user has MANAGE_BUNDLE, it would imply the user has all of the new proposed permissions (VIEW_ALL_BUNDLES, DEPLOY_BUNDLES, etc.) and can do anything and everything in the bundle subsystem.
We may want to rename MANAGE_BUNDLE permission to indicate this is a very powerful permission. We may even consider deprecated this permission, unless we have some users that still want this capability. For now, we will leave it.
Here are some use cases that help illustrate how the new bundle permissions and bundle groups can be utilized.
But first, all use cases must start with an admin user with MANAGE_SECURITY permission creating users and roles and assigning bundle permissions to those roles. In addition, that admin user must create bundle groups (or have a user with MANAGE_BUNDLE_GROUPS permission create bundle groups) and then associate the bundle group(s) with the appropriate role(s). The permissions assigned to the roles and the bundles assigned to the bundle groups will be different depending on the use case. But realize that an admin user must initially set up the security arrangements.
You can do this with one role:
Bundle Group A | v Resource Group X ---> Role R <--- User U ^ | Global.CREATE_BUNDLES, BundleGroup.VIEW_BUNDLES, ResourceGroup.DEPLOY_BUNDLES
or two roles:
Bundle Group A | v Role R1 <--- User U Resource Group X ---> Role R2 <--- User U ^ ^ | | BundleGroup.VIEW_BUNDLES, ResourceGroup.DEPLOY_BUNDLES Global.CREATE_BUNDLES
or three roles:
Bundle Group A | v Role R1 <--- User U Resource Group X ---> Role R2 <--- User U Role R3 <--- User U ^ ^ ^ | | | BundleGroup.VIEW_BUNDLES ResourceGroup.DEPLOY_BUNDLES Global.CREATE_BUNDLES
Actions By User: User U creates a bundle. Because the user has no BundleGroup.ASSIGN_BUNDLES permission, an admin must add his bundle to Bundle Group A. User goes through the deploy-bundle-wizard and is able to deploy to Resource Group X.
You can do this with one role:
Bundle Group A | v Resource Group X ---> Role R <--- User U ^ | BundleGroup.VIEW_BUNDLES, ResourceGroup.DEPLOY_BUNDLES
or two roles:
Bundle Group A | v Role R1 <--- User U Resource Group X ---> Role R2 <--- User U ^ ^ | | BundleGroup.VIEW_BUNDLES ResourceGroup.DEPLOY_BUNDLES
Actions By User: User cannot create any bundles. User selects a bundle from all bundle groups he has access to (in this case, Bundle Group A) and can deploy them to any resource group to which he has DEPLOY_BUNDLES permission (in this case, Resource Group X).
Bundle Group A Bundle Group A | | v v Role R1 <--- User TeamLeader Resource Group X ---> Role R2 <--- Users: TeamMember1, TeamMember2 ^ ^ | | Global.CREATE_BUNDLES, BundleGroup.VIEW_BUNDLES, BundleGroup.VIEW_BUNDLES, ResourceGroup.DEPLOY_BUNDLES BundleGroup.ASSIGN_BUNDLES
Actions By User TeamLeader: Team Leader creates a bundle. Because TeamLeader has BundleGroup.ASSIGN_BUNDLES permission on Role R1, he can add his new bundle to Bundle Group A since Bundle Group A is associated with Role R1. NOTE: TeamLeader cannot add any bundles that he, himself, did not create to Bundle Group A because he does not have Global.VIEW_ALL_BUNDLES and cannot see any other bundles - therefore, TeamLeader cannot give permissions to team members to deploy any other bundles. Note also that TeamLeader cannot deploy any bundles - he can only create them and assign them to bundle groups.
Actions By User TeamMember1: This user cannot create bundles, nor add/remove bundles from the bundle group, however, this user can deploy any bundle found in Bundle Group A to Resource Group X. Note that team members can only see bundles associated with Bundle Group A - no others are visible.
Role R1 <--- User TeamLeader | v Global.CREATE_BUNDLES Bundle Group A Bundle Group A | | v v Role R2 <--- User DeployManager Resource Group X ---> Role R3 <--- Users: TeamMember1, TeamMember2 ^ ^ | | Global.VIEW_ALL_BUNDLES, BundleGroup.VIEW_BUNDLES, BundleGroup.VIEW_BUNDLES, ResourceGroup.DEPLOY_BUNDLES BundleGroup.ASSIGN_BUNDLES, BundleGroup.UNASSIGN_BUNDLES,
Actions By User TeamLeader: User TeamLeader can create bundles. But he cannot deploy them or assign them to any groups.
Actions By DeployManager: User DeployManager cannot create bundles, but he can see all bundles created by TeamLeader (and any other user associated with Role R1). DeployManager can add any of those bundles he can see to Bundle Group A. This allows him to give the ability to let anyone associated with Role R3 to be able to deploy those bundles. DeployManager can also remove bundles from Bundle Group A, thus disallowing team members from deploying it. So, in short, DeployManager is the one who dictates which bundles can be deployed by whom, simply by assigning bundles to the appropriate bundle group.
Actions By User TeamMember1: TeamMember1 (and TeamMember2 for that matter) cannot create any bundles and cannot add any bundles to groups. But TeamMember1 can deploy bundles from Bundle Group A to Resource Group X.
This is a simple one. Just give the user in question a role with the global permissions VIEW_ALL_BUNDLES and DEPLOY_BUNDLES.
Role R1 <--- User U | v Global.VIEW_ALL_BUNDLES, Global.DEPLOY_BUNDLES
Notice that the user's role R1 need not have any resource groups or bundle groups associated with it. The two global permissions allow the user to see all bundles and to deploy them to any resource group the user has access to. So, while this role need not have any resource groups, the user still must have other roles that give him access to resource groups - the idea here is that any resource groups this user U has access to can have any bundle deployed to it by user U.
You can do this with one role:
Resource Group X ---> Role R <--- User U ^ | Global.VIEW_ALL_BUNDLES, ResourceGroup.DEPLOY_BUNDLES
or two roles:
Resource Group X ---> Role R1 <--- User U Role R2 <--- User U ^ ^ | | ResourceGroup.DEPLOY_BUNDLES Global.VIEW_ALL_BUNDLES
Actions by User U: The user cannot create or delete bundles nor can the user add or remove bundles from bundle groups. However, the user can see all bundles in the system and can deploy those bundles to Resource Group X (but only to Resource Group X).
This is another simple one. Just give the user in question a role with the global permissions MANAGE_BUNDLE_GROUPS, which will imply that RHQ will also give the user the global permission VIEW_ALL_BUNDLES.
Role R1 <--- User U | v Global.MANAGE_BUNDLE_GROUPS, Global.VIEW_ALL_BUNDLES
This will allow user U to create and delete bundle groups as well as adding and removing any bundle from any bundle group. However, note that this user has no ability to create or delete bundles nor can the user deploy bundles. This user can only operate on bundles that already exist.
This is another simple one. Just give the user in question a role with the global permissions CREATE_BUNDLES, VIEW_ALL_BUNDLES and DELETE_BUNDLES.
Role R1 <--- User U | v Global.CREATE_BUNDLES, Global.VIEW_ALL_BUNDLES, Global.DELETE_BUNDLES
This will allow user U to create bundles, and delete any bundle (whether or not those bundles are in bundle groups). The VIEW_ALL_BUNDLES allows the user to see all bundles, and DELETE_BUNDLES allows the user to delete all those bundles the user can see. However, note that this user has no ability to assign bundles to groups and the user cannot deploy bundles.
You can do this with one role:
Bundle Group A | v Role R1 <--- User U ^ | Global.DELETE_BUNDLES, BundleGroup.VIEW_BUNDLES
or two roles:
Bundle Group A | v Role R1 <--- User U Role R2 <--- User U ^ ^ | | BundleGroup.VIEW_BUNDLES Global.DELETE_BUNDLES
The user is restricted to being able to see only those bundles in Bundle Group A. The user is also given the global permission to delete bundles. Therefore, since the user can only see bundles in Bundle Group A, it means the user can only delete bundles found in Bundle Group A.
Bundle Group A | v Role R1 <--- User U1, U2, ..., Un Role R2 <--- User U1, U2, ..., Un ^ ^ | | BundleGroup.VIEW_BUNDLES Global.CREATE_BUNDLES, Global.DELETE_BUNDLES
This allows all users Ux to create and delete bundles (including uploading bundle versions for existing bundles) but ONLY for those bundles that the users can see. And this means only those bundles associated with Bundle Group A. If a user wants to create a new bundle, they can only associate them with Bundle Group A (that is because they have Global.CREATE_BUNDLES without Global.VIEW_ALL_BUNDLES).
Note also these users Ux cannot deploy any bundle anywhere - they are restricted to only creating and deleting them.
To be able to see all bundles, a user needs either Global.VIEW_ALL_BUNDLES or have BundleGroup.VIEW_BUNDLES for all bundle groups that exist.
To be able to create bundles, a user needs Global.CREATE_BUNDLES. But with this, the user is able to create bundles in any viewable bundle group - and since the user can see all bundles/bundle groups, it means the ability to create in any bundle group.
Therefore, you cannot have a user that can see all bundles in the system but only be allowed to create bundles in certain bundle groups but not others.
To be able to view bundle groups, a user must have BundleGroup.VIEW_BUNDLES on those groups.
To be able to create bundles in those viewable groups, a user needs Global.CREATE_BUNDLES.
However, since Global.CREATE_BUNDLES is a global permission, it applies across all bundle groups the user has BundleGroup.VIEW_BUNDLES so there is no way to give a user BundleGroup.VIEW_BUNDLES and not have his Global.CREATE_BUNDLES take effect.
Therefore, you cannot give a user the ability to create bundles in certain viewable groups but not other groups he can view. If the user can view it, he can create in it (of course, if you take away the Global.CREATE_BUNDLES, he can still view all the bundles in those groups, but he can't create in any of them).
Similiar to the previous use-case, only it involves Global.DELETE_BUNDLES rather than the create permission. But the situation is the same in all other respects.
Therefore, you cannot give a user the ability to delete bundles in certain viewable groups but not other groups he can view. If the user can view it, he can delete from it (of course, if you take away the Global.DELETE_BUNDLES, he can still view all the bundles in those groups, but he can't delete from any of them).
If we need to support these use cases above, we can add additional bundle-group-level permissions: CREATE_BUNDLES_IN_GROUP and DELETE_BUNDLES_IN_GROUP (for lack of better names, let's just go with those to avoid conflicting duplicate names in the Global space).
CREATE_BUNDLES_IN_GROUP would provide the user the ability to create new bundles (or update existing bundles by adding new bundle versions to existing bundles) but only for those bundles in the bundle group where this permission is granted.
DELETE_BUNDLES_IN_GROUP would provide the user the ability to delete bundles (or bundle versions) but only for those bundles in the bundle group where this permission is granted.
Note that we didn't originally place those two additional group-level permissions in the design because it could become confusing from a security standpoint as to who has permission to do what. If a bundle is in multiple bundle groups and some of those bundle groups are associated with multiple roles, a user need only have CREATE or DELETE permission for one of those roles/groups to be able to manipulate those bundles, even if he doesn't have those permissions on other roles. This could be confusing and may cause an admin user to accidentally give permissions that should not be granted.
But if we need to support those currently unsupported use cases, we can add two more Bundle Group Level Permissions such that the full group level permissions available would be:
ASSIGN_BUNDLES
UNASSIGN_BUNDLES
VIEW_BUNDLES
CREATE_BUNDLES_IN_GROUP
DELETE_BUNDLES_IN_GROUP