...
Panel | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
This topic is discussed in the "Grouper API - Part 2" training video. |
GrouperShell (gsh)
gsh is a command line shell for administering and interacting with the Grouper API. See architectural diagram. It can be used in both a batch and interactive manner. For Grouper 2.3.0 patch 72+, it is built on GroovyShell. For older versions of Grouper, it is built on Java BeanShell. The legacy BeanShell version is now deprecated, but you can switch back to it by using one of the options:
- Setting gsh.useLegacy = true in grouper.properties.
- Using a command line argument (gsh.sh -forceLegacyGsh)
GrouperShell is for Grouper admins. End users can script with the grouper client command line utility
GSH operations
NOTE: Some classes were added a later 2.5.x releases. Not all are documented as to when they were initially added.
Category | Subtype | Action | Class |
---|---|---|---|
Attestation | Folders | insert / update / delete | AttestationStemSave |
Groups | insert / update / delete | AttestationGroupSave | |
Attribute assignment | Attribute assignment | insert / update / delete | AttributeAssignToAssignmentSave (2.5.48+) |
Folders | insert / update / delete | AttributeAssignToStemSave | |
Group | insert / update / delete | AttributeAssignToGroupSave | |
Attribute definition | insert / update / delete | AttributeDefSave | |
Attribute name | insert / update / delete | AttributeDefNameSave | |
Attribute value | insert / update / delete | AttributeAssignValueSave | |
Composite | insert /update / delete | CompositeSave | |
finder | CompositeFinder | ||
Email SMTP | GrouperEmail | ||
Gc db access | gc db access | GcDbAccess | |
Grouper session | GrouperSession | ||
Group | insert / update / delete | GroupSave | |
finder | GroupFinder | ||
copy | GroupCopy | ||
gsh | gsh template exec | GshTemplateExec | |
Http | GrouperHttpClient | ||
Ldap | ldap session utils | LdapSessionUtils | |
Member | finder | MemberFinder | |
Membership | insert / update / delete | MembershipSave | |
finder | MembershipFinder | ||
Password | insert / update / delete | GrouperPasswordSave | |
Privilege inheritance | Attribute definitions | insert / update / delete | PrivilegeAttributeDefInheritanceSave |
Folders | insert / update / delete | PrivilegeStemInheritanceSave | |
Groups | insert / update / delete | PrivilegeGroupInheritanceSave | |
Provisionable | Folders | finder | ProvisionableStemFinder |
insert / update / delete | ProvisionableStemSave | ||
Groups | finder | ProvisionableGroupFinder | |
insert / update / delete | ProvisionableGroupSave | ||
Stem | insert/update/delete | StemSave | |
finder | StemFinder | ||
copy | StemCopy | ||
Subject | finder | SubjectFinder | |
Sync data to SQL table | GcTableSyncFromData | ||
Types | Folders | finder | GdgTypeStemFinder |
insert / update / delete | GdgTypeStemSave | ||
Groups | finder | GdgTypeGroupFinder | |
insert / update / delete | GdgTypeGroupSave |
GrouperShell (gsh)
gsh is a command line shell for administering and interacting with the Grouper API. See architectural diagram. It can be used in both a batch and interactive manner. For Grouper 2.3.0 patch 72+, it is built on GroovyShell. For older versions of Grouper, it is built on Java BeanShell. The legacy BeanShell version is now deprecated, but you can switch back to it by using one of the options:
- Setting gsh.useLegacy = true in grouper.properties.
- Using a command line argument (gsh.sh -forceLegacyGsh)
GrouperShell is for Grouper admins. End users can script with the grouper client command line utility
JEXL hints and tricks
Hints and tricks
Escape things in Escape things in groovysh with single backslash. e.g.
...
Code Block |
---|
FROM Object[] row = new Object[] {emailFromOutsystems, pennkeyPerhaps}; TO Object[] row = new Object[2]; row[0] = emailFromOutsystems; row[1] = pennkeyPerhaps; |
API Compability
Reset the shell after an error:
:c
Escape dollars, e.g. "${something}"
Code Block |
---|
'$' + "{something}" |
Externalized text
Code Block |
---|
if you add to externalized text (config in ui), just make a key, e.g. mySchoolEmailKey, then refer to it like this
import edu.internet2.middleware.grouper.cfg.text.GrouperTextContainer;
String template = GrouperTextContainer.textOrNull("mySchoolEmailKey"); |
API Compability
gsh gsh is now a core part of the Grouper API and so is always compatible with the current release.
...
Code Block |
---|
GrouperSession grouperSession = GrouperSession.startRootSession(); Stem stem = StemFinder.findByName(grouperSession, "test:gdg:app", true); AttributeDefName typeMarker = AttributeDefNameFinder.findByName("etc:objectTypes:grouperObjectTypeMarker", true); AttributeAssign attributeAssign = stem.getAttributeDelegate().hasAttribute(typeMarker) ? stem.getAttributeDelegate().retrieveAssignments(typeMarker).iterator().next() : stem.getAttributeDelegate().addAttribute(typeMarker).getAttributeAssign(); attributeAssign.getAttributeValueDelegate().assignValue("etc:objectTypes:grouperObjectTypeDirectAssignment", "true"); attributeAssign.getAttributeValueDelegate().assignValue("etc:objectTypes:grouperObjectTypeName", "app"); |
Set attribute on group
Provisionable on folder with metadata
Code Block | ||||
---|---|---|---|---|
GrouperSession grouperSession | ||||
Code Block | ||||
| ||||
grouperSession = GrouperSession.startRootSession(); g AttributeAssign attributeAssignMarker = null; attributeAssignMarker = GroupFinder.findByName(grouperSession, "admin:loader_groups"); type = typeAdd("sync_group"); type.addAttribute(grouperSession, "sync_group", false, "sync"); groupAddType("admin:loader_groups", "sync_group"); g.setAttribute("sync", "true"); |
...
Command
...
Description
...
groupAddType(group name, type name)
...
Add type to group
...
groupDelType(group name, type name)
...
Delete type from group
...
groupGetTypes(group name)
...
Get group's types
...
groupHasType(group name, type name)
...
Check whether group had type
...
typeAdd(type name)
...
Create custom group type
...
typeAddAttr(type name, attr name, read, write, required)
...
Create custom group attribute. read and write must be an AccessPrivilege
(e.g. AccessPrivilege.ADMIN
)
...
typeAddList(type name, attr name, read, write)
...
Create a custom list. read and write must be an AccessPrivilege
(e.g. AccessPrivilege.ADMIN
).
...
typeDel(type name)
...
Delete group type
...
typeDelField(type name, field name)
...
Delete custom field from group type
...
typeFind(type name)
...
Find the group
...
typeGetFields(type name)
...
Get fields associated with the group type
Member change subject
"Member change subject" will change the subject that a member refers to. You would want to do this when a person or entity changes their id, or if they were loaded wrong in the system. If the new subject does not have a member associated with it, this is a simple case, where the subject data is put in the member object. If the new subject does have a member object, then all data in all tables that referred to the old member object, will now refer to the new member object. The old member is deleted from the member table by default, though this is an option. Generally you will want it removed, unless there is a foreign key problem where you need to do as much work as possible. In GSH you can get a dry-run report of what will be done.
The operation is potentially time consuming only when two formerly separate Subjects are being merged into one, and that the time required is to replace the memberships (and audit fields e.g. modifiedBy) of the formerly separate Subject that is being retired with new ones associated with the other Subject.
grouperSession = GrouperSession.startRootSession();
oldSubject = findSubject("10021368");
member = MemberFinder.findBySubject(grouperSession, oldSubject);
newSubject = findSubject("10021366");
member.changeSubject(newSubject);
...
Command
...
Description
...
member.changeSubject(newSubject);
...
Change the subject of the member object. If the subject is the same, its a no-op. If the new subject does not have a Member object, then the existing member object simply gets new subject information. If the new subject does have a member object, then all objects in the grouper registry which uses the old member, will be updated to the new member. Then the old member object is deleted from the registry
...
member.changeSubject(newSubject,!Member.DELETE_OLD_MEMBER);
...
Change the subject, but dont delete the old member. Do this if the way which deletes the old member doesnt work due to foreign keys. This will do all the work it can, and the rest can be manual
...
member.changeSubjectReport(newSubject,Member.DELETE_OLD_MEMBER);
...
Dont do any of the work, just print a report to the screen of what will be done. Dry-run.
new AttributeAssignSave(grouperSession).assignOwnerStemName("test:chris:test").assignNameOfAttributeDefName("etc:provisioning:provisioningMarker").save();
new AttributeAssignSave(grouperSession).assignOwnerAttributeAssign(attributeAssignMarker).assignNameOfAttributeDefName("etc:provisioning:provisioningDirectAssign").addValue("true").save();
new AttributeAssignSave(grouperSession).assignOwnerAttributeAssign(attributeAssignMarker).assignNameOfAttributeDefName("etc:provisioning:provisioningDoProvision").addValue("ADTest").save();
new AttributeAssignSave(grouperSession).assignOwnerAttributeAssign(attributeAssignMarker).assignNameOfAttributeDefName("etc:provisioning:provisioningStemScope").addValue("sub").save();
new AttributeAssignSave(grouperSession).assignOwnerAttributeAssign(attributeAssignMarker).assignNameOfAttributeDefName("etc:provisioning:provisioningTarget").addValue("ADTest").save();
new AttributeAssignSave(grouperSession).assignOwnerAttributeAssign(attributeAssignMarker).assignNameOfAttributeDefName("etc:provisioning:provisioningMetadataJson").addValue("{\"md_trim_prefix\":\"whatever\",\"md_entityId\":\"theEntityId\"}").save();
|
Set attribute on group
Code Block | ||||
---|---|---|---|---|
| ||||
grouperSession = GrouperSession.startRootSession();
g = GroupFinder.findByName(grouperSession, "admin:loader_groups");
type = typeAdd("sync_group");
type.addAttribute(grouperSession, "sync_group", false, "sync");
groupAddType("admin:loader_groups", "sync_group");
g.setAttribute("sync", "true"); |
Command | Description |
---|---|
groupAddType(group name, type name) | Add type to group |
groupDelType(group name, type name) | Delete type from group |
groupGetTypes(group name) | Get group's types |
groupHasType(group name, type name) | Check whether group had type |
typeAdd(type name) | Create custom group type |
typeAddAttr(type name, attr name, read, write, required) | Create custom group attribute. read and write must be an |
typeAddList(type name, attr name, read, write) | Create a custom list. read and write must be an |
typeDel(type name) | Delete group type |
typeDelField(type name, field name) | Delete custom field from group type |
typeFind(type name) | Find the group |
typeGetFields(type name) | Get fields associated with the group type |
Member change subject
"Member change subject" will change the subject that a member refers to. You would want to do this when a person or entity changes their id, or if they were loaded wrong in the system. If the new subject does not have a member associated with it, this is a simple case, where the subject data is put in the member object. If the new subject does have a member object, then all data in all tables that referred to the old member object, will now refer to the new member object. The old member is deleted from the member table by default, though this is an option. Generally you will want it removed, unless there is a foreign key problem where you need to do as much work as possible. In GSH you can get a dry-run report of what will be done.
The operation is potentially time consuming only when two formerly separate Subjects are being merged into one, and that the time required is to replace the memberships (and audit fields e.g. modifiedBy) of the formerly separate Subject that is being retired with new ones associated with the other Subject.
grouperSession = GrouperSession.startRootSession();
oldSubject = findSubject("10021368");
member = MemberFinder.findBySubject(grouperSession, oldSubject);
newSubject = findSubject("10021366");
member.changeSubject(newSubject);
Command | Description |
---|---|
member.changeSubject(newSubject); | Change the subject of the member object. If the subject is the same, its a no-op. If the new subject does not have a Member object, then the existing member object simply gets new subject information. If the new subject does have a member object, then all objects in the grouper registry which uses the old member, will be updated to the new member. Then the old member object is deleted from the registry |
member.changeSubject(newSubject,!Member.DELETE_OLD_MEMBER); | Change the subject, but dont delete the old member. Do this if the way which deletes the old member doesnt work due to foreign keys. This will do all the work it can, and the rest can be manual |
member.changeSubjectReport(newSubject,Member.DELETE_OLD_MEMBER); | Dont do any of the work, just print a report to the screen of what will be done. Dry-run. |
Memberships
Command | Description |
---|---|
addComposite(group name, composite type, left group name, right group name) | Add composite membership. e.g. CompositeType.UNION |
addMember(group name, subject id) | Add member to the members list for the group. |
addMember(group name, subject id, field) | Add member to the specified list for the group. |
delComposite(group name) | Delete composite membership from group |
delMember(group name, subject id) | Delete member from the members list for the group |
delMember(group name, subject id, field) | Delete member from the specified list for the group |
getMembers(group name) | Get members of group |
hasMember(group name, subject id) | Check whether subject is member of the members list |
hasMember(group name, subject id, field) | Check whether subject is member of the specified list |
GrouperSession grouperSession = GrouperSession.startRootSession(); Group group = GroupFinder.findByName(grouperSession, "a:b:c", true); group.addMember(SubjectFinder.findByIdAndSource("someId", "sourceId", true), false); | Add member with subjectId and sourceId |
GrouperSession grouperSession = GrouperSession.startRootSession(); Group group = GroupFinder.findByName(grouperSession, "a:b:c", true); group.addMember(SubjectFinder.findByIdentifierAndSource("someIdentifier", "sourceId", true), false); | Add member with subjectIdentifier and sourceId |
Privileges
Command | Description |
---|---|
grantPriv(group name, subject id, privilege) | Grant privilege on group. privilege must be an AccessPrivilege (e.g. |
grantPriv(stem name, subject id, privilege) | Grant privilege on stem. privilege must be a NamingPrivilege (e.g. |
hasPriv(group name, subject id, privilege) | Check whether subject has privilege on group. privilege must be an AccessPrivilege (e.g. |
hasPriv(stem name, subject id, privilege) | Check whether subject has privilege on strem. privilege must be a NamingPrivilege (e.g. |
revokePriv(group name, subject id, privilege) | Revoke privilege on group. privilege must be an AccessPrivilege (e.g. |
revokePriv(stem name, subject id, privilege) | Revoke privilege on stem. privilege must be a NamingPrivilege (e.g. |
Registry
Command | Description |
---|---|
registryInitializeSchema() | Will generate schema DDL for the DB, and wont drop before creating, will not run script |
registryInitializeSchema(registryInitializeSchema.DROP_THEN_CREATE) | generate DDL for the DB, dropping existing tables, will not run script |
registryInitializeSchema.WRITE_AND_RUN_SCRIPT) | generate DDL for the DB, not dropping, but will run the script after writing it to file |
registryInitializeSchema(registryInitializeSchema.DROP_THEN_CREATE | registryInitializeSchema.WRITE_AND_RUN_SCRIPT) | generate DDL for the DB, drop existing grouper tables, and run the script after writing it to file |
resetRegistry() | Restore registry to default state(delete data from all tables, install defaults) |
registryInstall() | If the default Grouper data is not there, it will be added (e.g. root stem, default fields, etc) |
Stems
Command | Description | ||
---|---|---|---|
addRootStem(extension, displayExtension) | Add top-level stem to the registry | ||
addStem(parent stem name, extension, displayExtension) | Add stem to registry | ||
delStem(stem name) | Delete stem from registry | ||
obliterateStem(stem name, testOnlyBoolean, deleteFromPointInTimeBoolean) (Grouper v2.0.2+) | Delete stem, and subobjects. | ||
getStemAttr(stem name, attr) | Get value of stem attribute | ||
getStems(name) | Find all stems with a matching naming attribute value, returns a Set of stems | ||
setStemAttr(stem name, attr, value) | Set value of stem attribute | ||
StemFinder.findByName(grouperSession, name) | Find one stem by name | ||
StemFinder.findByUuid(grouperSession, uuid) | Find one stem by uuid | ||
Delete stem and subcontents |
|
Subjects
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. "person"), 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 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(idOrIdentifier) | Find a subject by id or identifier |
findSubject(idOrIdentifier, type) | Find a subject by id or identifier; type is a deprecated parameter that is ignored |
findSubject(idOrIdentifier, 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 |
Memberships
...
Command
...
Description
...
addComposite(group name, composite type, left group name, right group name)
...
Add composite membership. e.g. CompositeType.UNION
...
addMember(group name, subject id)
...
Add member to the members list for the group.
...
addMember(group name, subject id, field)
...
Add member to the specified list for the group.
...
delComposite(group name)
...
Delete composite membership from group
...
delMember(group name, subject id)
...
Delete member from the members list for the group
...
delMember(group name, subject id, field)
...
Delete member from the specified list for the group
...
getMembers(group name)
...
Get members of group
...
hasMember(group name, subject id)
...
Check whether subject is member of the members list
...
hasMember(group name, subject id, field)
...
Check whether subject is member of the specified list
...
Privileges
Command | Description |
---|---|
grantPriv(group name, subject id, privilege) | Grant privilege on group. privilege must be an AccessPrivilege (e.g. |
grantPriv(stem name, subject id, privilege) | Grant privilege on stem. privilege must be a NamingPrivilege (e.g. |
hasPriv(group name, subject id, privilege) | Check whether subject has privilege on group. privilege must be an AccessPrivilege (e.g. |
hasPriv(stem name, subject id, privilege) | Check whether subject has privilege on strem. privilege must be a NamingPrivilege (e.g. |
revokePriv(group name, subject id, privilege) | Revoke privilege on group. privilege must be an AccessPrivilege (e.g. |
revokePriv(stem name, subject id, privilege) | Revoke privilege on stem. privilege must be a NamingPrivilege (e.g. |
Registry
...
Command
...
Description
...
registryInitializeSchema()
...
Will generate schema DDL for the DB, and wont drop before creating, will not run script
...
registryInitializeSchema(registryInitializeSchema.DROP_THEN_CREATE)
...
generate DDL for the DB, dropping existing tables, will not run script
...
registryInitializeSchema.WRITE_AND_RUN_SCRIPT)
...
generate DDL for the DB, not dropping, but will run the script after writing it to file
...
registryInitializeSchema(registryInitializeSchema.DROP_THEN_CREATE | registryInitializeSchema.WRITE_AND_RUN_SCRIPT)
...
generate DDL for the DB, drop existing grouper tables, and run the script after writing it to file
...
resetRegistry()
...
Restore registry to default state(delete data from all tables, install defaults)
...
registryInstall()
...
If the default Grouper data is not there, it will be added (e.g. root stem, default fields, etc)
Stems
...
Command
...
Description
...
addRootStem(extension, displayExtension)
...
Add top-level stem to the registry
...
addStem(parent stem name, extension, displayExtension)
...
Add stem to registry
...
delStem(stem name)
...
Delete stem from registry
...
obliterateStem(stem name, testOnlyBoolean, deleteFromPointInTimeBoolean) (Grouper v2.0.2+)
...
getStemAttr(stem name, attr)
...
Get value of stem attribute
...
getStems(name)
...
Find all stems with a matching naming attribute value, returns a Set of stems
...
setStemAttr(stem name, attr, value)
...
Set value of stem attribute
...
StemFinder.findByName(grouperSession, name)
...
Find one stem by name
...
StemFinder.findByUuid(grouperSession, uuid)
...
Find one stem by uuid
...
Delete stem and subcontents
Code Block |
---|
grouperSession = GrouperSession.startRootSession();
stem = StemFinder.findByName(grouperSession, "a");
for(child : stem.getChildGroups(Stem.Scope.SUB)) { System.out.println("deleting: " + child.getName()); child.delete(); }
stemList = new ArrayList(stem.getChildStems(Stem.Scope.SUB));
Collections.sort(stemList);
Collections.reverse(stemList);
for(childStem : stemList) { System.out.println("deleting: " + childStem.getName()); childStem.delete(); }
stem.delete();
|
Subjects
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. "person"), 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 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(idOrIdentifier) | Find a subject by id or identifier | ||||||||||
findSubject(idOrIdentifier, type) | Find a subject by id or identifier; type is a deprecated parameter that is ignored | ||||||||||
findSubject(idOrIdentifier, 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) |
|
| subject api diagnostics |
Code Block |
---|
gsh.exitOnSubjectCheckConfigProblem = false |
gsh
Code Block |
---|
GrouperSession.startRootSession();
new edu.internet2.middleware.grouper.grouperUi.serviceLogic.SubjectSourceDiagnostics().assignSourceId("SMUPerson_DEV").assignSubjectId("empl1").assignSubjectIdentifier("netid@school.edu").assignSearchString("em").subjectSourceDiagnosticsFromGsh()
===>
SUCCESS: Found subject by id in 37ms: 'empl1'
with SubjectFinder.findByIdAndSource("empl1", "SMUPerson_DEV", false)
SUCCESS: Subject id in returned subject matches the subject id searched for: 'empl1'
WARNING: No subject found by identifier in 14ms: 'netid@school.edu'
with SubjectFinder.findByIdentifierAndSource("netid@school.edu", "SMUPerson_DEV", false) |
System
...
Command
...
Description
...
sqlRun(file)
...
Execute each line of a sql file, just like ant would. This can run the files generated by registryInitializeSchema()
...
sqlRun(string)
...
Executes a single sql statement
...
:exit
...
Terminate shell
...
help()
...
Display usage information
...
p(command)
...
Pretty print results.
...
:quit
...
Terminate shell
...
version()
...
Return version information
Find bad memberships
This command will find membership records in the database which are invalid, and prints them on the screen, along with a GSH script that will fix the memberships.
For more information, see Bad Membership Finder Utility
...
Command
...
Description
...
findBadMemberships()
...
complete findBadMemberships run
XML legacy
Command | Description |
---|---|
xmlFromFile(filename) | Load registry from XML in file |
xmlFromString(xml) | Load registry from XML in string |
xmlFromURL(url) | Load registry from XML at URL |
xmlToFile(filename) | Exports registry to file |
xmlToString() | Exports registry to string. |
xmlUpdateFromFile(filename) | Update registry from XML in file |
xmlUpdateFromString(xml) | Update registry from XML in string |
xmlUpdateFromURL(url) | Update registry from XML at URL |
XML export legacy
There is an object: XmlExport which has various chaining methods, which should be ended with an exportTo() method. You can export to file or string.
For more information, see Import-Export
...
Command
...
Description
...
XmlExport xmlExport.stem(stem)
...
The stem to export. Defaults to the ROOT stem.
...
XmlExport xmlExport.group(group)
...
The group to export
...
XmlExport xmlExport.relative(boolean)
...
If group or stem specified do not export parent Stems.
...
XmlExport xmlExport.includeParent(boolean)
...
If group specified, export from the parent stem
...
XmlExport xmlExport.childrenOnly(boolean)
...
If stem specified, export child stems and groups only - not the specified stem
...
XmlExport xmlExport.userProperties(file)
...
Properties file for extra settings for import
...
XmlExport xmlExport.grouperSession(grouperSession)
...
Operate within a certain grouper session (defaults to root session)
...
void xmlExport.exportToFile(file)
...
Export to an XML file
...
void xmlExport.exportToString(string)
...
Export to an XML string
| |||||
remove a subject with attributes (GSH) |
| ||||
subject api diagnostics | grouper.properties (temporarily)
gsh
|
System
Command | Description |
---|---|
sqlRun(file) | Execute each line of a sql file, just like ant would. This can run the files generated by registryInitializeSchema() |
sqlRun(string) | Executes a single sql statement |
:exit | Terminate shell |
help() | Display usage information |
p(command) | Pretty print results. |
:quit | Terminate shell |
version() | Return version information |
Find bad memberships
This command will find membership records in the database which are invalid, and prints them on the screen, along with a GSH script that will fix the memberships.
For more information, see Bad Membership Finder
Command | Description |
---|---|
findBadMemberships() | complete findBadMemberships run |
Grouper export to GSH script
See page: Grouper export to a GSH script
XML legacy
Command | Description |
---|---|
xmlFromFile(filename) | Load registry from XML in file |
xmlFromString(xml) | Load registry from XML in string |
xmlFromURL(url) | Load registry from XML at URL |
xmlToFile(filename) | Exports registry to file |
xmlToString() | Exports registry to string. |
xmlUpdateFromFile(filename) | Update registry from XML in file |
xmlUpdateFromString(xml) | Update registry from XML in string |
xmlUpdateFromURL(url) | Update registry from XML at URL |
XML export legacy
There is an object: XmlExport
Examples:
No Format |
---|
gsh 1% new XmlExport().exportToFile(new File("c:/temp/export.xml"))
|
No Format |
---|
gsh 1% grouperSession = GrouperSession.start(SubjectFinder.findById("mchyzer"));
gsh 2% stem = StemFinder.findByName(grouperSession, "aStem");
gsh 3% new XmlExport().stem(stem).relative(true).userProperties(new File("C:/temp/some.props")).grouperSession(grouperSession).exportToFile(new File("c:/temp/export.xml"));
|
-or- (without chaining)
No Format |
---|
gsh 3% xmlExport = new XmlExport();
gsh 4% xmlExport.stem(stem);
gsh 5% xmlExport.grouperSession(grouperSession);
gsh 6% xmlExport.exportToFile(new File("c:/temp/export.xml"))
|
XML import legacy
There is an object: XmlImport which has various chaining methods, which should be ended with an importFromexportTo() method. You can import from export to file , or string, or url.
For more information, see Import-Export
Command | Description | |
---|---|---|
XmlImport xmlImportXmlExport xmlExport.stem(stem) | The Stem into which data will be importedstem to export. Defaults to the ROOT stem. | |
XmlExport xmlExport.group(group) | The group to export | |
XmlExport xmlExport.relativeXmlImport xmlImport.updateList(boolean) | XML contains a flat list of Stems or Groups which may be updated. | If group or stem specified do not export parent Stems. |
XmlExport xmlExport.includeParent(boolean) | If group specified, export from the parent stem | |
XmlExport xmlExport.childrenOnly(boolean) | If stem specified, export child stems and groups only - not the specified stem | |
XmlExport xmlExportXmlImport xmlImport.userProperties(file) | Properties file for extra settings for import | |
XmlImport xmlImportXmlExport xmlExport.grouperSession(grouperSession) | Operate within a certain grouper session (defaults to root session)XmlImport xmlImport.ignoreInternal(boolean)Ignore internal attributes, including group and stem uuids. | |
void xmlImportxmlExport.importFromFileexportToFile(file) | Import from Export to an XML file | |
void xmlImportxmlExport.importFromStringexportToString(string) | Import from Export to an XML string | |
void xmlImport.importFromUrl(url) | Import XML from a URL |
Examples:
Examples:
No Format |
---|
gsh 1% new XmlImportXmlExport().importFromFileexportToFile(new File("c:/temp/export.xml")) |
...
No Format |
---|
gsh 1% grouperSession = GrouperSession.start(SubjectFinder.findById("mchyzer")); gsh 2% stem = StemFinder.findByName(grouperSession, "aStem"); gsh 3% new XmlImportXmlExport().stem(stem).updateListrelative(true).userProperties(new File("C:/temp/some.props")).grouperSession(grouperSession).importFromUrlexportToFile(new URLFile("httpc:/temp/whateverexport.xml")); |
-or- (without chaining)
No Format |
---|
gsh 3% xmlImportxmlExport = new XmlImportXmlExport(); gsh 4% xmlImportxmlExport.stem(stem); gsh 5% xmlImportxmlExport.grouperSession(grouperSession); gsh 6% xmlImportxmlExport.importFromFileexportToFile(new File("c:/temp/export.xml")) |
Transactions
XML import legacy
There is an object: XmlImport which has various chaining methods, which should be ended with an importFrom() method. You can import from file, string, or url.
For more information, see Import-ExportTransactions facilitate all commands succeeding or failing together, and perhaps some level of repeatable reads of the DB (depending on the DB). If there is an open transaction and an exception is thrown in a command, GSH will shut down so that subsequent commands will not execute outside of a transaction.
Command | Description |
---|---|
help("transaction") | print help information |
transactionStatus() | print the list of nested transactions |
transactionStart("<GrouperTransactionType>") | start a transaction, or make sure one is already started |
transactionCommit("<GrouperCommitType>") | commit a transaction |
transactionRollback("<GrouperRollbackType>") | rollback a transaction |
transactionEnd() | end a transaction |
Daemon
You can schedule daemon jobs (and in UI) in v2.5.23+
Code Block |
---|
GrouperSession.startRootSession();
edu.internet2.middleware.grouper.app.loader.GrouperLoader.scheduleJobs(); |
Loader
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
...
XmlImport xmlImport.stem(stem) | The Stem into which data will be imported. Defaults to the ROOT stem. |
XmlImport xmlImport.updateList(boolean) | XML contains a flat list of Stems or Groups which may be updated. |
XmlImport xmlImport.userProperties(file) | Properties file for extra settings for import |
XmlImport xmlImport.grouperSession(grouperSession) | Operate within a certain grouper session (defaults to root session) |
XmlImport xmlImport.ignoreInternal(boolean) | Ignore internal attributes, including group and stem uuids. |
void xmlImport.importFromFile(file) | Import from an XML file |
void xmlImport.importFromString(string) | Import from an XML string |
void xmlImport.importFromUrl(url) | Import XML from a URL |
Examples:
No Format |
---|
gsh 1% new XmlImport().importFromFile(new File("c:/temp/export.xml"))
|
No Format |
---|
gsh 1% grouperSession = GrouperSession.start(SubjectFinder.findById("mchyzer"));
gsh 2% stem = StemFinder.findByName(grouperSession, "aStem");
gsh 3% new XmlImport().stem(stem).updateList(true).userProperties(new File("C:/temp/some.props")).grouperSession(grouperSession).importFromUrl(new URL("http://whatever.xml"));
|
-or- (without chaining)
No Format |
---|
gsh 3% xmlImport = new XmlImport();
gsh 4% xmlImport.stem(stem);
gsh 5% xmlImport.grouperSession(grouperSession);
gsh 6% xmlImport.importFromFile(new File("c:/temp/export.xml"))
|
Transactions
Transactions facilitate all commands succeeding or failing together, and perhaps some level of repeatable reads of the DB (depending on the DB). If there is an open transaction and an exception is thrown in a command, GSH will shut down so that subsequent commands will not execute outside of a transaction.
Command | Description |
---|---|
help("transaction") | print help information |
transactionStatus() | print the list of nested transactions |
transactionStart("<GrouperTransactionType>") | start a transaction, or make sure one is already started |
transactionCommit("<GrouperCommitType>") | commit a transaction |
transactionRollback("<GrouperRollbackType>") | rollback a transaction |
transactionEnd() | end a transaction |
Daemon
You can schedule daemon jobs (and in UI) in v2.5.23+
Code Block |
---|
GrouperSession.startRootSession();
edu.internet2.middleware.grouper.app.loader.GrouperLoader.scheduleJobs(); |
Enable a job (OTHER_JOB_grouperLoaderJexlScriptFullSync is the job name)
Code Block |
---|
edu.internet2.middleware.grouper.app.loader.GrouperLoader.schedulerFactory().getScheduler().resumeJob(new org.quartz.JobKey("OTHER_JOB_grouperLoaderJexlScriptFullSync")); |
Loader
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(); | 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
Jobs not firing in daemon
- Stop all daemons
Run these sqls from a file: fixLoaderScheduler.sql
Code Block UPDATE GROUPER_QZ_TRIGGERS SET TRIGGER_STATE = 'WAITING'; DELETE FROM GROUPER_QZ_FIRED_TRIGGERS; commit;
Code Block gsh.sh -registry -runsqlfile fixLoaderScheduler.sql
- Restart daemons
It took a couple of hours to catch up on a few days of changes, but it seems to be back to normal. Thanks again, guys!
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 " + m.getSubject().getId());
} else {
System.out.println("Deleting " + m.getSubject().getId());
group.deleteMember(m, false);
}
}
# (3) Get the groups this subject is a member of. Note that a group is 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 MembershipFinder().addSubject(subject).findMembershipResult().getMembershipSubjectContainers();
for (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 https://software.internet2.edu/grouper/doc/master/grouper/apidocs/index.html?edu/internet2/middleware/grouper/MembershipFinder.html
|
Configuration in the database
Info |
---|
In v2.4.0 ui patch #56+, or 2.5 versions before 2.5.51, replace edu.internet2.middleware.grouper.cfg.dbConfig.GrouperDbConfig() in the script below with edu.internet2.middleware.grouper.grouperUi.beans.config.GrouperDbConfig(). Also, GSH must be run from the UI in WEB-INF/bin. In 2.5.51+, use class edu.internet2.middleware.grouper.cfg.dbConfig.GrouperDbConfig for ADD / DELETE and edu.internet2.middleware.grouper.grouperUi.beans.config.GrouperDbConfigImport for IMPORT as in the example. |
Code Block |
---|
GrouperSession.startRootSession();
ADD
new edu.internet2.middleware.grouper.cfg.dbConfig.GrouperDbConfig().configFileName("grouper.properties").propertyName("abc").value("123").store();
DELETE
new edu.internet2.middleware.grouper.cfg.dbConfig.GrouperDbConfig().configFileName("grouper.properties").propertyName("abc").delete();
GrouperDAOFactory.getFactory().getConfig().findAll(ConfigFileName.GROUPER_LOADER_PROPERTIES, null, "changeLog.consumer.pspng_oneprod.groupCreationLdifTemplate").iterator().next().delete();
IMPORT
new edu.internet2.middleware.grouper.grouperUi.beans.config.GrouperDbConfigImport().configFilePath("d:/temp/temp/grouper.properties").store(); |
Misc
Note: you can use the MorphString class to encrypt and update a password field, but it will be saved in the local GSH command history:
Code Block |
---|
import edu.internet2.middleware.morphString.Morph
new edu.internet2.middleware.grouper.cfg.dbConfig.GrouperDbConfig().configFileName("grouper-loader.properties").propertyName("loader.myApp.password").value(Morph.encrypt('xxxxxxxx')).store(); |
You can also encrypt the password outside of GSH:
No Format |
---|
java -cp "lib/*:classes" edu.internet2.middleware.morphString.Encrypt
Type the string to encrypt (note: pasting might echo it back):
The encrypted string is: ca8a15be4ad0fb45c6f1b3ca0cfd9c9e
|
v2.0: to sync up the point in time tables with regular tables. In v2.5.47+, run the one-time OTHER_JOB_syncAllPitTables daemon. In a prior version, you can run this.
Code Block |
---|
new edu.internet2.middleware.grouper.misc.SyncPITTables().syncAllPITTables()
|
To create missing group sets:
Code Block |
---|
new edu.internet2.middleware.grouper.misc.AddMissingGroupSets().addAllMissingGroupSets();
|
Delete memberships not in transaction
Code Block |
---|
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
Jobs not firing in daemon
...
Code Block |
---|
UPDATE GROUPER_QZ_TRIGGERS SET TRIGGER_STATE = 'WAITING';
DELETE FROM GROUPER_QZ_FIRED_TRIGGERS;
commit; |
Code Block |
---|
gsh.sh -registry -runsqlfile fixLoaderScheduler.sql |
...
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 " + m.getSubject().getId()); } else { System.out.println("Deleting " + m.getSubject().getId()); group.deleteMember(m, false); } } # (3) Get the groups this subject is a member of. Note that a group is 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:testGrouptestGroup3", true); Subject subject = g.toSubject(); Set<MembershipSubjectContainer> msc = new MembershipFinder().addSubject(subject).findMembershipResult().getMembershipSubjectContainers(); for (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) importfor (membership : group.getImmediateMemberships()) {membership.delete();} group.delete(); |
Note: in v2.4.0 patch 91+ ( unreleased at the time of writing ) you can use gsh to do simple sql tests through jdbc loader connection
Code Block | ||
---|---|---|
| ||
gcDbAccess = new edu.internet2.middleware.groupergrouperClient.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 https://software.internet2.edu/grouper/doc/master/grouper/apidocs/index.html?edu/internet2/middleware/grouper/MembershipFinder.html |
Configuration in the database
jdbc.GcDbAccess();
// "loaderConnection" is the string used in the grouper-loader.properties ( Example: db.warehouse.url --> "warehouse")
gcDbAccess.connectionName("loaderConnection").sql("select count(1) from test1").select(int.class); |
Code Block |
---|
List results = new edu.internet2.middleware.grouperClient.jdbc.GcDbAccess().sql("select name, id from grouper_groups").selectList(Object[].class);
for (Object[] row : results) { System.out.println(row[0] + ", " + row[1]);} |
See the WIKI for running the Grouper Report manually
External systems
Test all external systems
Code Block |
---|
import java.util.List;
import |
Info |
In v2.4.0 ui patch #56+, or 2.5 versions before 2.5.51, replace edu.internet2.middleware.grouper. cfgapp.dbConfig.GrouperDbConfig() in the script below with externalSystem.GrouperExternalSystem; import edu.internet2.middleware.grouper.grouperUi app.beans gsh.config.GrouperDbConfig(). Also, GSH must be run from the UI in WEB-INF/bin.In 2.5.51+, use class template.GshTemplateOutput; import edu.internet2.middleware.grouper.cfg app.gsh.dbConfig.GrouperDbConfig for ADD / DELETE and template.GshTemplateV2; import edu.internet2.middleware.grouper.grouperUi app.beans gsh.config.GrouperDbConfigImport for IMPORT as in the example. |
Code Block |
GrouperSession.startRootSession(); ADD newtemplate.GshTemplateV2input; import edu.internet2.middleware.grouper.cfgapp.dbConfiggsh.GrouperDbConfig().configFileName("grouper.properties").propertyName("abc").value("123").store(); DELETE newtemplate.GshTemplateV2output; import edu.internet2.middleware.grouper.cfg.dbConfig.GrouperDbConfig().configFileName("grouper.properties").propertyName("abc").delete(); GrouperDAOFactory.getFactory().getConfig().findAll(ConfigFileName.GROUPER_LOADER_PROPERTIES, null, "changeLog.consumer.pspng_oneprod.groupCreationLdifTemplate").iterator().next().delete(); IMPORT new edu.internet2.middleware.grouper.grouperUi.beans.config.GrouperDbConfigImport().configFilePath("d:/temp/temp/grouper.properties").store(); |
Misc
Note: you can use the MorphString class to encrypt and update a password field, but it will be saved in the local GSH command history:
Code Block |
---|
import edu.internet2.middleware.morphString.Morph
new edu.internet2.middleware.grouper.cfg.dbConfig.GrouperDbConfig().configFileName("grouper-loader.properties").propertyName("loader.myApp.password").value(Morph.encrypt('xxxxxxxx')).store(); |
You can also encrypt the password outside of GSH:
No Format |
---|
C:\mchyzer\isc\dev\grouper-qs-1.2.0\grouper>java -jar lib\morphString.jar
Enter the location of morphString.properties: conf/morphString.properties
Type the string to encrypt (note: pasting might echo it back):
The encrypted string is: ca8a15be4ad0fb45c6f1b3ca0cfd9c9e
|
v2.0: to sync up the point in time tables with regular tables. In v2.5.47+, run the one-time OTHER_JOB_syncAllPitTables daemon. In a prior version, you can run this.
Code Block |
---|
new edu.internet2.middleware.grouper.misc.SyncPITTables().syncAllPITTables()
|
To create missing group sets:
Code Block |
---|
new edu.internet2.middleware.grouper.misc.AddMissingGroupSets().addAllMissingGroupSets();
|
Delete memberships not in transaction
Code Block |
---|
grouperSession = GrouperSession.startRootSession();
group = GroupFinder.findByName(grouperSession, "test:testGroup3", true);
for (membership : group.getImmediateMemberships()) {membership.delete();}
group.delete(); |
Note: in v2.4.0 patch 91+ ( unreleased at the time of writing ) you can use gsh to do simple sql tests through jdbc loader connection
Code Block | ||
---|---|---|
| ||
gcDbAccess = new edu.internet2.middleware.grouperClient.jdbc.GcDbAccess();
// "loaderConnection" is the string used in the grouper-loader.properties ( Example: db.warehouse.url --> "warehouse")
gcDbAccess.connectionName("loaderConnection").sql("select count(1) from test1").select(int.class); |
Code Block |
---|
List results = new edu.internet2.middleware.grouperClient.jdbc.GcDbAccess().sql("select name, id from grouper_groups").selectList(Object[].class);
for (Object[] row : results) { System.out.println(row[0] + ", " + row[1]);} |
See the WIKI for running the Grouper Report manually
Create a script from SQL
Here is an example to remove access from someone... run a SQL to generate a GSH script, e.g. in oracle:
util.GrouperUtil;
public class Test77externalSystemTest extends GshTemplateV2 {
@Override
public void gshRunLogic(GshTemplateV2input gshTemplateV2input, GshTemplateV2output gshTemplateV2output) {
GshTemplateOutput gsh_builtin_gshTemplateOutput = gshTemplateV2output.getGsh_builtin_gshTemplateOutput();
gsh_builtin_gshTemplateOutput.assignRedirectToGrouperOperation("NONE");
List<GrouperExternalSystem> grouperExternalSystems = GrouperExternalSystem.retrieveAllGrouperExternalSystems();
for (GrouperExternalSystem grouperExternalSystem : grouperExternalSystems) {
try {
List<String> errors = grouperExternalSystem.test();
if (GrouperUtil.length(errors) == 0) {
gsh_builtin_gshTemplateOutput.addOutputLine("Success: extenal system '" + grouperExternalSystem.getConfigId() + "' passed its test");
continue;
}
for (String error : errors) {
gsh_builtin_gshTemplateOutput.addOutputLine("error", "Error: extenal system '" + grouperExternalSystem.getConfigId() + "': " + error);
}
} catch (Exception e) {
gsh_builtin_gshTemplateOutput.addOutputLine("error", "Error: extenal system '" + grouperExternalSystem.getConfigId() + "' failed: " + e.getMessage());
}
}
}
}
|
Create a script from SQL
Here is an example to remove access from someone... run a SQL to generate a GSH script, e.g. in oracle:
Code Block |
---|
set linesize 1000;
set pagesize 1000;
select 'delMember("' || gmlv.GROUP_NAME || '", "' || gmlv.SUBJECT_ID || '");' as script
from grouper_memberships_lw_v gmlv where subject_id = '12345678' and gmlv.LIST_NAME = 'members';
|
Put that script in a text editor and remove extra whitespace (probably optional), and add this to the beginning:
Code Block |
---|
grouperSession = GrouperSession.startRootSession();
|
Look at it and remove lines that dont apply... then run in GSH
Code Block |
---|
[appadmin@lorenzo bin]$ ./gsh.sh remove.script
|
Here is a more complicated example. I want all groups in a certain folder which do not have an ADMIN privilege assigned to my application service principal, to assign that privilege. Here is the query for oracle:
Code Block |
---|
select 'grantPriv("' || gg.name || '", "someid/server.school.edu", AccessPrivilege.ADMIN);' as script
from grouper_groups gg where gg.name like 'school:apps:appName:spaces:%'
and not exists
(select (1) |
Code Block |
set linesize 1000; set pagesize 1000; select 'delMember("' || gmlv.GROUP_NAME || '", "' || gmlv.SUBJECT_ID || '");' as script from grouper_memberships_lw_v gmlv where subject_idgg.name = '12345678'gmlv.group_name and gmlv.LISTlist_NAMEname = 'membersadmins'; |
Put that script in a text editor and remove extra whitespace (probably optional), and add this to the beginning:
Code Block |
---|
grouperSession = GrouperSession.startRootSession();
|
Look at it and remove lines that dont apply... then run in GSH
Code Block |
---|
[appadmin@lorenzo bin]$ ./gsh.sh remove.script
|
Here is a more complicated example. I want all groups in a certain folder which do not have an ADMIN privilege assigned to my application service principal, to assign that privilege. Here is the query for oracle:
and gmlv.subject_id = 'someid/server.school.edu');
|
Here is an example of deleting memberships for a user in oracle, dont forget at top of script to add grouperSession = GrouperSession.startRootSession():
Code Block |
---|
set linesize 1000;
set pagesize 1000;
select 'delMember |
Code Block |
select 'grantPriv("' || gg.name || '", "someid/server.school.edu", AccessPrivilege.ADMIN' || gm.subject_id || '");' as script script from grouper_memberships_all_groupsv gg where gg.name like 'school:apps:appName:spaces:%' and not exists (select (1) from grouper_memberships_lw_v gmlv where gg.name = gmlv.group_name and list_gmav, grouper_fields gf, grouper_groups gg, grouper_members gm where GMAV.FIELD_ID = GF.ID and gm.subject_id = '12345678' and GF.name = 'adminsmembers' and gmlv.subject_id = 'someid/server.school.edu'); GMAV.OWNER_GROUP_ID = gg.ID and GMAV.MEMBER_ID = GM.ID and GMAV.DEPTH = 0 |
Here is an example of deleting memberships for removing privileges from a user on groups in oracle, dont forget at top of script to add grouperSession = GrouperSession.startRootSession():
Code Block |
---|
set linesize 1000; set pagesize 1000; select 'delMemberrevokePriv("' || gggmlv.group_name || '", "' || gmlv.subject_id || '", || '", "' || gm.subject_id || '");' as script from grouper_memberships_all_v gmav, grouper_fields gf, grouper_groups gg, grouper_members gm where GMAV.FIELD_ID = GF.ID and gm.subject_id = '12345678' and GF.name = 'members' and GMAV.OWNER_GROUP_ID = gg.ID and GMAV.MEMBER_ID = GM.ID and GMAV.DEPTH = 0 AccessPrivilege.' || case when gmlv.LIST_NAME = 'admins' then 'ADMIN' when gmlv.LIST_NAME = 'readers' then 'READ' when gmlv.LIST_NAME = 'viewers' then 'VIEW' when gmlv.LIST_NAME = 'updaters' then 'UPDATE' when gmlv.LIST_NAME = 'optins' then 'OPTIN' when gmlv.LIST_NAME = 'optouts' then 'OPTOUT' else gmlv.LIST_NAME end || ');' as script from grouper_memberships_lw_v gmlv where subject_id = '12345678' and GMLV.LIST_TYPE = 'access' |
This oracle script will remove privileges on folders for a certain userHere is an example of removing privileges from a user on groups in oracle, dont forget at top of script to add grouperSession = GrouperSession.startRootSession():
Code Block |
---|
set linesize 1000; set pagesize 1000; select 'revokePriv("' || gmlvgs.group_name || '", "' || gmlvgm.subject_id || '", AccessPrivilegeNamingPrivilege.' || case when gmlvgf.LIST_NAME = 'admins' then 'ADMIN' when gmlv.LIST_NAME = 'readers' then 'READ' when gmlv.LIST_NAME = 'viewers' then 'VIEW' when gmlv.LIST_NAME = 'updaters' then 'UPDATE' when gmlv.LIST_NAME = 'optinsstemmers' then 'OPTINSTEM' when gmlvgf.LIST_NAME = 'optoutscreators' then 'OPTOUTCREATE' else gmlvgf.LIST_NAME end || ');' as script from grouper_memberships_lwall_v gmlv where gmav, grouper_fields gf, grouper_stems gs, grouper_members gm where GMAV.FIELD_ID = GF.ID and gm.subject_id = '12345678' and GMLVGF.LIST_TYPEtype = 'access' |
This oracle script will remove privileges on folders for a certain user, dont forget at top of script to add grouperSession = GrouperSession.startRootSession():
naming'
and GMAV.OWNER_STEM_ID = GS.ID and GMAV.MEMBER_ID = GM.ID
|
Example of copying memberships and enabled/disabled dates from one group to another (postgres/oracle)
Code Block |
---|
select 'new MembershipSave().assignGroupName("test:testGroup2").assignMemberId |
Code Block |
set linesize 1000; set pagesize 1000; select 'revokePriv("' || gsgm.namemember_id || '", ")' || (case when gm.enabled_timestamp is not null then '.assignImmediateMshipEnabledTime(' || cast(gm.subject_idenabled_timestamp as varchar) || '", NamingPrivilege.' || case when gf.NAME = 'stemmers'L)' else '' end) || (case when gm.disabled_timestamp is not null then 'STEM' when gf.NAME = 'creators' then 'CREATE' else gf.NAME end .assignImmediateMshipDisabledTime(' || cast(gm.disabled_timestamp as varchar) || 'L)' else '' end) || '.save();' as script from grouper_memberships_all_v gmavgm, grouper_fieldsgroups gfgg, grouper_stems gs, grouper_members gmfields gf where GMAVgm.FIELDfield_IDid = GFgf.IDid and gm.subjectowner_group_id = '12345678' gg.id and GFgf.typename = 'naming' and GMAV.OWNER_STEM_ID = GS.ID and GMAV.MEMBER_ID = GM.ID members' and gg.name = 'test:testGroup1' |
Attribute framework
Create a permission and configure action list:
...
Code Block |
---|
//note, or whatever user should be sending the messages grouperSession = GrouperSession.startRootSession(); GrouperSession.startRootSession(); //send message to queue GrouperMessagingEngine.send(new GrouperMessageSendParam().assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME).assignQueueType(GrouperMessageQueueType.queue).assignQueueOrTopicName("queueName").addMessageBody("Some message body")); //send message to queuetopic GrouperMessagingEngine.send(new GrouperMessageSendParam().assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME).assignQueueType(GrouperMessageQueueType.queuetopic).assignQueueOrTopicName("queueName").addMessageBody("Some message body")); //send message to topic GrouperMessagingEngine.send(new GrouperMessageSendParam().assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME).assignQueueType(GrouperMessageQueueType.topic).assignQueueOrTopicName("queueName").addMessageBody("Some message body")); //receive messages GrouperMessageReceiveResult grouperMessageReceiveResult = GrouperMessagingEngine.receive(new GrouperMessageReceiveParam().assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME).assignQueueName(queueName)); Collection<GrouperMessage> grouperMessages = grouperMessageReceiveResult.getGrouperMessages(); //acknowledge message as processedreceive messages GrouperMessageReceiveResult grouperMessageReceiveResult = GrouperMessagingEngine.receive(new GrouperMessageReceiveParam().assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME).assignQueueName(queueName)); Collection<GrouperMessage> grouperMessages = grouperMessageReceiveResult.getGrouperMessages(); //acknowledge message as processed GrouperMessagingEngine.acknowledge(new GrouperMessageAcknowledgeParam().assignAcknowledgeType(GrouperMessageAcknowledgeType.mark_as_processed).assignQueueName("abc").addGrouperMessage(grouperMessage).assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME)); //acknowledge message as return to queue (receive next time ask for messages) GrouperMessagingEngine.acknowledge(new GrouperMessageAcknowledgeParam().assignAcknowledgeType(GrouperMessageAcknowledgeType.return_to_queue).assignQueueName("abc").addGrouperMessage(grouperMessage).assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME)); //acknowledge message as return to queue (receive after other messages on the queue) GrouperMessagingEngine.acknowledge(new GrouperMessageAcknowledgeParam().assignAcknowledgeType(GrouperMessageAcknowledgeType.return_to_end_of_queue).assignQueueName("abc").addGrouperMessage(grouperMessage).assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME)); //acknowledge message send to another queue or topic (e.g. dead letter queue, dlq) GrouperMessagingEngine.acknowledge(new GrouperMessageAcknowledgeParam().assignAcknowledgeType(GrouperMessageAcknowledgeType.marksend_to_asanother_processedqueue).assignQueueName("abc").addGrouperMessage(grouperMessage).assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME).assignAnotherQueueParam(new GrouperMessageQueueParam().assignQueueOrTopicName("dlq").assignQueueType(GrouperMessageQueueType.queue)); //acknowledge message as return to queue (receive next time ask for messages) GrouperMessagingEngine.acknowledge(new GrouperMessageAcknowledgeParam().assignAcknowledgeType(GrouperMessageAcknowledgeType.return_to_queue).assignQueueName("abc").addGrouperMessage(grouperMessage).assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME)); //acknowledge message as return to queue (receive after other messages on the queue) GrouperMessagingEngine.acknowledge(new GrouperMessageAcknowledgeParam().assignAcknowledgeType(GrouperMessageAcknowledgeType.return_to_end_of_queue).assignQueueName("abc").addGrouperMessage(grouperMessage).assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME)); //acknowledge message send to another queue or topic (e.g. dead letter queue, dlq) GrouperMessagingEngine.acknowledge(new GrouperMessageAcknowledgeParam().assignAcknowledgeType(GrouperMessageAcknowledgeType.send_to_another_queue).assignQueueName("abc").addGrouperMessage(grouperMessage).assignGrouperMessageSystemName(GrouperBuiltinMessagingSystem.BUILTIN_NAME).assignAnotherQueueParam(new GrouperMessageQueueParam().assignQueueOrTopicName("dlq").assignQueueType(GrouperMessageQueueType.queue)); |
Expression language testing
Code Block |
---|
Set this in log4j.properties
log4j.logger.edu.internet2.middleware.grouper.util.GrouperUtil = DEBUG
Run GSH:
gsh 0% GrouperSession grouperSession = GrouperSession.startRootSession();
gsh 1% Group group = GroupFinder.findByName(grouperSession, "apps:loader");
gsh 2% Map variableMap = new HashMap();
gsh 3% variableMap.put("theGroup", group);
gsh 4% String result = GrouperUtil.substituteExpressionLanguage("Name: ${theGroup.name}", variableMap);
gsh 5% result
Name: apps:loader
This is the log entry:
2018-06-04 22:32:58,197: [main] DEBUG GrouperUtil.substituteExpressionLanguage(9416) - - Subsituting EL: 'Name: ${theGroup.name}', and with env vars: theGroup, grouperUtil with result: 'Name: apps:loader'
|
Example of attribute value assign to group and SQL query
Code Block |
---|
gsh 0% GrouperSession grouperSession = GrouperSession.startRootSession();
gsh 1% AttributeDef attributeDef = new AttributeDefSave(grouperSession).assignName("test:testAttribute:someAttrDef").assignCreateParentStemsIfNotExist(true).assignToGroup(true).assignAttributeDefType(AttributeDefType.attr).assignMultiAssignable(false).assignMultiValued(false).assignValueType(AttributeDefValueType.string).save();
gsh 2% AttributeDefName attributeDefName = new AttributeDefNameSave(grouperSession, attributeDef).assignName("test:testAttribute:someAttr").assignCreateParentStemsIfNotExist(true).save();
gsh 3% Group group = new GroupSave(grouperSession).assignName("test:testAttribute:group").assignCreateParentStemsIfNotExist(true).save()
gsh 4% group.getAttributeValueDelegate().assignValueString(attributeDefName.getName(), "someValue");
edu.internet2.middleware.grouper.attr.value.AttributeValueResult: edu.internet2.middleware.grouper.attr.value.AttributeValueResult@2f08e6d3
gsh 5% HibernateSession.bySqlStatic().select(String.class, "SELECT value_string FROM grouper_aval_asn_group_v WHERE group_name = 'test:testAttribute:group' AND attribute_def_name_name = 'test:testAttribute:someAttr'");
someValue
gsh 6% |
Example of finding groups with a certain attribute value
Code Block |
---|
GrouperSession grouperSession = GrouperSession.startRootSession();
Set<Group> groups = new GroupFinder().assignNameOfAttributeDefName("bath:provisionClass").assignAttributeValue("groupmanager-groups")
.assignPrivileges(AccessPrivilege.ATTRIBUTE_READ_PRIVILEGES).findGroups(); |
Example of finding groups with a certain attribute value on metadata assignments
This is useful for attestation and loader metadata, for example.
Code Block |
---|
//groups loaded by a particular group
def attrDef = AttributeDefNameFinder.findByName(GrouperCheckConfig.loaderMetadataStemName() + ":" + GrouperLoader.ATTRIBUTE_GROUPER_LOADER_METADATA_GROUP_ID, true)
def groups = new GroupFinder().assignIdOfAttributeDefName(attrDef.id).assignAttributeValuesOnAssignment(GrouperUtil.toSetObjectType("3779b51223804784b4a02ee238b73079")).findGroups()
// OR, without the extra attributeDef, look up the name directly in GroupFinder
def groups = new GroupFinder().assignNameOfAttributeDefName("etc:attribute:loaderMetadata:grouperLoaderMetadataGroupId").assignAttributeValuesOnAssignment(GrouperUtil.toSetObjectType("3779b51223804784b4a02ee238b73079")).findGroups()
//attestations that are due
import edu.internet2.middleware.grouper.app.attestation.GrouperAttestationJob
def groups = new GroupFinder().assignIdOfAttributeDefName(GrouperAttestationJob.retrieveAttributeDefNameCalculatedDaysLeft().id).assignAttributeValuesOnAssignment(GrouperUtil.toSetObjectType("0")).findGroups() |
Example of finding provisioning targets for PSPNG
Example of finding provisioning targets for PSPNG
Code Block |
---|
gsh 0% HibernateSession.bySqlStatic().listSelect(String.class, "SELECT DISTINCT gaaa.value_string FROM grouper_attribute_assign_value gaaa, grouper_attribute_assign gaa, grouper_attribute_def_name gadn WHERE gaaa.attribute_assign_id = gaa.id AND gaa.attribute_def_name_id = gadn.id AND gadn.extension IN ('provision_to', 'do_not_provision_to')", null, null);
java.util.ArrayList: [ad, ldap] |
Example of finding which groups are provisioned to a certain target (from daemon where PSPNG is installed)
Code Block |
---|
provisioner_name="xyz"; // Whatever your provisioner is called in grouper_loader.properties
gs=GrouperSession.startRootSession();
provisioner=edu.internet2.middleware.grouper.pspng.ProvisionerFactory.createProvisioner(provisioner_name,false);
provisioner.getAllGroupsForProvisioner(); |
Long hand example of which groups are provisioned to a certain target
|
Expression language testing
Code Block |
---|
Set this in log4j.properties
log4j.logger.edu.internet2.middleware.grouper.util.GrouperUtil = DEBUG
Run GSH:
gsh 0% GrouperSession grouperSession = GrouperSession.startRootSession();
gsh 1% Group group = GroupFinder.findByName(grouperSession, "apps:loader");
gsh 2% Map variableMap = new HashMap();
gsh 3% variableMap.put("theGroup", group);
gsh 4% String result = GrouperUtil.substituteExpressionLanguage("Name: ${theGroup.name}", variableMap);
gsh 5% result
Name: apps:loader
This is the log entry:
2018-06-04 22:32:58,197: [main] DEBUG GrouperUtil.substituteExpressionLanguage(9416) - - Subsituting EL: 'Name: ${theGroup.name}', and with env vars: theGroup, grouperUtil with result: 'Name: apps:loader'
|
Example of attribute value assign to group and SQL query
Code Block |
---|
gsh 0% GrouperSession grouperSession = GrouperSession.startRootSession();
gsh 1% AttributeDef attributeDef = new AttributeDefSave(grouperSession).assignName("test:testAttribute:someAttrDef").assignCreateParentStemsIfNotExist(true).assignToGroup(true).assignAttributeDefType(AttributeDefType.attr).assignMultiAssignable(false).assignMultiValued(false).assignValueType(AttributeDefValueType.string).save();
gsh 2% AttributeDefName attributeDefName = new AttributeDefNameSave(grouperSession, attributeDef).assignName("test:testAttribute:someAttr").assignCreateParentStemsIfNotExist(true).save();
gsh 3% Group group = new GroupSave(grouperSession).assignName("test:testAttribute:group").assignCreateParentStemsIfNotExist(true).save()
gsh 4% group.getAttributeValueDelegate().assignValueString(attributeDefName.getName(), "someValue");
edu.internet2.middleware.grouper.attr.value.AttributeValueResult: edu.internet2.middleware.grouper.attr.value.AttributeValueResult@2f08e6d3
gsh 5% HibernateSession.bySqlStatic().select(String.class, "SELECT value_string FROM grouper_aval_asn_group_v WHERE group_name = 'test:testAttribute:group' AND attribute_def_name_name = 'test:testAttribute:someAttr'");
someValue
gsh 6% |
Example of finding groups with a certain attribute value
Code Block |
---|
GrouperSession grouperSession = GrouperSession.startRootSession();
Set<Group> groups = new GroupFinder().assignNameOfAttributeDefName("bath:provisionClass").assignAttributeValue("groupmanager-groups")
.assignPrivileges(AccessPrivilege.ATTRIBUTE_READ_PRIVILEGES).findGroups(); |
Example of finding groups with a certain attribute value on metadata assignments
This is useful for attestation and loader metadata, for example.
Code Block |
---|
//groups loaded by a particular group
def attrDef = AttributeDefNameFinder.findByName(GrouperCheckConfig.loaderMetadataStemName() + ":" + GrouperLoader.ATTRIBUTE_GROUPER_LOADER_METADATA_GROUP_ID, true)
def groups = new GroupFinder().assignIdOfAttributeDefName(attrDef.id).assignAttributeValuesOnAssignment(GrouperUtil.toSetObjectType("3779b51223804784b4a02ee238b73079")).findGroups()
// OR, without the extra attributeDef, look up the name directly in GroupFinder
def groups = new GroupFinder().assignNameOfAttributeDefName("etc:attribute:loaderMetadata:grouperLoaderMetadataGroupId").assignAttributeValuesOnAssignment(GrouperUtil.toSetObjectType("3779b51223804784b4a02ee238b73079")).findGroups()
//attestations that are due
import edu.internet2.middleware.grouper.app.attestation.GrouperAttestationJob
def groups = new GroupFinder().assignIdOfAttributeDefName(GrouperAttestationJob.retrieveAttributeDefNameCalculatedDaysLeft().id).assignAttributeValuesOnAssignment(GrouperUtil.toSetObjectType("0")).findGroups() |
Example of finding provisioning targets for PSPNG
Example of finding provisioning targets for PSPNG
Code Block |
---|
gsh 0% HibernateSession.bySqlStatic().listSelect(String.class, "SELECT DISTINCT gaaa.value_string FROM grouper_attribute_assign_value gaaa, grouper_attribute_assign gaa, grouper_attribute_def_name gadn WHERE gaaa.attribute_assign_id = gaa.id AND gaa.attribute_def_name_id = gadn.id AND gadn.extension IN ('provision_to', 'do_not_provision_to')", null, null);
java.util.ArrayList: [ad, ldap] |
Example of finding which groups are provisioned to a certain target (from daemon where PSPNG is installed)
Code Block |
---|
provisioner_name="xyz"; // Whatever your provisioner is called in grouper_loader.properties
gs=GrouperSession.startRootSession();
provisioner=edu.internet2.middleware.grouper.pspng.ProvisionerFactory.createProvisioner(provisioner_name,false);
provisioner.getAllGroupsForProvisioner(); |
Long hand example of which groups are provisioned to a certain target
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 |
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 = 'do_not_provision_to' and aav.valueString = '" + provisionTarget + "'").listSet(Stem.class); for (Object stemObject : stemsToProvisionToSetstemsToNotProvisionToSet) { Stem stem = (Stem)stemObject; System.out.println("do_not_provision_to assigned to stem: " + stem.getName()); } Set stemsToNotProvisionToSetgroupsToProvisionToSet = HibernateSession.byHqlStatic().createQuery("select sg from StemGroup sg, AttributeAssign aa, AttributeDefName adn, AttributeAssignValue aav where sg.id = aa.ownerStemIdownerGroupId and aav.attributeAssignId = aa.id and aa.attributeDefNameId = adn.id and aa.attributeAssignTypeDb = 'stemgroup' and aa.enabledDb = 'T' and adn.extensionDb = 'do_not_provision_to' and aav.valueString = '" + provisionTarget + "'").listSet(Stem.class); for (Object stemObjectgroupObject : stemsToNotProvisionToSetgroupsToProvisionToSet) { StemGroup stemgroup = (StemGroup)stemObjectgroupObject; System.out.println("do_not_provision_to assigned to stemgroup: " + stemgroup.getName()); } Set groupsToProvisionToSetgroupsToNotProvisionToSet = 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).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(); 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.classSet 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 : groupsToNotProvisionToSetallGroups) { 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();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 stemToProvisiongroupObject : stemsToProvisionToSet) { stemNamesToProvisionTo.add(((Stem)stemToProvision).getNamegroupToPaths.keySet()); } {Group group = for (Object stemNotToProvision : stemsToNotProvisionToSet) { stemNamesToNotProvisionTo.add(((Stem)stemNotToProvision).getName()); } (Group)groupObject; List paths = (List)groupToPaths.get(group); for (Object stemToProvisionpathObject : stemsToProvisionToSetpaths) { allGroups.addAll(((Stem)stemToProvision).getChildGroups(edu.internet2.middleware.grouper.Stem.Scope.SUB)); } Map groupToPaths = new HashMap(); String path = (String)pathObject; if (stemNamesToProvisionTo.contains(path)) { allGroupsToProvision.add(group); break; } if (stemNamesToNotProvisionTo.contains(path)) { break; } } } for (Object groupObject : allGroupsallGroupsToProvision) { 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); } } System.out.println("configured to provision to: " + provisionTarget + ": " + group.getName()); } |
Include a common GSH file
If this is the file in the container:
Code Block |
---|
def addNewGroup(pathName, dispName,groupType, gsh_builtin_gshTemplateOutput,grouperSession ) { //Verify if allowgroup exist or not and provide appropriate messages groupVerify = GroupFinder.findByName(grouperSession, pathName,false); if (groupVerify != null) for (Object groupObject : groupToPaths.keySet()) {Groupgsh_builtin_gshTemplateOutput.addOutputLine( pathName + " 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()); } already exists!"); else { productGroup = new GroupSave(grouperSession).assignCreateParentStemsIfNotExist(true).assignName(pathName).assignDisplayName(dispName).save(); gsh_builtin_gshTemplateOutput.addOutputLine("Created "+ groupType +" group : " +pathName); gsh_builtin_gshTemplateOutput.addOutputLine("Added Group types: "+groupType+" for group : " + pathName); } GdgTypeGroupSave gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(productGroup).assignType(groupType); gdgTypeGroupSave.save(); return productGroup; } |
Include that in a GSH template or other script
Code Block |
---|
GroovyShell shell = new GroovyShell();
def external = shell.parse(new File('/opt/grouper/gsh/commonFunction.gsh'));
newGroup=external.addNewGroup |
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(); |
...