- Created by Chris Hyzer (upenn.edu) on Nov 30, 2021
This GSH template allows networking administrators to build out the structure for a new VPN
Screenshots
When creating a VPN you can initialize the roles
Configuration
GSH script
// 1. Check Owner pennkeys
// for rules
Group employeeGroup = GroupFinder.findByName(gsh_builtin_grouperSession, "penn:community:employeeOrContractorIncludingUphs", true);
StringBuilder emailBody = new StringBuilder();
Set<String> emailTos = new HashSet<String>();
// convert owner pennkeys from comma separate string to an array
String[] ownerPennkeys = null;
// convert owner pennkeys into subjects
Subject[] ownerSubjects = null;
if (!StringUtils.isBlank(gsh_input_ownerPennkeys)) {
ownerPennkeys = GrouperUtil.splitTrim(gsh_input_ownerPennkeys, ",");
ownerSubjects = new Subject[ownerPennkeys.length];
for (int i=0;i<ownerPennkeys.length;i++) {
Subject subject = SubjectFinder.findByIdOrIdentifierAndSource(ownerPennkeys[i], "pennperson", false);
if (subject == null) {
gsh_builtin_gshTemplateOutput.addValidationLine("gsh_input_ownerPennkeys",
"Error: Owner PennKey cannot be found '" + ownerPennkeys[i] + "'!");
}
ownerSubjects[i] = subject;
// 2. Owners must be employees
if (!new MembershipFinder().addGroup(employeeGroup).addSubject(ownerSubjects[i]).hasMembership()) {
gsh_builtin_gshTemplateOutput.addValidationLine("gsh_input_ownerPennkeys",
"Error: Owner PennKey '" + ownerPennkeys[i] + "' is not in group: " + employeeGroup.getName() + "!");
}
String emailOfOwner = GrouperEmail.retrieveEmailAddress(ownerSubjects[i]);
// 3. email goes to owners
if (!StringUtils.isBlank(emailOfOwner)) {
// dont email owners for now, we can tell them
// emailTos.add(emailOfOwner);
}
}
}
// convert admin pennkeys from comma separate string to an array
String[] adminPennkeys = null;
// convert admin pennkeys into subjects
Subject[] adminSubjects = null;
if (!StringUtils.isBlank(gsh_input_adminPennkeys)) {
adminPennkeys = GrouperUtil.splitTrim(gsh_input_adminPennkeys, ",");
adminSubjects = new Subject[adminPennkeys.length];
for (int i=0;i<adminPennkeys.length;i++) {
Subject subject = SubjectFinder.findByIdOrIdentifierAndSource(adminPennkeys[i], "pennperson", false);
if (subject == null) {
gsh_builtin_gshTemplateOutput.addValidationLine("gsh_input_adminPennkeys",
"Error: Admin PennKey cannot be found '" + adminPennkeys[i] + "'!");
}
adminSubjects[i] = subject;
// 4. admins must be employees
if (!new MembershipFinder().addGroup(employeeGroup).addSubject(adminSubjects[i]).hasMembership()) {
gsh_builtin_gshTemplateOutput.addValidationLine("gsh_input_adminPennkeys",
"Error: Admin PennKey '" + adminPennkeys[i] + "' is not in group: " + employeeGroup.getName() + "!");
}
}
}
// convert vpn pennkeys from comma separate string to an array
String[] vpnEmployeePennkeys = null;
// convert vpn pennkeys into subjects
Subject[] vpnEmployeeSubjects = null;
if (!StringUtils.isBlank(gsh_input_vpnEmployeePennkeys)) {
vpnEmployeePennkeys = GrouperUtil.splitTrim(gsh_input_vpnEmployeePennkeys, ",");
vpnEmployeeSubjects = new Subject[vpnEmployeePennkeys.length];
for (int i=0;i<vpnEmployeePennkeys.length;i++) {
Subject subject = SubjectFinder.findByIdOrIdentifierAndSource(vpnEmployeePennkeys[i], "pennperson", false);
if (subject == null) {
gsh_builtin_gshTemplateOutput.addValidationLine("gsh_input_vpnPennkeys",
"Error: VPN PennKey cannot be found '" + vpnEmployeePennkeys[i] + "'!");
}
vpnEmployeeSubjects[i] = subject;
// 5. vpns must be employees
if (!new MembershipFinder().addGroup(employeeGroup).addSubject(vpnEmployeeSubjects[i]).hasMembership()) {
gsh_builtin_gshTemplateOutput.addValidationLine("gsh_input_vpnPennkeys",
"Error: VPN PennKey '" + vpnEmployeePennkeys[i] + "' is not in group: " + employeeGroup.getName() + "!");
}
}
}
// convert owner ref groups from comma separate string to an array
String[] ownerRefGroupNames = null;
// convert owner ref group names into groups
Group[] ownerRefGroups = null;
if (!StringUtils.isBlank(gsh_input_ownerRefGroupName)) {
ownerRefGroupNames = GrouperUtil.splitTrim(gsh_input_ownerRefGroupName, ",");
ownerRefGroups = new Group[ownerRefGroupNames.length];
for (int i=0;i<ownerRefGroupNames.length;i++) {
Group group = GroupFinder.findByName(gsh_builtin_grouperSession, ownerRefGroupNames[i], false);
// 6. Make sure owner ref groups exist
if (group == null) {
gsh_builtin_gshTemplateOutput.addValidationLine("gsh_input_ownerRefGroupName",
"Error: Owner ref group cannot be found '" + ownerRefGroupNames[i] + "'!");
} else {
ownerRefGroups[i] = group;
}
}
}
// convert admin ref groups from comma separate string to an array
String[] adminRefGroupNames = null;
// convert admin ref group names into groups
Group[] adminRefGroups = null;
if (!StringUtils.isBlank(gsh_input_adminRefGroupName)) {
adminRefGroupNames = GrouperUtil.splitTrim(gsh_input_adminRefGroupName, ",");
adminRefGroups = new Group[adminRefGroupNames.length];
for (int i=0;i<adminRefGroupNames.length;i++) {
Group group = GroupFinder.findByName(gsh_builtin_grouperSession, adminRefGroupNames[i], false);
// 7. Make sure admin ref groups exist
if (group == null) {
gsh_builtin_gshTemplateOutput.addValidationLine("gsh_input_adminRefGroupName",
"Error: Admin ref group cannot be found '" + adminRefGroupNames[i] + "'!");
} else {
adminRefGroups[i] = group;
}
}
}
// convert VPN ref groups from comma separate string to an array
String[] vpnRefGroupNames = null;
// convert vpn ref group names into groups
Group[] vpnRefGroups = null;
if (!StringUtils.isBlank(gsh_input_vpnOrgsOrCenters)) {
vpnRefGroupNames = GrouperUtil.splitTrim(gsh_input_vpnOrgsOrCenters, ",");
vpnRefGroups = new Group[vpnRefGroupNames.length];
for (int i=0;i<vpnRefGroupNames.length;i++) {
// 8. convert org and center name to group name.
if (!vpnRefGroupNames[i].matches("^[0-9a-zA-Z]{2,4}\044")) { // groovy doesnt like dollar in string without escape. \044 is dollar
gsh_builtin_gshTemplateOutput.addValidationLine("group",
"Error: VPN ref group must be two chars for center or four chars for org '" + vpnRefGroupNames[i] + "'!");
continue;
}
Group group = null;
if (vpnRefGroupNames[i].length() == 2) {
// penn:community:employee:center:91_center:91_center, e.g. 99
vpnRefGroupNames[i] = "penn:community:employee:center:" + vpnRefGroupNames[i] + "_center:" + vpnRefGroupNames[i] + "_center";
group = GroupFinder.findByName(gsh_builtin_grouperSession, vpnRefGroupNames[i], false);
} else if (vpnRefGroupNames[i].length() == 4) {
String org = vpnRefGroupNames[i];
// penn:community:employee:org:9142:9142_personorg, e.g. 9104
vpnRefGroupNames[i] = "penn:community:employee:org:" + org + ":" + org + "_personorg";
group = GroupFinder.findByName(gsh_builtin_grouperSession, vpnRefGroupNames[i], false);
// could be a rollup org
if (group == null) {
vpnRefGroupNames[i] = "penn:community:employee:org:" + org + ":" + org + "_rolluporg";
group = GroupFinder.findByName(gsh_builtin_grouperSession, vpnRefGroupNames[i], false);
}
}
// 9. Check all orgs / centers exist
if (group == null) {
gsh_builtin_gshTemplateOutput.addValidationLine("gsh_input_vpnOrgsOrCenters",
"Error: VPN org or center group cannot be found '" + vpnRefGroupNames[i] + "'!");
} else {
vpnRefGroups[i] = group;
}
}
}
// Do not proceed is there is an error
if (GrouperUtil.length(gsh_builtin_gshTemplateOutput.getValidationLines()) > 0) {
gsh_builtin_gshTemplateOutput.assignIsError(true);
GrouperUtil.gshReturn();
}
// 10. email to the user who performed this so they can support it
String emailOfUserRunningTemplate = GrouperEmail.retrieveEmailAddress(gsh_builtin_subject);
if (!StringUtils.isBlank(emailOfUserRunningTemplate)) {
emailTos.add(emailOfUserRunningTemplate);
} else {
gsh_builtin_gshTemplateOutput.addValidationLine(
"Error: Cannot find your email address. Please edit it in the directory and try again an hour later");
}
// 11. main body of email
emailBody.append("You are an owner of the " + gsh_input_projectFriendlyName + " SRA VPN.\n");
emailBody.append("This is an organizational VPN to secure network resources to a specific population.\n");
emailBody.append("There are three roles for the VPN:\n");
emailBody.append(" - The owner role should have two or three people who manage the owners, admins, VPN users, and review the access monthly.\n");
emailBody.append(" - The admin role manages the VPN users. Usually the admins are the same people as the owners, but admins can contain more IT support specialists.\n");
emailBody.append(" - The VPN role can use the VPN.\n");
emailBody.append("Each role can have an automatic population based on other groups. For owners and admins this could be another group of IT employees. ");
emailBody.append("The VPN automatic population will generally be based on active employees in payroll ORG(s) or CENTER(s).\n");
emailBody.append("Each role has manual groups for the owners and admins (if applicable) to maintain. Owners can manage manual groups of owners and admins. ");
emailBody.append("Any owner or admin in the manual group, who is no longer an employee, will be automatically removed from the manual owner or admin group. ");
emailBody.append("The 'VPN employee manual' group is an ad hoc group of employees who have access to the VPN, but will be automatically removed ");
emailBody.append("when they are no longer an employee. The 'VPN guest' group can contain people who are not employees. You might want to set an 'end date' on those memberships.\n");
emailBody.append("In rare cases someone is automatically allowed to use the VPN but needs to be manually excluded. There is an Excludes list for that.\n");
emailBody.append("There is a management interface for admins and owners to easily manage and review the access for the VPN.\n\n");
String projectStemName = "penn:isc:ts:networking:service:sraVpn:service:" + gsh_input_projectSystemName;
// 12. Add project folder
Stem projectFolder = null;
boolean projectFolderAdded = false;
String reportConfigName = gsh_input_projectSystemName + "SraVpnReport";
PROJECT_FOLDER: {
StemSave projectFolderSave = new StemSave().assignName(projectStemName).assignDisplayExtension(gsh_input_projectFriendlyName + " SRA VPN").assignDescription("This folder holds groups involved in the " + gsh_input_projectFriendlyName + " SRA VPN. Owners are two or three people who review all the memberships lists and manage the Owners and Admins. Admins can manage the VPN memberships. Owners and admins can be automatic. If owners and admins are manual, then they will lose access when no longer Penn employees. Automatic VPN members will gain/lose access based on their org or other attribute. EmployeesManual are a manual list who will have access as long as they are employees. Guests will have access and do not need to be employees.");
projectFolder = projectFolderSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Project folder " + projectFolderSave.getSaveResultType() + ": " + projectStemName);
projectFolderAdded = projectFolderSave.getSaveResultType() == SaveResultType.INSERT;
// 13. Add report
if (projectFolderAdded) {
AttributeAssign attributeAssignMarker = new AttributeAssignToStemSave().assignStem(projectFolder).assignNameOfAttributeDefName("penn:etc:reportConfig:reportConfigMarker").save();
AttributeAssign attributeAssign = new AttributeAssignToAssignmentSave().assignAttributeAssign(attributeAssignMarker).assignAttributeDefNameName("penn:etc:reportConfig:reportConfigDescription").save().getAttributeAssign();
new AttributeAssignValueSave().assignAttributeAssign(attributeAssign).assignValue("Contains users, admins, and owner of the VPN. can_use_vpn means the user has access (if they have been in for 15 minutes and have been provisioned to LDAP). can_use_vpn_since is the timestamp when their VPN access started. could_use_vpn_until is when the vpn access was removed for this user. vpn_to_start_timestamp is the timestamp in the future the user will have access. vpn_to_end_timestamp is their end date of using the VPN. is_employee_manual means they are in the ad hoc population (otherwise to get access they would need to be in the automatic population), and if they are ever not a Penn employee they will lose access. is_guest means they can use the VPN and they do not need a Penn affiliation to do so. is_exclude means they are in the manual group of people excludes from the VPN (when the automatic population is wrong). active_employee is true if the user is an active employee at Penn or UPHS. is_owner is T (true) if the user is an owner of the VPN (can manage all lists). is_admin is T if the user can manage the VPN user lists. person_description is the user's name and affiliation.").save();
attributeAssign = new AttributeAssignToAssignmentSave().assignAttributeAssign(attributeAssignMarker).assignAttributeDefNameName("penn:etc:reportConfig:reportConfigEnabled").save().getAttributeAssign();
new AttributeAssignValueSave().assignAttributeAssign(attributeAssign).assignValue("true").save();
attributeAssign = new AttributeAssignToAssignmentSave().assignAttributeAssign(attributeAssignMarker).assignAttributeDefNameName("penn:etc:reportConfig:reportConfigFilename").save().getAttributeAssign();
new AttributeAssignValueSave().assignAttributeAssign(attributeAssign).assignValue(gsh_input_projectSystemName + "SraVpnReport_" + '$' + '$' + "timestamp" + '$' + '$' + ".csv").save();
attributeAssign = new AttributeAssignToAssignmentSave().assignAttributeAssign(attributeAssignMarker).assignAttributeDefNameName("penn:etc:reportConfig:reportConfigFormat").save().getAttributeAssign();
new AttributeAssignValueSave().assignAttributeAssign(attributeAssign).assignValue("CSV").save();
attributeAssign = new AttributeAssignToAssignmentSave().assignAttributeAssign(attributeAssignMarker).assignAttributeDefNameName("penn:etc:reportConfig:reportConfigName").save().getAttributeAssign();
new AttributeAssignValueSave().assignAttributeAssign(attributeAssign).assignValue(reportConfigName).save();
attributeAssign = new AttributeAssignToAssignmentSave().assignAttributeAssign(attributeAssignMarker).assignAttributeDefNameName("penn:etc:reportConfig:reportConfigType").save().getAttributeAssign();
new AttributeAssignValueSave().assignAttributeAssign(attributeAssign).assignValue("SQL").save();
attributeAssign = new AttributeAssignToAssignmentSave().assignAttributeAssign(attributeAssignMarker).assignAttributeDefNameName("penn:etc:reportConfig:reportConfigQuartzCron").save().getAttributeAssign();
// some random time between 7 and 9
int seconds = (int)(Math.random()*60);
int minutes = (int)(Math.random()*60);
int hours = 7 + (int)(Math.random()*2);
new AttributeAssignValueSave().assignAttributeAssign(attributeAssign).assignValue(seconds + " " + minutes + " " + hours + " * * ?").save();
attributeAssign = new AttributeAssignToAssignmentSave().assignAttributeAssign(attributeAssignMarker).assignAttributeDefNameName("penn:etc:reportConfig:reportConfigQuery").save().getAttributeAssign();
new AttributeAssignValueSave().assignAttributeAssign(attributeAssign).assignValue("select penn_id, penn_key, can_use_vpn, can_use_vpn_since, could_use_vpn_until, vpn_to_start_timestamp, vpn_to_end_timestamp, is_employee_manual, is_guest, is_exclude, active_employee, is_owner, is_admin, person_description from penn_sra_vpn_report_v where vpn_system_name = '" + gsh_input_projectSystemName + "'").save();
gsh_builtin_gshTemplateOutput.addOutputLine("Report: added to project folder: " + projectStemName);
GrouperReportConfigurationBean reportConfigBean = GrouperReportConfigService.getGrouperReportConfigBean(attributeAssignMarker.getId());
try {GrouperReportConfigService.scheduleJob(reportConfigBean, projectFolder); } catch (org.quartz.SchedulerException se) {throw new RuntimeException("error", se);}
gsh_builtin_gshTemplateOutput.addOutputLine("Report: scheduled");
}
}
emailBody.append("https://grouper.apps.upenn.edu/grouper/grouperUi/app/UiV2Main.index?operation=UiV2Template.newTemplate&stemId=" + projectFolder.getId() + "&templateType=sraVpnManage");
// 14. Create owners group
Group ownersGroup = null;
OWNERS_GROUP: {
GroupSave groupSave = new GroupSave().assignName(projectStemName + ":" + gsh_input_projectSystemName + "SraVpnOwners").assignDisplayExtension(gsh_input_projectFriendlyName + " SRA VPN Owners").assignDescription("Owners manage the Owners, and Admins. They receive periodic requests to review the VPN access report. There should be more than one and not more than a few Owners. Do not edit this group's memberships, edit the Owner manual group list. To add a new reference group here open a ticket with help@isc.upenn.edu");
ownersGroup = groupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Owners group " + groupSave.getSaveResultType() + ": " + ownersGroup.getName());
}
// 15. Add owner ref groups to owners
for (Group memberGroup : GrouperUtil.nonNull(ownerRefGroups, Group.class)) {
MembershipSave membershipSave = new MembershipSave().assignGroup(ownersGroup).assignSubject(memberGroup.toSubject());
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: " + memberGroup.getName() + " to Owners group: " + membershipSave.getSaveResultType());
}
// 16. Add read on owner ref groups to owners
for (Group refGroup : GrouperUtil.nonNull(ownerRefGroups, Group.class)) {
PrivilegeGroupSave privilegeGroupSave = new PrivilegeGroupSave().assignGroup(refGroup).assignFieldName("readers").assignSubject(ownersGroup.toSubject());
privilegeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Allowing: READ on " + refGroup.getName() + " to Owners group: " + privilegeGroupSave.getSaveResultType());
}
// 17. Add grouperSecurity type to Owners
OWNER_GROUP_TYPE: {
GdgTypeGroupSave gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(ownersGroup).assignType("grouperSecurity");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: grouperSecurity type on Owners group: " + gdgTypeGroupSave.getSaveResultType());
}
// 18. Create Owners manual group
Group ownersManualGroup = null;
OWNER_MANUAL_GROUP: {
GroupSave ownersManualGroupSave = new GroupSave().assignName(projectStemName + ":" + gsh_input_projectSystemName + "SraVpnOwnersManual").assignDisplayExtension(gsh_input_projectFriendlyName + " SRA VPN Owners Manual").assignDescription("Owners manage the Owners, and Admins. They receive periodic requests to review the VPN access report. There should be more than one and not more than a few Owners. Manually manage the list of employees who are owners here.");
ownersManualGroup = ownersManualGroupSave.save();
if (ownersManualGroupSave.getSaveResultType() == SaveResultType.INSERT) {
gsh_builtin_gshTemplateOutput.addOutputLine("Owners manual group created: " + ownersManualGroup.getName());
// 19. since we just created this, add a rule that removes members if not employees
RuleApi.groupIntersection(gsh_builtin_grouperSession.getSubject(), ownersManualGroup, employeeGroup);
gsh_builtin_gshTemplateOutput.addOutputLine("Rule added on owners manual group to require membership in: " + employeeGroup.getName());
} else {
gsh_builtin_gshTemplateOutput.addOutputLine("Owners manual group " + ownersManualGroupSave.getSaveResultType() + ": " + ownersManualGroup.getName());
}
}
// 19. Add Owners Manual to Owners
ADD_MANUAL_TO_OWNERS: {
MembershipSave membershipSave = new MembershipSave().assignGroup(ownersGroup).assignSubject(ownersManualGroup.toSubject());
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: Owners manual group to Owners group: " + membershipSave.getSaveResultType());
}
// 20. Add Owner to manage owner manual group (read/update)
OWNER_MANUAL_PRIVILEGES: {
PrivilegeGroupSave privilegeGroupSave = new PrivilegeGroupSave().assignGroup(ownersManualGroup).assignFieldName("updaters").assignSubject(ownersGroup.toSubject());
privilegeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Allowing: Owners group to update Owners manual group: " + privilegeGroupSave.getSaveResultType());
}
// 21. Add manual and grouperSecurity type to Owners manual
OWNER_MANUAL_TYPES: {
GdgTypeGroupSave gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(ownersManualGroup).assignType("manual");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: manual type on Owners manual group: " + gdgTypeGroupSave.getSaveResultType());
}
// 22. Add owner pennkeys to owner group
for (Subject subject : GrouperUtil.nonNull(ownerSubjects, Subject.class)) {
MembershipSave membershipSave = new MembershipSave().assignGroup(ownersManualGroup).assignSubject(subject);
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: " + subject.getDescription() + " to Owner manual group: " + membershipSave.getSaveResultType());
}
// 23. Create admins group
Group adminsGroup = null;
CREATE_ADMINS: {
GroupSave groupSave = new GroupSave().assignName(projectStemName + ":" + gsh_input_projectSystemName + "SraVpnAdmins").assignDisplayExtension(gsh_input_projectFriendlyName + " SRA VPN Admins").assignDescription("Admins manage the VPN users: EmployeesManual, Guests, Excludes. They can see the access report and all groups. Do not edit this group's memberships, edit the Admin manual group list. To add a new (automatic) reference group here open a ticket with help@isc.upenn.edu");
adminsGroup = groupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Admins group " + groupSave.getSaveResultType() + ": " + adminsGroup.getName());
}
// 24. Add admin ref groups to admins
for (Group memberGroup : GrouperUtil.nonNull(adminRefGroups, Group.class)) {
MembershipSave membershipSave = new MembershipSave().assignGroup(adminsGroup).assignSubject(memberGroup.toSubject());
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: " + memberGroup.getName() + " to Admins group: " + membershipSave.getSaveResultType());
}
// 25. Add read on admin ref groups to owners
for (Group refGroup : GrouperUtil.nonNull(adminRefGroups, Group.class)) {
PrivilegeGroupSave privilegeGroupSave = new PrivilegeGroupSave().assignGroup(refGroup).assignFieldName("readers").assignSubject(ownersGroup.toSubject());
privilegeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Allowing: READ on " + refGroup.getName() + " to Owners group: " + privilegeGroupSave.getSaveResultType());
}
// 26. Add Owners group to admins
ADD_OWNERS_TO_ADMINS: {
MembershipSave membershipSave = new MembershipSave().assignGroup(adminsGroup).assignSubject(ownersGroup.toSubject());
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: Owners group to Admins group: " + membershipSave.getSaveResultType());
}
// 27. Add grouperSecurity type to Admins
ADMIN_GROUP_TYPE: {
GdgTypeGroupSave gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(adminsGroup).assignType("grouperSecurity");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: grouperSecurity type on Admins group: " + gdgTypeGroupSave.getSaveResultType());
}
// 28. Create Admins manual group
Group adminsManualGroup = null;
ADMIN_MANUAL_GROUP: {
GroupSave adminsManualGroupSave = new GroupSave().assignName(projectStemName + ":" + gsh_input_projectSystemName + "SraVpnAdminsManual").assignDisplayExtension(gsh_input_projectFriendlyName + " SRA VPN Admins Manual").assignDescription("Admins manage the VPN users. They can add or remove members of the manual groups: EmployeesManual, Guests, Excludes. Admins are automatically removed when they are no longer employees. Manage the list of employees who are admins here.");
adminsManualGroup = adminsManualGroupSave.save();
if (adminsManualGroupSave.getSaveResultType() == SaveResultType.INSERT) {
gsh_builtin_gshTemplateOutput.addOutputLine("Admins manual group created: " + adminsManualGroup.getName());
// 29. since we just created this, add a rule that removes members if not employees
RuleApi.groupIntersection(gsh_builtin_grouperSession.getSubject(), adminsManualGroup, employeeGroup);
gsh_builtin_gshTemplateOutput.addOutputLine("Rule added on Admins manual group to require membership in: " + employeeGroup.getName());
} else {
gsh_builtin_gshTemplateOutput.addOutputLine("Admins manual group " + adminsManualGroupSave.getSaveResultType() + ": " + adminsManualGroup.getName());
}
}
// 30. Add manual type to Admins manual
ADMINS_MANUAL_TYPES: {
GdgTypeGroupSave gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(adminsManualGroup).assignType("manual");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: manual type on Admins manual group: " + gdgTypeGroupSave.getSaveResultType());
}
// 31. Add Owner to manage admin manual group (read/update)
ADMINS_MANUAL_PRIVILEGES: {
PrivilegeGroupSave privilegeGroupSave = new PrivilegeGroupSave().assignGroup(adminsManualGroup).assignFieldName("updaters").assignSubject(ownersGroup.toSubject());
privilegeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Allowing: Owners group to update Admin manual group: " + privilegeGroupSave.getSaveResultType());
}
// 32. Add Admin manual group to admins
ADMINS_MANUAL_TO_ADMIN: {
MembershipSave membershipSave = new MembershipSave().assignGroup(adminsGroup).assignSubject(adminsManualGroup.toSubject());
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: Admin manual group to Admins group: " + membershipSave.getSaveResultType());
}
// 33. Add READ on VPN ref groups to admins
for (Group refGroup : GrouperUtil.nonNull(vpnRefGroups, Group.class)) {
PrivilegeGroupSave privilegeGroupSave = new PrivilegeGroupSave().assignGroup(refGroup).assignFieldName("readers").assignSubject(adminsGroup.toSubject());
privilegeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Allowing: READ on " + refGroup.getName() + " to Admins group: " + privilegeGroupSave.getSaveResultType());
}
// 34. Add inherited READ on folder to admins
ADMIN_PRIV_READ_INHERIT: {
PrivilegeGroupInheritanceSave privilegeGroupInheritanceSave = new PrivilegeGroupInheritanceSave().assignStem(projectFolder).addPrivilegeName("read").assignSubject(adminsGroup.toSubject());
privilegeGroupInheritanceSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Allowing: Admins group can READ all groups in project folder: " + privilegeGroupInheritanceSave.getSaveResultType());
}
// 35. Add admin pennkeys to admin manual group
for (Subject subject : GrouperUtil.nonNull(adminSubjects, Subject.class)) {
MembershipSave membershipSave = new MembershipSave().assignGroup(adminsManualGroup).assignSubject(subject);
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: " + subject.getDescription() + " to Admin manual group: " + membershipSave.getSaveResultType());
}
// 36. Create group include employees
Group employeesManualGroup = null;
EMPLOYEES_MANUAL_GROUP: {
GroupSave employeesManualGroupSave = new GroupSave().assignName(projectStemName + ":" + gsh_input_projectSystemName + "SraVpnEmployeesManual").assignDisplayExtension(gsh_input_projectFriendlyName + " SRA VPN Employees Manual").assignDescription("If employees who use the VPN cannot be managed automatically (e.g. by payroll ORG), then manually manage the list of employees who can use the VPN here. If you need to add someone to the VPN who is not a VPN, add them to the Guest group. If there is a way to automate this population (e.g. by query against pcom or warehouse or another PennGroup), please contact help@isc.upenn.edu.");
employeesManualGroup = employeesManualGroupSave.save();
if (employeesManualGroupSave.getSaveResultType() == SaveResultType.INSERT) {
gsh_builtin_gshTemplateOutput.addOutputLine("Employees manual group created: " + employeesManualGroup.getName());
// 37. since we just created this, add a rule that removes members if not employees
RuleApi.groupIntersection(gsh_builtin_grouperSession.getSubject(), employeesManualGroup, employeeGroup);
gsh_builtin_gshTemplateOutput.addOutputLine("Rule added on employees manual group to require membership in: " + employeeGroup.getName());
} else {
gsh_builtin_gshTemplateOutput.addOutputLine("Employees manual group " + employeesManualGroupSave.getSaveResultType() + ": " + adminsManualGroup.getName());
}
}
// 38. Add manual and ref type to Employees manual
EMPLOYEES_MANUAL_TYPES: {
GdgTypeGroupSave gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(employeesManualGroup).assignType("manual");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: manual type on Employees manual group: " + gdgTypeGroupSave.getSaveResultType());
gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(employeesManualGroup).assignType("ref");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: ref type on Employees manual group: " + gdgTypeGroupSave.getSaveResultType());
}
// 39. Add UPDATE on employees group to admins
ADMINS_MANUAL_PRIVILEGES: {
PrivilegeGroupSave privilegeGroupSave = new PrivilegeGroupSave().assignGroup(employeesManualGroup).assignFieldName("updaters").assignSubject(adminsGroup.toSubject());
privilegeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Allowing: Admins to update Employees manual group: " + privilegeGroupSave.getSaveResultType());
}
// 40. Add admin pennkeys to admin manual group
for (Subject subject : GrouperUtil.nonNull(vpnEmployeeSubjects, Subject.class)) {
MembershipSave membershipSave = new MembershipSave().assignGroup(employeesManualGroup).assignSubject(subject);
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: " + subject.getDescription() + " to VPN employee manual group: " + membershipSave.getSaveResultType());
}
// 41. Create group Guest
Group guestsGroup = null;
GUESTS_GROUP: {
GroupSave guestGroupSave = new GroupSave().assignName(projectStemName + ":" + gsh_input_projectSystemName + "SraVpnGuests").assignDisplayExtension(gsh_input_projectFriendlyName + " SRA VPN Guests").assignDescription("Non-employees who need access to the VPN. This access needs to be removed when not needed. If you know when the access should end you should put an end-date on the membership.");
guestsGroup = guestGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Guests group " + guestGroupSave.getSaveResultType() + ": " + guestsGroup.getName());
}
// 42. Create group Guest
GUESTS_TYPES: {
GdgTypeGroupSave gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(guestsGroup).assignType("manual");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: manual type on Guests group: " + gdgTypeGroupSave.getSaveResultType());
gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(guestsGroup).assignType("ref");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: ref type on Guests group: " + gdgTypeGroupSave.getSaveResultType());
}
// 43. Add UPDATE on guests group to admins
ADMINS_GUESTS_PRIVILEGES: {
PrivilegeGroupSave privilegeGroupSave = new PrivilegeGroupSave().assignGroup(guestsGroup).assignFieldName("updaters").assignSubject(adminsGroup.toSubject());
privilegeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Allowing: Admins to update Guests group: " + privilegeGroupSave.getSaveResultType());
}
// 44. Create group excludes
Group excludesGroup = null;
EXCLUDES_GROUP: {
GroupSave excludesGroupSave = new GroupSave().assignName(projectStemName + ":" + gsh_input_projectSystemName + "SraVpnExcludes").assignDisplayExtension(gsh_input_projectFriendlyName + " SRA VPN Excludes").assignDescription("Manual excludes list. This is for people who are automatically included and need to be excluded");
excludesGroup = excludesGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Excludes group " + excludesGroupSave.getSaveResultType() + ": " + excludesGroup.getName());
}
// 45. Create group Guest
EXCLUDES_TYPES: {
GdgTypeGroupSave gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(excludesGroup).assignType("manual");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: manual type on Excludes group: " + gdgTypeGroupSave.getSaveResultType());
gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(excludesGroup).assignType("ref");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: ref type on Excludes group: " + gdgTypeGroupSave.getSaveResultType());
}
// 46. Add UPDATE on guests group to admins
ADMINS_EXCLUDES_PRIVILEGES: {
PrivilegeGroupSave privilegeGroupSave = new PrivilegeGroupSave().assignGroup(excludesGroup).assignFieldName("updaters").assignSubject(adminsGroup.toSubject());
privilegeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Allowing: Admins to update Excludes group: " + privilegeGroupSave.getSaveResultType());
}
// 47. Add allow group
Group allowGroup = null;
ALLOW_GROUP: {
GroupSave allowGroupSave = new GroupSave().assignName(projectStemName + ":" + gsh_input_projectSystemName + "SraVpnAllow").assignDisplayExtension(gsh_input_projectFriendlyName + " SRA VPN Allow").assignDescription("This is the allow part of the VPN policy. This is an internal group that can be ignored. You do not have access to manage the memberships. It consists of all the allows to the VPN before the denies. This group does not directly include individuals, it includes ref groups: the automatic employee groups (orgs/centers), Employees manual group, and Guests. To add/remove a reference group, open a ticket with help@isc.upenn.edu");
allowGroup = allowGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Allow group " + allowGroupSave.getSaveResultType() + ": " + allowGroup.getName());
}
// 48. Add intermediate type to allow group
ALLOW_TYPES: {
GdgTypeGroupSave gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(allowGroup).assignType("intermediate");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: intermediate type on Allow group: " + gdgTypeGroupSave.getSaveResultType());
}
// 49. Add members to allow group, ref groups, employees manual, guests
ALLOW_MEMBERS: {
for (Group memberGroup : GrouperUtil.nonNull(vpnRefGroups, Group.class)) {
MembershipSave membershipSave = new MembershipSave().assignGroup(allowGroup).assignSubject(memberGroup.toSubject());
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: " + memberGroup.getName() + " to Allow group: " + membershipSave.getSaveResultType());
}
MembershipSave membershipSave = new MembershipSave().assignGroup(allowGroup).assignSubject(employeesManualGroup.toSubject());
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: Employee manual group to Allow group: " + membershipSave.getSaveResultType());
membershipSave = new MembershipSave().assignGroup(allowGroup).assignSubject(guestsGroup.toSubject());
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: Guests to Allow group: " + membershipSave.getSaveResultType());
}
// 50. Add deny group
Group denyGroup = null;
DENY_GROUP: {
GroupSave denyGroupSave = new GroupSave().assignName(projectStemName + ":" + gsh_input_projectSystemName + "SraVpnDeny").assignDisplayExtension(gsh_input_projectFriendlyName + " SRA VPN Deny").assignDescription("This is the deny part of the VPN policy. This is an internal group that can be ignored. You do not have access to manage the memberships. It consists of all the denies to the VPN, which take precendence before the allows. This group does not directly include individuals, it includes ref groups: the automatic lockout group, and the Excludes (manual) group. To add/remove a reference group, open a ticket with help@isc.upenn.edu");
denyGroup = denyGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Deny group " + denyGroupSave.getSaveResultType() + ": " + denyGroup.getName());
}
// 51. Add intermediate type to deny group
DENY_TYPES: {
GdgTypeGroupSave gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(denyGroup).assignType("intermediate");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: intermediate type on Deny group: " + gdgTypeGroupSave.getSaveResultType());
}
// 52. Add members to deny group, lockout, and Excludes
DENY_MEMBERS: {
MembershipSave membershipSave = new MembershipSave().assignGroup(denyGroup).assignSubjectSourceId("g:gsa").assignSubjectIdentifier("penn:isc:security:lockout:employeeLockout");
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: Lockout group to Deny group: " + membershipSave.getSaveResultType());
membershipSave = new MembershipSave().assignGroup(denyGroup).assignSubject(excludesGroup.toSubject());
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: Excludes to Deny group: " + membershipSave.getSaveResultType());
}
// 53. Add overall group
Group overallGroup = null;
OVERALL_GROUP: {
GroupSave overallGroupSave = new GroupSave().assignName(projectStemName + ":" + gsh_input_projectSystemName + "SraVpnOverall").assignDisplayExtension(gsh_input_projectFriendlyName + " SRA VPN Overall").assignDescription("This is the VPN policy group of who can use the VPN. This takes into consideration the allows (automatic and manual), and the denies (automatic and manual). After membership changes in this group it takes 15-60 minutes to reach LDAP (and the VPN). You do not have access to manage the memberships. This group does not directly include individuals, it is the allows minus the denies. To change the policy, open a ticket with help@isc.upenn.edu");
overallGroup = overallGroupSave.save();
if (overallGroupSave.getSaveResultType() == SaveResultType.INSERT) {
gsh_builtin_gshTemplateOutput.addOutputLine("Overall group created: " + employeesManualGroup.getName());
// 54. since we just created this, provision to AD bushy
AttributeAssignToGroupSave attributeAssignToGroupSave = new AttributeAssignToGroupSave().assignGroup(overallGroup).assignNameOfAttributeDefName("penn:etc:pspng:provision_to");
AttributeAssign attributeAssign = attributeAssignToGroupSave.save();
new AttributeAssignValueSave().assignAttributeAssign(attributeAssign).assignValue("pspng_activedirectoryFull").save();
gsh_builtin_gshTemplateOutput.addOutputLine("Provisioning: Overall group to Kite AD: " + attributeAssignToGroupSave.getSaveResultType());
} else {
gsh_builtin_gshTemplateOutput.addOutputLine("Overall group " + overallGroupSave.getSaveResultType() + ": " + overallGroup.getName());
}
gsh_builtin_gshTemplateOutput.addOutputLine("Kite: CN=" + gsh_input_projectSystemName + "SraVpnOverall,OU=" + gsh_input_projectSystemName + ",OU=service,OU=sraVpn,OU=service,OU=networking,OU=ts,OU=isc,OU=penn,OU=GrouperFull,OU=LocalAuth,DC=kite,DC=upenn,DC=edu");
}
// 54.5 Add overall group to SRA overall group
SRA_OVERALL_GROUP: {
Group sraOverallGroup = GroupFinder.findByName(gsh_builtin_grouperSession, "penn:isc:ts:networking:service:sraVpn:sraVpnAllUsers", true);
MembershipSave membershipSave = new MembershipSave().assignGroup(sraOverallGroup).assignSubject(overallGroup.toSubject());
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: " + overallGroup.getName() + " to SRA overall users group: " + membershipSave.getSaveResultType());
}
// 55. Add policy type to overall group
OVERALL_TYPES: {
GdgTypeGroupSave gdgTypeGroupSave = new GdgTypeGroupSave().assignGroup(overallGroup).assignType("policy");
gdgTypeGroupSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Add: policy type on Overall group: " + gdgTypeGroupSave.getSaveResultType());
}
// 56. Add members to deny group: lockout, Excludes
OVERALL_COMPOSITE: {
CompositeSave compositeSave = new CompositeSave().assignOwnerName(overallGroup.getName()).assignLeftFactorName(allowGroup.getName()).assignType("complement").assignRightFactorName(denyGroup.getName());
compositeSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: Overall group is composite Allow minus Deny: " + compositeSave.getSaveResultType());
}
// Owners group should attest, whoever in group gets emails
String ownersAttestationEmailAddress = ownersGroup.getName() + "@grouper";
// 57. Add to grouper.properties that the owners group can receive email
GrouperEmail.addAllowEmailToGroup(ownersAttestationEmailAddress);
// 58. Add attestation to the super admins group to the project folder
ATTESTATION: {
AttestationStemSave attestationStemSave = new AttestationStemSave().assignStem(projectFolder).assignGroupCanAttest(adminsGroup);
attestationStemSave.assignReportConfigName(reportConfigName).addEmailAddress(ownersAttestationEmailAddress).assignSendEmail(true);
attestationStemSave.assignAttestationType(AttestationType.report).assignDaysUntilRecertify(30);
// dont reset the date if its likely already there
if (projectFolderAdded) {
attestationStemSave.assignMarkAsAttested(true);
}
attestationStemSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Attestation: on report: " + attestationStemSave.getSaveResultType());
}
// 59. Admins group needs to be in the "manage vpn" template runner group
TEMPLATE_RUNNER: {
MembershipSave membershipSave = new MembershipSave().assignGroupName("penn:isc:ts:networking:service:sraVpn:sraVpnManageVpnTemplateRunners").assignSubject(adminsGroup.toSubject());
membershipSave.save();
gsh_builtin_gshTemplateOutput.addOutputLine("Adding: Admins group to Manage VPN template runners group: " + membershipSave.getSaveResultType());
}
// 60. add template URL in email
// 61. send email
if (emailTos.size() > 0) {
String emailTo = StringUtils.join(emailTos.iterator(), ",");
new GrouperEmail().setTo(emailTo).setSubject("SRA VPN for " + gsh_input_projectFriendlyName).setBody(emailBody.toString()).send();
gsh_builtin_gshTemplateOutput.addOutputLine("Sent email with links and instructions to: " + emailTo);
}
// done!
gsh_builtin_gshTemplateOutput.addOutputLine("Finished running SRA VPN template for project: " + gsh_input_projectFriendlyName);
// 62. kick off dependent jobs on daemon (hopefully this tx commits before they run)
GrouperLoader.runOnceByJobName(gsh_builtin_grouperSession, "OTHER_JOB_sraVpnMships", true);
GrouperLoader.runOnceByJobName(gsh_builtin_grouperSession, "OTHER_JOB_sraVpnTimes", true);
GrouperLoader.runOnceByJobName(gsh_builtin_grouperSession, "OTHER_JOB_sraVpnPit", true);
- No labels