diff --git a/docs/401/401.1.rst b/docs/401/401.1.rst index 9e78cfd..2854fd6 100644 --- a/docs/401/401.1.rst +++ b/docs/401/401.1.rst @@ -18,7 +18,7 @@ Lab Components * Grouper * PSPNG * OpenLDAP -* `Grouper Deployment Guide `_ +* `Grouper Deployment Guide`_ -------- Overview @@ -26,7 +26,7 @@ Overview VPN access is currently controlled by an LDAP group. You are not exactly sure who is in the group or what the policy is, but have a general notion of a -natural language policy as all active faculty and staff, plus exceptions. +natural language policy as all active faculty and staff, plus some exceptions. However, people have been added to the VPN ldap group mostly by hand over many years with little to no lifecycle management in place. There is no easy way to determine who should or should not be in the group. We just had a major breach @@ -34,116 +34,176 @@ which was facilitated by access to the VPN. The compromised account used in the breach was given to a former consultant and was never deprovisioned. CISO is coming down hard on us to clean up our act! ----------------- -Exercise 401.1.1 ----------------- +------------------------------------------------------ +Exercise 401.1.1 Analyze legacy VPN authoization group +------------------------------------------------------ -*Gain insight into who exactly has access to the VPN based on the cohorts found -in the legacy VPN authorization group.* +Gain insight into who exactly has access to the VPN based on the cohorts found +in the legacy VPN authorization group. We'll do this by using well established +reference groups for faculty, staff, and students. -"""""""""""""""""""""" -Import Legacy VPN Data -"""""""""""""""""""""" +""""""""""""""""""""""""""""""""""""" +Import Legacy VPN authorization group +""""""""""""""""""""""""""""""""""""" -* Create a loader job from the existing ldap vpn authorization group. -* Make sure grouper group counts matches ldap group counts. -* First thing to notice is you can eyeball the types of subjects in Grouper UI. +First review the legacy VPN authorization group in LDAP. + +#. Log in to https://localhost:8443/phpldapadmin/ with username + `cn=root,dc=internet2,dc=edu` and password `password` + +#. Set the Search Filter to + "memberOf=cn=vpn_users,ou=groups,dc=internet2,dc=edu" + and Search Results to 5000. How many subjects are in `vpn_users`? + +.. figure:: ../figures/401-legacy-ldap-vpn.png + +3. Create a `vpn` folder under the `test` folder +4. Create a `vpn_legacy` group to load the ldap group +5. Added Loader settings to the `vpn_legacy` group + (vpn_legacy -> More -> Loader -> Loader actions -> Edit loader + configuration) + +* Loader: Yes, has loader configuration +* Source Type: LDAP +* Loader type: LDAP_SIMPLE +* Server ID: demo +* LDAP filter: (cn=vpn_users) +* Subject attribute name: member +* Search base DN: dc=internet2,dc=edu +* Schedule: 0 * * * * ? +* Subject source ID: ldap - EDU Ldap +* Subject lookup type: subjectid +* Search scope: SUBTREE_SCOPE +* Priority: +* Subject expression:${loaderLdapElUtils.convertDnToSpecificValue(subjectId)} +* Require members in other group(s): + +6. Run Loader diagnostics (Loader actions -> Loader diagnostics -> Run loader + diagnostics) + +.. figure:: ../figures/401-ldap-loader-diag.png + +7. Run loader (Loader actions -> Run loader process to sync group) +8. Review loader logs. How many subject added? + (Loader actions -> View loader logs) + +.. figure:: ../figures/401-ldap-loader-logs.png + +9. Review `vpn_legacy` members + +.. figure:: ../figures/401-vpn-legacy-members.png .. note:: - For small enough groups this might be sufficient, but our VPN group has - hundreds of subjects. + The first thing to notice is you can eyeball the types of subjects in the + Grouper UI. For small groups this might be sufficient, but our VPN group + has hundreds of subjects. -""""""""""""""""""""""""""""""" -Use Set Operations for Analysis -""""""""""""""""""""""""""""""" +"""""""""""""""""""""""""""""""""""""""""""""" +Use group math to gain insight into vpn_legacy +"""""""""""""""""""""""""""""""""""""""""""""" -Use intersect composite groups to gain insight into types of cohorts +We will use test composite groups to gain insight into the types of cohorts in +`vpn_legacy` by intersecting it with well known reference groups for faculy, +staff, and student. -* `test:vpn:vpn_faculty`: Intersect `ref:faculty` with `test:vpn:vpn_legacy`. - This yields faculty count (almost) - aha! This explains help desk calls! +1. Create `test:vpn:vpn_faculty` group, and make it a composite intersection of +`ref:faculty` with `test:vpn:vpn_legacy`. This yields faculty count (almost) - +aha! This explains those help desk calls! All faculty should automatically have +access to VPN by policy, but they don't. -* `test:vpn:vpn_employees`: Intersect `ref:staff` with `test:vpn:vpn_legacy`. - This yields staff count (again almost!) +2. Create `test:vpn:vpn_staff` group, and make it a composite intersection of +`ref:staff` with `test:vpn:vpn_legacy`. This yields staff count (again +almost!). We're also +missing some staff. -* `test:vpn:vpn_students`: Intersect `ref:students` with `test:vpn:vpn_legacy`. - This yields a small count - aha! +3. Create `test:vpn:vpn_students` group, and make it a composite intersect +`ref:students` with `test:vpn:vpn_legacy`. This yields a small count. As we +expected some students have been added to the vpn access control group as +exceptions, but we don't +know why, when, or by whom. -* Totals don’t add up...so we have other cohorts too. Who are they? +Hmm, the totals member counts don’t add up...so we have other cohorts too. +Who are they? Set up a composite group to filter out "other cohorts". -* Set up composite group to filter out "other cohorts". +4. Create a `test:vpn:other_cohorts` group. -* `test:vpn:other_cohorts` = `...:vpn_legacy` - (`...:vpn_faculty` + - `...:vpn_employees` + `...:vpn_students`) +5. Create `vpn_facstaffstudent` and add `vpn_faculty`, + `vpn_staff`, `vpn_students` as members. - * create `...:vpn_facstaffstudent` (include `...:vpn_faculty`, - `...:vpn_employees`, `...:vpn_students`) - * `...:other_cohorts` = `...:vpn_legacy` - `...:vpn_facstaffstudent` +6. Make `other_cohorts` a composite of `vpn_legacy` - `vpn_facstaffstudent` -* "Other cohorts" is a relatively small number ... can now eyeball those. +`Other cohorts` is a relatively small number. We can now eyeball those. - * fac/staff that are now longer active - * Contractors, sponsored accounts, etc - * Others +.. figure:: ../figures/401-other-cohorts.png ----------------- -Exercise 401.1.2 ----------------- +-------------------------------------------------------------------- +Exercise 401.1.2 Translate natural language policy to digital policy +-------------------------------------------------------------------- -*State the natural language policy and create VPN application group and digital -policy.* +The natural language policy is "Faculty, staff and exceptions (some students, +contractors, etc.)" -#. Natural language policy: "Faculty, staff and exceptions (some students, - contractors, etc.)" -#. Construct `app:vpn:vpn_authorized|allow|deny` policy groups from appropriate - reference groups. +#. Use the application template and the policy group template to create a new + `vpn` application folder and policy group called `vpn_authorized` - * `ref:faculty` - * `ref:employees` - * `app:vpn:ref:vpn_adhoc` +#. Create a new application specific reference group + `app:vpn:service:ref:vpn_adhoc`. -#. Compare counts between ldap vpn group and `app:vpn:vpn_authorized`. - `vpn_authorized` should be different from the legacy group in the following - ways: +#. Add `faculty`, `staff`, and `vpn_adhoc` to `vpn_authorized_allow` - * only active accounts - * only current exceptions (none!) +.. figure:: ../figures/401-vpn-policy.png ----------------- -Exercise 401.1.3 ----------------- +#. Compare counts between `vpn_legacy` and `vpn_authorized`. + `vpn_authorized`. Why are they different? -*Export `vpn_authorized` to LDAP for use with new VPN config.* -#. Mark/config `vpn_authorized` to export to LDAP. The PSPNG needs to be - configured to provision group members. +---------------------------------------------------- +Exercise 401.1.3 Export `vpn_authorized` to OpenLDAP +---------------------------------------------------- + +#. Configure `PSPNG`_ to provision group members to OpenLDAP groupOfNames .. literalinclude:: examples/401.1.3-pspng-config.properties :language: properties :lines: 72- - :caption: grouper-loader.properties + :caption: /opt/grouper/grouper.apiBinary/conf/grouper-loader.properties :name: 401.1.3-pspng-groupofnames :linenos: -#. Open a ticket to switch VPN config to use vpn_authorized. -#. Bask in the glow of TIER IAM goodness... +2. Mark `vpn_authorized` with the PSPNG `provision_to` attribute with a value +of `pspng_groupOfNames`. + +.. figure:: ../figures/401-vpn-provision-to.png + +3. Run the CHANGLE_LOG_consumer_pspng_groupOfNames + (Miscellaneous -> All deamon jobs -> Job Actions -> Run job now) + +4. Log in to https://localhost:8443/phpldapadmin and navigate to ou=groups. + Review your new Grouper managed vpn access control group! + +.. figure:: ../figures/401-vpn-authorized-ldap.png + +5. Open a service ticket to have the network team switch the VPN + config to use vpn_authorized. - * Automatic provisioning/deprovisioning for faculty and staff. - * Natural language policy - clear and visible. - * Exceptions management: +6. Bask in the glow of IAM greatness... :) - * Still dealing with tickets to add and remove subjects (well at least to add!). - * No way to distinguish different exceptions. - * Who is responsible for lifecycle, attestation, etc.? +* Automatic provisioning/deprovisioning of VPN access for faculty and staff. +* Natural language policy - clear and visible. +* Exceptions management ----------------- -Exercise 401.1.4 ----------------- +This is a huge improvement! However, we are still dealing with tickets to +add and remove subjects (well at least to add!) to `vpn_adhoc` group. +There is no way to distinguish different exceptions, and it is not +clear who is responsible for lifecycle and attestation. -*Implement distributed exception management.* +------------------------------------------------------------ +Exercise 401.1.4 Implement distributed exception management. +------------------------------------------------------------ We initially added exceptions to single application reference group. This a good step, but we still lack an easy way to know the "who and why" of -exceptions. IAM still also getting tickets to add people. In some case, the +exceptions. IAM is still getting tickets to add people. In some case, the expiration is known and added, but most are a one way street-- back to old practices. How can we do better? @@ -151,99 +211,202 @@ practices. How can we do better? Organize Exceptions to Policy """"""""""""""""""""""""""""" -Each policy exception is represented by an application specific reference group. +Each policy exception is represented by an application specific reference +group. #. Create `app:vpn:ref:vpn_consultants`. This ACL will be managed by the IAM team. #. Create `app:vpn:ref:vpn_ajohnson409`. Management of this ACL will be delegated to a professor. - +#. Add each of these ACLs to `vpn_adhoc` + +.. figure:: ../figures/401-vpn-acls-visual.png + +++++++++++++++++++++++++++++++++++ Professor Johnson's Special Project +++++++++++++++++++++++++++++++++++ -Professor Johnson (**ajohnson409**) runs a special project that includes various online -resources that can only be accessed from the VPN. The professor should be able to -control who is allowed to have VPN access for the purpose of accessing his -project's resources. - -ACL `app:vpn:ref:vpn_ajohnson409` represents subjects that will access resources -related to Professor Johnson's special project. In order to delegate management -of this ACL to the professor, we must create a security group and grant it -appropriate permissions: - -#. Create `app:vpn:etc:vpn_ajohnson409_mgr`. -#. Add subject `ajohnson409` to this security group. -#. Grant *UPDATE* and *READ* access on the `...:ajohnson409` access control - list to this security group. -#. In a private browser window, log into the GTE was account `ajohnson409`, - password "password". You should be able to add and remove members from the - `vpn_ajohnson409` ACL. - -"""""""""""""""""""""" -Put Limits on Policies -"""""""""""""""""""""" - -It is the IAM team's responsibility to make sure that VPN access is granted to the -correct subjects. Putting some limits in place can help make sure improper -access is not granted. Attestation makes sure that access which was granted -in the past is still appropriate. - -#. Create `ref:iam:global_deny`. This reference group represents a broad cohort - of subjects that should not be granted access to most policies. Subjects - that fall into this category may be: - - * Termed "with cause" +Professor Johnson (**ajohnson409**) runs a special project that includes +various online resources that can only be accessed from the VPN. The professor +should be able to control who is allowed to have VPN access for the purpose of +accessing his project's resources. + +We will create an access control list (ACL) `app:vpn:ref:vpn_ajohnson409` to +represent subjects that will access resources related to Professor Johnson's +special project. In order to delegate management of this ACL to the professor, +we must create a security group and grant it appropriate permissions: + +#. Create `app:vpn:security:vpn_ajohnson409_mgr`. +#. Grant `vpn_ajohnson_mgr` *UPDATE* and *READ* to `vpn_ajohnson409` +#. Add subject `ajohnson409` to this security group. +#. Review the privileges on `vpn_johnson409` + +.. figure:: ../figures/401-vpn-ajohnson409-privs.png + +5. In a private browser window, log in to http://localhost:8443/grouper with + username `ajohnson409` and password `password`. You should be able to add + and remove members from the `vpn_ajohnson409` ACL. +6. Add student `bsmith458` to `vpn_ajohnson409` +7. Find `bsmith458` in `vpn_authorized` and trace membership + +.. figure:: ../figures/401-bsmith458-trace-membership.png + +.. figure:: ../figures/401-bsmith458-trace.png + +-------------------------------------------------------- +Exercise 401.1.5 Implement additional policy constraints +-------------------------------------------------------- + +It is the IAM team's responsibility to make sure that VPN access is granted to +the correct subjects. Putting some limits in place can help make sure improper +access is not granted. Attestation makes sure that access which was granted in +the past is still appropriate. + +#. The `ref:iam:global_deny` reference group represents a broad cohort + of subjects that should not be granted access. Subjects that fall into + this category may include: + + * Termed with cause * Deceased * Other reasons -#. Add `ref:iam:global_deny` to the `app:vpn:vpn_deny` policy. -#. Add attestation requirements to the `app:vpn:ref:vpn_ajohnson409` ACL. +#. Add `ref:iam:global_deny` to the `vpn_authorized_deny` policy group. - * Create attestation requirements (30 days). - * Review notification settings. - * View :guilabel:`home` -> :guilabel:`misc` -> :guilabel:`attestation settings`. - * Log in as `ajohnson409` and attest! - * View audit log to see who attested group. +#. Add 30 day attestation requirements to the `vpn_ajohnson409` ACL. + (vpn_ajohnson409 -> More actions -> Attestation -> Attestion actions -> + Edit attestion settings...) -#. Add automatic age-off / lifecycle - exceptions only good for 180 days. - There are 2 techniques: +.. figure:: ../figures/401-vpn-attest.png - * Add member, edit membership, add membership end date. - * Better approach, use grouper rule to automatically add end date to - members. See :ref:`the appendix ` for - details. +#. Review attestations (Miscellaneous -> Attestation) -#. Use Grouper 2.4 affiliation-based deprovisioning. +.. figure:: ../figures/401-vpn-misc-attest.png -All access to VPN is now traceable to natural language policy and known -exceptions! Policy is enforced automatically and kept in sync with changing -subject attributes. Exceptions are known and managed with a defined -attestation lifecycle. VPN policy participates in the global deny policy. +Consultant exceptions should expire automatically after 180 days. There are 2 +techniques to accomplish this in Grouper. The first is to simply edit the +membership end date after you have added a subject to a group. The second, and +more reliable, is to have a rule that runs every time a subject is added which +autotmatically sets the membership end date. Let's implement the second +approach. ----------------- -Exercise 401.1.5 ----------------- +#. Run `./gte-shell 401.1.1` to get a command prompt. -*CISO is working on a investigation and wants to know if this particular NetID -"blee172" has access to the VPN now or in the past 90 days?* +#. Run `./bin/gsh` to start the Grouper shell -#. Navigate to `apps:vpn:vpn_authorized`. -#. Search for so-and-so. -#. Open up phpMyAdmin (https://localhost:8443/phpmyadmin/) -#. Open Views, Go to SQL tab, paste in - :ref:`PIT query `, Go! +#. Paste in the following gsh script: -.. _apdx-401.1.5-pit-query: +.. code-block:: groovy ----------------- -Exercise 401.1.6 ----------------- + // Automatically expire vpn_consultant subject memberships in 180 days + gs = GrouperSession.startRootSession(); + numberOfDays = 180; + actAs = SubjectFinder.findRootSubject(); + vpn_consultants = GroupFinder.findByName(gs, "app:vpn:service:ref:vpn_consultants"); + attribAssign = vpn_consultants.getAttributeDelegate().addAttribute(RuleUtils.ruleAttributeDefName()).getAttributeAssign(); + attribValueDelegate = attribAssign.getAttributeValueDelegate(); + attribValueDelegate.assignValue(RuleUtils.ruleActAsSubjectSourceIdName(), actAs.getSourceId()); + attribValueDelegate.assignValue(RuleUtils.ruleActAsSubjectIdName(), actAs.getId()); + attribValueDelegate.assignValue(RuleUtils.ruleCheckTypeName(), RuleCheckType.membershipAdd.name()); + attribValueDelegate.assignValue(RuleUtils.ruleThenEnumName(), RuleThenEnum.assignMembershipDisabledDaysForOwnerGroupId.name()); + attribValueDelegate.assignValue(RuleUtils.ruleThenEnumArg0Name(), numberOfDays.toString()); + attribValueDelegate.assignValue(RuleUtils.ruleThenEnumArg1Name(), "T"); -*CISO wants to know if anyone on this list of NetIDs has access to the VPN? And -why?* +#. Add `jsmith` to `vpn_consultants` and then review the membership end date. + (vpn_consultants -> jsmith -> Edit membership and privileges) -#. Import list to a test group. -#. Intersect with `vpn_authorized`. -#. Trace membership to determine what level of access and why. +.. figure:: ../figures/401-vpn-add-jsmith.png +.. figure:: ../figures/401-vpn-jsmith-end-date.png + +--------------------------------------------------- +Exercise 401.1.5 Does "blee172" have access to VPN? +--------------------------------------------------- + +The CISO is working on a investigation and wants to know if this particular +NetID "blee172" has access to the VPN now or in the past 90 days? + +#. Navigate to `apps:vpn:vpn_authorized`. +#. Search for `blee172` and trace membership. + +.. figure:: ../figures/401-vpn-trace-blee172.png + +Betty currently has access since she is staff. +The Point-In-Time (PIT) tables know if she's had access in the last 90 days. + +3. Log in to phpMyAdmin (https://localhost:8443/phpmyadmin/) with username +`root` and a blank password. + +4. In the database explore, open grouper Views, then go to SQL tab, paste in + the following block: + +.. code-block:: SQL + + SELECT + gpm.SUBJECT_ID, + gpg.NAME, + FROM_UNIXTIME(gpmav.MEMBERSHIP_START_TIME / 1000000) start_time, + FROM_UNIXTIME(gpmav.MEMBERSHIP_END_TIME / 1000000) end_time + FROM grouper_pit_memberships_all_v gpmav + INNER JOIN grouper_pit_groups gpg + ON gpmav.owner_group_id = gpg.id + INNER JOIN grouper_pit_members gpm + ON gpmav.MEMBER_ID = gpm.id + INNER JOIN grouper_pit_fields gpf + ON gpmav.field_id = gpf.id + WHERE gpg.name = 'app:vpn:service:policy:vpn_authorized' + AND gpm.subject_type = 'person' + AND gpf.name = 'members' + ORDER BY gpmav.MEMBERSHIP_START_TIME DESC + ; + +5. Filter rows for `blee172`. This shows Betty's earliest access was + 2019-06-03. + +.. figure:: ../figures/401-vpn-blee172-pit-query.png + +--------------------------------------------------- +Exercise 401.1.6 VPN access audit or list of NetIDs +--------------------------------------------------- + +CISO wants to know if anyone on this list of NetIDs has access to the VPN? And +why? + +1. Import the following list to `test:vpn:vpn_audit_list` + +.. code-block:: + + ahenderson36 + cpeterson37 + jclark39 + kbrown62 + tpeterson63 + pjohnson64 + aroberts95 + sdavis107 + mhenderson109 + jvales117 + sgrady139 + mprice142 + mwilliams144 + lpeterson153 + mvales154 + bsmith458 + +2. Create `test:vpn:vpn_audit` + +3. Edit composite on `vpn_audit` and create an interection of `vpn_authorized` + and `vpn_audit_list`. This will tell us who in `vpn_audit_list` is also in + `vpn_authorized`. + +#. Review and trace membership to determine why they have access. + +.. figure:: ../figures/401-vpn-audit-list.png + +Congrats! All access to VPN is now traceable to natural language policy and +known exceptions! Policy is enforced automatically and kept in sync with +changing subject attributes. Exceptions are known and managed with a defined +attestation lifecycle. Exception managment is distributed and VPN policy +participates in the global deny policy. + +.. _Grouper Deployment Guide: https://spaces.at.internet2.edu/display/Grouper/Grouper+Deployment+Guide+Work+-TIER+Program +.. _`PSPNG`: https://spaces.at.internet2.edu/x/iwfSBQ \ No newline at end of file diff --git a/docs/401/appendix.rst b/docs/401/appendix.rst index 81a25d4..64f3b6e 100644 --- a/docs/401/appendix.rst +++ b/docs/401/appendix.rst @@ -2,71 +2,6 @@ Appendix ======== -.. _apdx-401.1.4-auto-end-date: - -------------------------------- -401.1.4 Automatic End Date Rule -------------------------------- - -To configure the automatic rule end date on the access control list, -`app:vpn:ref:vpn_adhoc` you must use the Grouper Shell (GSH) to run -a short script. To run GSH, you must connect to the GTE container -that has the Grouper API installed: - -.. code-block:: bash - - root# docker exec -it CONTAINER_NAME /bin/bash - bash# cd bin - bash# gsh - -At this point you can paste in the following script: - -.. code-block:: groovy - :emphasize-lines: 1,3 - :linenos: - - numDays = 180; - actAs = SubjectFinder.findRootSubject(); - vpn_adhoc = getGroups("app:vpn:ref:vpn_adhoc")[0]; - attribAssign = vpn_adhoc.getAttributeDelegate().addAttribute(RuleUtils.ruleAttributeDefName()).getAttributeAssign(); - attribValueDelegate = attribAssign.getAttributeValueDelegate(); - attribValueDelegate.assignValue(RuleUtils.ruleActAsSubjectSourceIdName(), actAs.getSourceId()); - attribValueDelegate.assignValue(RuleUtils.ruleRunDaemonName(), "F"); - attribValueDelegate.assignValue(RuleUtils.ruleActAsSubjectIdName(), actAs.getId()); - attribValueDelegate.assignValue(RuleUtils.ruleCheckTypeName(), RuleCheckType.membershipAdd.name()); - attribValueDelegate.assignValue(RuleUtils.ruleIfConditionEnumName(), RuleIfConditionEnum.thisGroupHasImmediateEnabledNoEndDateMembership.name()); - attribValueDelegate.assignValue(RuleUtils.ruleThenEnumName(), RuleThenEnum.assignMembershipDisabledDaysForOwnerGroupId.name()); - attribValueDelegate.assignValue(RuleUtils.ruleThenEnumArg0Name(), numDays.toString()); - attribValueDelegate.assignValue(RuleUtils.ruleThenEnumArg1Name(), "T"); - -.. _apdx-401.1.5-pit-query: - --------------------------------------- -401.1.5 Point-in-Time Membership Query --------------------------------------- - -.. code-block:: sql - :linenos: - - SELECT - gpm.SUBJECT_ID, - gpg.NAME, - FROM_UNIXTIME(gpmav.MEMBERSHIP_START_TIME / 1000000) start_time, - FROM_UNIXTIME(gpmav.MEMBERSHIP_END_TIME / 1000000) end_time - FROM grouper_pit_memberships_all_v gpmav - INNER JOIN grouper_pit_groups gpg - ON gpmav.owner_group_id = gpg.id - INNER JOIN grouper_pit_members gpm - ON gpmav.MEMBER_ID = gpm.id - INNER JOIN grouper_pit_fields gpf - ON gpmav.field_id = gpf.id - WHERE gpg.name = 'app:vpn:vpn_authorized' - AND gpm.subject_type = 'person' - AND gpf.name = 'members' - ORDER BY gpmav.MEMBERSHIP_START_TIME DESC - ; - - .. _apdx-401.2.5-future-memberships-query: -------------------------------- diff --git a/docs/figures/401-bsmith458-trace-membership.png b/docs/figures/401-bsmith458-trace-membership.png new file mode 100644 index 0000000..0e8de92 Binary files /dev/null and b/docs/figures/401-bsmith458-trace-membership.png differ diff --git a/docs/figures/401-bsmith458-trace.png b/docs/figures/401-bsmith458-trace.png new file mode 100644 index 0000000..2a39714 Binary files /dev/null and b/docs/figures/401-bsmith458-trace.png differ diff --git a/docs/figures/401-ldap-loader-diag.png b/docs/figures/401-ldap-loader-diag.png new file mode 100644 index 0000000..38fab96 Binary files /dev/null and b/docs/figures/401-ldap-loader-diag.png differ diff --git a/docs/figures/401-ldap-loader-logs.png b/docs/figures/401-ldap-loader-logs.png new file mode 100644 index 0000000..8f064f7 Binary files /dev/null and b/docs/figures/401-ldap-loader-logs.png differ diff --git a/docs/figures/401-legacy-ldap-vpn.png b/docs/figures/401-legacy-ldap-vpn.png new file mode 100644 index 0000000..d9c0ceb Binary files /dev/null and b/docs/figures/401-legacy-ldap-vpn.png differ diff --git a/docs/figures/401-other-cohorts.png b/docs/figures/401-other-cohorts.png new file mode 100644 index 0000000..821957f Binary files /dev/null and b/docs/figures/401-other-cohorts.png differ diff --git a/docs/figures/401-vpn-acls-visual.png b/docs/figures/401-vpn-acls-visual.png new file mode 100644 index 0000000..a186953 Binary files /dev/null and b/docs/figures/401-vpn-acls-visual.png differ diff --git a/docs/figures/401-vpn-add-jsmith.png b/docs/figures/401-vpn-add-jsmith.png new file mode 100644 index 0000000..a828c5a Binary files /dev/null and b/docs/figures/401-vpn-add-jsmith.png differ diff --git a/docs/figures/401-vpn-ajohnson409-privs.png b/docs/figures/401-vpn-ajohnson409-privs.png new file mode 100644 index 0000000..0494903 Binary files /dev/null and b/docs/figures/401-vpn-ajohnson409-privs.png differ diff --git a/docs/figures/401-vpn-attest.png b/docs/figures/401-vpn-attest.png new file mode 100644 index 0000000..0e44f5f Binary files /dev/null and b/docs/figures/401-vpn-attest.png differ diff --git a/docs/figures/401-vpn-audit-list.png b/docs/figures/401-vpn-audit-list.png new file mode 100644 index 0000000..ff62416 Binary files /dev/null and b/docs/figures/401-vpn-audit-list.png differ diff --git a/docs/figures/401-vpn-authorized-ldap.png b/docs/figures/401-vpn-authorized-ldap.png new file mode 100644 index 0000000..a9e2774 Binary files /dev/null and b/docs/figures/401-vpn-authorized-ldap.png differ diff --git a/docs/figures/401-vpn-blee172-pit-query.png b/docs/figures/401-vpn-blee172-pit-query.png new file mode 100644 index 0000000..a295b01 Binary files /dev/null and b/docs/figures/401-vpn-blee172-pit-query.png differ diff --git a/docs/figures/401-vpn-legacy-members.png b/docs/figures/401-vpn-legacy-members.png new file mode 100644 index 0000000..99a96cf Binary files /dev/null and b/docs/figures/401-vpn-legacy-members.png differ diff --git a/docs/figures/401-vpn-misc-attest.png b/docs/figures/401-vpn-misc-attest.png new file mode 100644 index 0000000..3dab327 Binary files /dev/null and b/docs/figures/401-vpn-misc-attest.png differ diff --git a/docs/figures/401-vpn-policy.png b/docs/figures/401-vpn-policy.png new file mode 100644 index 0000000..2f7b607 Binary files /dev/null and b/docs/figures/401-vpn-policy.png differ diff --git a/docs/figures/401-vpn-provision-to.png b/docs/figures/401-vpn-provision-to.png new file mode 100644 index 0000000..1cd1ffb Binary files /dev/null and b/docs/figures/401-vpn-provision-to.png differ diff --git a/docs/figures/401-vpn-trace-blee172.png b/docs/figures/401-vpn-trace-blee172.png new file mode 100644 index 0000000..1a28b96 Binary files /dev/null and b/docs/figures/401-vpn-trace-blee172.png differ diff --git a/ex401/class-files/CisoQuestionalUsers.txt b/ex401/class-files/CisoQuestionalUsers.txt index 17027ce..1bc1554 100644 --- a/ex401/class-files/CisoQuestionalUsers.txt +++ b/ex401/class-files/CisoQuestionalUsers.txt @@ -13,3 +13,4 @@ mprice142 mwilliams144 lpeterson153 mvales154 +bsmith458 diff --git a/ex401/ex401.1.1/container_files/seed-data/bootstrap.gsh b/ex401/ex401.1.1/container_files/seed-data/bootstrap.gsh index 0b53733..eff9434 100644 --- a/ex401/ex401.1.1/container_files/seed-data/bootstrap.gsh +++ b/ex401/ex401.1.1/container_files/seed-data/bootstrap.gsh @@ -6,14 +6,19 @@ addRootStem("app", "app"); addRootStem("org", "org"); addRootStem("test", "test"); -addGroup("etc","rolesLoader", "Roles Loader"); +addRootStem("401.1.1", "401.1.1") + +addStem("ref", "iam", "iam"); +addGroup("ref:iam", "global_deny", "global_deny"); + +group = addGroup("etc","rolesLoader", "Roles Loader"); groupAddType("etc:rolesLoader", "grouperLoader"); setGroupAttr("etc:rolesLoader", "grouperLoaderDbName", "grouper"); setGroupAttr("etc:rolesLoader", "grouperLoaderType", "SQL_GROUP_LIST"); setGroupAttr("etc:rolesLoader", "grouperLoaderScheduleType", "CRON"); setGroupAttr("etc:rolesLoader", "grouperLoaderQuartzCron", "0 * * * * ?"); -setGroupAttr("etc:rolesLoader", "grouperLoaderQuartzCron", "0 * * * * ?"); setGroupAttr("etc:rolesLoader", "grouperLoaderQuery", "select distinct id as SUBJECT_IDENTIFIER, 'ldap' as SUBJECT_SOURCE_ID, CONCAT('ref:', role) as GROUP_NAME from HR_PEOPLE_ROLES"); +// loaderRunOneJob(group); group = new GroupSave(gs).assignName("etc:deptLoader").assignCreateParentStemsIfNotExist(true).save(); group.getAttributeDelegate().assignAttribute(LoaderLdapUtils.grouperLoaderLdapAttributeDefName()).getAttributeAssign(); @@ -29,3 +34,4 @@ attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperL attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapSubjectExpressionName(), '${subjectAttributes["subjectId"]}'); attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapGroupNameExpressionName(), 'ref:dept:${groupAttribute}'); attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapGroupDisplayNameExpressionName(), '${groupAttribute}'); +// loaderRunOneJob(group); diff --git a/ex401/ex401.1.3/container_files/seed-data/bootstrap.gsh b/ex401/ex401.1.3/container_files/seed-data/bootstrap.gsh index f6cd64b..2510b91 100644 --- a/ex401/ex401.1.3/container_files/seed-data/bootstrap.gsh +++ b/ex401/ex401.1.3/container_files/seed-data/bootstrap.gsh @@ -1,15 +1,19 @@ gs = GrouperSession.startRootSession(); addStem("app", "vpn", "vpn"); -addStem("app:vpn", "ref", "ref"); +addStem("app:vpn", "service", "service"); +addStem("app:vpn", "security", "security"); -addGroup("app:vpn:ref", "vpn_adhoc", "vpn_adhoc"); -addGroup("app:vpn", "vpn_authorized", "vpn_authorized"); -addGroup("app:vpn", "vpn_allow", "vpn_allow"); -addGroup("app:vpn", "vpn_deny", "vpn_deny"); +addStem("app:vpn:service", "ref", "ref") +addStem("app:vpn:service", "policy", "policy") -addMember("app:vpn:vpn_allow", "ref:faculty"); -addMember("app:vpn:vpn_allow", "ref:staff"); -addMember("app:vpn:vpn_allow", "app:vpn:ref:vpn_adhoc"); +addGroup("app:vpn:service:ref", "vpn_adhoc", "vpn_adhoc"); +addGroup("app:vpn:service:policy", "vpn_authorized", "vpn_authorized"); +addGroup("app:vpn:service:policy", "vpn_authorized_allow", "vpn_authorized_allow"); +addGroup("app:vpn:service:policy", "vpn_authorized_deny", "vpn_authorized_deny"); -addComposite("app:vpn:vpn_authorized", CompositeType.COMPLEMENT, "app:vpn:vpn_allow", "app:vpn:vpn_deny"); +addMember("app:vpn:service:policy:vpn_authorized_allow", "ref:faculty"); +addMember("app:vpn:service:policy:vpn_authorized_allow", "ref:staff"); +addMember("app:vpn:service:policy:vpn_authorized_allow", "app:vpn:service:ref:vpn_adhoc"); + +addComposite("app:vpn:service:policy:vpn_authorized", CompositeType.COMPLEMENT, "app:vpn:service:policy:vpn_authorized_allow", "app:vpn:service:policy:vpn_authorized_deny"); diff --git a/ex401/ex401.1.end/Dockerfile b/ex401/ex401.1.end/Dockerfile index 1bdcb6d..bbaa2e9 100644 --- a/ex401/ex401.1.end/Dockerfile +++ b/ex401/ex401.1.end/Dockerfile @@ -1,5 +1,5 @@ ARG VERSION_TAG -FROM tier/gte:401.1.6-$VERSION_TAG +FROM tier/gte:401.1.1-$VERSION_TAG LABEL author="tier-packaging@internet2.edu " \ Vendor="TIER" \ diff --git a/ex401/ex401.1.end/container_files/seed-data/bootstrap.gsh b/ex401/ex401.1.end/container_files/seed-data/bootstrap.gsh index 8646002..2dc7dc4 100644 --- a/ex401/ex401.1.end/container_files/seed-data/bootstrap.gsh +++ b/ex401/ex401.1.end/container_files/seed-data/bootstrap.gsh @@ -1,22 +1,150 @@ gs = GrouperSession.startRootSession(); +delStem("401.1.1") +addRootStem("401.1.end", "401.1.end") -addGroup("test", "cisoQuestionableVpnUsersList", "CISO VPN Questionable VPN List"); -addMember("test:cisoQuestionableVpnUsersList","ahenderson36"); -addMember("test:cisoQuestionableVpnUsersList","cpeterson37"); -addMember("test:cisoQuestionableVpnUsersList","jclark39"); -addMember("test:cisoQuestionableVpnUsersList","kbrown62"); -addMember("test:cisoQuestionableVpnUsersList","tpeterson63"); -addMember("test:cisoQuestionableVpnUsersList","pjohnson64"); -addMember("test:cisoQuestionableVpnUsersList","aroberts95"); -addMember("test:cisoQuestionableVpnUsersList","sdavis107"); -addMember("test:cisoQuestionableVpnUsersList","mhenderson109"); -addMember("test:cisoQuestionableVpnUsersList","jvales117"); -addMember("test:cisoQuestionableVpnUsersList","sgrady139"); -addMember("test:cisoQuestionableVpnUsersList","mprice142"); -addMember("test:cisoQuestionableVpnUsersList","mwilliams144"); -addMember("test:cisoQuestionableVpnUsersList","lpeterson153"); -addMember("test:cisoQuestionableVpnUsersList","mvales154"); - -addGroup("test", "whyvpnaccess", "Why Do They Have VPN Access"); -addComposite("test:whyvpnaccess", CompositeType.INTERSECTION, "app:vpn:vpn_authorized", "test:cisoQuestionableVpnUsersList"); +// 401.1.1 +addStem("test", "vpn", "vpn"); + +//Create a loader job to pull in the VPN users assigned in the directory. +group = new GroupSave(gs).assignName("test:vpn:vpn_legacy").assignCreateParentStemsIfNotExist(true).save(); +group.getAttributeDelegate().assignAttribute(LoaderLdapUtils.grouperLoaderLdapAttributeDefName()).getAttributeAssign(); +attributeAssign = group.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"); +attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapFilterName(), "(cn=vpn_users)"); +attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapSearchDnName(), "ou=groups,dc=internet2,dc=edu"); +attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapSubjectAttributeName(), "member"); +attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapSubjectIdTypeName(), "subjectId"); +attributeAssign.getAttributeValueDelegate().assignValue(LoaderLdapUtils.grouperLoaderLdapSubjectExpressionName(), "\${loaderLdapElUtils.convertDnToSpecificValue(subjectId)}"); +loaderRunOneJob(group); + +// stub out loader jobs +addGroup("ref", "faculty", "faculty"); +addGroup("ref", "staff", "staff"); +addGroup("ref", "student", "student"); + +// Create the groups that do the grouper math to analyze the tables. +addGroup("test:vpn", "vpn_faculty", "vpn_faculty"); +addComposite("test:vpn:vpn_faculty", CompositeType.INTERSECTION, "test:vpn:vpn_legacy", "ref:faculty"); +addGroup("test:vpn", "vpn_staff", "vpn_staff"); +addComposite("test:vpn:vpn_staff", CompositeType.INTERSECTION, "test:vpn:vpn_legacy", "ref:staff"); +addGroup("test:vpn", "vpn_students", "vpn_students"); +addComposite("test:vpn:vpn_students", CompositeType.INTERSECTION, "test:vpn:vpn_legacy", "ref:student"); +addGroup("test:vpn", "vpn_facstaffstudent", "vpn_facstaffstudent"); +addMember("test:vpn:vpn_facstaffstudent", "test:vpn:vpn_faculty"); +addMember("test:vpn:vpn_facstaffstudent", "test:vpn:vpn_staff"); +addMember("test:vpn:vpn_facstaffstudent", "test:vpn:vpn_students"); +addGroup("test:vpn", "other_cohorts", "other_cohorts"); +addComposite("test:vpn:other_cohorts", CompositeType.COMPLEMENT, "test:vpn:vpn_legacy", "test:vpn:vpn_facstaffstudent"); + +// 401.1.2 +addStem("app", "vpn", "vpn"); +addStem("app:vpn", "service", "service"); +addStem("app:vpn", "security", "security"); +addStem("app:vpn:service", "ref", "ref") +addStem("app:vpn:service", "policy", "policy") + +addGroup("app:vpn:service:ref", "vpn_adhoc", "vpn_adhoc"); +vpn_authorized = addGroup("app:vpn:service:policy", "vpn_authorized", "vpn_authorized"); +addGroup("app:vpn:service:policy", "vpn_authorized_allow", "vpn_authorized_allow"); +addGroup("app:vpn:service:policy", "vpn_authorized_deny", "vpn_authorized_deny"); + +addMember("app:vpn:service:policy:vpn_authorized_allow", "ref:faculty"); +addMember("app:vpn:service:policy:vpn_authorized_allow", "ref:staff"); +addMember("app:vpn:service:policy:vpn_authorized_allow", "app:vpn:service:ref:vpn_adhoc"); + +addComposite("app:vpn:service:policy:vpn_authorized", CompositeType.COMPLEMENT, "app:vpn:service:policy:vpn_authorized_allow", "app:vpn:service:policy:vpn_authorized_deny"); + +// 401.1.3 - not sure what this isn't working... comment out for now. +// Auto create the PSPNG attributes +// edu.internet2.middleware.grouper.pspng.FullSyncProvisionerFactory.getFullSyncer("pspng_groupOfNames"); +// pspngAttribute = AttributeDefNameFinder.findByName("etc:pspng:provision_to", true); +// AttributeAssignSave attributeAssignSave = new AttributeAssignSave(gs).assignPrintChangesToSystemOut(true); +// attributeAssignSave.assignAttributeDefName(pspngAttribute); +// attributeAssignSave.assignOwnerGroup(vpn_authorized); +// attributeAssignSave.addValue("pspng_groupOfNames"); +// attributeAssignSave.save(); + +// 401.1.4 +group=addGroup("app:vpn:service:ref", "vpn_consultants", "vpn_consultants"); +group.setDescription("Consultants, must be approved by VP and have expiration date set"); +group.store(); +addMember("app:vpn:service:ref:vpn_adhoc","app:vpn:service:ref:vpn_consultants"); + +group=addGroup("app:vpn:service:ref", "vpn_ajohnson409", "vpn_ajohnson409"); +group.setDescription("Special project managed by ajohnson409"); +group.store(); +addMember("app:vpn:service:ref:vpn_adhoc","app:vpn:service:ref:vpn_ajohnson409"); + +addGroup("app:vpn:security", "vpn_ajohnson409_mgr", "vpn_ajohnson409_mgr"); +grantPriv("app:vpn:service:ref:vpn_ajohnson409", "app:vpn:security:vpn_ajohnson409_mgr", AccessPrivilege.UPDATE); +grantPriv("app:vpn:service:ref:vpn_ajohnson409", "app:vpn:security:vpn_ajohnson409_mgr", AccessPrivilege.READ); +addMember("app:vpn:security:vpn_ajohnson409_mgr", "ajohnson409") + +GrouperSession.start(findSubject("ajohnson409")) +addMember("app:vpn:service:ref:vpn_ajohnson409", "bsmith458") + + +// 401.1.5 +// Attestation requirement +gs = GrouperSession.startRootSession(); +group = GroupFinder.findByName(gs, "app:vpn:service:ref:vpn_ajohnson409"); +attribute = AttributeDefNameFinder.findByName("etc:attribute:attestation:attestation", true); +attributeAssignSave = new AttributeAssignSave(gs).assignPrintChangesToSystemOut(true); +attributeAssignSave.assignAttributeDefName(attribute); +attributeAssignSave.assignOwnerGroup(group); + +attributeAssignOnAssignSave = new AttributeAssignSave(gs); +attributeAssignOnAssignSave.assignAttributeAssignType(AttributeAssignType.group_asgn); +attestationSendEmailAttributeDefName = AttributeDefNameFinder.findByName("etc:attribute:attestation:attestationSendEmail", false); +attributeAssignOnAssignSave.assignAttributeDefName(attestationSendEmailAttributeDefName); +attributeAssignOnAssignSave.addValue("true"); +attributeAssignSave.addAttributeAssignOnThisAssignment(attributeAssignOnAssignSave); + +attributeAssignOnAssignSave = new AttributeAssignSave(gs); +attributeAssignOnAssignSave.assignAttributeAssignType(AttributeAssignType.group_asgn); +attributeDefName = AttributeDefNameFinder.findByName("etc:attribute:attestation:attestationDirectAssignment", false); +attributeAssignOnAssignSave.assignAttributeDefName(attributeDefName); +attributeAssignOnAssignSave.addValue("true"); +attributeAssignSave.addAttributeAssignOnThisAssignment(attributeAssignOnAssignSave); + +attributeAssign = attributeAssignSave.save(); + +// Automatically expire vpn_consultant subject memberships in 180 days +numberOfDays = 180; +actAs = SubjectFinder.findRootSubject(); +vpn_consultants = GroupFinder.findByName(gs, "app:vpn:service:ref:vpn_consultants"); +attribAssign = vpn_consultants.getAttributeDelegate().addAttribute(RuleUtils.ruleAttributeDefName()).getAttributeAssign(); +attribValueDelegate = attribAssign.getAttributeValueDelegate(); +attribValueDelegate.assignValue(RuleUtils.ruleActAsSubjectSourceIdName(), actAs.getSourceId()); +attribValueDelegate.assignValue(RuleUtils.ruleActAsSubjectIdName(), actAs.getId()); +attribValueDelegate.assignValue(RuleUtils.ruleCheckTypeName(), RuleCheckType.membershipAdd.name()); +attribValueDelegate.assignValue(RuleUtils.ruleThenEnumName(), RuleThenEnum.assignMembershipDisabledDaysForOwnerGroupId.name()); +attribValueDelegate.assignValue(RuleUtils.ruleThenEnumArg0Name(), numberOfDays.toString()); +attribValueDelegate.assignValue(RuleUtils.ruleThenEnumArg1Name(), "T"); + +addMember("app:vpn:service:ref:vpn_consultants", "jsmith") + +// 401.1.4 VPN access audit for list of NetIDs +addGroup("test:vpn", "vpn_audit_list", "vpn_audit_list"); +addMember("test:vpn:vpn_audit_list","ahenderson36"); +addMember("test:vpn:vpn_audit_list","cpeterson37"); +addMember("test:vpn:vpn_audit_list","jclark39"); +addMember("test:vpn:vpn_audit_list","kbrown62"); +addMember("test:vpn:vpn_audit_list","tpeterson63"); +addMember("test:vpn:vpn_audit_list","pjohnson64"); +addMember("test:vpn:vpn_audit_list","aroberts95"); +addMember("test:vpn:vpn_audit_list","sdavis107"); +addMember("test:vpn:vpn_audit_list","mhenderson109"); +addMember("test:vpn:vpn_audit_list","jvales117"); +addMember("test:vpn:vpn_audit_list","sgrady139"); +addMember("test:vpn:vpn_audit_list","mprice142"); +addMember("test:vpn:vpn_audit_list","mwilliams144"); +addMember("test:vpn:vpn_audit_list","lpeterson153"); +addMember("test:vpn:vpn_audit_list","mvales154"); +addMember("test:vpn:vpn_audit_list","bsmith458"); + +addGroup("test:vpn", "vpn_audit", "vpn_audit"); +addComposite("test:vpn:vpn_audit", CompositeType.INTERSECTION, "app:vpn:service:policy:vpn_authorized", "test:vpn:vpn_audit_list"); diff --git a/ex401/manualBuild.sh b/ex401/manualBuild.sh index 5170708..26bc28c 100755 --- a/ex401/manualBuild.sh +++ b/ex401/manualBuild.sh @@ -1,11 +1,6 @@ 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.2-${VERSION_TAG} ex401.1.2 \ -&& docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.1.3-${VERSION_TAG} ex401.1.3 \ -&& docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.1.4-${VERSION_TAG} ex401.1.4 \ -&& docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.1.5-${VERSION_TAG} ex401.1.5 \ -&& docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.1.6-${VERSION_TAG} ex401.1.6 \ && 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.2.1-${VERSION_TAG} ex401.2.1 \ && docker build --build-arg VERSION_TAG=${VERSION_TAG} --tag=tier/gte:401.2.2-${VERSION_TAG} ex401.2.2 \