In Grouper 2.6.6 there is a first pass at JEXL loaded groups. It is basic and can be built on. Note: this is subject to change as we see a working solution and discuss the optimal path forward
We want to be able to craft policies by an expression instead of creating loaders or tons of reference groups based on cartesian products of basis/ref groups.
Individual groups can be configured to automatically have their membership managed with individual subjects (or in future groups as members)
Why do we need this feature?
Note in Grouper v2.6.6 you need to wait an hour after changing a script, or run the JEXL script loader full job. In the future we will have an incremental and run the full nightly. Note: there is one full daemon that handles all of the JEXL script ABAC groups. You do not add this, it is built-in
The script can only be written by people who can READ groups in the script and UPDATE the owner group. Since this is actually a JEXL script (not a JEXL expression), so you could have multiple lines, variables, conditionals, etc
In an entity script, the variable 'entity' is an instance of class: edu.internet2.middleware.grouper.abac.GrouperAbacEntity
You can use entity.memberOf('full:group:id:path') exactly like that to see if user is in a group or not.
Expression | Description | |
---|---|---|
| Three part intersection. Full time staff in MFA | |
| Example policy That means users who are not in globalLockout and not in vpnManualLockout | |
| Exclusive OR This is VPN users not in MFA and MFA users not in VPN: |
There are some trade-offs with performance and resources. This is the current implementation. It is optimized to reduce run-time. It does use a lot of memory, though that was a consideration.
Allow common reference groups to have user friendly labels
e.g. employee instead of ref:employee |
e.g.
FROM Member of employee, and member of app:jiraAdminsManualTO ${entity.memberOf(‘ref:employee’) && entity.memberOf(‘app:jiraAdminsManual’)} |
e.g.
FROM Has affiliation attribute with name of staff and dept of english, but not a member of lockout TO entity.hasAttribute('affiliation', 'name==staff && dept==english') && entity.notMemberOf('ref:lockout') |
This is for a future release
The high level strategy is you need two database tables, a table of people and a table of one-to-many records about those people. This will be configured in your global entity attribute resolver. abac jexl scripted groups would be able to use those similar to this
my_people_table employee_id (same as subject id or identifier) email 123 a@b.c 234 b@c.d my_people_affiliation employee_id affiliation_name dept 123 staff english 123 student history 234 guest chemistry ${ entity.attributeRecordFilter('myPeople', 'affiliation', "(affiliation_name == 'staff' || affiliation_name == 'student') && dept == 'english'") } |
The first argument "myPeople" identifies the entity resolver
The second argument "affiliation" identifies a one-to-many relationship on the main entity resolver table which is another table
The third argument is a filter on that one-to-many table for those people
This means find people where the affiliation has a name of staff or student and that affiliation is in dept english. The format of the filter would not be a well defined subset of jexl... thoughts? Note: this is a little weird since there is a JEXL script embedded in the JEXL script... but we can document it and see how it goes?
Entity resolver change log or last updated col could be used on incremental
Liam Hoekenga 2 minutes ago
why do you need the my_people_table? is there data already in grouper that could be used instead (GROUPER_MEMBERS)?
Chris Hyzer < 1 minute ago
yeah, i was kinda thinking that too. guess it could just be a table which has a col that could be mapped to a subject id or identifier...
Chris Hyzer < 1 minute ago
the entity resolver currently has a table or subjects, one per row. So I think the two tables makes sense. The person table could just be a view of select distinct subject_id from second table right? :slightly_smiling_face:
Chris Hyzer < 1 minute ago
or with one table we would just have the entity resolver be multi valued and have one table... need to think about that :slightly_smiling_face:
Feed the expression through this simple program
Output
Grouper can take that object model and see which group and subject attributes are related, print out a nice analysis of the policy, and know which policies are affected by real time changes Expression 2: campus is palmer or southern, or the term is current with some overlap
Expression 3: primaryAffiliation is faculty or staff and dept is physics or math
|
To confirm a policy is correct, a long form translation of the policy can be displayed along with group names and group counts (future state)
This is a complicated topic since it is parsing a programming language.
As a first pass we could have the overall group and lines from all component groups with count and the exact policy isnt there. This would apply for any unparsable policies once we have better visualization.
In a future pass, if the script follows certain standards and is "parsable" (allow-deny where parens and multiples could be involved), then I could picture a visualization for that. Note: either the visualization will be slow, or lots of data will be cached, or it will be stale from the last full sync. This is because JEXLs cannot be transformed into queries with counts, it needs the data in memory to allow JEXL to do its thing.
We need to get a list of sample policies people want to use so we can make sure we are going in the right direction.
A nightly full sync will occur. The incremental sync should stop. Make sure all the loaded groups are up to date.
An incremental change log consumer can