Skip to content

Choose Your Own SAML Adventure: A Self-Directed Journey to AWS Identity Federation Mastery

Use SAML attributes to enforce role assumption conditions, a.k.a. MFA-for-SAML (open-source variant)

When you use SAML federation with AWS, the Identity Provider (IdP) is solely responsible for the authentication and coarse grained authorization of users. As we've covered already during this workshop, this model is tremendously beneficial in a large number of ways. However, it does preclude the use of a small number of AWS features, most notably the ability to use AWS Multi-Factor Authentication. Many customers use AWS MFA as a simple best practice that adds an extra layer of protection on top of username and password authentication, and enjoy the benefits of this higher level of assurance. What's important to note however, is that what's precluded is only the use of AWS MFA, not MFA in general. You can (and should) require the use of your own MFA solution within your IdP, particularly for the set of users who are authorized for highly privileged AWS roles. AWS is then able to consume this additional context in the form of additional SAML assertion attributes, and use these attributes as required conditions for IAM role assumption. These two elements, customer side MFA & AWS role assumption conditions, combine to give you the desired elevated level of assurance.

In this advanced use case, you will walk through how to implement additional role assumption conditions within AWS that can be used to ensure that these types of conditions (e.g. multi-factor authentication) have been met. Since the specific MFA configurations are highly dependent on your choice of MFA provider and are time prohibitive, this exercise uses the LDAP attribute eduPersonAssurance as a surrogate for an actual MFA implementation. This attribute allows us to focus on the configurations necessary within the IdP and the AWS IAM role assumption conditions. However, towards the conclusion of this use case, we'll show you the specific modifications necessary to adapt what you've learned to an actual MFA implementation. As a side benefit of this surrogate approach, we're teaching you a more generic implementation of the concept; how to pass additional information about your users through the IdP and use that information within AWS.

Prerequisites

The following list identifies the prerequisites for this exercise. If you have not completed these tasks, please take the time to do so now.

  • Successful completion of all steps from the open source version of the first hour exercise. If you are having trouble with the first hour exercise, please seek help from one of the AWS workshop facilitators.

Configuring the MFA surrogate attribute

As described above, you will use the LDAP attribute eduPersonAssurance as a surrogate for MFA authentication during this exercise. You will set this attribute on both federated users, bob and alice, as follows:

  • bob == LowTrust (representing a user authenticated with username and password only).
  • alice == HighTrust (representing a user authenticated with a customer MFA solution).

Login via SSH

To get started, log in using SSH to your Shibboleth instance using the public IP address that you noted in the initial exercise. See directions for how to use SSH according to your client platform.

Connect via SSH

Load surrogate attribute

To automate the steps required to insert this additional LDAP attribute, we've created an LDAP Data Interchange Format (LDIF) file for you with the following contents.

dn: uid=bob,ou=accounts,dc=example,dc=com
changetype: modify
add: eduPersonAssurance
eduPersonAssurance: LowTrust

dn: uid=alice,ou=accounts,dc=example,dc=com
changetype: modify
add: eduPersonAssurance
eduPersonAssurance: HighTrust

Don't worry about the LDIF syntax if you aren't familiar with it, just note the values for each of bob and alice's account. Then, load these attributes using the command sequence, as shown in the following screenshot.

cd automation/
./loadedupersonassurance.sh

Load LDIF

Inspect the new attributes

Before moving on, let's inspect bob's object in the directory to see the results of the load operation above. Use the following ldapsearch command to inspect bob's object in the directory.

ldapsearch -D "cn=Manager,dc=example,dc=com" -W -b "dc=example,dc=com" -H ldap://localhost:389 '(uid=bob)'

Note: Recall that the password for cn=Manager,dc=example,dc=com has been set to ILov3F3d3ration!1.

Load LDIF

You can see the new eduPersonAssurance attribute is now part of bob's object in OpenLDAP.

Note: In addition to the relevant context of this attribute, it is also important to note that we've chosen eduPersonAssurance due to its inclusion within the set of assertion attributes that specifically map to AWS Trust Policy Context Keys. The use of this mapping will become clearer as you progress through the use case.

If time permits, you may also wish to review the overarching eduPerson object class, which contains some additional attribute definitions that you might find useful.

Update Shibboleth Configuration

Now that you've modified the backend directory, there are a couple of modifications required within the Shibboleth configuration. These configurations are necessary to query, translate, and send this additional attribute to AWS through the SAML assertion.

Backup existing configurations

To begin, use the following command sequence to quickly backup your existing configurations.

sudo su -
cd /opt/shibboleth-idp/conf/
cp attribute-resolver-ldap.xml attribute-resolver-ldap.xml.assumerolecond
cp attribute-filter.xml attribute-filter.xml.assumerolecond
cp ldap.properties ldap.properties.assumerolecond

Update ldap.properties

Next, we need to tell Shibboleth to include the eduPersonAssurance attribute in the overall set of attributes retrieved from OpenLDAP. Use your favorite text editor to modify the ldap.properties file where this configuration is stored.

vim ldap.properties

Search for idp.attribute.resolver.LDAP.returnAttributes, and add eduPersonAssurance to the end of the list, as shown in the following screenshot.

Adjust ldap.properties

Update attribute-resolver.xml

Next, we need to tell Shibboleth how to resolve this backend attribute into a SAML-specific attribute. Use your favorite text editor to modify the attribute-resolver.xml file where this configuration is defined.

vim attribute-resolver.xml

Search for the attribute definitions you inserted in the initial exercise. Immediately after the attribute definition for awsRoleSessionName, add the following definition.

<resolver:AttributeDefinition xsi:type="ad:Simple" id="eduPersonAssurance" sourceAttributeID="eduPersonAssurance">
    <resolver:Dependency ref="myLDAP"/>
    <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" friendlyName="eduPersonAssurance" />
</resolver:AttributeDefinition>

Adjust attribute-resolver.xml

This definition maps the source attribute of eduPersonAssurance into the SAML specific URI for this attribute. Refer to the documentation for information regarding the specific URI values that AWS expects.

Update attribute-filter.xml

Finally, we need to tell Shibboleth that it is allowed to send this attribute to AWS. Use your favorite text editor to modify the attribute-filter.xml file where this configuration is defined.

vim attribute-filter.xml

Find the AttributeFilterPolicy element named releaseAWSToAWS that you configured in the initial exercise. Add the following definition after awsRoleSessionName, but inside the close of the AttributeFilterPolicy element, as shown in the following screenshot.

<AttributeRule attributeID="eduPersonAssurance">
    <PermitValueRule xsi:type="ANY"/>
</AttributeRule>

Adjust attribute-filter.xml

Restart Tomcat

Restart Tomcat to ensure that your changes take effect.

service tomcat8 restart

Restart Tomcat

Add additional trust policy conditions to IAM roles

At this point, you've fully configured Shibboleth to send the additional attribute, eduPersonAssurance, to AWS through the SAML assertion. Now, you will configure additional conditions within the trust policy of the IAM roles for federation that you configured in the initial exercise. In a federated scenario AWS fully trusts the IdP to properly authenticate and authorize the user into a given IAM role, so this configuration principally serves as a defense in depth protection. These conditions firmly ensure that users cannot assume the role if they do not meet the necessary conditions, even if an error in the IdP configuration exists which prevents the multi-factor authentication from occurring.

Start by logging in to the AWS Management Console, and select Identity & Access Management.

AWS Management Console

Choose Roles from the left pane, and then choose the FederationWorkshop-ReadOnly role, as shown in the following screenshot.

AWS Management Console

On the role Summary page, choose the Trust Relationships tab, and then choose Edit Trust Relationships.

AWS Management Console

When the Edit Trust Relationship opens, you will see the default trust policy that was generated during the role creation workflow you performed during the initial exercise. Locate the condition within the policy that specifies that AWS must be the intended audience of the presented SAML assertion. It looks like the following snippet.

"StringEquals": {
  "SAML:aud": "https://signin.aws.amazon.com/saml"
}

Immediately following this condition, add a second condition using the following snippet. This snippet requires that the SAML:eduPersonAssurance trust policy context key is set to HighTrust in the SAML assertion. Be sure to add a comma at the end of line 13 to maintain properly formed json, and then choose Update Trust Policy to save your changes.

"ForAnyValue:StringEquals": {
  "SAML:eduPersonAssurance": "HighTrust"
}

AWS Management Console

Note: When an IAM policy specifies more than one condition, the conditions are evaluated using a logical AND.

Note: These context keys are only available for use within trust policies, and not within the standard permission policies.

Testing

You are now ready to test your enhanced trust policy. To do so, open a new browser window, and open the SAML tracer add on. We'll use SAML tracer to inspect the contents of the SAML assertions as they flow from the IdP to AWS, which allows you to see the results of your configurations and understand the information that AWS is consuming from your identity provider. See the following screenshot for help enabling SAML tracer.

Enable SAML Tracer

With SAML tracer enabled, switch back to the main browser window and enter the IdP initiated login URL for Shibboleth.

https://idp1.example.com:8443/idp/profile/SAML2/Unsolicited/SSO?providerId=urn:amazon:webservices

We'll start by testing the success condition of our configurations, so after Shibboleth returns the login page, log in using alice's credentials.

Note: Recall that alice's password has been set to a random value exposed as an output variable in the 1st hour CloudFormation template.

Shibboleth Login

After you log in, you see the AWS role chooser page. Before making your selection, switch back to the SAML tracer window, and scroll upwards until you find the entry for https://signin.aws.amazon.com/saml. Choose that entry, and select the SAML tab in the lower pane. As you look through the assertion, look for the <saml2:AttributeStatement>. This allows you to see how the configurations you applied above translate into the additional eduPersonAssurance SAML attribute. See the following screenshot for reference.

SAML Tracer

After you've finished inspecting the assertion, switch back to your main browser window, select the FederationWorkshop-ReadOnly role within your main AWS account and choose Sign In.

AWS role chooser page

Because alice was configured for High Trust, she can assume the role.

AWS Management Console

Now let's test the deny condition of our configurations. Open another private browser window, and enter the IdP initiated login URL for Shibboleth.

https://idp1.example.com:8443/idp/profile/SAML2/Unsolicited/SSO?providerId=urn:amazon:webservices

After Shibboleth returns the login page, log in using bob's credentials.

Note: Recall that bob's password has been set to a random value exposed as an output variable in the 1st hour CloudFormation template.

Shibboleth Login

After you log in, you see the AWS role chooser page. Select the FederationWorkshop-ReadOnly role within your main AWS account and choose Sign In. Because you configured Bob for Low Trust, he does not meet the eduPersonAssurance condition and receives a not authorized message, as shown in the following screenshot.

AWS role chooser page

Adapting for true MFA

After you've implemented the configurations above, adapting this pattern for use with an actual MFA solution is relatively straight forward. First, you must configure your IdP to perform multi-factor authentication, using the MFA solution of your choice. This process is dependent on your choice of IdP & MFA provider. Refer to the appropriate product documentation for instructions. For Shibboleth, each authentication method is referred to as an authentication flow. During the configuration of an authentication flow, the IdP administrator defines their desired definition of the PrincipalAuthenticationMethod attribute. In practice, this value is typically set using standard URIs, although this is not specifically required.

Once these steps have been performed, change attribute-resolver.xml so eduPersonAssurance is populated using the PrincipalAuthenticationMethod instead of the equivalent ldap attribute, as shown in the following snippet.

<resolver:AttributeDefinition xsi:type="PrincipalAuthenticationMethod" xmlns="urn:mace:shibboleth:2.0:resolver:ad" id="eduPersonAssurance">
            <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" friendlyName="eduPersonAssurance" />
</resolver:AttributeDefinition>

Next, you need to adjust the IAM role trust policy. Update the required value for the SAML:eduPersonAssurance context key according to the value that's being passed from Shibboleth. In the following example, Shibboleth is passing the standard URI for a time based token, urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken.

"ForAnyValue:StringEquals": {
  "SAML:eduPersonAssurance": "urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken"
}

Finally, test out your new configuration, using SAML tracer to help ensure that your assertions are properly formed in both the success and deny conditions.

Key take-aways

In summary, there are three key take-aways from this use case:

  • AWS provides a wide range of SAML attributes that are mapped to AWS trust policy context keys. You can use these keys to provide additional conditions for role assumption according to your requirements.
  • These additional attributes are configured and populated within your IdP and consumed by AWS through the SAML assertion.
  • To implement MFA-for-SAML, consider mapping the eduPersonAssurance attribute to the principal authentication method, and use standard URIs within your trust policy conditions.

Exercise complete

Congratulations! You have successfully completed the use SAML attributes to enforce role assumption conditions (also known as MFA-for-SAML) advanced use case.

With this use case complete, you are now ready to continue your journey through more of the advanced use cases. To continue, return to the index of advanced use cases.