acciente / oacc-core

OACC (Object ACcess Control) is an advanced Java Application Security Framework
http://oaccframework.org/
Apache License 2.0
107 stars 23 forks source link

Seperate resources #45

Closed WerVbn closed 7 years ago

WerVbn commented 7 years ago

Hallo,

I would like to know If I can implement the following use case with OACC and if my idea how to implement this is the right approach:

I have different resources of the resource class "device", I need to group then and separate them hierarchically and I have a resource class "users" which are going to have different permissions per group device.

Group A should contain all devices. Group B should contain a subset of devices. I would also like to split group B in different subsets. Called group B1 and B2.

I would like to add to each device group users, which will have different permissions for each group. A user in group A should have permissions for all devices, i.e. to edit and view devices in all groups. Users in group B should have permissions for all devices in group B and the subgroups of B.

Can I implement this scenario with domains and subdomains with oacc?

I would create a parent domain with child domains. Then, I would create device resources in the parent domain and create user resources in each domain.

Is it possible to "inherit" devices from the parent to the subdomain? Is it also possible, to create user roles which are going to define different permissions for a single domain?

fspinnenhirn commented 7 years ago

Hi Tesfel, I think you're on the right track with how you plan to model your secured objects in OACC using the concepts of hierarchical domains and resources representing user roles, but just to be sure we're on the same page, I've attached a diagram of a possible model, based on how I understand your requirements:

acciente_oacc_visual_devicehierarchy

As you can see, the magic happens with "roles" that define global permissions (i.e. permissions on tuples of resource class and domain) on the different hierarchical device groups, which are modeled as nested domains.

In the example, user Alice has the most privileges, because she inherits from Role A, which has both VIEW and EDIT permissions on resources of class Device in _DeviceGroupA, which happens to be the parent domain for all A and B devices. Bob, on the other hand, only inherits from Role B, which gives him VIEW permission on all devices in _DeviceGroupB and in its subdomains. So Bob can't VIEW any devices of the parent _DeviceGroupA and neither can he EDIT any of the B devices. Carol inherits from Role B, just like Bob, but has the additional Role C, which gives her VIEW and EDIT permissions on the innermost subdomain _DeviceGroupB1. This means Carol can VIEW all devices in _DeviceGroupB, but can also EDIT dev-b1-03.

Is it possible to "inherit" devices from the parent to the subdomain?

I'm not sure if I understand this question correctly, so please let me know. Each resource in a subdomain automatically belongs to the parent domain(s), so global permissions assigned on a parent domain will extend to the resources within the nested subdomains. Alice can VIEW and EDIT the dev-A-01 from the _DeviceGroupA, but has the same permissions on dev-B2-04 from the nested subdomain _DeviceGroupB2, because the global permission on the parent domain applies to all resources in that domain and in any of its subdomains.

Is it also possible, to create user roles which are going to define different permissions for a single domain?

Absolutely! For example, we could add another Role D that has global VIEW permission on _DeviceGroupA. Then you'd have two roles, Role A and Role D that both apply to the same domain, but provide different permission. That would be one way to model different roles for admin and regular users on shared resources, for example.

Hope this helps, tesfel! Let me know if you have any other questions.

WerVbn commented 7 years ago

Hi fspinnenhirn,

thanks for you fast reply, thats exactly what I need! :)

That means, Bob would inherit permissions of role B, which is a domain permission for the domain DeviceGroup_B?

setDomainPermissions(Resource accessorResource, String domainName, Set<DomainPermission> domainPermissions)

But how can I add the device resources to the sub domains?

Each resource in a subdomain automatically belongs to the parent domain(s), so global permissions assigned on a parent domain will extend to the resources within the nested subdomains.

All devices belong to DeviceGroup_A and can be added to DeviceGroup_B and DeviceGroup_B1 by creating a device resource in the lowest sub domain where the device should be available?

But how can I "add" a device which was created in DeviceGroup_A to DeviceGroup_B?

With

setResourcePermissions(Resource accessorResource, Resource accessedResource, Set<ResourcePermission> resourcePermissions)

I can set a resource permissions for a accessor resource (user) to a device resource in any domain. Can I move devices from DeviceGroup_A to a new subdomain?

I would like to create roles which are going to model this logic to be able that device resources can inherit of this roles. A role like RoleDeviceGroup_B1 which makes the device dev-b1-03 available to DeviceGroup_B1 and to all its parent domains, which is going to happen "automatically" since it is a subdomain. Is that possible?

I have another question: What is exactly the difference between

setResourcePermissions(Resource accessorResource, Resource accessedResource, Set<ResourcePermission> resourcePermissions)

and

grantResourcePermissions(Resource accessorResource, Resource accessedResource, Set<ResourcePermission> resourcePermissions) ?

Because it makes no difference, I can inherit the permissions of a role to a resource with both methods. Also, it makes no difference if I create permissions with getinstance(...) or with getInstanceWith GrantOption.

Please take a look at this:

Set<ResourcePermission> resourcePermissions = new HashSet<>();
// no difference?
//resourcePermissions.add(ResourcePermissions.getInstanceWithGrantOption("VIEW"));
resourcePermissions.add(ResourcePermissions.getInstance("VIEW"));

// set permission for role "testRole"       
accessControlContext.setGlobalResourcePermissions(Resources.getInstance("testRole"), "Device", "DeviceGroup_B", resourcePermissions);

// inherit permission of role "testRole"
Set<ResourcePermission> inheritPerm = new HashSet<>();
inheritPerm.add(ResourcePermissions.getInstance(ResourcePermissions.INHERIT));

//no difference?
// accessControlContext.setResourcePermissions(Resources.getInstance("userInTestRole"), Resources.getInstance("testRole"), inheritPerm );
accessControlContext.grantResourcePermissions(Resources.getInstance("userInTestRole"), Resources.getInstance("testRole"), inheritPerm );

Is my understanding of permission inheritance wrong? :/

BTW: Which tool do you use to model these fancy security graphs?

fspinnenhirn commented 7 years ago

I'll try and address each of your questions in order, below:

That means, Bob would inherit permissions of role B, which is a domain permission for the domain DeviceGroup_B? setDomainPermissions(Resource accessorResource, String domainName, Set<DomainPermission> domainPermissions)

Just to clarify, a DomainPermission is the type of permission used to grant an accessor permission to manage the domain itself, and is limited to the built-in permissions *SUPER-USER, *CREATE-CHILD-DOMAIN and *DELETE. There are no DomainPermissions in the scenario we've discussed so far.

What we're using here are "global" permissions:
a permission on a resource class + domain tuple, instead of between a resource and another resource (or domain). If a resource has a global permission, it effectively has that permission on all resources of that resource class in that domain (and in any of its sub-domains).

setGlobalResourcePermissions(Resource accessorResource,
                             String resourceClassName,
                             String domainName,
                             Set<ResourcePermission> resourcePermissions)

But how can I add the device resources to the sub domains?

All devices belong to DeviceGroup_A and can be added to DeviceGroup_B and DeviceGroup_B1 by creating a device resource in the lowest sub domain where the device should be available?

Yes, every resource is created in a specific domain. If that domain is part of a domain hierarchy, then the resource automatically belongs to any parent domain(s), as well. So there is no extra step required (or even possible) to "add" a resource from a subdomain to its parent domains.

But how can I "add" a device which was created in DeviceGroup_A to DeviceGroup_B? Can I move devices from DeviceGroup_A to a new subdomain?

You can't. From the FAQs:
Every resource in OACC exists inside a domain. Domains serve to scope groups of resources, and most security operations in OACC work within the context of a specified domain.
Domains are incredibly useful to isolate groups of resources in multi-tenant applications, but also constitute a useful abstraction in itself, because they allow permissions to be efficiently assigned and queried at the domain-level.
Once a resource created, it cannot be "moved" to another domain. Similarly, a resource can't belong to more than one domain, unless the resource's domain is a child within a domain hierarchy. So there is no way for a resource created in one domain to be considered part of one of its subdomains.

I would like to create roles which are going to model this logic to be able that device resources can inherit of this roles. A role like RoleDeviceGroup_B1 which makes the device dev-b1-03 available to DeviceGroup_B1 and to all its parent domains, which is going to happen "automatically" since it is a subdomain. Is that possible?

I'm not sure if I understand your scenario correctly:
If dev-b1-03 is in a subdomain, it will automatically be part of the parent domains - not just the immediate parent, but also all of its ancestor domains. Any global permissions on its parent domain will apply to the nested device, as well. This is why Alice can both VIEW and EDIT dev-b2-04 from the nested innermost subdomain via Role A's global permission on the ancestor domain _DeviceGroupA. If you're saying that permissions on a subdomain are not general enough to extend to all resources within the parent domain, then yes, you could set up a role resource that has global permission only to a subdomain (like Role C in the diagram) and assign it where appropriate. Roles can of course inherit from other roles, if need be, for example to make permission management easier.

What is exactly the difference between setResourcePermissions(Resource accessorResource, Resource accessedResource, Set<ResourcePermission> resourcePermissions) and grantResourcePermissions(Resource accessorResource, Resource accessedResource, Set<ResourcePermission> resourcePermissions)? Because it makes no difference, I can inherit the permissions of a role to a resource with both methods.

From the API Overview: OACC provides set-methods for each permission type, in order to specify to which permissions a resource is privileged. A successful invocation of a set-method for a permission type always assigns all direct permissions at once, thus overriding any existing direct permissions.
For more fine-grained control of permission assignment, OACC also provides grant and revoke methods for each permission type, which allow to add or remove one (or more) permissions from the set of existing direct permissions, respectively. Grant-methods can never remove an already existing permission; they can only add new permissions or expand the granting rights of existing ones. Conversely, revoke-methods can only be used to remove existing permissions (regardless of granting rights).

Note that the grant/revoke methods are overloaded to take varargs of permissions, so you don't have to create and populate a Set, if you aren't planning to reuse it.

Also, it makes no difference if I create permissions with getinstance(...) or with getInstanceWithGrantOption. [...] Is my understanding of permission inheritance wrong? :/

Your understanding of inheritance is correct. The grant option has nothing to do with inheritance, though - that's why you're not seeing a difference!

The grant option controls permission delegation, which means that the accessor resource would be able to assign that permission to another resource (= the accessor has the permission with the option to grant it to another resource).

In the SecureTodo sample application, the user that creates a todo item will get VIEW and EDIT permissions on that todo item. The VIEW permission comes with the grant option, but the EDIT permission doesn't. The user can then "share" the todo item with another user by giving the VIEW permission on that todo item to the other user, for example with grantResourcePermission(targetUserResource, todoItemResource, viewPermission). The original user does not have the grant option on the EDIT permission, which means the user can't assign the EDIT permission to the other user of the shared todo item, thus completely preventing that the other user accidentally is assigned EDIT permissions on the shared todo item.

BTW: Which tool do you use to model these fancy security graphs?

Great question! :thumbsup: (: I always find that visualizing helps understanding (and explaining) a problem, so I've been trying different things to illustrate OACC concepts for a while. It's a manual process that started in PowerPoint, but I then switched to Visio because it provides better control over the arrow line connectors (i.e. the lines illustrating the permissions).

WerVbn commented 7 years ago

Thank you very much for your great support! :)

My problem with the permissions delegation was, that I had the wrong access control context. Of course, to make the withGrantOption work, I need the context of the resource which is going to grant the option to another resource.

// add permissions to role resource
Set<ResourcePermission> resourcePermissions = new HashSet<>();
            resourcePermissions.add(ResourcePermissions.getInstanceWithGrantOption("VIEW"));
            resourcePermissions.add(ResourcePermissions.getInstance("EDIT"));

accessControlContext.setGlobalResourcePermissions(Resources.getInstance("testRole"), "Device", "DeviceGroup_B", resourcePermissions);

// inherit permission of role to userInTestRole
accessControlContext.grantResourcePermissions(Resources.getInstance("userInTestRole"), Resources.getInstance("testRole"), ResourcePermissions.getInstance(ResourcePermissions.INHERIT));

// get the context of userInTestRole

// assign VIEW permission for user2 to resource dev-b-01 - works
accessControlContext.grantResourcePermissions(Resources.getInstance("user2"), Resources.getInstance("dev-b-01"),  ResourcePermissions.getInstance("VIEW"));

// doesn't work
accessControlContext.grantResourcePermissions(Resources.getInstance("user2"), Resources.getInstance("dev-b-01"),  ResourcePermissions.getInstance("EDIT"));
fspinnenhirn commented 7 years ago

Yep, you got it!

Having a permission with the grant option on an accessed resource allows the permission holder (=the accessor resource) to grant the same permission relationship to another resource so that it will also be an accessor. Hence you need an access control context in which the original accessor resource is authenticated, in order to grant the permission to another resource.