Entra ID – Deep Dive – Workload Identity Federation – Bonus

Entra ID – Deep Dive – Workload Identity Federation – Bonus

This is part of my series on Microsoft Entra ID:

  1. Entra ID – Deep Dive – The Basics – Part 1
  2. Entra ID – Deep Dive – Protocol Primer – Part 2
  3. Entra ID – Deep Dive – Entra ID Authentication – Part 3
  4. Entra ID – Deep Dive – Workload Identity Federation – Bonus

Hello again!

I’ve been on an identity kick lately given all the chatter around IAM (identity access management) that has popped up as the industry tries to figure out how the hell they’re going to handle the disruption to existing IAM systems with the introduction of AI agents in the enterprise. This has raised more conversation within my customer base, with cross cloud identity being a hot topic. Recently, a customer asked me about Entra ID’s Workload Identity Federation feature. I hadn’t mucked with the feature much beyond reading a bit of the documentation, but given the increase in cross-cloud conversations and the customer ask, it seemed like the perfect time to do it! Hence this blog post!

Let’s get to it, shall we?

What is the problem this feature solves?

It’s this old dude’s take that the high-level question Entra ID WIF (workload identity federation) seeks to answer is, “How do we effectively allow two systems in different organizational or trust boundaries to communicate while allowing each boundary to retain control of its identity system?” This is not a new problem. If you’ve been around the block for a few decades, you’ve likely built federated solutions like Windows Active Directory trusts or federated trusts with SAML (security assertion markup language). Each of those solutions had similar goals which included things like:

  1. Simplify security by letting each organization be the authority over its human and non-human identities.
  2. Make it easier for the user by not saddling them with 100 identities and passwords to remember.
  3. Reduce costs by keeping avoiding having to build complex systems to maintain all those duplicate identities and the support personnel to manage them.

So yeah, the obvious stuff, right?

As cloud was adopted the problem grew in scale as organizations integrated with CSPs (cloud service providers) and demand around B2B collaboration drastically increased. SAML and OIDC made the human identity problem a small bit easier (notice I said bit, so don’t flame me!) to solve, but the non-human, or the machine, identity problem caused bloat in identities. Systems needed to interact and sometimes these systems were in different boundaries. This could be on-premises, sometimes in AWS, GCP, or Azure. You might have a AWS Lambda pulling data from a Microsoft Cloud API, GCP BigQuery grabbing data from both clouds, Kubernetes cluster pulling data from an Azure Storage Account, or an Azure Data Factory ripping data down from an Amazon S3 bucket. All this cross cloud hoopla meant lots of machine identities and credentials floating around.

The classic way to solve this problem for the AWS to Azure looked something like this:

The classic way to handle cross cloud machine identity resource access

Here, the Lambda would obtain a temporary credential from the AWS STS based on an IAM role it was assigned, pass that credential to AWS Secrets Manager to grab a secret which contain a Entra ID service principal client secret. It would then use that secret to authenticate to Entra ID as the service principal to obtain an access token issued by Entra ID which it would pass to access a blob in Azure Storage.

The above pattern is still incredibly common in enterprises today. It works no doubt, but there is that credential you gotta manage. Its usage has to be monitored, its lifecycle has to be tracked, it has to be rotated in Entra ID and updated in AWS Secrets Manager, it could get compromised by an attacker and used to exfiltrate data from Azure Storage, etc etc. Now scale this by multiple clouds and thousands of applications and you quickly see the challenge.

Years ago some smart folks across the industry came up with the concept of WIF to help address this problem.

You’re on Matt Felton’s blog so you’ll suffer with a Matt Felton explanation. WIF is all about eliminating that static secret and letting the workload provide some type of token issued by a trusted party (identity provider) to prove its identity to the trusting party (relying party). If you’re familiar with federation for user identities this should sound very familiar. Elimination of that static secret is where the money is at. No more operational overhead of managing thousands of secrets which be expire or be compromised.

All of this likely makes sense to you. Let’s take a look at how Microsoft implemented it.

How does Entra ID Workload Identity Federation work?

Before we get into the guts of how this works, it’s important to understand some core Entra ID concepts.

In Entra ID there are three main categories of identity: user identities, device identities, and workload identities. Given the feature is called WIF, you can probably figure out that last category is what we’re concerned with. These are identities that will be associated to some application, script, container, agent, etc. In the Entra world all of these things are represented by the core object class of a service principal. There are many types of service principals in Entra, but the two most relevant to our conversation are the application and managed identity types.

Service principals of type application are machine identities associated with an application resource. If you’re unfamiliar with the differences between a service principal and application resource take a read through my first post in my Entra series for the gory details. The main thing to understand is the application is the “template” representation of an application across all of Entra ID while the service principal is the identity of the application in a specific Entra ID tenant. The application resource (you’ll almost always hear it referred to as the application registration) is responsible for authentication of the application to Entra while the service principal is the associated identity that is granted permissions to do stuff within the tenant.

A service principal of type managed identity is the identity associated with an Azure managed identity. Managed identities are Azure’s version of an AWS IAM Role. Like an AWS IAM Role, the credential for the identity is managed by the CSP (in this case Microsoft) and workloads associated with a managed identity obtain temporary credentials (called access tokens in the Azure world) to access Azure resources.

Entra WIF can be enabled for either of the application resource or the managed identity. My personal take is if your use case is to simply consume Azure resources, create a managed identity representing your app in the other cloud. This way you can slap it in a resource group in some Azure subscription alongside the resources it is consuming or other resources that may be pieces of that application in Azure. If your use case is consuming Azure in addition to other APIs (such as the MS Graph API) that are protected by Entra use an application resource. Using an application resource will give you more visibility across all of Entra that you have some application that is consuming multiple pieces of the Microsoft cloud. You can technically grant access to something like the MS Graph API to a managed identity, but it’s not as intuitive or visible.

Once you determine whether you’re going to use an application resource or managed identity you’ll need to configure Entra ID to trust the external IdP (identity provider) so that when it receives tokens from your workload that were issued by the external IdP it can validate them and issue an access token from Entra. The high level flow looks like the below.

The process works in the following way. The workload obtain an access token from its IdP. For example, this could be the AWS STS, GCP’s authorization server, or another IdP using the SPIFFE (Secure Production Identity Framework for Everyone) standard. Once the token is issued, the workload sends that token to Entra ID which verifies it cryptographically using keys pulled from an endpoint exposed by the IdP. Once verified, Entra ID issues an access token to the workload which it can use to call the Azure service.

If you’re like me, you probably want to see an example. Well lucky for you, I got one!

Entra ID Workload Identity Federation in Action

To demonstrate this feature I’m going to use a managed identity for my workload instead of an application resource because it’s a quicker setup. My use case is I have an EC2 instance in AWS that needs to pull data from a storage account in Azure. My architecture is super basic and pictured below.

Simple lab to demonstrate WIF

The first step in is to setup AWS outbound federation for my AWS account. This will activate the STS’s capability of issuing tokens to external relying parties.

Next, I’ll need to create an AWS IAM Policy which will grant permissions to obtain tokens from the STS for a specific relying party. For that, I crafted the super basic IAM policy below. This policy grants permission to the security principal the policy is associated with to request tokens from the STS with an audience of my Entra tenant. You’ll need the audience set as api://AzureADTokenExchange. For mine, I added my tenant ID to the path to further constrain it. While not required, I slapped some requirements around the token duration and signing algorithm. There are a number of condition keys you can choose from to further constrain the permissions.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:GetWebIdentityToken",
"Resource": "*",
"Condition": {
"ForAllValues:StringEquals": {
"sts:IdentityTokenAudience": "api://AzureADTokenExchange/6c80de31-d5e4-4029-XXXX-XXXXXXXXXXXX"
},
"NumericLessThanEquals": {
"sts:DurationSeconds": 300
},
"StringEquals": {
"sts:SigningAlgorithm": "RS256"
}
}
}
]
}

I then associated this IAM Policy to the IAM role used by my EC2 instance. Once complete, at this stage the AWS account is setup for outbound federation and my EC2 instance has permissions to request a token destined for the my Entra ID tenant.

On the Azure side I created a resource group, storage account with a sample blob, and an UMI (user-assigned managed identity).

The UMI needs to be configured with a federated credential like you see below.

In the issuer URL I put my AWS account STS identifier I got when I setup the outbound federation. The subject identifier I set to the ARN of my IAM role and the audience I matched to the audience I put in the IAM policy.

One thing to note is that there are a maximum of 20 federated credentials per application resource or managed identity. If you have multiple workloads using the same identity on the Azure side, scale issues can come into play. There is a feature called flexible federated identity credentials which allow you to create an expression to match the incoming subject vs the specific subject itself. If you have those scale issues, you’ll want to look at this feature. It’s in preview as of the date of this blog.

Alright, at this point the plumbing is setup and now I need to toss together some code to make the magic happen.

For this I threw together a very basic Python snippet that requests an token from the AWS STS, exchanges it for an access token from Entra, and writes out the content of a blob stored in Azure Storage.

import boto3
import os
import base64
import json
import logging
import sys
from dotenv import load_dotenv
from azure.identity import ClientAssertionCredential
from azure.storage.blob import BlobServiceClient
load_dotenv(override=True)
TENANT_ID = os.getenv("ENTRA_TENANT_ID")
UMI_CLIENT_ID = os.getenv("AZURE_UMI_CLIENT_ID")
BLOB_ACCOUNT_URL = os.getenv("AZURE_BLOB_ACCOUNT_URL")
BLOB_CONTAINER_NAME = os.getenv("AZURE_BLOB_CONTAINER_NAME")
BLOB_NAME = os.getenv("AZURE_BLOB_NAME")
logging.basicConfig(
level=logging.DEBUG,
stream=sys.stdout,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger(__name__)
def print_jwt_claims(jwt: str) -> None:
print('Parsing AWS STS access token')
payload = jwt.split(".")[1]
payload += "=" * (-len(payload) % 4)
claims = json.loads(base64.urlsafe_b64decode(payload))
print(json.dumps(claims, indent=2))
def get_aws_sts_token() -> str:
print('Obtaining access token from AWS STS...')
sts_client = boto3.client('sts', region_name='us-east-1')
response = sts_client.get_web_identity_token(
Audience=[f"api://AzureADTokenExchange/{TENANT_ID}"],
DurationSeconds=300,
SigningAlgorithm='RS256'
)
token = response["WebIdentityToken"]
print_jwt_claims(token)
return token
try:
credential = ClientAssertionCredential(
tenant_id = TENANT_ID,
client_id = UMI_CLIENT_ID,
func = get_aws_sts_token
)
print(f"Contacting storage account {BLOB_ACCOUNT_URL}")
blob_service_client = BlobServiceClient(account_url=BLOB_ACCOUNT_URL,credential=credential)
blob_client = blob_service_client.get_blob_client(container=BLOB_CONTAINER_NAME,blob=BLOB_NAME)
blob_data = blob_client.download_blob().readall()
print(blob_data.decode("utf-8"))
except Exception as e:
print(f"Script failed: {e}")

Looking at the printed output of the script we first see the token generated by the AWS STS.

{
"aud": "api://AzureADTokenExchange/6c80de31-d5e4-4029-XXXX-XXXXXXXXXXXX",
"sub": "arn:aws:iam::XXXXXXXXXXXX:role/Azure-Access",
"https://sts.amazonaws.com/": {
"ec2_instance_source_vpc": "vpc-0a84fd0130401fcf9",
"ec2_role_delivery": "2.0",
"aws_account": "XXXXXXXXXXXX",
"original_session_exp": "2026-08-17T02:39:52Z",
"source_region": "us-east-1",
"ec2_source_instance_arn": "arn:aws:ec2:us-east-1:XXXXXXXXXXXX:instance/i-034a6ea7b8b83cba5",
"principal_id": "arn:aws:iam::XXXXXXXXXXXX:role/Azure-Access",
"ec2_instance_source_private_ipv4": "XX.XX.XX.XX"
},
"iss": "https://a1b2e322-9556-4319-XXXX-XXXXXXXXXXXX.tokens.sts.global.api.aws",
"exp": 1786912687,
"iat": 1786912387,
"jti": "7d6c05a6-10e8-46ab-8f15-6d4c595b55f0"
}

Here we see the audience set to my Entra tenant and the subject set to the ARN of the role associated to the EC2 instance.

The result of the exchange shows the content of the blob proving cross cloud authentication with no static secrets!

End to end the flow went something like this:

I covered the free pieces of WIF for this post. There are some pretty awesome Premium features that require licensing but extend Entra ID functionality like conditional access, identity protection, and privileged access review. The premium features will come with a cost per workload identity per month. My take is that functionality should be reserved for your high risk workloads unless you got cash to burn.

With those lessons learned, it’s a good time to review whether you’ve adopted WIF for your cross-cloud use cases. Less credentials = less pain. In the world that is tech today, I think we are all looking for a little less pain.

See you next post!

Deep Dive into Azure AD and AWS SSO Integration – Part 5

Deep Dive into Azure AD and AWS SSO Integration – Part 5

I’m back yet again with the fifth entry into my series on integrating Azure AD and AWS SSO.  It’s been a journey and the series has covered a lot of ground.  It started with outlining the challenge with the initial integration of Azure AD and AWS using the AWS app in the Azure Marketplace.  From there it took a deep dive into the components of the solution and how it compares to a standard integration using your SAML provider of choice.  It continued with the steps necessary to configure Azure AD and AWS SSO to support the federated trust to enable single sign-on.  The fourth post explored the benefits of SCIM and went step by step on how to configure SCIM between the two services.  For this final post I’m going to cover a few different scenarios to demonstrate what’s possible with this new integration.

Before I jump into the scenarios, there is one final task that needs to be completed now that the federated trust and SCIM have been setup.  That task is setting up the permission sets in AWS SSO.  Permission sets are simply IAM policies (either AWS-managed or custom policies you create).  For those of you from the Microsoft Azure world, an IAM policy is a collection of permissions which define what a security principal (such as a user or role) is authorized to do.  They are most similar to an Azure RBAC role definition but more flexible and granular due to advanced features such as condition keys.  Permission sets are projected into the AWS accounts they are assigned to as AWS IAM roles.  These are the IAM roles the security principal assumes.

As I mentioned above, AWS SSO supports both AWS-managed IAM policies and custom IAM policies for permission sets.  If you go into the AWS Accounts menu option of AWS SSO you’ll see the accounts associated with the AWS Organization and which permission sets have been associated to the AWS accounts thus resulting in AWS IAM Roles being created within the AWS account.  In the image below you can see that I’ve provisioned two permission sets to account1 and account2.

accountassignments.pngThe permission sets tab displays the permission sets I’ve created and whether or not they’ve been provisioned to any accounts.  In the screenshot below you’ll see I’ve added four AWS-managed policies for Billing, SecurityAudit, AdministratorAccess, and NetworkAdministrator.  Additionally, I created a new permission set named SystemsAdmin which uses a custom IAM policy which restricts the principal assuming the rule to EC2, CloudWatch, and ELB activities.

permissionsets.png

Back on the AWS organization tab, if you click on an account you can see the AWS SSO Users or Groups that have been assigned to a permission set.  In the image below, you can see that I’ve assigned both the B2B Security Admins group and the Security Admins group to the AdministratorAccess permission set and the System Operators group to the SystemsAdmin permission set.

assignments.png

With permission sets out of the way, let’s jump into the scenarios.

Scenario 1 – Windows AD User, AD FS, Azure AD, AWS SSOscenario1.PNG

In this scenario the user is Bart Simpson who is a member of the System Operators group on-premises and exists authoritatively in a Windows AD forest.  A federated trust has been established with Azure AD using an instance of AD FS running on-premises. Azure AD has been integrated with AWS SSO for both SSO (via SAML) and provisioning (via SCIM).

Once Bart was logged into a domain-joined machine, I popped open a browser and navigated to My Apps portal at https://myapps.microsoft.com.  This redirected me to the Azure AD login screen.  Here I entered Bart’s user name.

bartazuread.PNG

Azure AD performed its home realm discovery process, identified that the domain jogcloud.com is configured for federated authentication, and redirected me to AD FS.  Take note I purposely broke integrated windows authentication here to show you each step.  In a correctly configured browser, you wouldn’t see this screen.

bartadfs.PNG

After I successfully authenticated to AD FS, I was bounced back over to Azure AD where the assertion was delivered.  Azure AD then whipped up a SAML assertion for AWS SSO, returned it to the browser, and redirected the browser to the AWS SSO assertion consumer URL.  AWS SSO consumed the assertion and authenticated Bart into AWS SSO displaying the AWS IAM Role selection page with the relevant roles he has permission to access.

bartawssso.PNG

Scenario 2 – Windows AD User, AD FS with Certificate MFA, Azure AD with Conditional Access, AWS SSO

scenario2.PNG

Scenario 1 is pretty simple, so let’s get fancy and layer on some security.  Here I added an access control policy into AD FS requiring certificate-based authentication for members of the Security Admins group.  Additionally, I added a conditional access policy in Azure AD requiring MFA for any user that is a member of that same group.

Since Homer Simpson regularly runs a nuclear reactor, he’s also the Security Admin for JOGCLOUD.  He has been made member of the Windows AD Security Admin group.

As a first step I again popped open a browser and navigated to the My Apps portal.  After Homer’s username was plugged in, Azure AD redirected me to the AD FS server.  I again broke IWA to capture each step in the process.

signin2

After the password challenge was satisfied, I was prompted to provide the appropriate user certificate.

signin3.PNG

From there I was authenticated to Azure AD and served up the My Apps portal.

myapps.PNG

Wondering why I wasn’t prompted for Azure MFA?  No, I didn’t misconfigure it (at least this time).  A not well documented feature (at least in my opinion) of Azure AD is that you can pass a claim asserting a user has satisfied the MFA requirement thus making for a better user experience because the user isn’t required to authenticate multiple times.  Yes folks, this means you can layer your traditional certificate-based authentication on top of Azure AD and AWS. 

mfaonprem.png

After selecting the AWS SSO app, I was signed into AWS SSO and presented with the role selection screen.

awsssosignin1.PNG

I then selected a one of the roles and was signed into the relevant AWS account assuming the AdministratorAccess IAM Role.

awsssosignin2

Scenario 3 – Azure AD B2B User, AWS SSO

scenario3.PNG

What if you have a multi-tenant situation due to an acquisition or merger or perhaps you farm out operations to a managed service provider?  No worries there, B2B is also supported with this pattern.  In this scenario I’m using a user sourced from tenant that has been invited via Azure AD’s B2B.  The user has been added to the B2B Security Admins group which exists authoritatively in the inviting tenant (jogcloud.com) and was synchronized to AWS SSO via SCIM.

Opening a browser and navigating to the My Apps portal kicks off Azure AD authentication and drops the user into their source tenant.  Once there I can change my tenant by selecting the profile icon and selecting the jogcloud tenant.

myappsmultiple.png

I’m then presented with the apps that I’m authorized to use in the jogcloud tenant, which includes the AWS SSO app.

guestmyapp.PNG

Azure AD kicks off the federated authentication and I’m presented with the AWS role selection page where I can choose to assume the AdministratorAccess role in two of the AWS accounts.

guestawsso.png

Scenario 4 – AWS CLI

I know what you’re saying now, “But what about CLI?”  Well folks, for that you can leverage the AWS CLI v2.  It’s still in preview right now, but I did test it using the user from scenario 2 and it worked flawlessly.  The experience is pretty anti-climatic so I’m not going to dive into it.  The user experience is similar to using the Azure PowerShell cmdlets in that a web browser instance is opened and guides you through the authentication process.

That will sum up this series.

Few technologies get me excited enough to write five posts, but this integration is really amazing.  With AWS hooking into Azure AD as effectively as they have (especially love the CLI integration), it reduces operational overhead and improves security which is a combination you rarely see together.  Most importantly, it puts the customer first by optimizing the user experience.  If you weren’t convinced on Azure AD’s capabilities as an IDaaS, hopefully this series has helped educate you as to the value of the platform.

With that I’ll sign off.  A big thanks to the AWS product team that worked on this integration.  You did an amazing job that will greatly benefit our mutual customers.

To the rest of you, I wish you happy holidays!

 

 

 

Deep Dive into Azure AD and AWS SSO Integration – Part 4

Deep Dive into Azure AD and AWS SSO Integration – Part 4

Today we continue exploring the new integration between Microsoft’s Azure AD (Azure Active Directory) and AWS (Amazon Web Services) SSO (Single Sign-On).  Over the past three posts I’ve covered the high level concepts of both platforms, the challenges the integration seeks to solve, and how to enable the federated trust which facilitates the single sign-on experience.  If you haven’t read through those posts, I recommend you before you dive into this one.  In this post I’ll be covering the neatest feature of the new integration, which is the support for automated provisioning.

If you’ve ever worked in the identity realm before, you know the pains that come with managing the life cycle of an identity from initial provisioning, changes resulting to the identity such as department and position changes, to the often forgotten stage of de-provisioning.  On-premises these problems were used solved by cobbled together scripts or complex identity management solution such as SailPoint Identity IQ or Microsoft Identity Manager.  While these tools were challenging to implement and operate, they did their job in the world of Windows Active Directory, LDAP, SQL databases and the like.

Then came cloud, and all bets were off.  Identity data stores skyrocketed from less than a hundred to hundreds and sometimes thousands (B2C has exploded far beyond event that).  Each new cloud service introduced into the enterprise introduced yet another identity management challenge.  While some of these offerings have APIs that support identity management operations, most do not, and those that do are proprietary in nature.  Writing custom code to each of the APIs is a huge challenge that most enterprises can’t keep up.  The result is often manual management of an identity life cycle, through uploading exported CSV files or some poor soul pointing and clicking a thousand times in a vendor portal.

Wouldn’t it be great if there was some mythical standard out that would help to solve this problem, use a standard API through REST, and support the JSON format?  Turns out there is and that standard is SCIM (System for Cross-domain Identity Management).  You may be surprised to know the standard has been around for a while now (technically 2011).  I recall hearing about it at a Gartner conference many many hears ago.  Unfortunately, it’s taken a long time to catch on but support is steadily increasing.

Thankfully for us, Microsoft has baked support into Azure AD and AWS recognized the value and took advantage of the feature.  By doing this, the identity life cycle challenges of managing an Azure AD and AWS integration has been heavily re-mediated and our lives made easier.

Azure AD Provisioning - Example

Azure AD Provisioning – Example

Let’s take a look at how set it up, shall we?

The first place you’ll need to go is into the AWS account which is the master for the organization and into the AWS SSO Settings.  In Settings you’ll see the provisioning option which is initially set as manual.  Select to enable automatic provisioning.

AWS SSO Settings - Provisioning

AWS SSO Settings – Provisioning

Once complete, a SCIM endpoint will be created.  This is the endpoint in AWS (referred to as the SCIM service provider in the SCIM standard) that the SCIM service on Azure AD (referred to as the client in the SCIM standard) will interact with to search for, create, modify, and delete AWS users and groups.  To interact with this endpoint, Azure AD must authenticate to it, which it does with a bearer access token that is issued by AWS SSO.  Be aware that the access token has a one year life span, so ensure you set some type of reminder.  A quick search through the boto3 API doesn’t show a way to query for issued access tokens (yes you can issue more than one at at time) so you won’t be able to automate the process as of yet.

awssso-scimendpoint.png

After SCIM is enabled, AWS SSO Settings for provisioning now reports SCIM in use.

awssso-scimenabled.png

Next you’ll need to bounce over to Azure AD and go into the enterprise app you created (refer to my third post for this process).   There you’ll navigate to the Provisioning blade and select Automatic as the provisioning method.

azuread-scimprov.png

You’ll then need to configure the URL and access token you collected from AWS and test the connection.  This will cause Azure AD to test querying the endpoint for a random user and group to validate functionality.

azuread-scimtest.png

If your test is successful you can then save the settings.

azuread-scimtestsucccess.PNG

You’re not done yet.  Next you have to configure a mapping which map attributes in Azure AD to the resource and attributes in the SCIM schema.  Yes folks, SCIM does have a schema for attributes and resources (like users and groups).  You can extend it as needed, but in this integration it looks to be using the default user and group resources.

azuread-scimmappings

Let’s take a look at what the group mappings look like.

azuread-scimgroupmappings.PNG

The attribute names on the left are the names of the attributes in Azure AD and the attributes on the right are the names of the attributes Azure AD will write the values of the attributes to in AWS SSO.  Nothing too surprising here.

How about the user mappings?

azuread-scimusermappings1azuread-scimusermappings2

Lots more attributes in the user mappings by default.  Now I’m not sure how many of these attributes AWS SSO supports.  According to the SCIM standard, a client can attempt to write whatever it wants and any attributes the service provider doesn’t understand is simply discarded.  The best list of attributes I could find were located here, and it’s not near this number.  I can’t speak to what the minimum required attributes are to make AWS work, because their official instructions on this integration doesn’t say.  I know some of the product team sometimes reads the blog, so maybe we’ll luck out and someone will respond with that answer.

The one tweak you’ll need to make here is to delete the mailNickName mapping and replace it with a mapping of objectId to externalId.  After you make the change, click the save icon.

I don’t know why AWS requires this so I can only theorize.  Maybe they’re using this attribute as a primary key in the back end database or perhaps they’re using it to map the users to the groups?  I’m not sure how Azure AD is writing the members attribute over to AWS.  Maybe in the future I’ll throw together a basic app to visualize what the service provider end looks like.

newmapping.PNG

Now you need to decide what users and groups you want to sync to AWS SSO.  Towards the bottom of the provisioning blade, you’ll see the option to toggle the provisioning status.  The scope drop down box has an option to sync all users and groups or to sync only assigned users and groups.  Best practice here is basic security, only sync what you need to sync, so leave the option on sync only assigned users and group.

The assigned users and groups refers to users that have been assigned to the enterprise application in Azure AD.  This is configured on the Users and Groups blade for the enterprise app.  I tested a few different scenarios using an Azure AD dynamic group, standard group, and a group synchronized from Windows AD.  All worked successfully and synchronized the relevant users over.

Once you’re happy with your settings, toggle the provisioning status and save the changes.  It may take some time depending on how much you’re syncing.

syncsuccess.PNG

If the sync is successful, you’ll be able to hop back over to AWS SSO and you’ll see your users and groups.

awssyncedusersawssyncedgroup

Microsoft’s official documentation does a great job explaining the end to end cycle.  The short of it is there’s an initial cycle which grabs all users and groups from Azure AD, then filters the list down to the users and groups assigned to the application.  From there it queries the target system to match the user with the matching attribute and if it isn’t found creates it, and if found and needs updating, updates it.

Incremental cycles are down from that point forward every 40 minutes.  I couldn’t find any documentation on how to adjust the synchronization frequency.  Be aware of that 40 minute sync and consider the end to end synchronization if you’re sourcing from Windows Active Directory.  In that case making changes in Windows AD could take just over an hour (assuming you’re using the 30 minute sync interval in Azure AD Connect) to fully synchronize.

awsssotime.PNG

As I described in my third post, I have a lab environment setup where a Windows Active Directory domain is syncing to Azure AD.  I used that environment to play out a few scenarios.

In the first scenario I disabled Marge Simpson’s account.  After waiting some time for changes to synchronize across both platforms, I saw in AWS SSO that Marge Simpson was now disabled.

margedisabled.PNG

For another scenario, I removed Barney Gumble from the Network Operators Active Directory group.  After waiting time for the sync to complete, the Network Operators group is now empty reflecting Barney’s removal from the group.

networkoperators.PNG

Recall that I assigned four groups to the app in Azure AD, Network Operators, Security Admins, Security Auditors, and Systems Operators.  These are the four groups syncing to AWS SSO.  Barney Gumble was only a member of the Network Operators group, which means removing him put him out of scope for the app assignment.  In AWS SSO, he now reports as being disabled.

barneydisabled.PNG

For our final scenario, let’s look at what happens when I deleted Barney Gumble from Windows Active Directory.  After waiting the required replication time, Barney Gumble’s user account was still present in AWS SSO, but set as disabled.  While Barney wouldn’t be able to login to AWS SSO, there would still be cleanup that would need to happen on the AWS SSO directory to remove the stale identity records.

barneydisabled.PNG

The last thing I want to cover is the logging capabilities of the SCIM service in Azure AD.  There are two separate logs you can reference.  The first are the Provisioning Logs which are currently in preview.  These logs are going to be your go to to troubleshoot issues with the provisioning process.  They’re available with an Azure AD P1 or above license and are kept for 30 days.  Supposedly they’re kept for free for 7 days, but the documentation isn’t clear whether or not you have the ability to consume them.  I also couldn’t find any documentation on if it’s possible to pull the logs from an API for longer term retention or analysis in Log Analytics or a 3rd party logging solution.

If you’ve ever used Azure AD, you’ll be familiar with the second source of logs.  In the Azure AD Audit logs, you get additional information, which while useful, is more catered to tracking the process vs troubleshooting the process like the provisioning logs.

Before I wrap up, let’s cover a few key findings:

  • The access token used to access the SCIM endpoint in AWS SSO has a one year lifetime.  There doesn’t seem to be a way to query what tokens have been issued by AWS SSO at this time, so you’ll need to manage the life cycle in another manner until the capability is introduced.
  • Users that are removed from the scope of the sync, either by unassigning them from the app or deleting their user object, become disabled in AWS SSO.  The records will need to be cleaned up via another process.
  • If synchronizing changes from a Windows AD the end to end synchronization process can take over an hour (30 minutes from Windows AD to Azure AD and 40 minutes from Azure AD to AWS SSO).

That will wrap up this post.  In my opinion the SCIM service available in Azure AD is extremely under utilized.  SCIM is a great specification that needs more love.  While there is a growing adoption from large enterprise software vendors, there is a real opportunity for your organization to take advantage of the features it offers in the same way AWS has.  It can greatly ease the pain your customers and enterprise users experience having to manage the life cycle of an identity and makes for a nice belt and suspenders to modern identity capabilities in an application.

In the last post of my series I’ll demonstrate a few scenarios showing how simple the end to end experience is for users.  I’ll include some examples of how you can incorporate some of the advanced security features of Azure AD to help protect your multi-cloud experience.

See you next post!

 

Deep Dive into Azure AD and AWS SSO Integration – Part 3

Deep Dive into Azure AD and AWS SSO Integration – Part 3

Back for more are you?

Over the past few posts I’ve been covering the new integration between Azure AD and AWS SSO.  The first post covered high level concepts of both platforms and some of the problems with the initial integration which used the AWS app in the Azure Marketplace.  In the second post I provided a deep dive into the traditional integration with AWS using a non-Azure AD security token service like AD FS (Active Directory Federation Services), what the challenges were, how the new integration between Azure AD and AWS SSO addresses those challenges, and the components that make up both the traditional and the new solution.  If you haven’t read the prior posts, I highly recommend you at least read through the second post.

Azure AD and AWS SSO Integration

New Azure AD and AWS SSO Integration

In this post I’m going to get my hands dirty and step through the implementation steps to establish the SAML trust between the two platforms.  I’ve setup a fairly simple lab environment in Azure.  The lab environment consists of a single VNet (virtual network) with a four virtual machines with the following functions:

  • dc1 – Windows Active Directory domain controller for jogcloud.com domain
  • adcs – Active Directory Certificate Services
  • aadc1 – Azure Active Directory Connect (AADC)
  • adfs1 – Active Directory Federation Services

AADC has been configured to synchronize to the jogcloud.com Azure Active Directory tenant.  I’ve configured federated authentication in Azure AD with the AD FS server acting as an identity provider and Windows Active Directory as the credential services provider.

visio of lab environment

Lab Environment

On the AWS side I have three AWS accounts setup associated with an AWS Organization.  AWS SSO has not yet been setup in the master account.

Let’s setup it up, shall we?

The first thing you’ll need to do is log into the AWS Organization master account with an account with appropriate permissions to enable AWS SSO for the organization.  If you’ve never enabled AWS SSO before, you’ll be greeted by the following screen.

1.png

Click the Enable AWS SSO button and let the magic happen in the background.  That magic is provisioning of a service-linked role for AWS SSO in each AWS account in the organization.  This role has a set of permissions which include the permission to write to the AWS IAM instance in the child account.  This is used to push the permission sets configured in AWS SSO to IAM roles in the accounts.

Screenshot of AWS SSO IAM Role

AWS SSO Service-Linked IAM Role

After about a minute (this could differ depending on how many AWS accounts you have associated with your organization), AWS SSO is enabled and you’re redirected to the page below.

Screenshot of AWS SSO successfully enabled page

AWS SSO Successfully Enabled

Now that AWS SSO has been configured, it’s time to hop over to the Azure Portal.  You’ll need to log into the portal as a user with sufficient permissions to register new enterprise applications.  Once logged in, go into the Azure Active Directory blade and select the Enterprise Applications option.

Register new Enterprise Application

Register new Enterprise Application

Once the new blade opens select the New Application option.

Register new application

Register new application

Choose the Non-gallery application potion since we don’t want to use the AWS app in the Azure Marketplace due to the issues I covered in the first post.

Choose Non-gallery application

Choose Non-gallery application

Name the application whatever you want, I went with AWS SSO to keep it simple.  The registration process will take a minute or two.

Registering application

Registering application

Once the process is complete, you’ll want to open the new application and to go the Single sign-on menu item and select the SAML option.  This is the menu where you will configure the federated trust between your Azure AD tenant and AWS SSO on the Azure  AD end.

SAML Configuration Menu

SAML Configuration Menu

At this point you need to collect the federation metadata containing all the information necessary to register Azure AD with AWS SSO.  To make it easy, Azure AD provides you with a link to directly download the metadata.

Download federation metadata

Download federation metadata

Now that the new application is registered in Azure AD and you’ve gotten a copy of the federation metadata, you need to hop back over to AWS SSO.  Here you’ll need to go to Settings.  In the settings menu you can adjust the identity source, authentication, and provisioning methods for AWS SSO.  By default AWS SSO is set to use its own local directory as an identity source and itself for the other two options.

AWS SSO Settings

AWS SSO Settings

Next up, you select the Change option next to the identity source.  As seen in the screenshot below, AWS SSO can use its own local directory, an instance of Managed AD or BYOAD using the AD Connector, or an external identity provider (the new option).  Selecting the External Identity Provider option opens up the option to configure a SAML trust with AWS SSO.

Like any good authentication expert, you know that you need to configure the federated trust on both the identity provider and service provider.  To do this we need to get the federation metadata from AWS SSO, which AWS has been lovely enough to also provide it to us via a simple download link which you’ll want to use to get a copy of the metadata we’ll later import into Azure AD.

Now you’ll need to upload the federation metadata you downloaded from Azure AD in the Identity provider metadata section.  This establishes the trust in AWS SSO for assertions created from Azure AD.  Click the Next: Review button and complete the process.

AWS SSO Identity Sources

Configure SAML trust

You’ll be asked to confirm changing the identity source.  There a few key points I want to call out in the confirmation page.

  • AWS SSO will preserve your existing users and assignments -> If you have created existing AWS SSO users in the local directory and permission sets to go along with them, they will remain even after you enable it but those users will no longer be able to login.
  • All existing MFA configurations will be deleted when customer switches from AWS SSO to IdP.  MFA policy controls will be managed on IdP -> Yes folks, you’ll now need to handle MFA.  Thankfully you’re using Azure AD so you plenty of options there.
  • All items about provisioning – You have to option to manually provision identities into AWS SSO or use the SCIM endpoint to automatically provision accounts.  I won’t be covering it, but I tested manual provisioning and the single sign-on aspect worked flawless.  Know it’s an option if you opt to use another IdP that isn’t as fully featured as Azure AD.

Confirmation prompt

Confirmation prompt

Because I had to, I popped up the federation metadata to see what AWS requiring in the order of claims in the SAML assertion.  In the screenshot below we see is requesting the single claim of nameid-format:emailaddress.  This value of this claim will be used to map the user to the relevant identity in AWS SSO.

AWS SSO Metadata

Back to the Azure Portal once again where you’ll want to hop back to Single sign-on blade of the application you registered.  Here you’ll click the Upload metadata file button and upload the AWS metadata.

Uploading AWS federation metadata

Uploading AWS federation metadata

After the upload is successful you’ll receive a confirmation screen.  You can simple hit the Save button here and move on.

Confirming SAML

Confirming SAML

At this stage you’ve now registered your Azure AD tenant as an identity provider to AWS SSO.  If you were using a non-Azure AD security token service, you could now manually provision your users AWS SSO, create the necessary groups and permissions sets, and administer away.

I’ll wrap up there and cover the SCIM provisioning in the next post.  To sum it up, in this post we configured AWS SSO in the AWS Organization and established the SAML federated trust between the Azure AD tenant and AWS SSO.

See you next post!