Update: In November 2019 AWS introduced support for integration between Azure AD and AWS SSO. The integration offers a ton more features, including out of the box support for multiple AWS accounts. I highly recommend you go that route if you’re looking to integrate the two platforms. Check out my series on the new integration here.
We’ve reached the end of the road for my series on integrating Azure Active Directory (Azure AD) and Amazon Web Services (AWS) for single sign-on and role management. In part 1 I walked through the many reasons the integration is worth looking at if your organization is consuming both clouds. In part 2 I described the lab I used to for this series, described the different way application identities (service accounts for those of you in the Microsoft space) are handled in Active Directory Domain Services versus Azure AD, and walked through what a typical application identity looks like in Azure AD. In part 3 I walked through a portion of the configuration steps, did a deep dive into the Azure AD and AWS federation metadata, examined a SAML assertion, and configured the AWS end of the federated trust through the AWS Management Console. This included creation of an identity provider representing the Azure AD tenant and creation of a new IAM role for users within the Azure AD tenant to assert.
In this final post I’ll cover the remainder of the configuration, describe the “provisioning” capabilities of Azure AD in this integration, and pointing out some of the issues with the recommended steps in the Microsoft tutorial.
Before I continue with the configuration, let me cover what I’ve done so far.
- Part 2
- Added the AWS application from the Azure AD Application Gallery through the Azure Portal.
- Part 3
- Assigned an Azure Active Directory user to the application through the Azure Portal.
- Configured the Azure AD to pass the Role and RoleSessionName claims through the Azure Portal.
- Created the SAML identity provider representing Azure AD in the AWS Management Console.
- Created an AWS IAM Role and associated it with the identity provider representing Azure AD in the AWS Management Console.
At this point JoG users can assert their identity to their heart’s content but we don’t have a list of what AWS IAM roles stored in Azure AD for our users to assert. So how do we assert a role from Azure AD if the listing of the roles exists in AWS? The wonderful concept of application programmatic interfaces (APIs) swoops in and saves the day. Don’t get me wrong, if you hate yourself you can certainly provision them manually by modifying the application manifest file every time a new role is created or deleted. However, there is an easier route of having Azure AD pick up those roles directly from AWS on an automated schedule. How does this work? Well nothing works better than demonstrating how the roles can be queried from the AWS API.
The AWS SDK for .NET makes querying the API incredibly easy. We’re not stuck worrying about assembling the request and signing it. As you can see below the script is six lines of code in PowerShell.
The result is a listing of the roles configured in AWS which includes the AzureADEC2Admins role I created earlier. This example demonstrates the power a robust API brings to the table when integrating cloud services.
When Microsoft speaks of provisioning in regards to the AWS integration, they are talking about provisioning the roles defined in AWS to the the application manifest file in Azure AD. This provides us with the ability to assign the roles from within the Azure Portal as we’ll see later. This differs from many of the Azure AD integrations I’ve observed in the past where it will provision a record for the user into the software as a service (SaaS) offering. Below is a simple diagram of the provisioning process.
To do support provisioning we need to navigate to the AWS Management Console, open the Services Menu, and select IAM. We then select Users and hit the Add User button. I named the user AzureAD, gave it programmatic access type, and attached the IAMReadOnlyAccess policy. AWS then presented me with the access key ID and secret access key I’ll need to provide to Azure AD. Yes, we are going to follow security best practices and provide the account with the minimum rights and permissions it needs to provide the functionality. The Microsoft tutorial instructs you to generate the credentials under the context of the AWS administrator effectively giving the application full rights to the AWS account. No Microsoft, just no.
I next bounce back to the Azure portal and to the AWS application configuration. From here I select the Provisioning option, switch the drop-down box to Automatic, and plug the access key ID into the clientsecret field and the secret access key into the secret token field. A quick test connection shows success and I then save the configuration. Note that you must first save the configuration before you can turn on the synchronization.
After the screen refreshes I move down to the Settings section and turn the Provisioning Status to On and set the Scope to Sync only assigned users and groups (kind of a moot point for this, but oh well). I then Save the configuration once again and give it about 10 minutes to pull down the roles.
I then navigate back to the Users and Groups section and edit the Rick Sanchez assignment. Hitting the role option now shows me the AzureADEC2Admins role I configured in AWS IAM.
Let’s take another look at the service principle representing the AWS application in PowerShell. Using the Azure AD PowerShell cmdlets I referenced in entry 2 we connect to Azure AD and run the cmdlet Get-AzureADServicePrincipal which when run shows the manifest has been updated to include the newly synchronized application role.
We’ve configured the SAML trust on both ends, defined the necessary attributes, setup synchronization, and assigned Rick Sanchez an IAM role. In a moment we’ll demonstrate all of the pieces coming together.
Before I wrap it up, I want to quickly mention a few issues I ran into with this integration that seemed to resolve themselves without any intervention.
- Up to a few nights ago I was unable to get the Provisioning piece working. I’m not putting it past user error (this is me we’re talking about) but I tried numerous times and failed but was successful a few nights ago. I also noticed from some recent comments in the Microsoft tutorial people complaining of similar errors. Maybe something broke for a bit?
- The value of the audience attribute in the audienceRestriction section of the SAML assertion generated by Azure AD doesn’t match the identifier within the AWS federation metadata. Azure AD inserts some garbage looking audience value by default which was causing the assertions to be rejected by AWS. After setting the identifier to the value of urn:amazon:webservices as referenced in the AWS federation metadata the assertion was consumed without issue. I saw similar complaints in the Microsoft tutorial so I’m fairly confident this wasn’t just my issue.The story gets a bit stranger. I wanted to demonstrate the behavior for this series by removing the identifier I had previously added. Oddly enough the assertion was consumed without issue by AWS. I verified using Fiddler that the audience value was populated with that garbage entry. Either way, I would err on the side of caution and would recommend populating the identifier with the entry referenced in the AWS metadata as seen below.
The last thing I want to point out is the Microsoft tutorial states that you are required to create the users in AWS prior to asserting their identity. This is inaccurate as AWS does not require a user record to be pre-created in AWS. This is different from a majority (if not all) of the SaaS integrations I’ve done in the past so this surprised me as well. Either way, it’s not required which is a nice benefit if you’ve ever had to deal with the challenging of managing the identify lifecycle across cloud offerings.
Let’s wrap up this series by having Rick Sanchez log into the AWS Management Console and shutdown an EC2 instance. Here I have logged into the Windows 10 machine named CLIENT running in Azure. We navigate to https://myapps.microsoft.com and log into Azure AD as Rick Sanchez. We then hit the Amazon Web Services icon and are seamless logged into the AWS Management Console.
Examining the assertion in Fiddler shows the Role and RoleSessionName claims in the assertion.
Navigating to the EC2 Dashboard displays the instance I prepared earlier using my primary account. Rick has full rights over administration of the instance for activities such as starting and starting the instance. After successfully terminating the instance I log into the AWS Management Console as my primary AWS account and go to CloudTrail and see the log entries recording the activities of Rick Sanchez.
With that let’s cover some key pieces of information to draw from the series.
- The Azure AD and AWS integration differs from most SaaS integrations I’ve done when it comes to user provisioning. Most of the time a user record must exist prior to the user authenticating. There are a growing number of SaaS providers provisioning upon successful authentication as provisioning challenges grow to further consumption of cloud services, but they are still few and far between. AWS does a solid job with eliminating the pain of pre-provisioning users.
- The concept of associating roles with specific identity providers is really neat on Amazon’s part. It allows the customer to manage permissions and associate those permissions with roles in AWS, but delegate the right on a per identity provider basis to assert a specific set of roles.
- Microsoft’s definition of provisioning in this integration is pulling a listing of roles from AWS and making them configurable in the Azure Portal.
- The AWS API is solid and quite easy to leverage when using the AWS SDKs. I would like to see AWS switch from what seems to be proprietary method of application access to OAuth to become more aligned with the rest of the industry.
- Don’t trust vendors to make everything point and click. Take the time to understand what’s going on in the background. In a SAML integration such as this, a quick review of the metadata can save you a lot of headaches when troubleshooting issues.
I learned a ton about AWS over these past few weeks and also got some good deep dive time into Azure AD which I haven’t had time for in a while. Hopefully you found this series valuable and learned a thing or two yourself.
In my next series I plan on writing a simple application to consume the Cognito service offered by AWS. For those of you more familiar with the Microsoft side of the fence, it’s similar to Azure AD B2C but with some unique features Microsoft hasn’t put in place yet making a great option to solve those B2C identity woes.
Thanks and have a wonderful holiday!