AWS

Lab A5 – Integrate Azure AD with AWS Control Tower

Overview

In this lab we will walk through how to integrate Azure AD with Control Tower. We will be leveraging a public blog post and an Azure AD Lambda function for most of the work, with a modification to take advantage of StackSets and the account structure already provided by AWS Control Tower.

TIP: It is a best practice to keep AWS SSO configured to be used in a break glass scenario when using a third-party Identity provider.

Prerequisites

  1. This lab requires an account with Administrator privileges and Control Tower.
  2. We will be utilizing an Azure free account to create our Azure AD and test users for this lab. Follow the steps from Microsoft to create a free account and free access to Azure AD Premium trial https://azure.microsoft.com/en-us/trial/get-started-active-directory/.

As of the writing of this lab, the control tower deployed the AWSControlTowerAdmin in master account and AWSControlTowerExecution in all the accounts. You can also deploy it using the template provided as part of the AWS CloudFormation StackSets prerequisites.

Use the master account number for the AdministratorAccountId parameter.

Step 1: Configure Microsoft Azure Active Directory

TIP: If the Azure portal becomes unresponsive, or does not display some parts of the console, try with a different browser.

1.1) Copy your Azure AD domain (AKA Tenant ID)

Note: if a custom domain was not created with the account, or if you deleted it, you can create a new one y following these steps: https://docs.microsoft.com/en-us/azure/active-directory-domain-services/create-instance
1.2) Create a new User

Got to Active Directory/Users/All Users/New User

1.3) Login to the Azure portal with the new user and change its password

Since the user you created has an OTP (One Time Password) you need to login, change the password, and copy the new password to Notepad for later.
1.4) Add a New Enterprise Application

Login with the Account Owner again and go to Active Directory/Enterprise applications/Application

Filter on AWS and select Amazon Web Services

Customize the Name and Add the Application
1.5) Open the Amazon Web Services Application, and click Edit

Note: Depending on the portal behavior this step may not be necessary because you may already be in the application summary

1.6) Enable SAML



1.7) Update the Identifier (Entity ID) field with the default value

WARNING: Do NOT rely on the default value (it doesn't work and the error message will be unhelpful. Copy the default https://signin.aws.amazon.com/saml and remember to save

You can use the default https://signin.aws.amazon.com/saml value. Just be aware the identifier must be unique within your Azure account.

1.8) Configure the User Attributes

You need to tell Azure AD what SAML attributes and values are expected and accepted on the AWS side. AWS requires two mandatory attributes in any incoming SAML assertion.

A) Go and edit User Attributes & Claims


B) Add the RoleSessionName | https://aws.amazon.com/SAML/Attributes | user.userprincipalname claim


C) Add the Role | https://aws.amazon.com/SAML/Attributes | user.assignedroles claim


D) [OPTIONAL] Add the SessionDuration | https://aws.amazon.com/SAML/Attributes | 43200 claim


Your claim list should now be similar to this one

Summary of User Attributes

Name (case-sensitive) Value Namespace (case-sensitive) Required or optional?
RoleSessionName user.userprincipalname (this will show logged in user ID in AWS portal, if you want user name, replace it with user.displayName) https://aws.amazon.com/SAML/Attributes Required
Role user.assignedroles https://aws.amazon.com/SAML/Attributes Required
SessionDuration An integer between 900 seconds (15 minutes) and 43200 seconds (12 hours). https://aws.amazon.com/SAML/Attributes Required

Note: This lab assumes users are directly created within your Azure AD tenant. If you’re using an external user such as a Hotmail, Live, or Gmail account for proof-of-concept purposes, RoleSessionName should be set to user.mail instead.

1.9) Copy the Federation Metadata XML URI

Copy the URI to the Application Metadata XML file and save it in Notepad
1.10 Copy the Manifest Object ID. Open Azure Portal / Azure Active Directory / App Registrations / your application name (for example, “Amazon Web Services (AWS)”) / Manifest / Download
TIP: If you don’t see your application in the list on the App Registrations page, select All apps from the drop-down list on top of that page and search for it. Information: All Azure AD applications are described as a JavaScript Object Notification (JSON) document called manifest. For AWS, this manifest defines all AWS to Azure AD role mappings. Later, we’ll be using automation to generate updates to this file. Steps:

A) Go into the Amazon Web Services (AWS) application


B) Copy the Object ID. then select the application Manifest


1.11) Set the user you created as the Application Owner

Go to the Settings pane of your registered application

Set the owner of the application
1.12) Copy the Login URL

Go back to Single Sign-on: Azure Active Directory / Enterprise applications / Amazon Web Services (AWS) / Single sign-on. Scroll down to section 4 and copy the Login URL.



At this point, we’re done with the initial configuration of Azure AD.
You should have the following:

Information Sample Content
Azure Tenant ID myazaccount.onmicrosoft.com
Azure User Name emma@myazaccount.onmicrosoft.com
Azure User password Password you have set after login in with that user
The Federation Metadata URL https://login.microsoftonline.com/b4f8e8b2-ABCD-XYZ-9399-097dd6669707/federationmetadata/2007-06/federationmetadata.xml?appid=ed1b3a1f-470c-4717-aadd-36bf7a9487ac
Login URL https://login.microsoftonline.com/b4f8e8b2-ABCD-XYZ-9399-097dd6669707/saml2
Application Object ID ed1b3a1f-460c-4717-aadd-36bf7a9487ac

At this point, we’re done with the initial configuration of Azure AD. All remaining steps will be performed in your AWS accounts.

Step 2: Configure AWS IAM Identity Providers and Roles

This customization has the roles and a SAML Identity Provider Role lambda function in a CloudFormation template that we will use StackSets to deploy to all of the accounts in our Organization.

2.01) Create a AWSControlTowerExecution role in the Master account

Verify if you have a AWSControlTowerExecution role in the master account. If you don't you will have to create one
  1. Go into the Identity and Access Management Console (IAM), and create a Role named AWSControlTowerExecution
  2. For the Trust Entity, select Another AWS account and use your Master Account Number
  3. For permission policies, attach the AdinistratorAccess policy
  4. Name the role AWSControlTowerExecution and complete creation
  5. Search the role, go back in Edit mode, and click on the Trust relationship tab
  6. Edit the trust relationship and paste the one below but REPLACE THE ACCOUNT NUMBER WITH YOUR MASTER ACCOUNT NUMBER
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::012345678912:role/service-role/AWSControlTowerStackSetRole"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}
2.1) Download and Unzip the CloudFormation aws-landing-zone-default-azure-roles.template for this lab

It is available from: aws-landing-zone-default-azure-roles.template

2.2) Launch the aws-landing-zone-default-azure-roles.template as a CloudFormation StackSet to create roles

  1. Navigate to the StackSet console under CloudFormation in the master account and click “Create StackSet”.


  2. Select “Upload a template to Amazon S3” and select the aws-landing-zone-default-azure-roles.template


  3. Give the StackSet a good name like AzureADIntegration. If you are using a shared account, then use aliasAzureADIntegration and enter the AzureADMetadataUrl you copied from your Azure AD application configuration above.



  4. Specify Accounts or OUs and 1 region, click Next-Next and Create. Deploy only into Accounts or OUs you want Azure AD to authorize.



  5. Remember to select the checkbox: 'I acknowledge that AWS CloudFormation might create IAM resources with custom names.'

  6. Use Control Tower roles: AWSControlTowerStackSetRole and AWSControlTowerExecution.



  7. If you have deployed any of the other labs, make sure that you enter unique role names for the three role name parameters and shorten them, e.g. aliasAzureADAdmin, aliasAzureADPower, aliasAzureADRead etc.

Step 3: Synchronizing AWS Roles to AzureAD

In this step, we configure the Azure AD Role Sync Lambda code to synchronize our AWS roles with Azure AD.

Run these steps on the Master account.

3.1 Create IAM Roles and the Lambda function to Sync them to Azure
  1. Download, Unzip, and run the CloudFormation template from azure-ec2.template in the Master account
    Give the stack a unique name like alias-azure-ec2, and create the stack with default values.
    Note: If you are using a SHARED account: First edit the template, search for 'CT-Lab07' and add your user prefix (aliasCT-Lab07) to make it easier to locate your instance
  2. Wait for the stack to be fully deployed
  3. Connect to the instance from the AWS Console with an AWS System Manager (SSM) session
    1. Go to the AWS System Manager service
    2. Click on Session Manager
    3. Click Start Session, and select the CT-Lab07 instance
      NOTE: Alternatively, you can do this directly from a terminal session on your laptop. This required the AWS CLI and the Session Manager Plugin to be installed. For details see the References section at the end of the lab.
      To connect to the instance with the CLI:
      1. Connect with SSO to the Master account but instead of accessing the console, copy credentials from the CLI access link
      2. Paste these credentials in your terminal and use aws ssm start-session --region *REGION* --target *INSTANCEDID*
  4. On the SSM Session Terminal execute the following line by line (not as a block) and REPLACE expected values (like **YOUR-REGION**) with your own values.

screen
bash
export AWS_DEFAULT_REGION=**YOUR-REGION**
cd ~
## The following will confirm your environment in correctly setup
pip --version

curl -O http://www.awsmanagementweek.com/controlTower/ctlab07/Aad-iam-sync-lambda.zip
unzip -q Aad-iam-sync-lambda.zip
cd Aad-iam-sync-lambda
chmod -R +x .
##################################################
##### ---- STEP 1: Create an S3 Bucket ----- #####
##################################################

# Follow steps and COPY the output bucket name
./create-bucket.sh
### ---- generated output -----
### this will generate output from the S3 bucket creation and configuration
### do a 'cat create-bucket.sh' if you are curious of details
### REMEMBER to take note of your deployment bucket name. It is part of the script output
###
### ---- end of simulated output -----

####################################################################
##### ---- STEP 2: Configure your deployment environment ----- #####
####################################################################

######## define the ".env" file ##########
### TIP: see the template with 'cat env.template'
### EXAMPLE BELOW(replace with your own values)

cat <<EOF >.env
STACK_NAME=azure-ad-sync-lambda               (this name must be UNIQUE)
S3_BUCKET_NAME=***deploy-bucket-name***       (from STEP 1)
AWS_ASSUME_ROLE_NAME=***azure-ad-sync-role*** (add your PREFIX if necessary)
AZURE_OBJECT_ID=3e635845-xxxx-xxxx-xxxx-408c998862e5
AZURE_TENANT_ID=eggXXXXXXX.onmicrosoft.com
AZURE_USERNAME=adsync@eggXXXXXXX.onmicrosoft.com
AZURE_USERNAME=azure-username
AZURE_PASSWORD=azure-password
SAMLIDENTITYPROVIDERNAME=AzureAD              (add your PREFIX if necessary)
ACCOUNTLIST=none
EOF

############################################################################
##### ---- STEP 2: Deploy a Lambda to Sync IAM Roles to Azure AD ----- #####
############################################################################
## test the environment
make test
## clean up artifacts from a previous execution
make clean
## deploy the template with CloudFormation
make deploy-app

## Once deployment completes with success go to the next step
## if experiencing an issue go in the CloudFormation consiole to look at the error
## or seek assistance from the lab instructor

################################################################################################
##### ---- STEP 3: Execute the Lambda function to force an immediate synchronization ----- #####
################################################################################################

## you need to locate the function to execute it.
## It can be done from the console but we will do it with the CLI

aws lambda list-functions --query "Functions[*].FunctionName" --output text
  azure-ad-sync-lambda-AzureADSyncFunc-1QTLOW22NS44F   

## If in a shared account you will more than 1. Copy the function that uses your prefix
## Then execute the function
aws lambda invoke  --function-name azure-ad-sync-lambda-AzureADSyncFunc-1QTLOW22NS44F /tmp/output.txt

3.2) Navigate to the AWS Lambda function in the console and verify that it executes successfully

The function will be named with this prefix: aad-sync-function-AzureADSyncFunc-...

Information: the function is invoked on a schedule every 15 minutes by Amazon CloudWatch Event so you will have to wait until the next invocation.
Troubleshooting tips:
  • Look at details of the Lambda execution in CloudWatch Logs. This is available from the Monitoring pane in Lambda
  • If 0 roles are found, you either did not y roles or you are using a shared account and forgot to add your prefix to roles or the AWSService.js file. Roles are discovered because they use the same saml-provider: AzureAD or aliasAzureAD
  • If you have Sync errors with the Azure account you may have entered incorrect values when executing configure.sh. You can look up these values in the System Manager Parameter Store. You can re-execute configure.sh but you will also have to rebuild and redeploy the package because the lambda function is CACHING values.


Step 4: Entitling Azure AD users to assume AWS Roles

Now we are back to following the blog post, the section titled Entitling Azure AD users to assume AWS Roles.

4.1) Open Azure Portal > Azure Active Directory > Enterprise applications > All applications > (your application name)

4.2) Select Users and groups > Add user, and assign a role to the user

4.3) Navigate to Azure Active Directory > Enterprise Applications > Amazon Web Services (AWS) > Properties and copy the User access URL

Step 5: Login to the Azure MyApps portal

Now we can use the new user and new User access URL to login to the myapps portal and select a role to login to the AWS console.

  • Ideally using a different browser instance, login to the myapps portal using the URL you copied previously.

  • Select the AWS account and AWS role that you want to use to sign in. Or if you only have one account you will be automatically logged into the console for that account.


Exploring the Solution

You deployed 3 templates. One created IAM roles in AWS accounts to handle user authorizations, another deployed an EC2 instance used to build a deploy the third template with the Lambda function used to synchronize IAM roles to Azure AD.

  1. Go into the IAM console in one of these accounts, locate one of the deployed role, and look at the trust policy. Each role trusts the same SAML provider named AzureAD or yourAliasAzureAD.
  2. The second template deployed an AWS Lambda function that synchronize some IAM roles with Azure AD. See you can locate the Amazon CloudWatch scheduled event that invokes this function.
  3. On the AWS side everything could be deployed with a single template. Some manual steps were kept to allow you to explore other aspects. Look at:
  4. The EC2 instance you deployed.
    1. Try executing: ec2-metadata --all. For details on instance metadata, see References at the end of the lab
    2. It does not have any PEM key but you still were able to use it through AWS Systems Manager. This EC2 instance does not allow any public traffic and could have been deployed in a private subnet and you still could create a session to it.
    3. The instance is using an IAM Role for EC2. See if you can locate this role in the EC2 Console.
    4. Instead of starting a session through the Session Manager Console, you can start session from a terminal and the Session Manager Plugin for the AWS CLI
    5. If you configure the service for it, the Session Manager can also Audit and Log Session Activity.
    6. Finally, have you noticed the CloudFormation template used to deploy the instance did not specify an AMI? Instead it used a template parameter to get the latest AMI for the requested architecture. See Query for the latest Amazon Linux AMI IDs using AWS Systems Manager Parameter Store for details

Deleting AWS resources deployed in this lab

In the Master account:

  1. Delete the CloudFormation stack you deployed from the azure-ec2.template
  2. Delete the Stackset 'aliasAzureADIntegration' deployed from the aws-landing-zone-default-azure-roles.template
  3. First delete the deployed Stacks of the StackSet
  4. Then delete the StackSet itself
  5. Delete the 'aad-sync-function' stack.
  6. In the System Manager Parameter store you can delete:

  7. /azuread-sync/username

  8. /azuread-sync/tennant
  9. /azuread-sync/password
  10. /azuread-sync/objectid

  11. Delete the alias-640271645869-us-east-2-demosync bucket

  12. You can also delete Amazon CloudWatch Log Groups that were created for AWS Lambda functions and System Manager Sessions
  13. In the Azure Console, delete the AWS application

REFERENCES

  1. Instance metadata: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
  2. EC2 Instance Metadata Query Tool: https://aws.amazon.com/code/ec2-instance-metadata-query-tool/
  3. Installing the AWS CLI: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html
  4. Installing the Session Manager plug-in: https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html
  5. AWS Systems Manager Session Manager: https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html
  6. How to automate SAML federation to multiple AWS accounts from Microsoft Azure Active Directory
  7. SAML Developer Tools
  8. Enabling SAML for Your AWS Resources
  9. Query for the latest Amazon Linux AMI IDs using AWS Systems Manager Parameter Store
  10. Azure AD does not provide an easy way to use the command line but there are solutions like aws-azure-login on Github.
  11. How to Use Linux Screen

Copyright 2019, Amazon Web Services, All Rights Reserved.