I’ve been looking into application entitlements and the Amazon Web Services (AWS) users, groups and entitlements has perplexed me for some time. I’ve had the opportunity to explore it, try to understand it and build some integration between Okta Workforce Identity Cloud (via Okta Workflows). This post is a summary of my findings.
AWS and IAM
To say the AWS entitlement model is complex is an understatement. Whilst AWS does have the standard users, groups and entitlements approach, the implementation is not straightforward. Some users/groups are defined within an AWS Account, some across accounts and some users have federated access but are not known to AWS. Similarly there are different entitlements, in the form of Roles, Policies and Permission Sets to grant access. There are also two IAM functions in AWS – IAM and IAM Identity Centre, where objects and management are very different. Lets look at the two.
AWS Identity and Access Management (IAM)
AWS IAM is the older mechanism for managing users and access. It resides within an account and controls access for functions in that account.
It has three types of users: the root user, IAM Users and Federated Users. IAM users are defined locally, whereas federated users are not defined in IAM. There are local IAM groups for grouping IAM users (but not federated users).
It defines Policy to control access, using Permissions (defining the resources and actions possible against those resources). These policies can be associated with users (IAM users), groups (IAM groups) and roles. Federated users do not have a user object in IAM, they will assume a Role (e.g. passed in the SAML assertion).
These objects and their relationships are shown in the following figure.
We will explore the Okta integrations later, but there is no provisioning of Okta users (or pushing of Okta groups) to AWS IAM. IAM Users and IAM Groups are locally managed. Okta users assigned to the AWS application can SSO to AWS using an assumed Role (the Role lists is pulled from AWS into Okta).
AWS IAM Identity Centre
The (newer) AWS IAM Identity Centre operates across AWS Accounts, so you can manage users and their access from one central location for all your AWS Accounts. It also has Users and Groups. These can be managed directly in the AWS admin console, or programmatically via the SCIM APIs.
The entitlement in IAM Identity Centre is the Permission Set. This is mapped to one or more Policies in different AWS accounts (via an IAM role). You could have a permission set that covers permissions across different AWS accounts. The assignment is done via the account, i.e. in the UI you need to look at the account assigned to the permission set to see the users (and groups) assigned.
These objects and their relationships are shown in the following figure.
Again, we will explore the Okta integration points below, but the Okta Integration Network integration for Identity Centre supports provisioning users and pushing groups to Identity Centre.
AWS IAM and Okta WIC
The previous sections of this article have presented the two IAM functions available in AWS and the users, group and entitlement objects each has. We’ve also introduced some of the Okta integration points and patterns.
The following figure provides a complete view.
On the right of the diagram is AWS, with one or more AWS accounts. Across all the accounts is the shared IAM Identity Centre, and within each account there is IAM. The diagram also shows the IAM objects for each. AWS Lambda is also shown as a means to run code in AWS, such as using APIs to interact with the different IAM functions.
From Okta there are both OIN integrations and Workflows connectors.
Okta OIN Integrations with AWS
There are multiple OIN integrations for AWS, but two are important for IAM: AWS Account Federation and AWS IAM Identity Centre.
The AWS Account Federation integration supports SSO (SAML and SWA). The OIN page says it supports provisioning (Create, Update), but the only function it really supports is importing the Role list for use in SSO – it cannot provision Okta users nor push Okta groups to AWS IAM. It’s main function is to support Okta users that are assigned to the app to SSO to AWS.
The AWS IAM Identity Centre integration supports both SSO (SAML) and provisioning/group push to AWS IAM Identity Centre. Okta users and groups can be pushed to IAM Identity Centre and mapped to permission sets to grant access to AWS functions in specific accounts. It also provides an Okta Workflows connector and template.
Okta Workflows Integrations with AWS
There are currently three connectors available for AWS: AWS S3 (not relevant here), AWS Multi-Acct Access (for IAM Identity Centre) and AWS Lambda.
The AWS Multi-Acct Access connector (listed as part of the AWS IAM Identity Centre OIN integration) is a standard connector with Workflows and also ships with a template. It works with entitlements (permission sets) in IAM Identity Centre and has five actions:
- Add AWS Entitlements – add a permission set to a user/group
- List AWS Entitlements – list permission sets assigned to a user/group
- List Instances – list the instances (accounts) tied to the user the connector is authenticated as (i.e. what accounts this user can centrally manage).
- Remove All AWS Entitlements – remove all permission sets from a user/group
- Remove AWS Entitlements – remove a permission set from a user/group
These actions will address most IAM Identity Centre needs. Where they don’t, or there are challenges with using the actions, you need to revert to a programmatic approach to working with the IAM APIs.
This is where the AWS Lambda connector is useful. You can create Lambda functions that invoke API calls to both IAM and IAM Identity Centre. This has it’s own challenges and design considerations. We will look at an example implementation of this next.
Using the AWS Lambda Connector for AWS IAM Management
In this last section of the document I look at an example of managing AWS IAM objects (in this case Identity Centre) via Lambda functions from Workflows.
I was looking for a way to manage IAM objects in Identity Centre from objects and events in Okta. The key requirements were:
- I needed to be able to discover all the users, permission sets and user-permission set mappings in Identity Centre,
- I needed to be able to provision/deprovision permission sets based on added/removed groups in Okta,
- I needed to be able to create user-permission set mappings when a user was added to a specific group in Okta, and
- I needed to be able to remove user-permission set mappings when a user was removed from a specific group in Okta.
I am using Okta groups to represent the entitlements in Okta, and I have the AWS IAM Identity Centre OIN implemented to provision/push Okta users and groups to AWS.
Given these requirements I needed to use Okta Workflows for discovery and provisioning. The discovery flows could be manually run whereas the provisioning flows could be event driven from group change events in the Okta System Log.
The AWS Multi-Acct Access connector addressed some of my requirements but not all, whereas there are APIs for everything I needed. I also hit some challenges with some of the AWS Multi-Acct Access cards and slow running processing in AWS. To simplify the flows and bypass these issues, I decided to build Lambda functions for all use cases and leverage the AWS Lambda connector exclusively.
From a workflows design perspective I tried to focus on performance (over security). This involved storing data in Workflows tables, including security credentials passed to the Lambda functions. This is not ideal, but achieved the aim (you would look to a more secure approach in a production deployment).
There were three things to be built for the implementation:
- A common IAM Role to allow the Lambda functions to run the APIs,
- Lambda functions for each of API calls I wanted to make, and
- The Workflows to implement the use cases
I created a common IAM Role to allow the Lambda functions to make the IAM API calls.
The policies tied to the role include some logging permissions and full access for IAM and Identity Centre functions. You would trim this back to the minimum if deploying into production,
Next I built a series of Lambda functions, one for each API call I wanted to make.
Each of these were written in Python, leveraging the IAM Identity Centre APIs (each API call has a link to language-specific pages, eg. Python). Note that the APIs refer to single signon, and the Python component is called sso-admin.
The function had the same basic structure – pass in a JSON object, make the API call and return the results or error info to the caller. Here is an example:
The key bit of code is as follows: run the boto3 client (for Python) with the passed API key id and secret, then try the API call.
client = boto3.client("sso-admin",region_name="us-west-2",
response = client.list_permission_sets(
All the values inside the event instructions are passed into the function via the payload object in the AWS Lambda connector Invoke card.
Lastly I built the Workflows that leveraged the AWS Lambda connector, the Okta connector and some Workflows tables for data storage (environment variables, AWS permission sets and AWS users) to reduce the amount of lookup calls into Okta and AWS. As there were multiple layers of data in the discovery flows, I had to use some sub (or helper) flows.
The provisioning flows (PROV*) were triggered by group change events through the System Log (e.g. group created/deleted, user added to/removed from group). I also used some shared, utility flows.
The use of the AWS Lambda connector was straightforward and having the same IAM Role and same code structure in the functions made it simple to build them. The main challenge is making sure you’re passing the correct payload values in the object (and haven’t mistyped the label used in the function when creating the Object in the Construct card).
One thing to be aware of is that the Lambda function will return a success code the the connector action even if the API call failed and was handled. In this case you need to code the workflow to interrogate the Output from the action to check for error responses.
With these flows and Lambda functions, I was able to discover the users, permission sets and mappings in AWS, then create/delete permission sets based off Okta groups and add/remove users based off Okta group memberships.
Understanding the IAM mechanisms and objects in Amazon Web Services (AWS) is not as straightforward as it could be. This article has explored the different mechanisms, object and how Okta can interact with them.
It has also shown a sample implementation leveraging Okta Workflows, the AWS Lambda connector, some Lambda functions and the IAM Identity Centre APIs to discover and manage Identity Centre objects from Okta.
Hopefully this article will help clear the fog around AWS IAM and how Okta can work with it (them).