Shawn, 

I started implementing this and one of the things I am concerned with is 
duplicate ftPA entries. Most of our permissions will likely share the same 
attribute(s), so the ftPA entires will be duplicated across several permissions 
in what I proposed. I am considering creating an objectclass, something like 
ftAttributeSet to store the attribute(s), then have ftPA point to the attribute 
set. Then in the ftRC, for the filter type, I can specify the attribute set 
instead of trying to infer which one is applicable. Any thoughts or concerns 
with that change?

FYI - My plan is to provide an ldif export with some sample data once I have it 
all implemented, but if you are interested in what I've done so far you can 
take a look here 
(https://github.com/PennState/directory-fortress-core-1/tree/feature/addPermAttrAndUserRoleConstraints).
 

Thanks,

~Chris P.


----- Original Message -----
From: "Shawn McKinney" <[email protected]>
To: [email protected]
Sent: Monday, January 18, 2016 8:31:37 AM
Subject: Re: Fortress Constraints

Chris I’m not concerned with loading the user object with new multi-occurring 
attributes as much as the runtime complexity of joining with the ftPA’s during 
sessionPermissions call.  

Having said that I believe your proposal has merit due to its potential of 
reducing the number of roles needed to manage complex security use cases.  

Runtime performance is a critical concern and we’ll need to optimize this 
algorithm to the extent possible.  Our runtime complexity target should be 
O(log N).  That means we’ll need to find an efficient way to join without 
(much) looping.  We’ll also need to ensure the complexity doesn’t leak into 
areas where the attribute feature isn’t used / needed.  

Shawn

> On Jan 17, 2016, at 7:04 AM, Chris Pike <[email protected]> wrote:
> 
> Shawn,
> 
> Thanks for taking a look!
> 
> 1. Yes, I think that is correct.
> 
> 3a. I think the assignUser operation will optionally accept a list of ftPAs. 
> There will need to be a way to return the list of possible ftPA, either as 
> part of readRole, or a new method.
> 
> 3b. Either the "filter" ftRC would be left as raw string, or we could create 
> a new object to represent that data. Either way, the data would need attached 
> to UserRole and also possibly Permission. Currently, our application runs the 
> accessMgr_.sessionPermissions(session) to get permissions for a user, so 
> would also need a way to return them there as well. (see #4)
> 
> 3c. Potentially yes, would this cause performance issues?
> 
> 4. Yes, I'll have to look at how the code works, but perhaps something like
> 
> for(UserRole userRole : roles)
> {
>  List<FilterConstraint> constraints = userRole.getFilterConstraints();
>  for (Permission permission : perms)
>  {
>    if (perms.attributes != null)
>      for(PermAttribute attribute : perm.attributes)
>      {
>        if(constraints.contains(attribute)
>           perm.addConstraint(attribute);
>      }
>  }
> } 
> 
> 
> Thanks!
> 
> ~Chris
> 
> 
> 
> ----- Original Message -----
> From: "Shawn McKinney" <[email protected]>
> To: [email protected]
> Sent: Thursday, January 14, 2016 1:09:24 PM
> Subject: Re: Fortress Constraints
> 
>> On Jan 14, 2016, at 10:07 AM, Chris Pike <[email protected]> wrote:
>> 
>> We want to be able to store attributes/constraints in fortress so that we 
>> can do fine grained security checks. We would like to get thoughts/feedback 
>> on this proposal. Our goal is to store permission attributes and role 
>> constraints based on those attribute in fortress, but not necessarily have 
>> fortress make the decision. In our applications, we pull back the list of 
>> roles and permissions when the user logs in, not on every security check, so 
>> we would have the application interpret the constraints. That being said, 
>> here is the proposal...
>> 
> 
> Sounds like an interesting idea.  I’ve got a few questions/comments below….
> 
> 
>> On Jan 14, 2016, at 10:07 AM, Chris Pike <[email protected]> wrote:
>> 
>> 1. Add a new ldap attribute type (ftPA) to store 0 to many attributes about 
>> a permission and other metadata about the attribute (required, valid values, 
>> etc...). It would be up to each application to define it's permissions and 
>> any attributes that are relevant to each permission. In this example, we 
>> have an account.withdraw permission that needs constraints for the account 
>> id and a withdraw limit for each user.
>> 
>> Permission: account.withdraw
>> - ftPA: 
>> AccountId?dataType=int&required=true&validValues=SELF,ANY,int&comparator=equals&default=SELF
>> - ftPA: WithdrawLimit?dataType=int&comparator=max
>> 
> 
> The LDAP schema would look like this?
> 
> # A15: User Role Constraints, type STRING, MULTI VALUE
> attributetype ( 1.3.6.1.4.1.1.38088.1.31
>    NAME 'ftPA'
>    DESC 'Fortress Permission Attribute Constraints'
>    EQUALITY caseIgnoreMatch
>    SUBSTR caseIgnoreSubstringsMatch
>    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
> 
> ftPA is added to 
> 
> ## OC3: Fortress Operation Structural Object Class
> objectclass    ( 1.3.6.1.4.1.38088.2.3
>    NAME 'ftOperation'
>    DESC 'Fortress Permission Operation Structural Object Class'
>    SUP organizationalrole
>    STRUCTURAL
>    MUST (
>        ftId $
>        ftPermName $
>        ftObjNm $
>        ftOpNm
>        )
>    MAY (
>        ftObjId $
>        ftRoles $
>        ftUsers $
>        ftType  $
>        ftPA
>        )
>    )
> 
> The new attribute ftPA is a multi-value string that is optionally attached to 
> the ftOperation structural object class.  Furthermore this attribute will not 
> undergo any constraint checking when being added or modified.  
> 
>> 
>> On Jan 14, 2016, at 10:07 AM, Chris Pike <[email protected]> wrote:
>> 
>> 3. When a user is assigned to a role that has a permission with a ftPA, we 
>> would allow adding of role constraints to the user-role assignment. In this 
>> example, we are changing ftRC so that it can specify a type of constraint 
>> (temporal or filter). There could be many "filter" ftRC entries if the ftPA 
>> were different. We may also want to add a "seq" to allow grouping ftRCs 
>> together.
>> 
>> User: chris
>> - ftRA: BANK_USER
>> - ftRC: 
>> BANK_USER$seq$0$type$temporal$role1$0$1000$0000$none$none$none$none$all
>> - ftRC: BANK_USER$seq$0type$filter$AccountId=12345&WithdrawLimit=500
>> 
> 
> a. The opening phrase, when a user is assigned a role that has a permission 
> with a ftPA, needs to be clarified.  Do you mean that the admin function 
> assignUser operation, will interrogate the role-permissions dataset and 
> determine if one of those permissions has a ftPA attribute assigned?
> 
> b. wrt to ftRC’s.  Currently fortress parses the ftRC (temporal data) into 
> user-role entities and adds to session (List<UserRole> roles) during 
> createSession.  How does it map the data stored in ftRC if the type is 
> filter?  Will it be parsed by fortress or left as raw data inside of a list, 
> (i.e. List<String> filters) that is a member attribute of UserRole or User?
> 
> The same is true in reverse.  When a temporal constraint is added to an 
> entity it uses the Constraint entity to store the data.  If the data passes 
> the validations, i.e. valid date ranges, the DAO will convert to raw data 
> format before adding the ldap entry.
> 
> With our filter attributes are we just going to accept raw data from the 
> caller and persist that directly to the entry in ldap?  
> 
> c. What if there are a 1000 permissions associated with this user that have 
> the ftPA attribute.  Will there be potentially that many ftRC filter strings 
> on a user object?
> 
>> 
>> On Jan 14, 2016, at 10:07 AM, Chris Pike <[email protected]> wrote:
>> 
>> 
>> 4. When getting roles or session permissions for a user, the additional 
>> constraints would need to be returned.
>> 
>> {
>>   "objName": "account",
>>   "opName": "withdraw",
>>   "constraints": [ "AccountId=12345&WithdrawLimit=500" ]
>> }
>> 
> 
> Did fortress join the data found here:
> 
>> Permission: account.withdraw
>> - ftPA: 
>> AccountId?dataType=int&required=true&validValues=SELF,ANY,int&comparator=equals&default=SELF
>> - ftPA: WithdrawLimit?dataType=int&comparator=max
>> 
> 
> 
> with the data found here:
> 
>> User: chris
>> - ftRA: BANK_USER
>> - ftRC: 
>> BANK_USER$seq$0$type$temporal$role1$0$1000$0000$none$none$none$none$all
>> - ftRC: BANK_USER$seq$0type$filter$AccountId=12345&WithdrawLimit=500
> 
> and add that combined data into the Permission entity?  
> 
> If ‘yes’, how will that join happen?
> 
> for(UserRole role : roles)
> {
>  for (Permission permission : perms)
>  {
>    if (perms.attributes != null)
>      for(PermAttribute attribute : perm.attributes)
>      {
>        // if attribute.contains (what?) add value to role
>      }
>  }
> } 
> 
>> 
>> On Jan 14, 2016, at 10:07 AM, Chris Pike <[email protected]> wrote:
>> 
>> 
>> 5. Once our application had the list of permissions and constraints, it 
>> would then do it's own checks, potentially something like...
>> 
>> @PermissionRequired("account.withdraw") //coarse grained check
>> public void withdraw(Account account, float amount){
>> Map map = new HashMap();
>> map.put("WithdrawLimit", amount);
>> map.put("AccountId", account.getId());
>> 
>> doesUserHavePermission("account.withdraw", map); //fine grained check
>> }
> 
> Yes this is fine, or we could add a callback module here that allows your app 
> to be plugged into the flow.
> 
> Shawn

Reply via email to