401.2 MFA Policy Governance

Learning Objectives

  • Use Grouper policy to control Shibboleth MFA behavior
  • Create eduPersonEntitlement value to represent desired MFA behavior
  • Evolve digital policy to match changing natural language policy

Lab Components

Overview

Your institution is deploying multi-factor authentication (MFA). The first target application is Web SSO. Any account enabled for MFA will experience common MFA behaviors sufficient to assert the REFEDS MFA profile during WebSSO authentication. The project plan calls for an initial pilot phase, followed by a number phases where different cohorts will be required or may opt-in. During the initial pilot phase, select cohorts will be asked to volunteer. Your mission, should you choose to accept, is to create and evolve the digital policy necessary to achieve the project goals.

Exercise 401.2.1

Create initial MFA application folder set and policy in Grouper

  1. Create app:mfa:mfa_enabled|allow|deny.
  2. Create app:mfa:ref:pilot. This reference group is an access control list (ACL) as opposed to ABAC policy.
  3. Add app:mfa:ref:pilot to app:mfa:mfa_enabled_allow.

Exercise 401.2.2

Establish an eduPersonEntitlement value to signal “MFA enabled”

We will assign a unique eduPersonEntitilement (ePE) value to LDAP accounts that are MFA enabled. We choose the value http://tier.internet2.edu/mfa/enabled.

There are 2 steps to accomplish this:

  1. Assign PSPNG provision_to attribute (attribute def provision_to_def) to app:mfa:mfa_enabled with a value of pspng_entitlements.

  2. Configure PSPNG to provision this attribute.

    grouper-loader.properties
    1
    2
    3
    4
    5
    6
    7
    8
    9
    changeLog.consumer.pspng_entitlements.class = edu.internet2.middleware.grouper.pspng.PspChangelogConsumerShim
    changeLog.consumer.pspng_entitlements.type = edu.internet2.middleware.grouper.pspng.LdapAttributeProvisioner
    changeLog.consumer.pspng_entitlements.quartzCron = 0 * * * * ?
    changeLog.consumer.pspng_entitlements.ldapPoolName = demo
    changeLog.consumer.pspng_entitlements.provisionedAttributeName = eduPersonEntitlement
    changeLog.consumer.pspng_entitlements.provisionedAttributeValueFormat = ${group.name.equalsIgnoreCase('app:mfa:mfa_enabled') ? 'http://tier.internet2.edu/mfa/enabled' : 'urn:mace:example.edu:' + group.extension}
    changeLog.consumer.pspng_entitlements.userSearchBaseDn = ou=people,dc=internet2,dc=edu
    changeLog.consumer.pspng_entitlements.userSearchFilter = uid=${subject.id}
    changeLog.consumer.pspng_entitlements.allProvisionedValuesPrefix=*
    

Exercise 401.2.3

Configure Shibboleth IdP to honor MFA enabled ePE value and assert REFEDS MFA profile

mfa-authn-config.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
        <!-- A Mock MFA provider for this tutorial -->
        <bean id="authn/Gaspo" parent="shibboleth.AuthenticationFlow"
                p:forcedAuthenticationSupported="true"
                p:nonBrowserSupported="false">
            <!--
            The list below should be changed to reflect whatever locally- or
            community-defined values are appropriate to represent MFA. It is
            strongly advised that the value not be specific to Duo or any
            particular technology.
            -->
            <property name="supportedPrincipals">
                <list>
                    <bean parent="shibboleth.SAML2AuthnContextClassRef"
                        c:classRef="https://refeds.org/profile/mfa" />
                    <bean parent="shibboleth.SAML1AuthenticationMethod"
                        c:method="https://refeds.org/profile/mfa" />
                </list>
            </property>
        </bean>
mfa-authn-config.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    <!-- Example script to see if second factor is required. -->
    <bean id="checkSecondFactor" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript"
        p:customObject-ref="shibboleth.AttributeResolverService">
        <constructor-arg>
            <value>
            <![CDATA[
                nextFlow = null;
                // Go straight to second factor if we have to, or set up for an attribute lookup first.
                authCtx = input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");
                mfaCtx = authCtx.getSubcontext("net.shibboleth.idp.authn.context.MultiFactorAuthenticationContext");
                if (mfaCtx.isAcceptable()) {
                    // Attribute check is required to decide if first factor alone is enough.
                    resCtx = input.getSubcontext(
                        "net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext", true);
                    // Look up the username using a standard function.
                    usernameLookupStrategyClass
                        = Java.type("net.shibboleth.idp.session.context.navigate.CanonicalUsernameLookupStrategy");
                    usernameLookupStrategy = new usernameLookupStrategyClass();
                    resCtx.setPrincipal(usernameLookupStrategy.apply(input));
                    resCtx.getRequestedIdPAttributeNames().add("eduPersonEntitlement");
                    resCtx.resolveAttributes(custom);
                    // Check for an attribute that authorizes use of first factor.
                    attribute = resCtx.getResolvedIdPAttributes().get("eduPersonEntitlement");
                    valueType =  Java.type("net.shibboleth.idp.attribute.StringAttributeValue");
                    if (attribute != null && attribute.getValues().contains(new valueType("http://tier.internet2.edu/mfa/enabled"))) {
                        nextFlow = "authn/Gaspo";
                    }
                    input.removeSubcontext(resCtx);   // cleanup
                }
                nextFlow;   // pass control to second factor or end with the first
            ]]>
            </value>
        </constructor-arg>
    </bean>

Now have a working MFA policy. Adding new volunteers to the pilot is as easy as adding members to the pilot group. The next rollout phase calls for onboarding select departments, but allow for exceptions.

Exercise 401.2.4

Onboard select departments, but allow for exceptions

  1. Add ref:dept:its to app:mfa:mfa_enabled_allow.

  2. Add app:mfa:ref:mfa_bypass to app:mfa:mfa_enabled_deny. Add [NetID] to mfa_bypass to exclude from mfa_enabled.

  3. Athletics departement

    • You don’t have a reference group, but you were provided a list of subject IDs:

      Athletics Department
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      ahenderson36
      amorrison42
      bsmith65
      cthompson28
      janderson13
      jdavis4
      jlangenberg100
      jprice108
      jvales117
      ldavis5
      mgrady137
      mmartinez133
      nscott103
      pthompson61
      rdavis16
      
    • Import the list as a temporary app-specific reference group.

    • Add this reference group to mfa_enabled_allow.

The MFA pilot is going well when the institution is hit with some direct deposit fraud. Mandate comes from leadership to add some required cohorts. The new policy is “any non-faculty who has access to sensitive data (i.e. Banner INB) must have mfa enabled”. The new policy should be active within two days.

Exercise 401.2.5

Update policy to include all non-faculty employees who have access to sensitive data in Banner

The Banner support team provides a list of NetIDs to satisfy the “non-faculty who have access to sensitive data in Banner” part of the policy.

  1. Create app:mfa:ref:NonFacultyBannerINB and import list of NetIDs.

    agasper508
    agasper678
    alopez899
    aprice362
    agrady791
    
  2. Add NonFacultyBannerINB to app:mfa:mfa_enabled_allow. Edit the start date for this group to be in the future.

  3. Use SQL to view memberships enabled in the future.

That’s was easy! Except– the list is not quite right. Some faculty were included for some reason. Help desk calling! Need to remove faculty members.

Exercise 401.2.6

Update policy to include all Banner users except faculty

  1. Create app:mfa:ref:BannerUsersMinusFaculty.
  2. Edit this reference group to make it composite of NonFacultyBannerINB minus ref:faculty.

The new policy is in place and the pilot continues to expand. The next phase calls for any faculty, staff, or student who are not already required to be able to opt-in or out of MFA at their discretion.

Exercise 401.2.7

Allow any faculty, staff, or student to opt-in/out if they are not already required by other policy

  1. Create app:mfa:ref:mfa_opt_in, an opt-in group for individuals who want to join or leave the service.
  2. Add mfa_opt_in to mfa_enabled_allow.
  3. Create a new grouper security group, app:mfa:etc:mfa_opt_in_access|allow|deny.
  4. Add faculty, staff, and student reference groups to app:mfa:etc:mfa_opt_in_access_allow.
  5. Create app:mfa:ref:mfa_required and copy your required members from the mfa_enabled_allow policy to mfa_required.
  6. Add mfa_required to mfa_enabled_allow and remove the redundant members.
  7. Add app:mfa:ref:mfa_required to mfa_opt_in_access_deny.
  8. Configure mfa_opt_in privileges to grant mfa_opt_in_access OptIn and OptOut rights.

Now, subject awhite318 (Amber White) can log in and see the mfa_opt_in group. This subject is able to join or leave at will.

Improving the User Experience

The Grouper UI is sufficient for simple user interaction, but not a great user experience. Another approach is to build a small, web-based application to manage membership directly or via database and grouper loader.

  • Web application maintains a database of NetIDs that have opted in.
  • Grouper loader job imports opt-in members into a reerence group.
  • The web app needs to know what NetIDs are required to use MFA and are therefore ineligible to use the web app. Grouper can provision a 2nd ePE, http://tier.internet2.edu/mfa/required.

Working great! But, accounts that were put in early bypass for some reason now can’t opt-in. It looks like they enabled it, but they get filtered out of mfa_enabled because of the bypass membership. Removing those accounts from bypass puts them in mfa_enabled.

Exercise 401.2.8

Refactor `…:ref:bypass` to accommodate users who opt-in to MFA

  1. Refactor …:ref:bypass to …:basis:mfa_bypass.
  2. Create new …:ref:mfa_bypass_not_opt_in composite (…:basis:mfa_bypass - …:ref:mfa_opt_in).
  3. Add …:ref:mfa_bypass_not_opt_in to app:mfa:mfa_enabled_deny.

Another way might be to use Grouper rules.

Pilot has been a success. Leadership wants all remaining faculty, staff, and students to be enabled by policy.

Exercise 401.2.9

Add all remaining faculty, staff, and students to policy

  1. Add appropriate reference groups to allow policy.
  2. Clean up intermediate policy and application reference groups.
    • Add faculty, staff, and student reference groups to policy.
    • Remove app specific reference and basis groups.

We should now have a fairly clean app policy folder. We were able to update digital policy without affecting service.

Kick back and have a margarita!