Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Grouper rules are configurable declarative scripts which run at certain times and perform actions on the registry.  They are similar to hooks though you don't have to write Java, and it does not require a change to a config file to enable a rule (i.e. anyone with authority in the folder hierarchy could enable a rule).  This is similar to JBoss drools.  There is no heuristic to find the best rule, it finds all matching rules to fire.  Rules are unordered.  Some rule "Then" clauses could kick off more rules.

Table of Contents


Info

Check out this page from the API docs for help with Grouper rules


Here is an object which has a rule on it.  Note: rules are configured with the attribute framework.  The attributes that set the rules metadata are set in a configured namespace. Ask your Grouper admins which folder holds these attributes.

...

Here is a diagram which describes what happens when rules fire, and in the background

...


...

Use cases

Click here to see the use cases and examples of how the Grouper rules engine can address them

...

  • actAs: subject that the rule will act as.  If blank, then it will be filled in with the user who created the rule (probably a bad idea since the person might leave at some point, unless it is a service principal).  There can be configurations in the grouper.properties (details) which allow users to act as other users or GrouperSysAdmin.

...

  • ifCondition: this might not be needed if the check contains all the information about when the rule should fire.  You can configure a premade check (enum) or a scriptlet or EL (Expression language).  e.g.

    Code Block
    ${!RulesUtils.hasMember(groupName, subjectSourceId, subjectId)}
    


  • then: this is a premade (enum) or scriptlet (EL: expression language).  e.g. thenType is removeMember and groupName is a:b, or a scriptlet:

    Code Block
    ${RulesUtils.removeMember(groupName, subjectSourceId, subjectId}
    


...

The check component will see if the rule should continue to the "if condition".  The check part is an enum class: edu.internet2.middleware.grouper.rules.RuleCheckType

Look at the javadoc or source for the most recent check types, currently they are:

...

Code Block
grouperSession = GrouperSession.startRootSession();
stem = StemFinder.findByName(grouperSession, "test:testRules");
RuleApi.inheritGroupPrivileges(SubjectFinder.findRootSubject(), stem, Stem.Scope.SUB, SubjectFinder.findRootSubject(), Privilege.getInstances("admin"));
RuleApi.rulesToString(stem);
stem.getAttributeDelegate().removeAttributeByAssignId("af0aa3601b5149a08b71d7d82ea6a906");

 


Error handling

If the rule execution fails for some reason, it should be logged (which could include emailing administrators), but it probably should not affect the transaction of the operation that triggered the rule.  Maybe this can be a setting on a per rule basis and where applicable (e.g. if it is a flattened membership rule trigger, then there is no transaction since the rule fires post commit anyways.

Anchor
ActAs_grouperProperties
ActAs_grouperProperties
Act as

Note that the subject source should be set before the subject id or identifier (if the id or identifier arent unique).  Anyways, you can act as yourself, though I dont know why you would want to do that since if you leave the institution the rule might break.  You can configure in the grouper.properties what the act as rules are, similar to the grouper WS act as.

...

Code Block
gsh 0% new GrouperEmail().setTo("something@somewhere.edu").setBody("email body").setSubject("email subject").send();

Extended EL API
Anchor
Extended_EL_API
Extended_EL_API

There is a special group which has access to more objects in EL:

...

Code Block
attributeAssign.getAttributeValueDelegate().assignValue(
        RuleUtils.ruleThenElName(),
        "${myRuleUtils.removeMemberFromGroupId(ownerGroupId, memberId)}");

...


Validate rules dependent groups/stems

Periodically a Grouper administrator should look at rules and see if dependent objects no longer exist.  You should review the offending rules and probably delete them.  Delete them by navigating to the owner object and removing the attribute assignment for that rule.

First look for invalid rules

Code Block
select * from grouper_rules_v where rule_valid != 'T'

Look at the rule_valid column for the reason.  You might want to run this query and see if any of the results are problems.  Note, this will also show some of the invalid rules

Code Block
select assigned_to_type, assigned_to_group_name, assigned_to_stem_name, assigned_to_attribute_def_name, 'memberSubjectIdNotFound' as reason, assigned_to_member_subject_id as the_data
from grouper_rules_v where assigned_to_member_subject_id is not null and 
not exists (select 1 from grouper_members gm where gm.subject_id = assigned_to_member_subject_id)
union all 
select assigned_to_type, assigned_to_group_name, assigned_to_stem_name, assigned_to_attribute_def_name, 'missingRuleCheckOwnerId' as reason, rule_check_owner_id as the_data
from grouper_rules_v where rule_check_owner_id  is not null 
and not exists (select 1 from grouper_groups gg where gg.id = rule_check_owner_id)
and not exists (select 1 from grouper_stems gs where gs.id = rule_check_owner_id)
and not exists (select 1 from grouper_attribute_def gad where gad.id = rule_check_owner_id)
union all 
select assigned_to_type, assigned_to_group_name, assigned_to_stem_name, assigned_to_attribute_def_name, 'missingRuleCheckOwnerName' as reason, rule_check_owner_name as the_data
from grouper_rules_v where rule_check_owner_name is not null 
and not exists (select 1 from grouper_groups gg where gg.name = rule_check_owner_name)
and not exists (select 1 from grouper_stems gs where gs.name = rule_check_owner_name)
and not exists (select 1 from grouper_attribute_def gad where gad.name = rule_check_owner_name)
union all 
select assigned_to_type, assigned_to_group_name, assigned_to_stem_name, assigned_to_attribute_def_name, 'missingRuleIfOwnerId' as reason, rule_if_owner_id as the_data
from grouper_rules_v where rule_if_owner_id is not null 
and not exists (select 1 from grouper_groups gg where gg.id = rule_if_owner_id)
and not exists (select 1 from grouper_stems gs where gs.id = rule_if_owner_id)
and not exists (select 1 from grouper_attribute_def gad where gad.id = rule_if_owner_id)
union all 
select assigned_to_type, assigned_to_group_name, assigned_to_stem_name, assigned_to_attribute_def_name, 'missingRuleIfOwnerName' as reason, rule_if_owner_name as the_data
from grouper_rules_v where rule_if_owner_name is not null 
and not exists (select 1 from grouper_groups gg where gg.name = rule_if_owner_name)
and not exists (select 1 from grouper_stems gs where gs.name = rule_if_owner_name)
and not exists (select 1 from grouper_attribute_def gad where gad.name = rule_if_owner_name)
union all
select assigned_to_type, assigned_to_group_name, assigned_to_stem_name, assigned_to_attribute_def_name, 'missingRuleThenArg0' as reason, rule_then_enum_arg0 as the_data
from grouper_rules_v where rule_then_enum_arg0 like 'g:gsa :::: %' and not exists (select 1 from grouper_groups gg where 
rule_then_enum_arg0 = concat('g:gsa :::: ', gg.id ));

To find a missing group in PIT run this:

Code Block
select * from grouper_pit_groups where source_id = 'f4ae2524dda34129b8b17abeebb7c8c9';


Troubleshooting rules

To troubleshoot rules, set the logging debug level, and check the grouper logs.  Edit the log4j.properties:

...