diff --git a/docs/401/401.3.rst b/docs/401/401.3.rst index 92b2b35..1f173d8 100644 --- a/docs/401/401.3.rst +++ b/docs/401/401.3.rst @@ -316,4 +316,4 @@ The End .. _Grouper Deployment Guide: https://spaces.at.internet2.edu/display/Grouper/Grouper+Deployment+Guide+Work+-TIER+Program .. _Grouper ESB Connector: https://spaces.at.internet2.edu/display/Grouper/Grouper+ESB+Connector -.. _COmanage: https://www.internet2.edu/products-services/trust-identity/comanage/ \ No newline at end of file +.. _COmanage: https://www.internet2.edu/products-services/trust-identity/comanage/ diff --git a/docs/401/401.4-example-solution.rst b/docs/401/401.4-example-solution.rst index 4aba227..42679d4 100644 --- a/docs/401/401.4-example-solution.rst +++ b/docs/401/401.4-example-solution.rst @@ -3,24 +3,24 @@ 401.4 Untangling Legacy Access Policies - Example Solution ========================================================== -The follwing solution uses techniques demonstrated in the other 401 series -labs in order to create an independent policy for the LMS service. +The following solution uses techniques demonstrated in the 201 and 401 labs. +The general solution is to create an independent access policy for the LMS +service based on the legacy community members LDAP group and a new visiting +scholars reference group. -#. Use Grouper Loader to import existing LDAP cohort group into a "community - members" reference group-- `ref:legacy:community_members` -#. Add loader job to populate `communtiy_members` from - `cn=community_members,ou=groups,dc=example,dc=edu`. -#. Run loader job to import members into reference group. -#. Create a Grouper service folder for the LMS with a policy for LMS - authorization: `app:lms:lms_authorize|allow|deny` -#. Add the "institutional people" reference group, `ref:community_members`, - to the allow policy for the LMS, `app:lms:lms_allow`. -#. Create `app:lms:ref:visiting_scholars`. Import the NetIDs for the visiting - scholors into this reference group. -#. Add `visiting_scholars` to `lms_allow`. -#. Provision this policy to a new group in the LDAP DIT that the LMS group can - use to allow access to the service. +#. Create a new application folder `lms` +#. Create a new access policy group `lms_access` +#. Configure PSPNG attributes to `provision_to` `groupOfNames` on `lms_access` +#. Create a new institutional reference `ref:legacy:community_members`. +#. Configure `community_members` with an LDAP loader job. +#. Add `community_members` to `lms_access_allow` +#. Create an application-specific reference group for the visiting scholars + `app:lms:service:ref:visiting_scholars` +#. Import the NetID list into `visiting_scholars` +#. Add `visiting_scholars` to `lms_access_allow` +#. File a ticket with Vicky to switch the LMS LDAP access control group +#. Head to your happy place! :) -Congrats! You are now a certified Grouper Guru associate level 1! -And remember nothing gets'em going like chum! +.. figure:: ../figures/401-lms-solution.png +Congrats! You are now a certified Grouper Guru associate level 1! diff --git a/docs/401/401.4.rst b/docs/401/401.4.rst index 712f57d..7a03f70 100644 --- a/docs/401/401.4.rst +++ b/docs/401/401.4.rst @@ -14,54 +14,121 @@ Lab Components -------------- * Grouper +* OpenLDAP +* `Grouper Deployment Guide`_ + -------- Overview -------- -A baseline of core services services are enabled by default for a broad range of -community cohorts. The current approach uses a hodge-podge of scripts and -manual intervention to establish a group of "institutional people" that are -granted access to a wide range of services. The system can best be described as -fragile, brittle, and difficult, if not impossible, to evolve and maintain. In -other words-- state of the industry. +A baseline of core services services are enabled by default for a broad range +of community cohorts. The current approach uses a hodge-podge of scripts and +manual intervention to establish a group of "community members" that are +granted access to a wide range of services. The system can best be described +as fragile, brittle, and difficult, if not impossible, to evolve and maintain. +In other words-- state-of-the-industry! -Last year your CIO came back from Internet2 Summit and declared that your -institution is going to deploy TIER. You've just managed to get the Grouper -software up and running, when the head of your LMS group, Vicky, bursts into your -office space and tells you that there are 50 visiting scholars showing up on -campus tomorrow, and they all need access to the LMS for a campus-wide lecture -series. +Last year your CIO came back from Internet2 Summit, and declared that your +institution was going to deploy the InCommon Trusted Access Platform. You have +just managed to get Grouper up and running, when the head of your Learning +Management System group, Vicky, bursts into your office and tells you that +there are 50 visiting scholars showing up on campus tomorrow, and they all need +access to the LMS for a campus-wide lecture series. Your co-worker had mentioned this to you before she left for her month long -vacation. She had told you she had taken care of creating the guest accounts, -and not to worry. You just need to grant access to the LMS when the time comes. -No problem. - -But suddenly, you realize that access is controlled via the "institutional -people" group in your Enterprise Directory Information Tree! If you add the -scholars to that group, they'll have access to everything on campus! +vacation. She had told you she had taken care of creating the sponsored +accounts in `COmanage`_, and not to worry. You just need to grant access to the +LMS when the time comes. No problem. -Before panic sets in, you remember your Grouper training. You'll need a little -help from Vicky, but with Grouper, you've got this covered. "OK, Vicky," you say -in a calm, steady voice. "Here's what I'm going to need your team to do ..." +But suddenly, you realize that access to the LMS is controlled via the dreaded +"community members" group in your Enterprise LDAP! If you add the scholars +to that group, they'll have access to everything on campus! ----------------- -Exercise 401.4.1 ----------------- +Before panic sets in, you remember your Grouper training. You will need a +little help from Vicky, but with Grouper, you've got this covered. "OK, +Vicky," you say in a calm, steady voice. "Here's what I'm going to need your +team to do ..." -*Untangling Policies from Cohorts* +-------------------------------------------------------- +Exercise 401.4.1 Untangling policies from legacy cohorts +-------------------------------------------------------- The goal of this exercise is to grant access to the LMS for the 50 visiting -scholar guest accounts *without* granting additional access to those accounts. -Since access control does not happen in a vacuum, you'll need some minimal -assistance from the LMS team. Vicky's team can configure the LMS to point to a -new group in the LDAP DIT, but that's all the help you'll get. - -The basic issue is that the legacy access control mechanisms are based on a -cohort of loosely defined "institutional people". All your institution's services -are using this cohort directly to determine who is supposed to have access. - -You'll need to use your new Grouper skills to resolve this issue. - - +scholar sponsored accounts *without* granting any additional unnecessary +access. Since access control does not happen in a vacuum, you'll need some +minimal assistance from the LMS team. Vicky's team can configure the LMS to +point to a new authorization group in LDAP, but that's all the help you'll get. + +The basic issue is that the legacy access control mechanisms are based on a +cohort of loosely defined "institutional people". All your institution's +services are using this cohort directly to determine who is supposed to have +access, so any changes or additions have far reaching impact. + +The dreaded "community members" group that the LMS currenty uses for access +control is in LDAP at "cn=community_members,ou=groups,dc=internet2,dc=edu". You +can log in to https://localhost:8443/phpldapadmin/ to review the group. + +Here are the 50 visiting scholar NetIDs: + +.. code-block:: + + adoe852 + agonazles804 + alopez751 + alopez802 + anielson378 + anielson51 + athompson526 + athompson713 + athompson866 + awalters247 + awhite131 + awhite631 + bdavis150 + bdavis999 + bgasper2 + bgonazles239 + bgrady115 + blee298 + cjohnson933 + clangenberg923 + clee357 + cthompson231 + cthompson287 + cwalters316 + cwalters536 + cwilliams606 + danderson959 + dbrown402 + ddavis762 + ddoe822 + dwhite663 + dwilliams299 + eanderson919 + escott173 + gbutler381 + ggrady118 + ggrady649 + glangenberg234 + gwalters810 + gwhite647 + hpeterson10 + jgrady499 + jlee308 + jnielson505 + jsmith466 + jvales111 + jvales645 + jwalters24 + kdavis686 + kjohnson872 + +You will need to use your new Grouper skills to resolve this issue. Your next +step is up to you! + +If you get stuck or bored, check out the `401.4 example solution`_! + +.. _Grouper Deployment Guide: https://spaces.at.internet2.edu/display/Grouper/Grouper+Deployment+Guide+Work+-TIER+Program +.. _COmanage: https://www.internet2.edu/products-services/trust-identity/comanage/ +.. _401.4 example solution: 401.4-example-solution.html diff --git a/docs/401/index.rst b/docs/401/index.rst index 59cd18e..16cee6d 100644 --- a/docs/401/index.rst +++ b/docs/401/index.rst @@ -17,6 +17,5 @@ experience. 401.3 401.4 401.4-example-solution - appendix .. _InCommon Trusted Access Platform: https://www.incommon.org/tap/ diff --git a/docs/figures/401-lms-solution.png b/docs/figures/401-lms-solution.png new file mode 100644 index 0000000..21f8f38 Binary files /dev/null and b/docs/figures/401-lms-solution.png differ diff --git a/ex401/ex401.4.1/container_files/seed-data/bootstrap.gsh b/ex401/ex401.4.1/container_files/seed-data/bootstrap.gsh index 5d8860c..3bcbbb6 100644 --- a/ex401/ex401.4.1/container_files/seed-data/bootstrap.gsh +++ b/ex401/ex401.4.1/container_files/seed-data/bootstrap.gsh @@ -1,2 +1,3 @@ gs = GrouperSession.startRootSession(); - +delStem("401.3.end") +addRootStem("401.4.1", "401.4.1") diff --git a/ex401/ex401.4.end/container_files/seed-data/bootstrap.gsh b/ex401/ex401.4.end/container_files/seed-data/bootstrap.gsh index 989df48..a16a438 100644 --- a/ex401/ex401.4.end/container_files/seed-data/bootstrap.gsh +++ b/ex401/ex401.4.end/container_files/seed-data/bootstrap.gsh @@ -1,8 +1,11 @@ gs = GrouperSession.startRootSession(); +delStem("401.4.1") +addRootStem("401.4.end", "401.4.end") -group = new GroupSave(gs).assignName("ref:legacy:community_members").assignCreateParentStemsIfNotExist(true).save(); -group.getAttributeDelegate().assignAttribute(LoaderLdapUtils.grouperLoaderLdapAttributeDefName()).getAttributeAssign(); -attributeAssign = group.getAttributeDelegate().retrieveAssignment(null, LoaderLdapUtils.grouperLoaderLdapAttributeDefName(), false, true); +// import "community members" into a legacy reference group +community = new GroupSave(gs).assignName("ref:legacy:community_members").assignCreateParentStemsIfNotExist(true).save(); +community.getAttributeDelegate().assignAttribute(LoaderLdapUtils.grouperLoaderLdapAttributeDefName()).getAttributeAssign(); +attributeAssign = community.getAttributeDelegate().retrieveAssignment(null, LoaderLdapUtils.grouperLoaderLdapAttributeDefName(), false, true); attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapQuartzCronName(), "0 * * * * ?"); attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapTypeName(), "LDAP_SIMPLE"); attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapServerIdName(), "demo"); @@ -11,19 +14,11 @@ attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperL attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapSubjectAttributeName(), "member"); attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapSubjectIdTypeName(), "subjectId"); attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapSubjectExpressionName(), "\${loaderLdapElUtils.convertDnToSpecificValue(subjectId)}"); +loaderRunOneJob(community); - - -# SET THESE parent_stem_path = "app"; app_extension = "lms"; -app_name = ""; - - -if (!app_name?.trim()) -{ - app_name = app_extension; -} +app_name = "lms"; def makeStemInheritable(obj, stemName, groupName, priv="admin") { baseStem = obj.getStems(stemName)[0]; @@ -49,39 +44,40 @@ def makeStemInheritable(obj, stemName, groupName, priv="admin") { } stem = addStem(parent_stem_path, app_extension, app_name); -etc_stem = addStem(stem.name, "etc", "etc"); -admin_group_name = "${app_extension}_admins"; -admin_group = addGroup(etc_stem.name, admin_group_name, admin_group_name); +service = addStem(stem.name, "service", "service"); +policy = addStem(service.name, "policy", "policy"); +ref = addStem(service.name, "ref", "ref"); +security = addStem(stem.name, "security", "security"); +admin_group_name = "${app_extension}Admin"; +admin_group = addGroup(security.name, admin_group_name, admin_group_name); admin_group.grantPriv(admin_group.toMember().getSubject(), AccessPrivilege.ADMIN); -mgr_group_name = "${app_extension}_mgr"; -mgr_group = addGroup(etc_stem.name, mgr_group_name, mgr_group_name); +mgr_group_name = "${app_extension}Updaters"; +mgr_group = addGroup(security.name, mgr_group_name, mgr_group_name); mgr_group.grantPriv(admin_group.toMember().getSubject(), AccessPrivilege.ADMIN); mgr_group.grantPriv(mgr_group.toMember().getSubject(), AccessPrivilege.UPDATE); mgr_group.grantPriv(mgr_group.toMember().getSubject(), AccessPrivilege.READ); -view_group_name = "${app_extension}_viewers"; -view_group = addGroup(etc_stem.name, view_group_name, view_group_name); +view_group_name = "${app_extension}Readers"; +view_group = addGroup(security.name, view_group_name, view_group_name); view_group.grantPriv(view_group.toMember().getSubject(), AccessPrivilege.READ); view_group.grantPriv(admin_group.toMember().getSubject(), AccessPrivilege.ADMIN); view_group.grantPriv(mgr_group.toMember().getSubject(), AccessPrivilege.UPDATE); view_group.grantPriv(mgr_group.toMember().getSubject(), AccessPrivilege.READ); admin_group.grantPriv(view_group.toMember().getSubject(), AccessPrivilege.READ); mgr_group.grantPriv(view_group.toMember().getSubject(), AccessPrivilege.READ); -# Child objects should also grant perms to these groups. +// Child objects should also grant perms to these groups. makeStemInheritable(this, stem.name, admin_group.name, 'admin'); makeStemInheritable(this, stem.name, mgr_group.name, 'update'); makeStemInheritable(this, stem.name, mgr_group.name, 'read'); makeStemInheritable(this, stem.name, view_group.name, 'read'); -admin_group.revokePriv(mgr_group.toMember().getSubject(), AccessPrivilege.UPDATE); +// admin_group.revokePriv(mgr_group.toMember().getSubject(), AccessPrivilege.UPDATE); +group = addGroup(policy.name, "lms_access", "lms_access"); +addGroup(policy.name, "lms_access_allow", "lms_access_allow"); +addGroup(policy.name, "lms_access_deny", "lms_access_deny"); +addComposite("app:lms:service:policy:lms_access", CompositeType.COMPLEMENT, "app:lms:service:policy:lms_access_allow", "app:lms:service:policy:lms_access_deny"); -#addStem("app", "lms", "lms"); -group = addGroup("app:lms", "lms_authorized", "lms_authorized"); -addGroup("app:lms", "lms_authorized_allow", "lms_authorized_allow"); -addGroup("app:lms", "lms_authorized_deny", "lms_authorized_deny"); -addComposite("app:lms:lms_authorized", CompositeType.COMPLEMENT, "app:lms:lms_authorized_allow", "app:lms:lms_authorized_deny"); - -addMember("app:lms:lms_authorized_allow", "ref:legacy:community_members"); +addMember("app:lms:service:policy:lms_access_allow", "ref:legacy:community_members"); pspngAttribute = AttributeDefNameFinder.findByName("etc:pspng:provision_to", true); AttributeAssignSave attributeAssignSave = new AttributeAssignSave(gs).assignPrintChangesToSystemOut(true); @@ -90,43 +86,57 @@ attributeAssignSave.assignOwnerGroup(group); attributeAssignSave.addValue("pspng_groupOfNames"); attributeAssignSave.save(); - -addStem("app:lms", "ref", "ref"); - - -group = addGroup("app:lms:ref", "visiting_scholars", "visiting_scholars"); -addMember("app:lms:ref:visiting_scholars","glee303"); -addMember("app:lms:ref:visiting_scholars","jlee308"); -addMember("app:lms:ref:visiting_scholars","cbutler313"); -addMember("app:lms:ref:visiting_scholars","cwalters316"); -addMember("app:lms:ref:visiting_scholars","bbutler317"); -addMember("app:lms:ref:visiting_scholars","mwilliams323"); -addMember("app:lms:ref:visiting_scholars","jgrady326"); -addMember("app:lms:ref:visiting_scholars","ewalters329"); -addMember("app:lms:ref:visiting_scholars","aroberts334"); -addMember("app:lms:ref:visiting_scholars","mgrady336"); -addMember("app:lms:ref:visiting_scholars","gdavis354"); -addMember("app:lms:ref:visiting_scholars","hpeterson355"); -addMember("app:lms:ref:visiting_scholars","clee357"); -addMember("app:lms:ref:visiting_scholars","mwalters363"); -addMember("app:lms:ref:visiting_scholars","svales364"); -addMember("app:lms:ref:visiting_scholars","sthompson365"); -addMember("app:lms:ref:visiting_scholars","iwhite370"); -addMember("app:lms:ref:visiting_scholars","sdavis372"); -addMember("app:lms:ref:visiting_scholars","aclark373"); -addMember("app:lms:ref:visiting_scholars","pmartinez374"); -addMember("app:lms:ref:visiting_scholars","anielson378"); -addMember("app:lms:ref:visiting_scholars","adavis379"); -addMember("app:lms:ref:visiting_scholars","gbutler381"); -addMember("app:lms:ref:visiting_scholars","clopez383"); -addMember("app:lms:ref:visiting_scholars","apeterson387"); - - -addMember("app:lms:lms_authorized_allow", "app:lms:ref:visiting_scholars"); - -pspngAttribute = AttributeDefNameFinder.findByName("etc:pspng:provision_to", true); -AttributeAssignSave attributeAssignSave = new AttributeAssignSave(gs).assignPrintChangesToSystemOut(true); -attributeAssignSave.assignAttributeDefName(pspngAttribute); -attributeAssignSave.assignOwnerGroup(group); -attributeAssignSave.addValue("pspng_groupOfNames"); -attributeAssignSave.save(); +group = addGroup(ref.name, "visiting_scholars", "visiting_scholars"); +addMember("app:lms:service:ref:visiting_scholars","adoe852"); +addMember("app:lms:service:ref:visiting_scholars","agonazles804"); +addMember("app:lms:service:ref:visiting_scholars","alopez751"); +addMember("app:lms:service:ref:visiting_scholars","alopez802"); +addMember("app:lms:service:ref:visiting_scholars","anielson378"); +addMember("app:lms:service:ref:visiting_scholars","anielson51"); +addMember("app:lms:service:ref:visiting_scholars","athompson526"); +addMember("app:lms:service:ref:visiting_scholars","athompson713"); +addMember("app:lms:service:ref:visiting_scholars","athompson866"); +addMember("app:lms:service:ref:visiting_scholars","awalters247"); +addMember("app:lms:service:ref:visiting_scholars","awhite131"); +addMember("app:lms:service:ref:visiting_scholars","awhite631"); +addMember("app:lms:service:ref:visiting_scholars","bdavis150"); +addMember("app:lms:service:ref:visiting_scholars","bdavis999"); +addMember("app:lms:service:ref:visiting_scholars","bgasper2"); +addMember("app:lms:service:ref:visiting_scholars","bgonazles239"); +addMember("app:lms:service:ref:visiting_scholars","bgrady115"); +addMember("app:lms:service:ref:visiting_scholars","blee298"); +addMember("app:lms:service:ref:visiting_scholars","cjohnson933"); +addMember("app:lms:service:ref:visiting_scholars","clangenberg923"); +addMember("app:lms:service:ref:visiting_scholars","clee357"); +addMember("app:lms:service:ref:visiting_scholars","cthompson231"); +addMember("app:lms:service:ref:visiting_scholars","cthompson287"); +addMember("app:lms:service:ref:visiting_scholars","cwalters316"); +addMember("app:lms:service:ref:visiting_scholars","cwalters536"); +addMember("app:lms:service:ref:visiting_scholars","cwilliams606"); +addMember("app:lms:service:ref:visiting_scholars","danderson959"); +addMember("app:lms:service:ref:visiting_scholars","dbrown402"); +addMember("app:lms:service:ref:visiting_scholars","ddavis762"); +addMember("app:lms:service:ref:visiting_scholars","ddoe822"); +addMember("app:lms:service:ref:visiting_scholars","dwhite663"); +addMember("app:lms:service:ref:visiting_scholars","dwilliams299"); +addMember("app:lms:service:ref:visiting_scholars","eanderson919"); +addMember("app:lms:service:ref:visiting_scholars","escott173"); +addMember("app:lms:service:ref:visiting_scholars","gbutler381"); +addMember("app:lms:service:ref:visiting_scholars","ggrady118"); +addMember("app:lms:service:ref:visiting_scholars","ggrady649"); +addMember("app:lms:service:ref:visiting_scholars","glangenberg234"); +addMember("app:lms:service:ref:visiting_scholars","gwalters810"); +addMember("app:lms:service:ref:visiting_scholars","gwhite647"); +addMember("app:lms:service:ref:visiting_scholars","hpeterson10"); +addMember("app:lms:service:ref:visiting_scholars","jgrady499"); +addMember("app:lms:service:ref:visiting_scholars","jlee308"); +addMember("app:lms:service:ref:visiting_scholars","jnielson505"); +addMember("app:lms:service:ref:visiting_scholars","jsmith466"); +addMember("app:lms:service:ref:visiting_scholars","jvales111"); +addMember("app:lms:service:ref:visiting_scholars","jvales645"); +addMember("app:lms:service:ref:visiting_scholars","jwalters24"); +addMember("app:lms:service:ref:visiting_scholars","kdavis686"); +addMember("app:lms:service:ref:visiting_scholars","kjohnson872"); + +addMember("app:lms:service:policy:lms_access_allow", "app:lms:service:ref:visiting_scholars"); +addMember("app:lms:service:policy:lms_access_deny", "ref:iam:global_deny"); \ No newline at end of file