Enabling Federation to AWS Using Windows Active Directory, ADFS, and SAML 2.0

At this year’s re:Invent I had the opportunity to present on the topic of delegating access to your AWS environment. One use case I demonstrated was enterprise federation to AWS using Windows Active Directory (AD), Active Directory Federation Services (ADFS) 2.0, and SAML (Security Assertion Markup Language) 2.0. The presentation must have struck a nerve, because a number of folks approached me afterwards and asked me if I could publish my configuration—hence the inspiration for this post.

In this post I describe the use case for enterprise federation, describe how the integration between ADFS and AWS works, and then provide the setup details that I used for my re:Invent demo. If you missed my session and you’re interested in hearing my talk, you can catch the recording or view my slides

Background

AWS recently added support for SAML, an open standard used by many identity providers. This new feature enables federated single sign-on (SSO), which lets users sign into the AWS Management Console or make programmatic calls to AWS APIs by using assertions from a SAML-compliant identity provider (IdP) like ADFS. Many of you are using Windows AD for your corporate directory. And since Windows Server includes ADFS, it makes sense that you might use ADFS as your IdP. That's one reason I used Windows AD with ADFS as one of my re:Invent demos.

To set up my domain, I used Amazon EC2 because that made it easy to access the domain from anywhere. My EC2 instance used Windows Server 2008 R2 running Internet Information Server (IIS), AD, and ADFS. If you want to do the same, I encourage you to use a nifty CloudFormation template that creates a Windows instance and sets up a domain for you.

How Integration Between AD FS and AWS Works

Before we get too far into the configuration details, let’s walk through how this all works.

 

  1. The flow is initiated when a user (let’s call him Bob) browses to the ADFS sample site (https://Fully.Qualified.Domain.Name.Here/adfs/ls/IdpInitiatedSignOn.aspx) inside his domain. When you install ADFS, you get a new virtual directory named adfs for your default website, which includes this page
  2. The sign-on page authenticates Bob against AD. Depending on the browser Bob is using, he might be prompted for his AD username and password.
  3. Bob’s browser receives a SAML assertion in the form of an authentication response from ADFS.
  4. Bob’s browser posts the SAML assertion to the AWS sign-in endpoint for SAML (https://signin.aws.amazon.com/saml). Behind the scenes, sign-in uses the AssumeRoleWithSAML API to request temporary security credentials and then constructs a sign-in URL for the AWS Management Console.
  5. Bob’s browser receives the sign-in URL and is redirected to the console.

From Bob’s perspective, the process happens transparently. He starts at an internal web site and ends up at the AWS Management Console, without ever having to supply any AWS credentials.

Now that we understand how it works, let’s take a look at setting it all up.

BTW this post is fairly long. The next couple sections cover installing and configuring ADFS. If you already have ADFS in your environment, you may want to skip ahead to the Configuring AWS section.

Configuring Active Directory

If you want follow along with my description, you’re going to need a Windows domain. If you don’t already have one, I recommend that you take advantage of the CloudFormation template I mentioned earlier to quickly launch an Amazon EC2 Windows instance as a Windows AD domain controller. For demonstration purposes, I used a single user (Bob) who is a member of two AD groups (AWS-Production and AWS-Dev) and a service account (ADFSSVC) used by ADFS. Note that the names of the AD groups both start with AWS-. This is significant, because Bob's permission to sign in to AWS will be based on a match of group names that start with AWS-, as I'll explain later.

Note If you follow along with the instructions, make sure you use exactly the same names we do for users, AD groups, and IAM roles, including  uppercase and lowercase letters. 

Perform the following in your domain:

  1. Create two AD Groups named AWS-Production and AWS-Dev.
  2. Create a user named Bob
  3. Give Bob an email address (e.g., bob@example.com).
  4. Add Bob to the AWS-Production and AWS-Dev groups.
  5. Create another user named ADFSSVC. This account will be used as the ADFS service account later on.

Installing ADFS

With my accounts and groups set up, I moved on to installing ADFS. The Windows Server 2008 R2 I used came with an older version of ADFS. I skipped installing that version and instead downloaded ADFS 2.0 from http://www.microsoft.com/en-us/download/details.aspx?id=10909. After downloading the package, you launch the ADFS setup wizard by double-clicking AdfsSetup.exe. I set up my environment as a federation server using the default settings. In other words, I made no special settings. The screenshots show the process.

 

 

 

Configuring ADFS

The next step is to configure ADFS. During setup, I checked the Start the AD FS 2.0 Management snap-in when this wizard closes box, so the window loaded after I clicked Finish. If you don’t check that box during setup, you can get to the window from Start > All Programs > Administration Tools > AD FS 2.0 Management. When ADFS is launched, it looks like this:

 

To launch the configuration wizard, you click AD FS 2.0 Federation Server Configuration Wizard. If you want to follow along with my configuration, do this:

1.   Select Create a new Federation Service.

 

 

2.  Select New federation server farm.

 

3.   Select an SSL certificate. On my instance, I had an existing certificate I could use. If you don’t have a certificate, you can create a self-signed certificate using IIS. Self-signed certificates are convenient for testing and development. For production use, you’ll want to use a certificate from a trusted certificate authority (CA).

 

4.   Remember the service account I mentioned earlier? This is where you use it.

 

5.  Almost there – just need to confirm your settings and click Next.

 

6.  Nothing left but to click Close to finish.

If all goes well you get a report with all successful configurations. If so, skip ahead to the Configuring AWS section.

 

During my testing, I went through this wizard on several different Windows servers and didn’t always have 100% success. In some cases I encountered the following error message:

 

It turns out this is a known issue that can be fixed by running the following at the command line. (Make sure you run the command window as an administrator.)

setspn -a host/localhost adfssvc

Note that is the name of the service account I used.

If the command is successful, you see output like this:

Registering ServicePrincipalNames for 
CN=ADFSSVC,CN=Users,DC=mydomain,DC=aws,DC=amazon,DC=com     
host/localhost

 

Configuring AWS

You've finished configuring AD FS. The next step is to configure the AWS end of things. To do this, I used the AWS Management Console.

The first step is to create a SAML provider. If you’ve never done this, I recommend taking a look at the IAM user guide. Before you create a SAML provider, you need to download the SAML metadata document for your ADFS federation server. By default, you can download it from following address:

https://<yourservername>/FederationMetadata/2007-06/FederationMetadata.xml

I named my SAML provider ADFS. When you have the SAML metadata document, you can create the SAML provider in AWS. As part of that process, you upload the metadata document.

When I finished creating the SAML provider, I created two IAM roles. Once again the IAM documentation has a great walkthrough of these steps, so I won’t repeat them here. I created two roles using the Grant Web Single Sign-On (WebSSO) access to SAML providers role wizard template and specified the ADFS SAML provider that I just created. I named the two roles ADFS-Production and ADFS-Dev. Do these names look familiar? They should. They are the complement to the AD groups created earlier. During the SAML authentication process in AWS, these IAM roles will be matched by name to the AD groups (AWS-Production and AWS-Dev) via ADFS claim rules.

Note: Remember that if you're following along with this description, you need to use exactly the same names that we use. Make sure that you name the IAM roles ADFS-Production and ADFS-Dev.

Find the ARNs for the SAML provider and for the roles that you created and record them. You'll need the ARNs later when you configure claims in the IdP.

That's it for the AWS configuration steps.

 

Configuring AWS as a Trusted Relying Party

Federation using SAML requires setting up two-way trust. In the preceding section I created a SAML provider and some IAM roles. This is one half of the trust relationship, where the ADFS server is trusted as an identity provider. Similarly, ADFS has to be configured to trust AWS as a relying party. I configured this by returning to the AD FS Management Console. To recreate my setup, perform the following:

1.   From the ADFS Management Console, right-click ADFS 2.0 and select Add Relying Party Trust.

 

2.  In the Add Relying Party Trust Wizard, click Start.

 

3.  Check Import data about the relying party published online or on a local network, enter https://signin.aws.amazon.com/static/saml-metadata.xml, and then click Next. The metadata XML file is a standard SAML metadata document that describes AWS as a relying party.

 

4.  Set the display name for the relying party and then click Next.

 

5.  Choose your authorization rules. For my scenario, I chose Permit all users to access this relying party. When you're done, click Next.

 

6.   Review your settings and then click Next.

 

7.  Check Open the Edit Claim Rules dialog for this relying part trust when the wizard closes and then click Close

 

You’re done configuring AWS as a relying party.

 

Configuring Claim Rules for the AWS Relying Party

In these steps we’re going to add the claim rules so that the elements AWS requires and ADFS doesn't provide by default (NameId, RoleSessionName, and Roles) are added to the SAML authentication response. If you forgot to check the box to launch the claim rule dialog, right-click on the relying party (in this case Amazon Web Services) and then click Edit Claim Rules.

 

Here are the steps I used to create the claim rules for NameId, RoleSessionName, and Roles.

Adding NameId

1.  In the Edit Claim Rules for <relying party> dialog box, click Add Rule.

 

2.  Select Transform an Incoming Claim and then click Next.

 

3.  Use the following settings:
a.  Claim rule name: NameId
b.  Incoming claim type: Windows Account Name
c.  Outgoing claim type: Name ID
d. Outgoing name ID format: Persistent Identifier
e. Pass through all claim values: checked
 
 
4.  Click Finish.
 
Adding a RoleSessionName
 
1.   Click Add Rule
2.   In the Claim rule template list, select Send LDAP Attributes as Claims.
 
3.  Use the following settings:
Claim rule name: RoleSessionName
Attribute store: Active Directory
LDAP Attribute: E-Mail-Addresses
Outgoing Claim Type: https://aws.amazon.com/SAML/Attributes/RoleSessionName 
 
 

4. Click Finish

Adding Role Attributes

I’ll pause here to provide a little more context because for these steps it might not be as obvious what's going on. Unlike the two previous claims, here I used custom rules to send role attributes. This is done by retrieving all the authenticated user’s AD groups and then matching the groups that start with to IAM roles of a similar name. I used the names of these groups to create Amazon Resource Names (ARNs) of IAM roles in my AWS account (i.e., those that start with AWS-).

Sending role attributes required two custom rules. The first rule retrieves all the authenticated user’s AD group memberships and the second rule performs the transformation to the roles claim. Here’s how I did it.

1.  Click Add Rule.
2.  In the Claim rule template list, select Send Claims Using a Custom Rule and then click Next.

 

3. For Claim Rule Name, select Get AD Groups, and then in Custom rule, enter the following:

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"] => add(store = "Active Directory", types = ("http://temp/variable"), query = ";tokenGroups;{0}", param = c.Value);

 

This custom rule uses a script in the claim rule language that retrieves all the groups the authenticated user is a member of and places them into a temporary claim named http://temp/variable. (Think of this as a variable you can access later.) I use this in the next rule to transform the groups into IAM role ARNs.

4.  Click OK.
5.  Click Add Rule.
6.  Repeat the preceding steps, but this time enter Roles for Claim rule name and use the following script:
c:[Type == "http://temp/variable", Value =~ "(?i)^AWS-"] => issue(Type = "https://aws.amazon.com/SAML/Attributes/Role", Value = RegExReplace(c.Value, "AWS-", "arn:aws:iam::123456789012:saml-provider/ADFS,arn:aws:iam::123456789012:role/ADFS-"));

 

This rule uses a custom script to get all the groups from the temporary claim () and then uses the name of the group to create the principal/role pair, which has this format:

ARN of SAML provider,ARN of role to assume

In my example, it comes out this way:

arn:aws:iam:123456789012:saml-provider/ADFS,arn:aws:iam:123456789012:role/ADFS-

In the example, I used an account number of 123456789012. Make sure you change this to your own AWS account.

7.  Click OK.

Testing the configuration

Setup is complete. If you're using any browser except Chrome, you're ready to test—skip ahead to the testing steps.

If you're using Chrome as your browser, you need to configure the browser to work with AD FS. The default AD FS site uses a feature called Extended Protection that by default isn't compatible with Chrome. However, it’s easy to turn off extended protection for the ADFS->LS website.

1.  In Windows Server, select Start > Administrative Tools > IIS Manager.
2.  Expand: <server-name>, Sites, Default Web Site, and adfs.
3.  Select the ls application and double-click Authentication.
4.  Select Windows Authentication and select Advanced Settings...
5   Set Extended Protection to Off and then click OK.
6.  Restart ADFS and IIS by running the following as an administrator at the command line:
 
a.  IISReset
b.  Net Stop "AD FS 2.0 Windows Service"
c.  Net Start "AD FS 2.0 Windows Service"  

Testing steps

1.  In your domain, browse to the following address:  https://localhost/adfs/ls/IdpInitiatedSignOn.aspx

If you're using a locally signed certificate from IIS, you might get a certificate warning.

2.  Select Sign in to one of the following sites, select Amazon Web Services from the list, and then click Continue to Sign In.

 

3.  If prompted, enter in a username and password (remember to use Bob’s account). You are redirected to the Amazon Web Services Sign-In page.

4.  Select a role and then click Sign In. (If you are mapped to only a single IAM role, you skip the role selection step and are automatically signed into the AWS Management Console.)

 

You see Bob has signed in.

 

I’m interested in hearing your feedback on this. Feel free to post comments below or start a thread in the Identity and Access Management forum.

-Jeff

Addendum:

Ever since I published this blog post, some readers have asked how to configure the AD FS claims using multiple AWS accounts. Those of you with multiple AWS accounts can leverage AD FS and SSO without adding claim rules for each account. Though there may be other ways to do this, one approach recommended by AWS Senior Solutions Architect Jamie Butler is to use Regex and a common Active Directory security group naming convention. Then, AD FS can provide cross-account authentication for an entire enterprise. Jamie's solution follows.

When using this approach, your security group naming convention must start with an identifier (for example, AWS-). This will distinguish your AWS groups from others within the organization. Next, include the 12-digit AWS account number. Finally, add the matching role name within the AWS account. Here is an example.

Next, update the Roles AD FS claim rule that you created earlier, by using the following code.

c:[Type == "http://temp/variable", Value =~ "(?i)^AWS-([^d]{12})"] => issue(Type = "https://aws.amazon.com/SAML/Attributes/Role", Value = RegExReplace(c.Value, "AWS-([^d]{12})-", "arn:aws:iam::$1:saml-provider/ADFS,arn:aws:iam::$1:role/"));

This new claim rule limits scope to only Active Directory security groups that begin with AWS- and any twelve-digit number. The claim rule then constructs the SAML assertion in the proper format using the AWS account number and the role name from the Active Directory group name. All AWS accounts must be configured with the same IdP name (in this case ADFS) as described in the “Configuring AWS” section earlier in this post.

Any users with membership in the Active Directory security group will now be able to authenticate to AWS using their Active Directory credentials and assume the matching AWS role. If a user is associated with multiple Active Directory groups and AWS accounts, they will see a list of roles by AWS account and will have the option to choose which role to assume.

Know of a better way? Please add a comment to this post.

** If you would like to implement federated API and CLI access using SAML 2.0 and ADFS, check out this blog post from AWS Senior IT Transformation Consultant Quint Van Deman.

Comments