Grouper custom template via GSH
The Grouper custom template via GSH is in Grouper 2.5.43+
- Grouper custom template via GSH Internet2 example
- Grouper custom template via GSH zoom deprovisioning
- Grouper programmatic JSON
- Grouper custom template via GSH invoked by daemon - load group attributes
- Grouper custom template via GSH role mapper
- Grouper custom template via GSH web service attributes on users in group
- Grouper custom template via GSH user membership history
- Grouper custom template via GSH used by daemon for CSV report
- Grouper custom template via GSH impersonate testing helper
- Grouper custom template via GSH analyze groups for orgs
- Grouper custom template via GSH - V2
- Grouper custom template via GSH impersonate example
- Grouper custom template via GSH testing the Grouper health
- Grouper custom template via GSH analyze people
- Grouper custom templates via GSH - converting an existing GSH script - insert a row in table
- Grouper custom template via GSH - AI ABAC script writer
- Grouper custom template via GSH onboarding org example
- Grouper custom template via GSH impersonate delete example
- Grouper custom template via GSH - provisionable groups
- Grouper custom template via GSH departmental Grouper onboarding
- GSH template AI GPT to write script
- Grouper custom template via GSH custom policy group example V1
- Grouper custom template via GSH custom policy group example V2
- Grouper custom template via GSH - loader import / export
- Grouper GSH template security
- Grouper custom template via GSH report compare Banner security envs
- Grouper custom template via GSH membership trace - V2
- Writing GSH templates in Java
- Debugging a compiled Java GSH template in an IDE
- Migrate a custom UI GSH script to compiled Java
- Migrate a groovy GSH template to compiled Java
- Migrate a GSH change-log daemon to compiled Java
- Migrate a GSH provisioner to compiled Java
- Migrate a GSH report to compiled Java
- Migrate a GSH scripted daemon to compiled Java
- Migrate a jar-deployed hook to a compiled GSH hook
- Roadmap: interpreted Groovy or only compiled Java
- Grouper custom template via GSH manage credential SQL subject source
- Grouper custom template via GSH web service membership counts
- Grouper custom template via GSH web service membership counts - V2 - bean inputs
- Grouper custom template via GSH web service membership counts - V2 - bean inputs with test
- Grouper custom template via GSH web service membership counts - V1 - bean inputs
- Grouper custom template via GSH web service membership counts - V1 - json inputs / outputs
- Grouper custom template via GSH web service membership counts - V1 - arbitrary inputs map
- Grouper custom template via GSH web service membership counts - V1 - basic
- Grouper custom template via GSH web service membership counts - V2 - basic
- Grouper custom template via GSH web service membership counts - V2 - json inputs
- Grouper custom template via GSH web service membership counts - V2 - arbitrary inputs
- Grouper custom template via GSH delegated VPN management
- Grouper custom template via GSH - provisionable groups member of
- Grouper GSH template simplified UI
- Grouper custom template via GSH inherited privileges WS example
Intro
Custom templates via GSH are a function of Grouper that evolves the idea of an Access Management Platform. You can make a UI screen or a web service call that is completely custom. The inputs are dynamic, flexible, and have built-in validations. The GSH script to process those inputs has full control of Grouper or Java. There is security around who can run the template, and the user they run-as. There are easy-to-use APIs to perform a list of actions.
Custom templates via GSH are good for:
Performing actions that are not available in the UI
check LDAP to see if provisioning happened, for example
make an ad hoc report and send it to the user
add/remove a service principal to a subject source table
Automating multiple tasks into one
Creating a custom access management interface for a user to simplify actions
e.g. to add a user to a VPN instance, you need to remove an exclude if there, and if not in the automatic population and an employee, add them to the VPN employee group, otherwise guest group. All can be automated
Create a Web Service call that does not exist in Grouper
Reduce time to perform tasks
Reduce Help Desk Tickets
The sky is the limit
Reminder: "Custom UI" and "Custom Template via GSH" are two different features in Grouper.
Use a Custom UI when you want an end-user facing UI where the end user can:
See their status and why (e.g. they might need a training or a different affiliation)
Can (optionally) enroll or unenroll easily into a service
Redirect based on certain conditions to other services
You don't want the end user to see the full Grouper UI
Use Grouper Custom Templates via GSH (the info on this page):
For people who use the Grouper UI
Can have custom inputs
Logic can use the input values and performance queries or tasks
Automate multiple tasks in one operation
Can expose via web service
Best practices
If you get errors with dollar signs in strings use this
Script2.groovy: 603: illegal string body character after dollar sign;
solution: either escape a literal dollar sign "\$5" or bracket the value expression "${5}"
FROM: "$whatever"
TO: '$' + "whatever"You cannot line wrap unless you put an operator at end of line
No signature of method: java.lang.String.positive() is applicable for argument types: () values: []
FROM: String something = ""
+ "hey";
TO: String something = "" +
"hey";
Configuring
There is a wizard in the UI. These are the configs that the wizard controls
grouper.properties
grouperGshTemplate.<configId>.suffix
config id suffix | value example | description | notes |
|---|---|---|---|
enabled | true | false | if this template is enabled | if false, do not show it in menu on folders or allow it to run |
templateVersion | V1 | V2 | V1 is the legacy version, the script is in the gshTemplate V2 is the newer way where you extend a class and can include tests |
|
showOnGroups | true | false | if this template option is available on groups | default false (TODO as of 2.5.36) |
groupShowType | certainGroup, groupsInFolder, allGroups | is this supposed to show for one group, groups in a certain folder, or allGroups | required, show if showOnGroups=true (TODO as of 2.5.36) |
groupUuidToShow | xyz321 | which group to show the template on. could be uuid or name. | required, show if groupShowType=certainGroup |
groupShowOnDescendants | oneChildLevel, descendants | oneChildLevel: only show on groups directly in folder | required, show if groupShowType = groupsInfolder |
showOnFolders | true | false | if this template option is available on folders | default false |
folderShowType | certainFolder, allFolders | where should this template be available | drop down, required, show if showOnFolders = true |
folderUuidToShow | abc123 | uuid or name of folder to show this template | eventually we can have a folder combobox, currently textfield. show if folderShowType = 'specifiedFolder' or groupShowType = 'groupsInFolder'. Required |
folderShowOnDescendants | certainFolder, oneChildLevel, certainFolderAndOneChildLevel, descendants, certainFolderAndDescendants | certainFolder: just show on one folder | if folderShowType = 'specifiedFolder'. Required |
runButtonGroupOrFolder | group | folder | If you want a run button on the GSH template page, this will allow configuration of a default group or folder |
|
defaultRunButtonGroupUuidOrName | a:b:c | Default group name or uuid for the run now button |
|
defaultRunButtonFolderUuidOrName | a:b:c | Default folder name or uuid for the run now button |
|
securityRunType | wheel | specifiedGroup | privilegeOnObject | everyone | who can run this template. Only GrouperSystem / wheel group, or specify a group. If privilegeOnObject, then check to see if user has certain privileges on the object where the template was invoked from. | drop down, Required |
groupUuidCanRun | def456 | uuid or name of group that can run this template. | eventually we can have a group combobox, currently textfield. Show if securityRunType = 'specifiedGroup'. Required |
requireFolderPrivilege | admin, create, stemAttrRead, stemAttrUpdate | If running this template requires any of these privs on the folder it is run on | show if showOnFolders = true. required if securityRunType = 'privilegeOnObject' |
requireGroupPrivilege | admin, read, update, read_and_update, optin, optout, view, groupAttrRead, groupAttrUpdate | the option to run the template will only show if the user has this privilege on the group at least (e.g. if the user has ADMIN they can READ) | show if showOnGroups = true. |
runAsType | currentUser | GrouperSystem| specifiedSubject | select the type of user to run as. "currentUser" means | drop down. Required |
runAsSpecifiedSubjectSourceId | pennperson | select the source ID of the specified subject to run as | drop down (subject source picker). Required |
runAsSpecifiedSubjectId | 12345678 | subject id of the specified subject to run as | eventually we can have a subject combobox, currently textfield. Required |
templateNameExternalizedTextKey | grouperGshTemplate_<configId>_templateNameExternalizedTextKey | this is hardcoded for each template | this is readonly, not editable, eventually we can have |
templateDescriptionExternalizedTextKey | grouperGshTemplate_<configId>_templateDescriptionExternalizedTextKey | this is hardcoded for each template | this is readonly |
simplifiedUi | true | false | If the UI should not show the normal Grouper menus, to not confuse users who are not familiar with Grouper |
|
allowWsFromNoOwner | true | false | if WS can call the template without identifying a stem or group owner |
|
gshTemplate | // | this is the GSH template to run | if we can get a textarea that would be good. Should convert from windows or mac newlines to unix newlines on submit. Required |
numberOfInputs | 5 | number of inputs (form elements on ui or in ws) | drop down from 0-50 repeat group. Default value: 0 |
input.i.name | gsh_input_folderName | name of the ui form element, ws param, template variable, | validation: must start with gsh_input_, must be alphanumeric/underscore. Required |
input.i.labelExternalizedTextKey | grouperGshTemplate_<configId>_input_<inputName>_labelExternalizedTextKey | externalized text key of the label on the UI for this input | readonly |
input.i.descriptionExternalizedTextKey | grouperGshTemplate_<configId>_input_<inputName>_descriptionExternalizedTextKey | externalized text key of the label on the UI for this input | readonly |
input.i.type | int | boolean | string | type of the data | drop down with supported types. suggested starting point: int, boolean, string. Default value: string |
input.i.formElementType | textfield, dropdown, checkbox | form element type on UI | show if type is not equal to "boolean" (if boolean its a radio). Default value: textfield. |
input.i.index | 10 | form elements will show on the form in order of "index". DefaultValue is 0. If two elements have the same index then they will show in order of configuration. | textfield |
input.i.validationType | regex | jexl | none | type of validation on the input | required (none is not blank, it is an option) |
input.i.validationRegex | ^[a-zA-Z0-9_]{1,50}$ | regex to check the input and if it doesnt match then fail. For example, this is alphanumeric or underscore length between 1 and 50 | show if validationType = 'regex', required |
input.i.validationJexl | ${gsh_input_myField.startsWith('whatever')} | run a validation (and include all variables for cross-validations), return true for valid, and false for invalid | show if validationType = 'jexl', required |
input.i.validationMessageExternalizedTextKey | grouperGshTemplate_<configId>_input_<inputName>_validationMessageExternalizedTextKey | readonly key in externalized text for validation message (e.g. for jexl or regex) | readonly |
input.i.required | true | false | if this input is required for template to run | default value: false |
input.i.defaultValue | abc | default value for the input if none is provided | show if required is false |
input.i.showEl | ${gsh_input_someField = 'something'} for boolean, ${gsh_input_type == "Bulk"} for string value matching. | jexl for if this field should show, note all inputs are available to use as variables |
|
numberOfTests | 3 | number of tests to make sure this template functions | drop down from 0-20 repeat group. Default value: 0 |
test.i.deleteSideEffectsIfExistGsh | gsh script | will be run before and after test (first and last) to clean up what the test and setup and verification do. Will not run after test if test fails | textarea |
test.i.setupGsh | gsh script | will be run before test | textarea |
test.i.testGsh | gsh script | call the Java API for the template exec with inputs | textarea, required |
test.i.verifyGsh | gsh script | verify that the test succeeded | textarea |
A grouper admin would configure this in the UI under miscellaneous
Text on screen similar to custom UI
This template could be called via ws REST JSON and pass in the input name/value form elements just like the UI would
Developing GSH templates with java
See this wiki as an example of developing GSH templates with java
Built in variables, inputs, and methods
Before the configured GSH script is executed, it will be prefixed with some built in variables, and the inputs from the user (supplied in the UI or less commonly the WS).
Type | V1 variable | V2 location | Value |
|---|---|---|---|
n/a | gshTemplateV2input | gshRunLogic method parameter for inputs. This depends on how you name the param @Override
public void gshRunLogic(GshTemplateV2input gshTemplateV2input,
GshTemplateV2output gshTemplateV2output) {
| |
n/a | gshTemplateV2output | gshRunLogic method parameter for outputs. This depends on how you name the param @Override
public void gshRunLogic(GshTemplateV2input gshTemplateV2input,
GshTemplateV2output gshTemplateV2output) { | |
GshTemplateRuntime | n/a | gshTemplateV2input.getGsh_builtin_gshTemplateRuntime() |
|
|
|
|
|
|
|
|
|
gsh_builtin_gshTemplateOutput | GshTemplateOutput gsh_builtin_gshTemplateOutput = gshTemplateV2output.getGsh_builtin_gshTemplateOutput(); | Object that helps print output, notify about validation errors, or identify that an error occurred | |
gsh_builtin_gshTemplateRuntime | gshTemplateV2input.getGsh_builtin_gshTemplateRuntime() | Internal object that is used to help with other variables | |
GrouperSession | gsh_builtin_grouperSession | gshTemplateV2input.getGsh_builtin_grouperSession() | Session based on who the template is running is (this is configured, recommended to be the user who is running the template) |
Subject | gsh_builtin_subject | gshTemplateV2input.getGsh_builtin_gshTemplateRuntime().getCurrentSubject() | Subject who is running the template |
String | gsh_builtin_subjectId | gshTemplateV2input.getGsh_builtin_gshTemplateRuntime().getCurrentSubject().getId() | Subject ID of gsh_builtin_subject |
String | gsh_builtin_ownerStemName | gshTemplateV2input.getGsh_builtin_gshTemplateRuntime().getOwnerStemName() | Folder name of the folder where the script is run (if stem script, otherwise null) |
String | gsh_builtin_ownerGroupName | gshTemplateV2input.getGsh_builtin_gshTemplateRuntime().getOwnerGroupName() | Group name for the group where the script was run (if group script, otherwise null) |
String | gsh_input_XXXXXX | gshTemplateV2input.getGsh_builtin_inputString("gsh_input_org") | String inputs |
Integer | gsh_input_YYYYYYY | gshTemplateV2input.getGsh_builtin_inputInteger("gsh_input_numberOfRows") | Integer inputs |
Boolean | gsh_input_ZZZZZZZ | gshTemplateV2input.getGsh_builtin_inputBoolean("gsh_input_isEmployee") | Boolean inputs |
String | <none> | gshTemplateV2input.getGsh_builtin_gshTemplateRuntime().getRemoteAddr() | Source IP address |
String | <none> | gshTemplateV2input.getGsh_builtin_gshTemplateRuntime().getTemplateConfigId() | Config ID of template. This is useful if the same GSH source is used |
void | gsh_builtin_gshTemplateOutput.assignRedirectToGrouperOperation("NONE"); | Do not navigate after running template (or put another link in there) | |
void | gsh_builtin_gshTemplateOutput.assignRedirectToGrouperOperation("operation=UiV2Group.viewGroup&groupName=" + groupName);
| ||