Include Page | ||||
---|---|---|---|---|
|
Table of Contents |
---|
Panel | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
This topic is discussed in the "Grouper API - Part 2" training video. |
...
Code Block |
---|
export GSH_JVMARGS="-Dlibrary.jansi.path=/some/other/temp/path/with/exec" |
Supported Commands
Grouper API methods
Any Grouper API method can be directly invoked just by referencing it, inclusive of the class in which it is defined. Methods return a java object which can be stored in a variable. For example, the following gsh session determines all of the groups to which a given subject belongs:
Environment variables that affect GSH startup:
- GROUPER_HOME: if set to a valid Grouper directory, it will use this directory. Otherwise, it will determine it based on the path to gsh
- GROUPER_CONF: if set to a valid conf directory, it will use this directory. Otherwise it will determine it based on GROUPER_HOME
- MEM_START: Override the default -Xms Java parameter (initial Java heap size)
- MEM_MAX: Override the default -Xmx Java parameter (maximum Java heap size)
- CLASSPATH: Will prepend to the constructed classpath
- GSH_JVMARGS: Additional arguments to pass to Java
- GSH_CYGWIN: (since 2.4.0 api patch 3) if set and not blank, the script will convert paths and the classpath to Windows-style, for use with Windows Java under Cygwin
- GSH_QUIET: (since 2.4.0 api patch 3) if set and not blank, will not output preliminary diagnostic information before starting Java, other than errors
Command line arg in script
Code Block |
---|
./gsh -runarg 'userToFind="user1"\n:load "/opt/grouper/scripts/myGSHScript.gsh"' |
Supported Commands
Grouper API methods
Any Grouper API method can be directly invoked just by referencing it, inclusive of the class in which it is defined. Methods return a java object which can be stored in a variable. For example, the following gsh session determines all of the groups to which a given subject belongs:
No Format |
---|
gsh 0% GrouperSession.startRootSession();
gsh 0% subj = findSubject("SD00125")
subject: |
No Format |
gsh 0% GrouperSession.startRootSession(); gsh 0% subj = findSubject("SD00125") subject: id='SD00125' type='person' source='kitn-person' name='Barton, Tom' gsh 1% sess = GrouperSession.start(subj) edu.internet2.middleware.grouper.GrouperSession: 29c40f97-9fb0-4e45-88bc-a14877a6c9b5,'SD00125','person' gsh 2% member = MemberFinder.findBySubject(sess, subj) member: id='SD00125' type='person' source='kitn-person' uuidname='d0fa765e-1439-4701-89b1-9b08b4ce9daaBarton, Tom' gsh 1% sess 3%= memberGrouperSession.getGroupsstart(subj) edu.internet2.middleware.grouper.GrouperSession: 29c40f97-9fb0-4e45-88bc-a14877a6c9b5,'SD00125','person' gsh 2% member = MemberFinder.findBySubject(sess, subj) member: id='SD00125' type='person' source='kitn-person' uuid='d0fa765e-1439-4701-89b1-9b08b4ce9daa' gsh 3% member.getGroups() group: name='etc:sysadmingroup' displayName='Grouper Administration:SysAdmin Group' uuid='6f77fb36-b466-481a-84a7-7af609f1ad09' |
...
Command | Description | ||
---|---|---|---|
addSubject(id, type, name) | Add local subject to registry. You need the jdbc source for this to work. The type parameter describes the type of subject (e.g. "people"), and is required non-null even though there are few useful api methods to query it. In 2.4.0.api.41+ patch, this will In 2.4.0.api.41+ patch, this will also create the id, name, description, and loginid attribute (unless grouper.properties create.attributes.when.creating.registry.subjects is false) | ||
RegistrySubject.addOrUpdate(grouperSession, id, type, name, nameAttributeValue, loginid, description, email) | In 2.4.0.api.41+ patch, add a registry subject like addSubject, but specify the attribute values of name, loginid, etc e.g. RegistrySubject.addOrUpdate(grouperSession, "someTestSubject", "person", "Some Testsubject", "Name Some Test Subject", "stsub", "Some Testsubject - employee - also alumni", "some@test.subject"); | ||
RegistrySubject.find(id, errorOnNotFound) | In 2.4.0.api.41+ patch, get a registry subject e.g. registrySubject = RegistrySubject.find("someTestSubject", false); | ||
registrySubject.delete(grouperSession) | In 2.4.0.api.41+ patch, delete a registry subject e.g. registrySubject.delete(grouperSession); | ||
RegistrySubjectAttribute.addOrUpdate(subjectId, attributeName, attributeValue) | In 2.4.0.api.41+ patch, add or update a registry subject attribute | ||
registrySubjectAttribute.delete() | In 2.4.0.api.41+ patch, delete an attribute value | ||
findSubject(ididOrIdentifier) | Find a subject by id or identifier | ||
findSubject(ididOrIdentifier, type) | Find a subject by id or identifier; type is a deprecated parameter that is ignored | ||
findSubject(ididOrIdentifier, type, source) | Find a subject by id or identifier for a specific subject source; type is a deprecated parameter that is ignored | ||
getSources() | Find all Subject sources | ||
grouperSession = GrouperSession.startRootSession(); | Find all subjects in a source by search string | ||
grouperSession = GrouperSession.startRootSession(); | Find a subject by id in a certain source | ||
grouperSession = GrouperSession.startRootSession(); | Find a subject by identifier in a certain source | ||
grouperSession = GrouperSession.startRootSession(); | Find a subject by id or identifier in a certain source | ||
add test subjects to registry (e.g. test.subject.0 through 9) | grouperSession = GrouperSession.startRootSession(); | ||
Edit subject (in this case name) | RegistrySubject registrySubject = GrouperDAOFactory.getFactory().getRegistrySubject().find("user1a", "person", true); | ||
add a subject application principal with attributes (GSH) |
| ||
remove a subject with attributes (GSH) |
|
...
Above, it describes how you can kick off the loader in daemon mode. You can also execute one job with:
...
Command
...
Description
...
grouperSession = GrouperSession.startRootSession();
loaderGroup = GroupFinder.findByName(grouperSession, "stem:group");
loaderRunOneJob(loaderGroup);
...
Kick off the loader for one group (configured by group attributes)
...
loaderRunOneJob("MAINTENANCE_cleanLogs");
...
Kick off the loader by job name
...
loaderRunOneJob("CHANGE_LOG_changeLogTempToChangeLog");
...
Move change log entries from the temp table to the real table
...
loaderRunOneJob("CHANGE_LOG_consumer_grouperRules");
loaderRunOneJob("MAINTENANCE__rules");
...
Run the Grouper Rules daemon (the changelog or full version)
...
loaderRunOneJob("CHANGE_LOG_consumer_test");
...
Run a change log consumer
This query (in Oracle) will find jobs with no success in the last day and make a gsh script:
Code Block |
---|
select distinct 'loaderRunOneJob("' || job_name || '");' as script
from grouper_loader_log gll where started_time > sysdate-1 and status != 'SUCCESS'
and gll.job_name not like 'subjobFor%'
and not exists (select 1 from grouper_loader_log gll2 where gll2.started_time > sysdate-1
and gll2.status = 'SUCCESS' and gll2.job_name = gll.job_name) |
Code Block | ||||
---|---|---|---|---|
| ||||
select distinct job_name from grouper_loader_log gll where started_time > CURRENT_DATE - 1 DAY and status != 'SUCCESS' and gll.job_name not like 'subjobFor%'
AND NOT EXISTS (select job_name from grouper_loader_log gll2 where gll2.started_time > CURRENT_DATE - 1 DAY and gll2.status = 'SUCCESS' and gll2.job_name = gll.job_name) |
v1.6+ loader
...
Command
...
Description
...
loaderRunOneJobAttr(attirbuteDef)
...
Run an attribute definition loader job
You can run the loader as a linux service
GrouperShell Variables (BeanShell only)
gsh has several variables that can be set to modify runtime behavior
...
Variable
...
Description
...
GSH_DEBUG
...
Stack traces will be printed upon failure if true
...
GSH_DEVEL
...
Summaries of returned objects are not automatically printed if true
...
GSH_TIMER
...
Prints time spent evaluating each command if true
loader in daemon mode. You can also execute one job with:
Command | Description |
---|---|
grouperSession = GrouperSession.startRootSession(); | Kick off the loader for one group (configured by group attributes) |
loaderRunOneJob("MAINTENANCE_cleanLogs"); | Kick off the loader by job name |
loaderRunOneJob("CHANGE_LOG_changeLogTempToChangeLog"); | Move change log entries from the temp table to the real table |
loaderRunOneJob("CHANGE_LOG_consumer_grouperRules"); | Run the Grouper Rules daemon (the changelog or full version) |
loaderRunOneJob("CHANGE_LOG_consumer_test"); | Run a change log consumer |
GrouperLoaderType.validateAndScheduleSqlLoad(group, null, false) | Schedule SQL job |
GrouperLoaderType.validateAndScheduleLdapLoad(attributeAssign, null, false) | Schedule LDAP job |
GrouperLoaderType.scheduleAttributeLoads(); | Schedule all attribute loader jobs |
This query (in Oracle) will find jobs with no success in the last day and make a gsh script:
Code Block |
---|
select distinct 'loaderRunOneJob("' || job_name || '");' as script
from grouper_loader_log gll where started_time > sysdate-1 and status != 'SUCCESS'
and gll.job_name not like 'subjobFor%'
and not exists (select 1 from grouper_loader_log gll2 where gll2.started_time > sysdate-1
and gll2.status = 'SUCCESS' and gll2.job_name = gll.job_name) |
Code Block | ||||
---|---|---|---|---|
| ||||
select distinct job_name from grouper_loader_log gll where started_time > CURRENT_DATE - 1 DAY and status != 'SUCCESS' and gll.job_name not like 'subjobFor%'
AND NOT EXISTS (select job_name from grouper_loader_log gll2 where gll2.started_time > CURRENT_DATE - 1 DAY and gll2.status = 'SUCCESS' and gll2.job_name = gll.job_name) |
v1.6+ loader
Command | Description |
---|---|
loaderRunOneJobAttr(attirbuteDef) | Run an attribute definition loader job |
You can run the loader as a linux service
GrouperShell Variables (BeanShell only)
gsh has several variables that can be set to modify runtime behavior
Variable | Description |
---|---|
GSH_DEBUG | Stack traces will be printed upon failure if true |
GSH_DEVEL | Summaries of returned objects are not automatically printed if true |
GSH_TIMER | Prints time spent evaluating each command if true |
Example:
No Format |
---|
gsh 4% GSH_DEVEL = true
gsh 5% subj = findSubject("SD00125")
gsh 6% sess = GrouperSession.start(subj)
gsh 7% member = MemberFinder.findBySubject(sess, subj)
gsh 8% p(member.getGroups())
group: name='etc:sysadmingroup' displayName='Grouper Administration:SysAdmin Group' uuid='6f77fb36-b466-481a-84a7-7af609f1ad09'
|
Membership scripts
Code Block |
---|
# (1) Print tab-separated summary of all group members, and flags for direct, indirect, or both
# Depending on the results, you could use the data to create a scrutinized list of Ids to delete, then import it and delete in a loop
me = SubjectFinder.findByIdentifierAndSource("my-username", "pid", true);
session = GrouperSession.start(me);
// OR: session = GrouperSession.startRootSession(True)
group = GroupFinder.findByName(session, "tmp:my:group", true);
effectiveMembers = group.getEffectiveMembers();
immediateMembers = group.getImmediateMembers();
System.out.println(String.join("\t", "id", "name", "Effective", "Immediate"));
for (Member m: group.getMembers()) {
System.out.print(m.getSubject().getId() + "\t" + m.getSubject().getName() + "\t");
System.out.print(effectiveMembers.contains(m).toString() + "\t");
System.out.println(immediateMembers.contains(m).toString() + "\t");
}
# (2) Get the immediate and effective members for a specific source ("pid" in this example), intersect them to find the redundant ones
# This has a dryRun flag, so you can test first
sources = new HashSet<Source>()
sources.add(SourceManager.getInstance().getSource("pid"))
effectiveUsers = group.getEffectiveMembers(Group.getDefaultList(), sources, null)
immediateUsers = group.getImmediateMembers(Group.getDefaultList(), sources, null)
# use retainAll() to find the intersection; i.e., users both as effective and immediate member
immediateUsers.retainAll(effectiveUsers)
System.out.println("There are " + immediateUsers.size() + " users having both direct + indirect memberships");
dryRun = true
for (Member m: immediateUsers) {
if (dryRun) {
System.out.println("Ok to delete |
Example:
No Format |
---|
gsh 4% GSH_DEVEL = true
gsh 5% subj = findSubject("SD00125")
gsh 6% sess = GrouperSession.start(subj)
gsh 7% member = MemberFinder.findBySubject(sess, subj)
gsh 8% p(member.getGroups())
group: name='etc:sysadmingroup' displayName='Grouper Administration:SysAdmin Group' uuid='6f77fb36-b466-481a-84a7-7af609f1ad09'
|
Membership scripts
Code Block |
---|
# (1) Print tab-separated summary of all group members, and flags for direct, indirect, or both # Depending on the results, you could use the data to create a scrutinized list of Ids to delete, then import it and delete in a loop me = SubjectFinder.findByIdentifierAndSource("my-username", "pid", true); session = GrouperSession.start(me); // OR: session = GrouperSession.startRootSession(True) group = GroupFinder.findByName(session, "tmp:my:group", true); effectiveMembers = group.getEffectiveMembers(); immediateMembers = group.getImmediateMembers(); System.out.println(String.join("\t", "id", "name", "Effective", "Immediate")); for (Member m: group.getMembers()) { System.out.print(m.getSubject().getId() + "\t" + m.getSubject().getNamegetId()) + "\t"); ; } else { System.out.print(effectiveMembers.contains(m).toString() + "\t"println("Deleting " + m.getSubject().getId()); System.out.println(immediateMembers.contains(m).toString() + "\t"); } group.deleteMember(m, false); } } # (23) Get the immediate and effective members for groups this subject is a member of. Note that a specificgroup source ("pid" in this example), intersect them to find the redundant ones # This has a dryRun flag, so you can test first sourcesis a kind of subject, and has a toSubject() method to convert it. import edu.internet2.middleware.grouper.membership.MembershipSubjectContainer GrouperSession grouperSession = GrouperSession.startRootSession(); Group group = GroupFinder.findByName(grouperSession, "test:testGroup", true); Subject subject = g.toSubject(); Set<MembershipSubjectContainer> msc = new HashSet<Source>MembershipFinder() sources.addaddSubject(SourceManagersubject).getInstancefindMembershipResult().getSourcegetMembershipSubjectContainers("pid")); effectiveUsersfor = group.getEffectiveMembers(Group.getDefaultList(), sources, null) immediateUsers = group.getImmediateMembers(Group.getDefaultList(), sources, null) # use retainAll() to find the intersection; i.e., users both as effective and immediate member immediateUsers.retainAll(effectiveUsers) System.out.println("There are " + immediateUsers.size() + " users having both direct + indirect memberships"); dryRun = true for (Member m: immediateUsers) { if (dryRun) { System.out.println("Ok to delete " + m.getSubject().getId()); } else { System.out.println("Deleting " + m.getSubject().getId()); group.deleteMember(m, false); } } (MembershipSubjectContainer membershipSubjectContainer : msc) { println(membershipSubjectContainer.getGroupOwner().getName());} //Note there are a few other options for the search. Add these to the MembershipFinder method chain before calling findMembershipResult(): // - search immediate, effective, etc. (needs to import MembershipType) import edu.internet2.middleware.grouper.membership.MembershipType membershipFinder.assignMembershipType(MembershipType.IMMEDIATE) // options are IMMEDIATE|NONIMMEDIATE|EFFECTIVE|COMPOSITE // - retrieve specific groups based on pattern membershipFinder.assignScope("%:test:%") // - Enabled status -- true means enabled only, false, means disabled only, and null means all membershipFinder.assignEnabled(false) // For other methods, refer to the Javadoc at http://internet2.github.io/grouper/master/grouper-parent/apidocs/edu/internet2/middleware/grouper/MembershipFinder.html |
Misc
Note: you cannot encrypt passwords with GSH since the passwords end up in the GSH history. To encrypt passwords, issue the command:
...
Code Block |
---|
String provisionTarget = "ad";
GrouperSession grouperSession = GrouperSession.startRootSession();
Set stemsToProvisionToSet = HibernateSession.byHqlStatic().createQuery("select s from Stem s, AttributeAssign aa, AttributeDefName adn, AttributeAssignValue aav where s.id = aa.ownerStemId and aav.attributeAssignId = aa.id and aa.attributeDefNameId = adn.id and aa.attributeAssignTypeDb = 'stem' and aa.enabledDb = 'T' and adn.extensionDb = 'provision_to' and aav.valueString = '" + provisionTarget + "'").listSet(Stem.class);
for (Object stemObject : stemsToProvisionToSet) { Stem stem = (Stem)stemObject; System.out.println("provision_to assigned to stem: " + stem.getName()); }
Set stemsToNotProvisionToSet = HibernateSession.byHqlStatic().createQuery("select s from Stem s, AttributeAssign aa, AttributeDefName adn, AttributeAssignValue aav where s.id = aa.ownerStemId and aav.attributeAssignId = aa.id and aa.attributeDefNameId = adn.id and aa.attributeAssignTypeDb = 'stem' and aa.enabledDb = 'T' and adn.extensionDb = 'do_not_provision_to' and aav.valueString = '" + provisionTarget + "'").listSet(Stem.class);
for (Object stemObject : stemsToNotProvisionToSet) { Stem stem = (Stem)stemObject; System.out.println("do_not_provision_to assigned to stem: " + stem.getName()); }
Set groupsToProvisionToSet = HibernateSession.byHqlStatic().createQuery("select g from Group g, AttributeAssign aa, AttributeDefName adn, AttributeAssignValue aav where g.id = aa.ownerGroupId and aav.attributeAssignId = aa.id and aa.attributeDefNameId = adn.id and aa.attributeAssignTypeDb = 'group' and aa.enabledDb = 'T' and adn.extensionDb = 'provision_to' and aav.valueString = '" + provisionTarget + "'").listSet(Stem.class);
for (Object groupObject : groupsToProvisionToSet) { Group group = (Group)groupObject; System.out.println("provision_to assigned to group: " + group.getName()); }
Set groupsToNotProvisionToSet = HibernateSession.byHqlStatic().createQuery("select g from Group g, AttributeAssign aa, AttributeDefName adn, AttributeAssignValue aav where g.id = aa.ownerGroupId and aav.attributeAssignId = aa.id and aa.attributeDefNameId = adn.id and aa.attributeAssignTypeDb = 'group' and aa.enabledDb = 'T' and adn.extensionDb = 'do_not_provision_to' and aav.valueString = '" + provisionTarget + "'").listSet(Stem.class);
for (Object groupObject : groupsToNotProvisionToSet) { Group group = (Group)groupObject; System.out.println("do_not_provision_to assigned to group: " + group.getName()); }
Set allGroups = new LinkedHashSet();
Set allGroupsToProvision = new TreeSet();
allGroupsToProvision.addAll(groupsToProvisionToSet);
Set stemNamesToNotProvisionTo = new HashSet();
Set stemNamesToProvisionTo = new HashSet();
for (Object stemToProvision : stemsToProvisionToSet) { stemNamesToProvisionTo.add(((Stem)stemToProvision).getName()); }
for (Object stemNotToProvision : stemsToNotProvisionToSet) { stemNamesToNotProvisionTo.add(((Stem)stemNotToProvision).getName()); }
for (Object stemToProvision : stemsToProvisionToSet) { allGroups.addAll(((Stem)stemToProvision).getChildGroups(edu.internet2.middleware.grouper.Stem.Scope.SUB)); }
Map groupToPaths = new HashMap();
for (Object groupObject : allGroups) { Group group = (Group)groupObject; if (allGroupsToProvision.contains(group)) {continue;} if (groupsToNotProvisionToSet.contains(group)) {continue;} List paths = new ArrayList(); groupToPaths.put(group, paths); String currentName = group.getName(); paths.add(currentName); while(true) { currentName = GrouperUtil.parentStemNameFromName(currentName); if (GrouperUtil.isBlank(currentName)) {break;} paths.add(currentName); } }
for (Object groupObject : groupToPaths.keySet()) {Group group = (Group)groupObject; List paths = (List)groupToPaths.get(group); for (Object pathObject : paths) { String path = (String)pathObject; if (stemNamesToProvisionTo.contains(path)) { allGroupsToProvision.add(group); break; } if (stemNamesToNotProvisionTo.contains(path)) { break; } } }
for (Object groupObject : allGroupsToProvision) { Group group = (Group)groupObject; System.out.println("configured to provision to: " + provisionTarget + ": " + group.getName()); }
|
Stem move
try this:
Code Block |
---|
GrouperSession.startRootSession(); stemFrom = StemFinder.findByName(grouperSession, "a:b", true); stemTo = StemFinder.findByName(grouperSession, "a:c", true); new edu.internet2.middleware.grouper.StemMove(stemFrom, stemTo).assignAlternateName(false).save(); |