Manage AWS permission sets dynamically by using Terraform
Vinicius Elias and Marcos Vinicius Pinto Jordao, Amazon Web Services
Summary
AWS IAM Identity Center enhances AWS Identity and Access Management (IAM) by providing a centralized hub for managing single sign-on access to AWS accounts and cloud applications. However, manual management of IAM Identity Center permission sets can become increasingly complex and error-prone as your organization grows. This complexity can lead to potential security gaps and administrative overhead.
This solution enables you to manage permission sets through infrastructure as code (IaC) using a continuous integration and continuous delivery (CI/CD) pipeline built with native AWS services. It enables a seamless integration of the permission set assignment mechanism with AWS Control Tower lifecycle events or an Account Factory for Terraform (AFT) environment. This approach provides dynamic identity configurations for both new and existing AWS accounts.
Amazon EventBridge rules monitor AWS account creation and updates, which helps your identity configurations to remain synchronized with your organizational structure. After creating or updating accounts in AWS Control Tower or AFT, the pipeline is triggered. It evaluates a set of JSON files with permission set definitions and assignment rules. Then the pipeline applies and synchronizes the settings across all accounts.
This approach provides the following benefits:
Consistency – Eliminates manual configuration drift across your AWS organization
Auditability – Maintains a complete history of all identity management changes
Scalability – Automatically applies configurations as your AWS environment grows
Security – Reduces human error in permission assignments
Compliance – Facilitates meeting regulatory requirements through documented changes and assignment rules
Prerequisites and limitations
A multi-account environment with AWS Control Tower and AWS Organizations set up. Optionally, you can use AFT with AWS Control Tower.
An IAM Identity Center delegated administrator AWS account to receive the solution. For more information, see Delegated administration in the IAM Identity Center documentation.
A version control system (VCS) repository to handle the main code. For a sample, see the solution’s GitHub repository
. Necessary AWS resources for the Terraform backend management, such as an Amazon Simple Storage Service (Amazon S3) bucket and Amazon DynamoDB table.
Limitations
The pipeline uses AWS native resources and open source Terraform. The pipeline is not prepared to make calls to third-party ecosystems.
Some AWS services aren’t available in all AWS Regions. For Region availability, see AWS Services by Region
. For specific endpoints, see Service endpoints and quotas, and choose the link for the service.
Architecture
The following diagram shows the components and workflow for this pattern.

AWS Control Tower events flow
The solution begins with the integration of events coming from either AWS Control Tower or AFT. The choice between one or the other service is made at the implementation time through variable definition. Regardless of the method used, the pipeline is triggered whenever an account is created or updated. The pipeline reconciles the policies stored in the permission sets management repository.
Following are the AWS Control Tower lifecycle events:
CreateManagedAccount
– When a new account is createdUpdateManagedAccount
– When an existing account is updated
Event routing
EventBridge serves as the central event processing service, capturing events generated in the AWS Control Tower account. When events occur, EventBridge intelligently routes them to a centralized event bus in the solution account. AWS Control Tower lifecycle events follow distinct routing patterns. If AFT is defined as the event source, the AFT management account handles the events instead of the AWS Control Tower account. This event-driven architecture enables automated responses to organizational changes without manual intervention.
AFT integration process
When AWS Control Tower lifecycle events reach the AFT management account, they automatically trigger multiple downstream processes that are intrinsic to AFT. After the AFT account customization workflow completes, it publishes a message to the dedicated aft-notifications
Amazon Simple Notification Service (Amazon SNS) topic. That topic triggers the aft-new-account-forward-event
AWS Lambda function that’s implemented by this solution. The Lambda function sends the event to the solution account event bus, where it’s used to start the pipeline.
Infrastructure as code pipeline
The solution pipeline operates as a fully automated deployment mechanism. The AWS CodePipeline service continuously monitors the repository for changes. Upon detecting new commits, it automatically initiates the deployment workflow and initiates a sequential process that includes validation and execution phases. The system runs Terraform plan
operations to identify proposed changes, followed by Terraform apply
commands to implement those changes in the AWS environment. Notably, the pipeline runs without any manual approval gates. This approach enables rapid deployment of infrastructure changes while maintaining auditability through pipeline logs and Terraform state files.
The pipeline leverages AWS CodeBuild to run Terraform operations in a controlled environment with appropriate permissions. Through this IaC approach, the pipeline can perform comprehensive permission management operations including:
Create new permission sets.
Update existing permission sets.
Remove unnecessary permission sets.
Manage the assignment of these permissions across accounts and groups within the AWS organizations.
To maintain infrastructure consistency and prevent conflicting changes, the solution implements the Terraform backend state management system using an Amazon S3 bucket and dedicated Amazon DynamoDB table. This approach provides persistent storage location for Terraform state files and state locking mechanisms to prevent concurrent modifications to the same resources.
The main Terraform code uses the official AWS permission-sets
Terraform module. This module can dynamically manage permission sets in IAM Identity Center, based on permission set templates.
Source control management
The permission set templates (JSON files) reside in an external version control system, such as GitHub, that provides a centralized repository for identity management configurations. This approach establishes a single source of truth for permission set definitions, while enabling collaborative development through standard code review practices. Authorized users can commit changes to these templates following organizational change management processes. These commits serve as the primary trigger for the automated deployment pipeline, initiating the infrastructure update process.
For an example of how to configure the permission sets using the JSON file in the repository, see Additional information.
Tools
AWS services
AWS CodeBuild is a fully managed build service that helps you compile source code, run unit tests, and produce artifacts that are ready to deploy.
AWS CodeConnections enables AWS resources and services, such as CodePipeline, to connect to external code repositories, such as GitHub.
AWS CodePipeline helps you quickly model and configure the different stages of a software release and automate the steps required to release software changes continuously.
AWS Command Line Interface (AWS CLI) is an open source tool that helps you interact with AWS services through commands in your command line shell.
AWS Control Tower helps you set up and govern an AWS multi-account environment, following prescriptive best practices.
Amazon DynamoDB is a fully managed NoSQL database service that provides fast, predictable, and scalable performance.
Amazon EventBridge is a serverless event bus service that helps you connect your applications with real-time data from a variety of sources. For example, AWS Lambda functions, HTTP invocation endpoints using API destinations, or event buses in other AWS accounts.
AWS Identity and Access Management (IAM) helps you securely manage access to your AWS resources by controlling who is authenticated and authorized to use them.
AWS IAM Identity Center helps you centrally manage single sign-on (SSO) access to all of your AWS accounts and cloud applications.
AWS Lambda is a compute service that helps you run code without needing to provision or manage servers. It runs your code only when needed and scales automatically, so you pay only for the compute time that you use.
AWS Organizations is an account management service that helps you consolidate multiple AWS accounts into an organization that you create and centrally manage.
Amazon Simple Notification Service (Amazon SNS) helps you coordinate and manage the exchange of messages between publishers and clients, including web servers and email addresses. It enables push notifications for account management events, ensuring that relevant parties are informed of important changes or actions within the system.
Amazon Simple Storage Service (Amazon S3) is a cloud-based object storage service that helps you store, protect, and retrieve any amount of data.
Other tools
Terraform
is an infrastructure as code (IaC) tool from HashiCorp that helps you create and manage cloud and on-premises resources.
Code repository
The code for this pattern is available in the AWS Samples organization on GitHub in the sample-terraform-aws-permission-sets-pipeline
Best practices
Always pin the versions of the Terraform modules and providers used to run code in production.
Use a static code analysis tool, such as Checkov
, to scan your code and then solve the security issues. Follow the principle of least privilege and grant the minimum permissions required to perform a task. For more information, see Grant least privilege and Security best practices in the IAM documentation.
Epics
Task | Description | Skills required |
---|---|---|
Create Terraform backend resources. | If you haven't created your Terraform backend AWS resources yet, use the following steps to create an Amazon S3 bucket (
| AWS administrator |
Create a cross-account role. | You must provide a cross-account IAM role in the
This example uses the AWS managed IAM policy AdministratorAccess. If you prefer, you can use a more specific policy. | AWS administrator |
Task | Description | Skills required |
---|---|---|
Create a dedicated repository. | This task assumes that you’re using GitHub. Create a dedicated repository to store the main Terraform code and the permission set template JSON files. | DevOps engineer |
Prepare the permission set code. | For information about how you can structure the following files, see the sample code ├── main.tf ├── outputs.tf ├── providers.jinja └── templates Copy the content, keep the | DevOps engineer |
Commit your changes. | Commit and push the changes to the repository that you created earlier. Save the repository name and its GitHub organization, for example, | DevOps engineer |
Task | Description | Skills required |
---|---|---|
Download the content. | Download (clone) the content from the solution repository | DevOps engineer |
Fulfill the variables. | Create a
For information about additional variable options, see the variables.tf | DevOps engineer |
Adjust the Terraform backend configuration. | In the
If you prefer, you can use your own Terraform backend configuration. | DevOps engineer |
Adjust the Terraform provider configuration. | In the
| DevOps engineer |
Task | Description | Skills required |
---|---|---|
Select the AWS account. | We recommend that you deploy the solution in the IAM Identity Center delegated administrator account. However, you can also deploy it in the AWS Organizations management account. To sign in to the selected account in the same Region as the IAM Identity Center instance, use the AWS CLI. Make sure that the IAM role you’re using has permission to assume the role that’s specified for the | AWS administrator |
Run Terraform manually. | To initialize, plan and apply the configurations, run the following Terraform commands in the order shown:
| DevOps engineer |
Check the deployment results. | In the IAM Identity Center delegated administrator account, check that the | AWS DevOps |
Finish the CodeConnections configuration. | To finish the CodeConnections configuration, use the following steps:
The pipeline should now have access to the permission set repository. For detailed instructions, see Update a pending connection in the Developer Tools console documentation. | AWS DevOps |
Task | Description | Skills required |
---|---|---|
Run the pipeline by AWS Control Tower or AFT updates. | After an account is created or changed by using AWS Control Tower or AFT (depending on the type of lifecycle events that you chose), the pipeline starts. | AWS administrator |
Run the pipeline by changing the code. | After you change the code and commit it to the | AWS DevOps |
Run the pipeline manually. | To start the pipeline manually, use the Release change feature in AWS CodePipeline. | AWS DevOps |
Troubleshooting
Issue | Solution |
---|---|
Access denied | Verify that you have the permissions required to deploy the solution. |
CodeConnections issues |
|
Pipeline execution problems |
|
Permission sets deployment issues |
|
Related resources
AWS service documentation
Manage AWS accounts with permission sets (IAM Identity Center documentation)
Other resources
AWS Permission Sets module
(Terraform)
Additional information
JSON file with sample permission set
The following example shows how to configure a permission set by using the JSON file in the repository:
{ "Name": "ps-billing", // Permission set identifier "Comment": "Sample permission set for billing access", // Comment to document the purpose of the permission set "Description": "Billing access in AWS", // Detailed description "SessionDuration": "PT4H", // Session duration = 4 hours (ISO 8601 format) "ManagedPolicies": [ // List of AWS IAM managed policies "arn:aws:iam::aws:policy/job-function/Billing", "arn:aws:iam::aws:policy/job-function/SupportUser", "arn:aws:iam::aws:policy/AWSSupportAccess", "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess" ], "CustomerPolicies": [], // References to IAM policies previously created "CustomPolicy": {}, // Inline IAM policy defined directly in the permission set "PermissionBoundary": { // AWS or customer managed IAM policy to be used as boundary "ManagedPolicy": "", "CustomerPolicy": "" }, "Assignments": [ // Define the assignment rules { "all_accounts": true, // Apply to ALL active AWS accounts in organization "principal": "G_BILLING_USERS", // Group/user name in Identity Center "type": "GROUP", // Can be "GROUP" or "USER" "account_id": [], // List of AWS account ID (empty since all_accounts=true) "account_ou": [], // List of AWS Organizational Unit IDs with target AWS accounts "account_tag": [] // List of tags (key:value) to match AWS Organization accounts tags } ] }
For more information, see the JSON schema in the AWS Permission Sets module
Tips
You can use Terraform import blocks
to import an existing permission set to the solution. You can use AFT to implement the AWS permission set pipeline in a delegated account. For more information, see AFT Blueprints
.