diff --git a/ex101/ex101.1.1/container_files/seed-data/bootstrap.gsh b/ex101/ex101.1.1/container_files/seed-data/bootstrap.gsh index 4eed0db..620aa53 100644 --- a/ex101/ex101.1.1/container_files/seed-data/bootstrap.gsh +++ b/ex101/ex101.1.1/container_files/seed-data/bootstrap.gsh @@ -285,7 +285,7 @@ config.propertyName("provisioner.eduPersonAffiliation.subjectSourcesToProvision" config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.0.fieldName").value('''name''').store() config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.0.isFieldElseAttribute").value('''true''').store() config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.0.select").value('''true''').store() -config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.0.translateExpression").value('''${'uid=' + grouperProvisioningEntity.subjectId + ',ou=people,dc=internet2,dc=edu'}''').store() +config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.0.translateExpression").value('''${'uid=' + grouperProvisioningEntity.retrieveAttributeValueString('subjectIdentifier0') + ',ou=people,dc=internet2,dc=edu'}''').store() config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.0.translateExpressionType").value('''translationScript''').store() config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.0.translateToMemberSyncField").value('''memberToId2''').store() config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.0.valueType").value('''string''').store() @@ -295,7 +295,7 @@ config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.1.na config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.1.searchAttribute").value('''true''').store() config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.1.select").value('''true''').store() config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.1.translateExpressionType").value('''grouperProvisioningEntityField''').store() -config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.1.translateFromGrouperProvisioningEntityField").value('''subjectId''').store() +config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.1.translateFromGrouperProvisioningEntityField").value('''attribute__subjectIdentifier0''').store() config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.1.valueType").value('''string''').store() config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.2.isFieldElseAttribute").value('''false''').store() config.propertyName("provisioner.eduPersonAffiliation.targetEntityAttribute.2.membershipAttribute").value('''true''').store() @@ -337,7 +337,7 @@ config.propertyName("provisioner.eduPersonEntitlement.subjectSourcesToProvision" config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.0.fieldName").value('''name''').store() config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.0.isFieldElseAttribute").value('''true''').store() config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.0.select").value('''true''').store() -config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.0.translateExpression").value('''${'uid=' + grouperProvisioningEntity.subjectId + ',ou=people,dc=internet2,dc=edu'}''').store() +config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.0.translateExpression").value('''${'uid=' + grouperProvisioningEntity.retrieveAttributeValueString('subjectIdentifier0') + ',ou=people,dc=internet2,dc=edu'}''').store() config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.0.translateExpressionType").value('''translationScript''').store() config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.0.valueType").value('''string''').store() config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.1.isFieldElseAttribute").value('''false''').store() @@ -346,7 +346,7 @@ config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.1.na config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.1.searchAttribute").value('''true''').store() config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.1.select").value('''true''').store() config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.1.translateExpressionType").value('''grouperProvisioningEntityField''').store() -config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.1.translateFromGrouperProvisioningEntityField").value('''subjectId''').store() +config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.1.translateFromGrouperProvisioningEntityField").value('''attribute__subjectIdentifier0''').store() config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.1.valueType").value('''string''').store() config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.2.isFieldElseAttribute").value('''false''').store() config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.2.membershipAttribute").value('''true''').store() @@ -356,7 +356,7 @@ config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.2.tr config.propertyName("provisioner.eduPersonEntitlement.targetEntityAttribute.2.valueType").value('''string''').store() config.propertyName("provisioner.eduPersonEntitlement.targetGroupAttribute.0.isFieldElseAttribute").value('''false''').store() config.propertyName("provisioner.eduPersonEntitlement.targetGroupAttribute.0.name").value('''entitlement''').store() -config.propertyName("provisioner.eduPersonEntitlement.targetGroupAttribute.0.translateExpression").value('''${grouperUtil.defaultIfBlank(grouperProvisioningGroup.retrieveAttributeValueString('md_entitlementValue') , grouperProvisioningGroup.extension )}''').store() +config.propertyName("provisioner.eduPersonEntitlement.targetGroupAttribute.0.translateExpression").value('''${grouperUtil.defaultIfBlank(grouperProvisioningGroup.retrieveAttributeValueString('md_entitlementValue') , grouperProvisioningGroup.name )}''').store() config.propertyName("provisioner.eduPersonEntitlement.targetGroupAttribute.0.translateExpressionType").value('''translationScript''').store() config.propertyName("provisioner.eduPersonEntitlement.targetGroupAttribute.0.translateGrouperToGroupSyncField").value('''groupFromId2''').store() config.propertyName("provisioner.eduPersonEntitlement.targetGroupAttribute.0.valueType").value('''string''').store() @@ -364,6 +364,8 @@ config.propertyName("provisioner.eduPersonEntitlement.userSearchAllFilter").valu config.propertyName("provisioner.eduPersonEntitlement.userSearchBaseDn").value('''ou=people,dc=internet2,dc=edu''').store() textConfig.propertyName("md_entitlementValue_eduPersonEntitlement_label").value('''Entitlement String''').store() +textConfig.propertyName("md_entitlementValue_eduPersonEntitlement_description").value( + '''Static string value to use as the entitlement. Will use the group name if not set''').store() /* for this exercise, they will create a full sync provisioner in the UI */ @@ -508,8 +510,3 @@ def group = new GroupSave(gs).assignName("ref:role:all_facstaff").assignDisplayE /***** Schedule jobs is an upgrade task for 2.5.55 ****/ GrouperLoader.scheduleJobs() - -/* TODO - * - Groups not picking up object types from parent folder, even after running object type daemon - * - Check the groupOfNames provisioner for grouper authoritative -- it is deleting vpn_users - */ diff --git a/ex201/ex201.end/container_files/seed-data/bootstrap.gsh b/ex201/ex201.end/container_files/seed-data/bootstrap.gsh index 8592c70..1b71cc6 100644 --- a/ex201/ex201.end/container_files/seed-data/bootstrap.gsh +++ b/ex201/ex201.end/container_files/seed-data/bootstrap.gsh @@ -6,6 +6,9 @@ import edu.internet2.middleware.grouper.app.grouperTypes.* import edu.internet2.middleware.grouper.app.provisioning.GrouperProvisioningAttributeNames import edu.internet2.middleware.grouper.app.provisioning.GrouperProvisioningSettings import edu.internet2.middleware.grouper.cfg.dbConfig.GrouperDbConfig +import edu.internet2.middleware.grouper.app.attestation.*; +import java.text.SimpleDateFormat; + /***** START Defaults that may need to be changed for each class *****/ @@ -17,8 +20,7 @@ java.util.Date RECENT_GRAD_END_DATE = cal.time /***** END Defaults that may need to be changed for each class *****/ - -GrouperSession gs = GrouperSession.startRootSession() +GrouperSession gs = GrouperSession.start(SubjectFinder.findByIdentifierAndSource("banderson", "eduLDAP", true)) /* Creating a class for methods helps with gsh from the command line, which can't do functions called from other functions */ class HelperMethods { @@ -44,10 +46,14 @@ class HelperMethods { save() } + static int countPersonSubjects(Group g) { + return g.members.findAll {it.subjectType.name == "person"}.size() + } + static void addSubjectWithCount(Group g, Subject s) { - int countBefore = g.members.findAll {it.subjectType.name == "person"}.size() + int countBefore = countPersonSubjects(g) g.addMember(s, false) - int countAfter = g.members.findAll {it.subjectType.name == "person"}.size() + int countAfter = countPersonSubjects(g) println "\tAdd ${s.name} to ${g.name}: ${countBefore} -> ${countAfter} (${countAfter - countBefore})" } @@ -109,24 +115,44 @@ class HelperMethods { } } - static void provisionObject(AttributeAssignable object, String provisioningTargetId) { - AttributeDefName provisioningMarkerAttributeDefName = GrouperProvisioningAttributeNames.retrieveAttributeDefNameBase() - AttributeDefName provisioningDirectAttributeDefName = GrouperProvisioningAttributeNames.retrieveAttributeDefNameDirectAssignment() - AttributeDefName provisioningTargetAttributeDefName = GrouperProvisioningAttributeNames.retrieveAttributeDefNameTarget() - AttributeDefName provisioningStemScopeAttributeDefName = GrouperProvisioningAttributeNames.retrieveAttributeDefNameStemScope() - AttributeDefName provisioningDoProvisionAttributeDefName = GrouperProvisioningAttributeNames.retrieveAttributeDefNameDoProvision() - // GRP-3592 no method for provisioningMetadataJson - AttributeDefName provisioningMdJsonAttributeDefName = AttributeDefNameFinder.findByName( - GrouperProvisioningSettings.provisioningConfigStemName() + ":" + GrouperProvisioningAttributeNames.PROVISIONING_METADATA_JSON, true) + static void provisionObject(AttributeAssignable object, String provisioningTargetId, String metadataJson=null) { + + AttributeAssign attributeAssign = object.attributeDelegate.assignAttribute(GrouperProvisioningAttributeNames.retrieveAttributeDefNameBase()).getAttributeAssign() + attributeAssign.attributeValueDelegate.with { + assignValue(GrouperProvisioningAttributeNames.retrieveAttributeDefNameDirectAssignment().getName(), "true") + assignValue(GrouperProvisioningAttributeNames.retrieveAttributeDefNameDoProvision().getName(), provisioningTargetId) + assignValue(GrouperProvisioningAttributeNames.retrieveAttributeDefNameTarget().getName(), provisioningTargetId) + + if (object instanceof Stem) { + assignValue(GrouperProvisioningAttributeNames.retrieveAttributeDefNameStemScope().getName(), "sub") + } + + if (metadataJson != null) { + // GRP-3592 no method for provisioningMetadataJson + assignValue(AttributeDefNameFinder.findByName( + GrouperProvisioningSettings.provisioningConfigStemName() + ":" + GrouperProvisioningAttributeNames.PROVISIONING_METADATA_JSON, true). + getName(), metadataJson) + } + } + } - AttributeAssign aa = object.getAttributeDelegate().addAttribute(provisioningMarkerAttributeDefName).getAttributeAssign() - aa.getAttributeValueDelegate().assignValue(provisioningDirectAttributeDefName.getName(), "true") - aa.getAttributeValueDelegate().assignValue(provisioningTargetAttributeDefName.getName(), provisioningTargetId) - aa.getAttributeValueDelegate().assignValue(provisioningDoProvisionAttributeDefName.getName(), "false") - aa.getAttributeValueDelegate().assignValue(provisioningStemScopeAttributeDefName.getName(), "sub") - aa.getAttributeValueDelegate().assignValue(provisioningMdJsonAttributeDefName.getName(), '''{"md_grouper_allowPolicyGroupOverride":true}''') + static void addAttestation(g, isSendMail, daysUntilRecertify) { + AttributeAssign attributeAssign = g.attributeDelegate.assignAttribute(GrouperAttestationJob.retrieveAttributeDefNameValueDef()).getAttributeAssign() + // Set date certified to today, so that it won't force attestation until the next time due + def date = new SimpleDateFormat("yyyy/MM/dd").format(new Date()) + attributeAssign.attributeValueDelegate.with { + assignValue(GrouperAttestationJob.retrieveAttributeDefNameDirectAssignment().getName(), "true") + assignValue(GrouperAttestationJob.retrieveAttributeDefNameSendEmail().getName(), isSendMail) + assignValue(GrouperAttestationJob.retrieveAttributeDefNameHasAttestation().getName(), "true") + assignValue(GrouperAttestationJob.retrieveAttributeDefNameEmailAddresses().getName(), null) + assignValue(GrouperAttestationJob.retrieveAttributeDefNameDaysUntilRecertify().getName(), daysUntilRecertify) + assignValue(GrouperAttestationJob.retrieveAttributeDefNameDateCertified().getName(), date) + } + } + static void attestGroup(Group g) { + //TODO } } @@ -251,10 +277,10 @@ Stem policyStem = StemFinder.findByName(gs, "app:eduPersonAffiliation:service:po HelperMethods.assignObjectTypeForStem(policyStem, "policy") [ - "ePA_student": ["ref:student:students"], - "ePA_staff": ["ref:role:emp:staff"], - "ePA_faculty": ["ref:role:emp:faculty"], - "ePA_member": ["${policyStem.name}:ePA_student", "${policyStem.name}:ePA_staff", "${policyStem.name}:ePA_faculty"] + "student": ["ref:student:students"], + "staff": ["ref:role:emp:staff"], + "faculty": ["ref:role:emp:faculty"], + "member": ["${policyStem.name}:student", "${policyStem.name}:staff", "${policyStem.name}:faculty"] ].each { policyName, memberNames -> Group group = new GroupSave(gs).assignName("${policyStem.name}:${policyName}").save() memberNames.each { memberName -> @@ -263,9 +289,8 @@ HelperMethods.assignObjectTypeForStem(policyStem, "policy") } } -/* Provisioning - the edupersonAffiliation provisioner should already be set up in 101.1.1 */ -HelperMethods.provisionObject(policyStem, "eduPersonAffiliation") - +/* Provisioning - the eduPersonAffiliation provisioner should already be set up in 101.1.1 */ +HelperMethods.provisionObject(policyStem, "eduPersonAffiliation", '''{"md_grouper_allowPolicyGroupOverride":true}''') /***** 201.4 eduPersonEntitlement *****/ @@ -314,10 +339,84 @@ config.propertyName("otherJob.eduPersonEntitlement_full_sync.provisionerConfigId config.propertyName("otherJob.eduPersonEntitlement_full_sync.quartzCron").value('''0 0 4 * * ?''').store() +/* Provisioning - the eduPersonEntitlement provisioner should already be set up in 101.1.1 */ +Group group = GroupFinder.findByName(gs, "app:wiki:service:policy:wiki_user", true) + +HelperMethods.provisionObject(group, "eduPersonEntitlement", '''{"md_entitlementValue":"http://sp.example.org/wiki"}''') + + +/***** 201.5: Policy groups and dynamic application permissions (Cognos) *****/ + +HelperMethods.newApplicationTemplate(StemFinder.findByName(gs, "app", true), + "cognos", + "cognos", + "Manage poicy roles for Cognos application", + null) + +Stem policyStem = StemFinder.findByName(gs, "app:cognos:service:policy", true) +ArrayList myServiceActionIds = [ + 'policyGroupCreate', + 'policyGroupType', + 'policyGroupAllowGroupCreate', + 'allowIntermediatgeGroupType', + //'policyGroupAllowManualGroupCreate', + //'policyGroupAddManualToAllow', + //'allowManualGroupType', + 'policyGroupDenyGroupCreate', + 'denyIntermediatgeGroupType', + 'policyGroupLockoutGroup_0', + //'policyGroupDenyManualGroupCreate', + //'policyGroupAddManualToDeny', + //'denyManualGroupType', + //'policyGroupRequireGroup_0' +] + +HelperMethods.newPolicyTemplate(policyStem, + "cg_fin_report_reader", + "cg_fin_report_reader", + "Report Reader Access Policy", + myServiceActionIds +) + +HelperMethods.newPolicyTemplate(policyStem, + "cg_fin_report_writer", + "cg_fin_report_writer", + "Report Writer Access Policy", + myServiceActionIds +) + + +Group financeStaff = GroupFinder.findByName(gs, "basis:hr:employee:dept:10810:staff", true) +Group cg_fin_report_reader_allow = GroupFinder.findByName(gs, "app:cognos:service:policy:cg_fin_report_reader_allow", true) +"app:cognos:service:policy:cg_fin_report_reader_allow" + +HelperMethods.addSubjectWithCount(cg_fin_report_reader_allow, financeStaff.toSubject()) + + +Group financeWritersRef = new GroupSave(gs).assignName("app:cognos:service:ref:finance_report_writer"). + assignCreateParentStemsIfNotExist(true). + save() + +HelperMethods.assignObjectTypeForGroup(financeWritersRef, "ref", "Finance Manager", $/Employees authorized by the Finance Manager have access to write reports/$) + + +Group financeMgrRole = new GroupSave(gs).assignName("ref:role:financeManager"). + assignDisplayExtension("Finance Manager"). + save() +HelperMethods.assignObjectTypeForGroup(financeMgrRole, "ref") + +Subject driddle = SubjectFinder.findByIdentifierAndSource("driddle", "eduLDAP", true) +financeMgrRole.addMember(driddle, false) + +financeWritersRef.grantPriv(financeMgrRole.toSubject(), AccessPrivilege.READ, false) +financeWritersRef.grantPriv(financeMgrRole.toSubject(), AccessPrivilege.UPDATE, false) +HelperMethods.addAttestation(financeWritersRef, "true", "30") -/* Provisioning - the edupersonAffiliation provisioner should already be set up in 101.1.1 */ -HelperMethods.provisionObject(policyStem, "eduPersonAffiliation") +GrouperSession gs2 = GrouperSession.start(SubjectFinder.findByIdentifierAndSource("driddle", "eduLDAP", true)) -/* TODO ePA and ePT full sync provisioners are not working */ +Subject ccampbe2 = SubjectFinder.findByIdentifierAndSource("ccampbe2", "eduLDAP", true) +financeWritersRef.addMember(ccampbe2, false) +// Mark reviewed +//TODO HelperMethods.attestGroup(financeWritersRef) diff --git a/ex401/ex401.end/Dockerfile b/ex401/ex401.end/Dockerfile new file mode 100644 index 0000000..6ade754 --- /dev/null +++ b/ex401/ex401.end/Dockerfile @@ -0,0 +1,33 @@ +ARG VERSION_TAG +FROM tier/gte:201.end-$VERSION_TAG + +LABEL author="tier-packaging@internet2.edu " \ + Vendor="TIER" \ + ImageType="Grouper Training" \ + ImageName=$imagename \ + ImageOS=centos7 + +ENV USERTOKEN=gte-401.1.end + +COPY container_files/seed-data/ /seed-data/ + +# won't work if no files in here, since the folder won't be in git. Uncomment only if there are any property files to override +#COPY container_files/conf/ /opt/grouper/grouperWebapp/WEB-INF/classes/ + +# && setupFiles +RUN . /usr/local/bin/library.sh \ + && prep_conf && prep_finish; \ + (/usr/sbin/slapd -h "ldap:/// ldaps:/// ldapi:///" -u ldap &) \ + && while ! curl -s ldap://localhost:389 > /dev/null; do echo waiting for ldap to start; sleep 1; done; \ + (mysqld_safe & ) \ + && while ! curl -s localhost:3306 > /dev/null; do echo waiting for mysqld to start; sleep 3; done; \ + cd /opt/grouper/grouperWebapp/WEB-INF \ + && ldapadd -x -D cn=root,dc=internet2,dc=edu -w password -f /seed-data/users.ldif \ + && mysql grouper < /seed-data/sisData.sql \ + && cp -r /opt/grouper/grouperWebapp/WEB-INF/libUiAndDaemon/* /opt/grouper/grouperWebapp/WEB-INF/lib/ \ + && if [ ! -f /usr/local/bin/java ]; then ln -s /usr/lib/jvm/java-1.8.0-amazon-corretto/bin/java /usr/local/bin/java; fi \ + && sudo --preserve-env=PATH -u tomcat bin/gsh.sh /seed-data/bootstrap.gsh \ + && pkill -HUP slapd \ + && while curl -s ldap://localhost:389 > /dev/null; do echo waiting for ldap to stop; sleep 1; done; \ + pkill -u mysql mysqld \ + && while curl -s localhost:3306 > /dev/null; do echo waiting for mysqld to stop; sleep 1; done diff --git a/ex401/ex401.end/container_files/seed-data/bootstrap.gsh b/ex401/ex401.end/container_files/seed-data/bootstrap.gsh new file mode 100644 index 0000000..3dcb12d --- /dev/null +++ b/ex401/ex401.end/container_files/seed-data/bootstrap.gsh @@ -0,0 +1,500 @@ +import edu.internet2.middleware.grouper.grouperUi.beans.ui.GrouperNewServiceTemplateLogic +import edu.internet2.middleware.grouper.grouperUi.beans.ui.GrouperTemplatePolicyGroupLogic +import edu.internet2.middleware.grouper.grouperUi.beans.ui.ServiceAction +import edu.internet2.middleware.grouper.grouperUi.beans.ui.StemTemplateContainer +import edu.internet2.middleware.grouper.app.grouperTypes.* +import edu.internet2.middleware.grouper.app.provisioning.GrouperProvisioningAttributeNames +import edu.internet2.middleware.grouper.app.provisioning.GrouperProvisioningSettings +import edu.internet2.middleware.grouper.app.attestation.*; +import java.text.SimpleDateFormat; + +GrouperSession gs = GrouperSession.start(SubjectFinder.findByIdentifierAndSource("banderson", "eduLDAP", true)) + +/* Creating a class for methods helps with gsh from the command line, which can't do functions called from other functions */ +class HelperMethods { + static void assignObjectTypeForGroup(Group g, String type, String owner=null, String description=null) { + new GdgTypeGroupSave(). + assignGroup(g). + assignType(type). + assignDataOwner(owner). + assignMemberDescription(description). + assignSaveMode(SaveMode.INSERT_OR_UPDATE). + assignReplaceAllSettings(true). + save() + } + + static void assignObjectTypeForStem(Stem s, String type, String owner=null, String description=null) { + new GdgTypeStemSave(). + assignStem(s). + assignType(type). + assignDataOwner(owner). + assignMemberDescription(description). + assignSaveMode(SaveMode.INSERT_OR_UPDATE). + assignReplaceAllSettings(true). + save() + } + + static int countPersonSubjects(Group g) { + return g.members.findAll {it.subjectType.name == "person"}.size() + } + + static void addSubjectWithCount(Group g, Subject s) { + int countBefore = countPersonSubjects(g) + g.addMember(s, false) + int countAfter = countPersonSubjects(g) + println "\tAdd ${s.name} to ${g.name}: ${countBefore} -> ${countAfter} (${countAfter - countBefore})" + } + + static void newApplicationTemplate(Stem parentStem, String templateKey, String templateFriendlyName, String templateDescription, List myServiceActionIds = []) { + def stemTemplateContainer = new StemTemplateContainer() + stemTemplateContainer.templateKey = templateKey + stemTemplateContainer.templateFriendlyName = templateFriendlyName + stemTemplateContainer.templateDescription = templateDescription + + GrouperNewServiceTemplateLogic templateLogic = new GrouperNewServiceTemplateLogic() + templateLogic.stemId = parentStem.uuid + templateLogic.stemTemplateContainer = stemTemplateContainer + + List selectedServiceActions = [] + if (myServiceActionIds == null || myServiceActionIds.isEmpty()) { + selectedServiceActions = templateLogic.getServiceActions() + } else { + Map allPolicyServiceActionMap = templateLogic.getServiceActions().collectEntries { [it.id, it] } + selectedServiceActions = myServiceActionIds.collect { allPolicyServiceActionMap[it] } + } + templateLogic.validate(selectedServiceActions) + + selectedServiceActions.each {serviceAction -> + serviceAction.getServiceActionType().createTemplateItem(serviceAction) + } + String errorKey = templateLogic.postCreateSelectedActions(selectedServiceActions) + if (errorKey != null) { + println "Creating policy group returned error: ${errorKey}" + } + } + + static void newPolicyTemplate(Stem parentStem, String templateKey, String templateFriendlyName, String templateDescription, List myServiceActionIds = []) { + // note that this doesn't work < 2.5.56 due to dependence on the UI + def policyStemTemplateContainer = new StemTemplateContainer() + policyStemTemplateContainer.templateKey = templateKey + policyStemTemplateContainer.templateFriendlyName = templateFriendlyName + policyStemTemplateContainer.templateDescription = templateDescription + + GrouperTemplatePolicyGroupLogic policyTemplateLogic = new GrouperTemplatePolicyGroupLogic() + policyTemplateLogic.stemId = parentStem.uuid + policyTemplateLogic.stemTemplateContainer = policyStemTemplateContainer + + // simulate checking certain boxes in the ui + List selectedServiceActions = [] + if (myServiceActionIds == null || myServiceActionIds.isEmpty()) { + selectedServiceActions = policyTemplateLogic.getServiceActions() + } else { + Map allPolicyServiceActionMap = policyTemplateLogic.getServiceActions().collectEntries { [it.id, it] } + selectedServiceActions = myServiceActionIds.collect { allPolicyServiceActionMap[it] } + } + + policyTemplateLogic.validate(selectedServiceActions) + selectedServiceActions.each { serviceAction -> + serviceAction.getServiceActionType().createTemplateItem(serviceAction) + } + String policyErrorKey = policyTemplateLogic.postCreateSelectedActions(selectedServiceActions) + if (policyErrorKey != null) { + println "Creating policy group returned error: ${policyErrorKey}" + } + } + + static void provisionObject(AttributeAssignable object, String provisioningTargetId, String metadataJson=null) { + + AttributeAssign attributeAssign = object.attributeDelegate.assignAttribute(GrouperProvisioningAttributeNames.retrieveAttributeDefNameBase()).getAttributeAssign() + attributeAssign.attributeValueDelegate.with { + assignValue(GrouperProvisioningAttributeNames.retrieveAttributeDefNameDirectAssignment().getName(), "true") + assignValue(GrouperProvisioningAttributeNames.retrieveAttributeDefNameDoProvision().getName(), provisioningTargetId) + assignValue(GrouperProvisioningAttributeNames.retrieveAttributeDefNameTarget().getName(), provisioningTargetId) + + if (object instanceof Stem) { + assignValue(GrouperProvisioningAttributeNames.retrieveAttributeDefNameStemScope().getName(), "sub") + } + + if (metadataJson != null) { + // GRP-3592 no method for provisioningMetadataJson + assignValue(AttributeDefNameFinder.findByName( + GrouperProvisioningSettings.provisioningConfigStemName() + ":" + GrouperProvisioningAttributeNames.PROVISIONING_METADATA_JSON, true). + getName(), metadataJson) + } + } + + } + + static void addAttestation(g, isSendMail, daysUntilRecertify) { + AttributeAssign attributeAssign = g.attributeDelegate.assignAttribute(GrouperAttestationJob.retrieveAttributeDefNameValueDef()).getAttributeAssign() + // Set date certified to today, so that it won't force attestation until the next time due + def date = new SimpleDateFormat("yyyy/MM/dd").format(new Date()) + attributeAssign.attributeValueDelegate.with { + assignValue(GrouperAttestationJob.retrieveAttributeDefNameDirectAssignment().getName(), "true") + assignValue(GrouperAttestationJob.retrieveAttributeDefNameSendEmail().getName(), isSendMail) + assignValue(GrouperAttestationJob.retrieveAttributeDefNameHasAttestation().getName(), "true") + assignValue(GrouperAttestationJob.retrieveAttributeDefNameEmailAddresses().getName(), null) + assignValue(GrouperAttestationJob.retrieveAttributeDefNameDaysUntilRecertify().getName(), daysUntilRecertify) + assignValue(GrouperAttestationJob.retrieveAttributeDefNameDateCertified().getName(), date) + } + } + + static void attestGroup(Group g) { + //TODO + } +} + +def oldStem = StemFinder.findByName(gs, "201_end", false) +if (oldStem != null) { + oldStem.delete() +} + +new StemSave(gs).assignName("401_end"). + assignDisplayExtension("401.end"). + assignCreateParentStemsIfNotExist(true). + save() + + +/***** 401.1: VPN Access Control (I) *****/ + +Group vpnLegacyGroup = new GroupSave(gs).assignName("test:vpn:vpn_legacy"). + assignCreateParentStemsIfNotExist(true). + save() + +AttributeAssign attributeAssign = vpnLegacyGroup.attributeDelegate.assignAttribute(LoaderLdapUtils.grouperLoaderLdapAttributeDefName()).getAttributeAssign() + +attributeAssign.attributeValueDelegate.with { + assignValue(LoaderLdapUtils.grouperLoaderLdapTypeName(), "LDAP_SIMPLE") + assignValue(LoaderLdapUtils.grouperLoaderLdapServerIdName(), "demo") + assignValue(LoaderLdapUtils.grouperLoaderLdapFilterName(), "(cn=vpn_users)") + assignValue(LoaderLdapUtils.grouperLoaderLdapSubjectAttributeName(), "member") + assignValue(LoaderLdapUtils.grouperLoaderLdapSearchDnName(), "ou=groups,dc=internet2,dc=edu") + assignValue(LoaderLdapUtils.grouperLoaderLdapQuartzCronName(), "0 * * * * ?") + assignValue(LoaderLdapUtils.grouperLoaderLdapSourceIdName(), "eduLDAP") + assignValue(LoaderLdapUtils.grouperLoaderLdapSubjectIdTypeName(), "subjectIdentifier") + assignValue(LoaderLdapUtils.grouperLoaderLdapSearchScopeName(), "SUBTREE_SCOPE") + assignValue(LoaderLdapUtils.grouperLoaderLdapSubjectExpressionName(), "\${loaderLdapElUtils.convertDnToSpecificValue(subjectId)}") +} + +GrouperLoaderType.validateAndScheduleLdapLoad(attributeAssign, null, false) +GrouperLoader.runJobOnceForGroup(gs, vpnLegacyGroup) + + +// Create vpn_facstaff +Group allFacStaff = GroupFinder.findByName("ref:role:all_facstaff", true) +Group vpnFacStaff = new GroupSave(gs).assignName("test:vpn:vpn_facstaff").save() +vpnFacStaff.assignCompositeMember(CompositeType.INTERSECTION, allFacStaff, vpnLegacyGroup) + +println "${allFacStaff.extension}: Person subjects = ${HelperMethods.countPersonSubjects(allFacStaff)}" +println "${vpnLegacyGroup.extension}: Person subjects = ${HelperMethods.countPersonSubjects(vpnLegacyGroup)}" +println "${vpnFacStaff.extension}: Person subjects = ${HelperMethods.countPersonSubjects(vpnFacStaff)}" + +// Create vpn_legacy_exceptions +Group vpnLegacyExceptions = new GroupSave(gs).assignName("test:vpn:vpn_legacy_exceptions").save() +vpnLegacyExceptions.assignCompositeMember(CompositeType.COMPLEMENT, vpnLegacyGroup, allFacStaff) + +println "${vpnLegacyExceptions.extension}: Person subjects = ${HelperMethods.countPersonSubjects(vpnLegacyExceptions)}" + +// Create app template + +HelperMethods.newApplicationTemplate(StemFinder.findByName(gs, "app", true), + "vpn", + "vpn", + "VPN access policies", + null) + + +/* New policy Template */ + +Stem policyStem = StemFinder.findByName(gs, "app:vpn:service:policy", true) +ArrayList myServiceActionIds = [ + 'policyGroupCreate', + 'policyGroupType', + 'policyGroupAllowGroupCreate', + 'allowIntermediatgeGroupType', + 'policyGroupAllowManualGroupCreate', + 'policyGroupAddManualToAllow', + 'allowManualGroupType', + 'policyGroupDenyGroupCreate', + 'denyIntermediatgeGroupType', + 'policyGroupLockoutGroup_0', + //'policyGroupDenyManualGroupCreate', + //'policyGroupAddManualToDeny', + //'denyManualGroupType', +] + +HelperMethods.newPolicyTemplate(policyStem, + "vpn_authorized", + "vpn_authorized", + "Access policy for the campus VPN", + myServiceActionIds +) + +/* Add members to vpn_authorized_allow */ +Group vpnAccessAllow = GroupFinder.findByName(gs, "app:vpn:service:policy:vpn_authorized_allow", true) +HelperMethods.addSubjectWithCount(vpnAccessAllow, allFacStaff.toSubject()) + + +/***** 401.2: VPN Access Control (II) *****/ + +HelperMethods.newApplicationTemplate(StemFinder.findByName(gs, "app", true), + "eduPersonAffiliation", + "eduPersonAffiliation", + "eduPersonAffiliation (defined in eduPerson 1.0); OID: 1.3.6.1.4.1.5923.1.1.1.1 Specifies the person's relationship(s) to the institution in broad categories such as student, faculty, staff, alum, etc.", + null) + +Group policyGroup = GroupFinder.findByName(gs, "app:vpn:service:policy:vpn_authorized", true) +HelperMethods.assignObjectTypeForGroup(policyGroup, "policy") + +/* Provisioning - the groupOfNames provisioner should already be set up */ +HelperMethods.provisionObject(policyGroup, "groupOfNames") + +GrouperLoader.runOnceByJobName(gs, "OTHER_JOB_groupOfNames_full_sync") + + +// Create ref group vpn_consultants + +Group vpnConsultantsRef = new GroupSave(gs).assignName("app:vpn:service:ref:vpn_consultants").save() +Group wri250Ref = new GroupSave(gs).assignName("app:vpn:service:ref:vpn_wri250").save() +Group manualGroup = GroupFinder.findByName(gs, "app:vpn:service:policy:vpn_authorized_allow_manual", true) + +[vpnConsultantsRef, wri250Ref].each { + manualGroup.addMember(it.toSubject()) +} + +// Create security group and grant privileges + +Group wri250Sec = new GroupSave(gs).assignName("app:vpn:security:vpn_wri250_mgr").save() +Group wri250Instructors = GroupFinder.findByName(gs, "basis:sis:course:wri:wri250:instructor", true) +wri250Sec.addMember(wri250Instructors.toSubject()) +wri250Ref.grantPriv(wri250Sec.toSubject(), AccessPrivilege.READ) +wri250Ref.grantPriv(wri250Sec.toSubject(), AccessPrivilege.UPDATE) + +// Add member as kjenkins + +GrouperSession gs2 = GrouperSession.start(SubjectFinder.findByIdentifierAndSource("kjenkins", "eduLDAP", true)) + +wri250Ref.addMember(SubjectFinder.findByIdentifierAndSource("mwest", "eduLDAP", true), false) + +// switch back to banderson +GrouperSession.start(gs.subject) + +HelperMethods.addAttestation(wri250Ref, "true", "30") + + +// Set a rule on the consultants group vpnConsultantsRef +AttributeAssign attribAssign = vpnConsultantsRef.attributeDelegate.addAttribute(RuleUtils.ruleAttributeDefName()).attributeAssign + +Subject actAs = SubjectFinder.findRootSubject() +int numberOfDays = 180 +attribAssign.attributeValueDelegate.with { + assignValue(RuleUtils.ruleActAsSubjectSourceIdName(), actAs.sourceId); + assignValue(RuleUtils.ruleActAsSubjectIdName(), actAs.id) + assignValue(RuleUtils.ruleCheckTypeName(), RuleCheckType.membershipAdd.name()) + assignValue(RuleUtils.ruleThenEnumName(), RuleThenEnum.assignMembershipDisabledDaysForOwnerGroupId.name()) + assignValue(RuleUtils.ruleThenEnumArg0Name(), numberOfDays.toString()) + assignValue(RuleUtils.ruleThenEnumArg1Name(), "T") +} + +vpnConsultantsRef.addMember(SubjectFinder.findByIdentifierAndSource("rjohnso5", "eduLDAP", true), false) + + +//VPN access audit for a list of NetIDs + +Group vpnAuditList = new GroupSave(gs).assignName("test:vpn:vpn_audit_list").save() + +[ + "groberts", + "shenders", + "mwest", + "mpeterso", + "kclark", +].each { + vpnAuditList.addMember(SubjectFinder.findByIdentifierAndSource(it, "eduLDAP", true), false) +} + +Group vpnAudit = new GroupSave(gs).assignName("test:vpn:vpn_audit").save() + +vpnAudit.addCompositeMember(CompositeType.INTERSECTION, + GroupFinder.findByName(gs, "app:vpn:service:policy:vpn_authorized", true), + vpnAuditList +) + + +/***** 401.3: MFA Policy Governance part 1 *****/ + +// Create app template + +HelperMethods.newApplicationTemplate(StemFinder.findByName(gs, "app", true), + "mfa", + "mfa", + "Multi-factor authentication (MFA) policies", + null) + + +/* New policy Template */ + +Stem policyStem = StemFinder.findByName(gs, "app:mfa:service:policy", true) +ArrayList myServiceActionIds = [ + 'policyGroupCreate', + 'policyGroupType', + 'policyGroupAllowGroupCreate', + 'allowIntermediatgeGroupType', + //'policyGroupAllowManualGroupCreate', + //'policyGroupAddManualToAllow', + //'allowManualGroupType', + 'policyGroupDenyGroupCreate', + 'denyIntermediatgeGroupType', + //'policyGroupLockoutGroup_0', + //'policyGroupDenyManualGroupCreate', + //'policyGroupAddManualToDeny', + //'denyManualGroupType', +] + +HelperMethods.newPolicyTemplate(policyStem, + "mfa_enabled", + "mfa_enabled", + "Users with MFA enabled", + myServiceActionIds +) + + +// reference group + +Group mfaPilotRef = new GroupSave(gs).assignName("app:mfa:service:ref:mfa_pilot").save() + +Group mfaEnabledAllow = GroupFinder.findByName(gs, "app:mfa:service:policy:mfa_enabled_allow", true) +mfaEnabledAllow.addMember(mfaPilotRef.toSubject(), false) + +// Provisioning +Group mfaEnabled = GroupFinder.findByName(gs, "app:mfa:service:policy:mfa_enabled", true) +HelperMethods.provisionObject(mfaEnabled, "eduPersonEntitlement", '''{"md_entitlementValue":"http://tier.internet2.edu/mfa/enabled"}''') + + +// Onboard select departments +Group mfaBypass = new GroupSave(gs).assignName("app:mfa:service:ref:mfa_bypass").save() +Group mfaEnabledDeny = GroupFinder.findByName(gs, "app:mfa:service:policy:mfa_enabled_allow", true) +mfaEnabledDeny.addMember(mfaBypass.toSubject(), false) + +["10904", "10902", "10903"].each { + Group g = GroupFinder.findByName(gs, "basis:hr:employee:dept:${it}:staff", true) + mfaEnabledAllow.addMember(g.toSubject(), false) +} + + +Group peerCounselRef = new GroupSave(gs).assignName("app:mfa:service:ref:mfa_peer_counseling").save() +[ + "jhoover", + "csmith", + "jthornto", + "tgarrett", + "cgarcia", + "cpreston", + "rnelson", + "sberry", + "pwilliam", +].each { + Subject s = SubjectFinder.findByIdentifierAndSource(it, "eduLDAP", true) + peerCounselRef.addMember(s, false) +} + +mfaEnabledAllow.addMember(peerCounselRef.toSubject(), false) + +// Add sensitive data group + +Group sensitiveData = new GroupSave(gs).assignName("app:mfa:service:ref:sensitive_data").save() +Group eaStaff = GroupFinder.findByName(gs, "basis:hr:employee:dept:10830:staff", true) +sensitiveData.addMember(eaStaff.toSubject(), true) + +Calendar cal = Calendar.getInstance(); +cal.setTime(new Date()); +cal.add(Calendar.DAY_OF_YEAR, 2); +mfaEnabledAllow.addOrEditMember(sensitiveData.toSubject(), true, true, cal.time, null, false) + +// subtract faculty + +Group sensitiveDataNoFaculty = new GroupSave(gs).assignName("app:mfa:service:ref:sensitive_no_faculty").save() +Group allFaculty = GroupFinder.findByName(gs, "ref:role:emp:faculty", true) +sensitiveDataNoFaculty.addCompositeMember(CompositeType.COMPLEMENT, sensitiveData, allFaculty) +mfaEnabledAllow.addOrEditMember(sensitiveDataNoFaculty.toSubject(), true, true, cal.time, null, false) +mfaEnabledAllow.deleteMember(sensitiveData.toSubject()) + + +/***** 401.4 MFA Policy Governance part 2 *****/ + +Group mfaOptIn = new GroupSave(gs).assignName("app:mfa:service:ref:mfa_opt_in").save() +mfaEnabledAllow.addMember(mfaOptIn.toSubject(), false) + + +Stem policyStem = StemFinder.findByName(gs, "app:mfa:security", true) +ArrayList myServiceActionIds = [ + 'policyGroupCreate', + 'policyGroupType', + 'policyGroupAllowGroupCreate', + 'allowIntermediatgeGroupType', + //'policyGroupAllowManualGroupCreate', + //'policyGroupAddManualToAllow', + //'allowManualGroupType', + 'policyGroupDenyGroupCreate', + 'denyIntermediatgeGroupType', + 'policyGroupLockoutGroup_0', + //'policyGroupDenyManualGroupCreate', + //'policyGroupAddManualToDeny', + //'denyManualGroupType', +] + +HelperMethods.newPolicyTemplate(policyStem, + "mfa_opt_in_access", + "mfa_opt_in_access", + "Users with opt-in privileges", + myServiceActionIds +) + +Group mfaOptInAllowSec = GroupFinder.findByName(gs, "app:mfa:security:mfa_opt_in_access_allow", true) +["ref:role:emp:staff", "ref:role:emp:faculty", "ref:student:students"].each { + Group allX = GroupFinder.findByName(gs, it, true) + mfaOptInAllowSec.addMember(allX.toSubject(), false) +} + +Group mfaOptInSec = GroupFinder.findByName(gs, "app:mfa:security:mfa_opt_in_access", true) +mfaOptIn.grantPriv(mfaOptInSec.toSubject(), AccessPrivilege.OPTIN) +mfaOptIn.grantPriv(mfaOptInSec.toSubject(), AccessPrivilege.OPTOUT) + + +// app:mfa:ref:mfa_required + +Group mfaRequired = new GroupSave(gs).assignName("app:mfa:service:ref:mfa_required").save() +mfaEnabledAllow.addMember(mfaRequired.toSubject(), false) + +[ + sensitiveDataNoFaculty.name, + "basis:hr:employee:dept:10904:staff", + "basis:hr:employee:dept:10902:staff", + "basis:hr:employee:dept:10903:staff", + peerCounselRef.name, + mfaPilotRef.name +].each { + Group g = GroupFinder.findByName(gs, it, true) + mfaRequired.addMember(g.toSubject(), false) + mfaEnabledAllow.deleteMember(g.toSubject()) +} + + +// Users that are required to use MFA can not opt-in/out. + +Group optinAccessDeny = GroupFinder.findByName(gs, "app:mfa:security:mfa_opt_in_access_deny", true) +optinAccessDeny.addMember(mfaRequired.toSubject(), false) + + +// Add all faculty, staff, and students to policy + +List currentMembers = mfaEnabledAllow.immediateMembers.collect {it.subject} + +["ref:role:emp:staff", "ref:role:emp:faculty", "ref:student:students"].each { + Group g = GroupFinder.findByName(gs, it, true) + mfaEnabledAllow.addMember(g.toSubject(), false) +} + +currentMembers.each { + mfaEnabledAllow.deleteMember(it) +} diff --git a/ex401/ex401.end/container_files/seed-data/sisData.sql b/ex401/ex401.end/container_files/seed-data/sisData.sql new file mode 100644 index 0000000..e69de29 diff --git a/ex401/ex401.end/container_files/seed-data/users.ldif b/ex401/ex401.end/container_files/seed-data/users.ldif new file mode 100644 index 0000000..e69de29 diff --git a/ex401/manualBuild.sh b/ex401/manualBuild.sh index 4172204..b809e50 100755 --- a/ex401/manualBuild.sh +++ b/ex401/manualBuild.sh @@ -1,13 +1,16 @@ source ../buildVersion.sh echo "Building gte:401 version ${VERSION_TAG}" -docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.1.1-${VERSION_TAG} ex401.1.1 \ -&& docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.1.end-${VERSION_TAG} ex401.1.end \ -&& docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.3.1-${VERSION_TAG} ex401.3.1 \ -&& docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.3.end-${VERSION_TAG} ex401.3.end \ -# && docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.5.1-${VERSION_TAG} ex401.5.1 \ -# && docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.5.end-${VERSION_TAG} ex401.5.end \ -# && docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.7.1-${VERSION_TAG} ex401.7.1 \ -# && docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.7.end-${VERSION_TAG} ex401.7.end + +docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.end-${VERSION_TAG} ex401.end \ + +#docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.1.1-${VERSION_TAG} ex401.1.1 \ +#&& docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.1.end-${VERSION_TAG} ex401.1.end \ +#&& docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.3.1-${VERSION_TAG} ex401.3.1 \ +#&& docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.3.end-${VERSION_TAG} ex401.3.end \ +## && docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.5.1-${VERSION_TAG} ex401.5.1 \ +## && docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.5.end-${VERSION_TAG} ex401.5.end \ +## && docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.7.1-${VERSION_TAG} ex401.7.1 \ +## && docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.7.end-${VERSION_TAG} ex401.7.end if [[ "$OSTYPE" == "darwin"* ]]; then say exercises for 401 build complete diff --git a/manualBuild.sh b/manualBuild.sh index 1749643..b5950b2 100755 --- a/manualBuild.sh +++ b/manualBuild.sh @@ -7,9 +7,9 @@ pushd ex101 ./manualBuild.sh popd - pushd ex201 - ./manualBuild.sh - popd +pushd ex201 +./manualBuild.sh +popd # pushd ex211 # ./manualBuild.sh @@ -18,11 +18,10 @@ popd # pushd ex301 # ./manualBuild.sh # popd -# -# pushd ex401 -# ./manualBuild.sh -# popd -# + +pushd ex401 +./manualBuild.sh +popd if [[ "$OSTYPE" == "darwin"* ]]; then say full build complete