Managing AWS resources across different accounts is a common requirement when using Terraform. AWS AssumeRole provides a secure mechanism to grant your Terraform code temporary credentials to operate in a target account without requiring long-term access keys. This approach aligns with the principle of least privilege, enhancing the security of your infrastructure. Here's a step-by-step guide on how to leverage AssumeRole in your Terraform workflows to manage resources in different AWS accounts effectively.
When using Terraform to manage AWS resources, you might need to access and manage resources in an AWS account different from where your Terraform code runs. This is where AWS AssumeRole comes in handy.
AssumeRole allows you to grant your Terraform code temporary credentials to operate within a different AWS account, adhering to the principle of least privilege.
Here's how it works:
-
Define an IAM role in the target account: This role will hold the necessary permissions for your Terraform code to operate on resources in that account.
-
Grant permissions to assume the role: In the target account's IAM role policy, you need to specify who (or what) is allowed to assume this role. This could be a user, another role, or an AWS service like EC2. For instance, if your Terraform code runs on an EC2 instance, you would specify EC2 as the principal.
-
Configure the AWS Provider in your Terraform code: Within your Terraform code, you need to configure the AWS provider to use AssumeRole. You provide the ARN (Amazon Resource Name) of the IAM role you created in the target account.
-
Terraform assumes the role: When you run your Terraform code, the AWS provider uses the provided ARN to request temporary credentials from AWS Security Token Service (STS).
-
Terraform interacts with the target account: With the temporary credentials, Terraform can now provision and manage resources in the target AWS account.
Important Considerations:
-
Security: Ensure that the IAM role in the target account has only the necessary permissions for your Terraform code. Avoid granting overly broad permissions.
-
Instance Profiles: If your Terraform code runs on an EC2 instance, you can use an instance profile to associate the IAM role with the instance. This simplifies the process as the AWS provider can automatically retrieve credentials from the instance metadata service.
-
Skip Metadata API Check: In specific scenarios, you might need to use the
skip_metadata_api_check
flag in your AWS provider configuration. This flag disables the default behavior of the provider attempting to retrieve credentials from the instance metadata service. Use this flag cautiously as it can have security implications.
By using AssumeRole, you can enhance the security and flexibility of your Terraform deployments, allowing you to manage resources across different AWS accounts securely.
This code demonstrates how to use Terraform to manage resources in a different AWS account using AssumeRole. It shows how to create an IAM role and policy in the target account, and then configure the AWS provider in Terraform to assume that role. This allows Terraform to create resources in the target account on behalf of the user. The example specifically shows how to create an S3 bucket in a different account, but the same principles can be applied to other AWS resources.
This example demonstrates how to use Terraform to create an S3 bucket in a different AWS account using AssumeRole.
Target Account (Account B):
- Create an IAM role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<Account A ID>:root"
},
"Action": "sts:AssumeRole"
}
]
}
Replace <Account A ID>
with the actual AWS account ID where your Terraform code runs.
- Create an IAM policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:CreateBucket",
"s3:DeleteBucket"
],
"Resource": "arn:aws:s3:::my-bucket-in-account-b"
}
]
}
Replace my-bucket-in-account-b
with your desired bucket name.
- Attach the policy to the IAM role.
Main Account (Account A):
- Configure the AWS provider:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
provider "aws" {
region = "us-west-2"
assume_role {
role_arn = "arn:aws:iam::<Account B ID>:role/terraform-role"
}
}
resource "aws_s3_bucket" "example" {
bucket = "my-bucket-in-account-b"
acl = "private"
force_destroy = true
}
Replace <Account B ID>
with the actual AWS account ID of the target account and terraform-role
with the name of the IAM role you created.
Explanation:
- The
assume_role
block within the aws
provider tells Terraform to assume the specified IAM role in Account B.
- When you run
terraform apply
, Terraform will use the assume_role
configuration to request temporary credentials from AWS STS.
- With these temporary credentials, Terraform can then create the S3 bucket in Account B.
Important:
- This is a basic example. You can customize the IAM policies and Terraform code to fit your specific needs.
- Always follow the principle of least privilege and grant only the necessary permissions to your IAM roles.
This example demonstrates the basic principles of using AssumeRole with Terraform. You can adapt this approach to manage various AWS resources across different accounts securely.
Permissions & Policies:
-
Granularity is Key: Don't grant the
*:*
(all actions, all resources) permission in your target account role. Be as specific as possible about the actions and resources your Terraform code needs.
-
Policy Attachments: You can attach multiple policies to an IAM role. This allows you to separate concerns and manage permissions more effectively.
-
Policy Simulator: Use the AWS Policy Simulator to test your IAM policies and ensure they grant the intended permissions.
AssumeRole Mechanics:
-
Temporary Credentials: The credentials obtained via AssumeRole have a limited lifespan (default is 1 hour, configurable up to 12 hours). Terraform automatically refreshes these credentials as needed.
-
External ID (Optional): For added security, you can use an external ID when assuming a role. This adds an extra layer of validation to the AssumeRole API call.
-
Session Tags (Optional): You can pass session tags when assuming a role to add metadata to the temporary credentials. This can be useful for auditing and cost allocation.
Best Practices:
-
Separate Accounts for Environments: Use different AWS accounts for development, staging, and production environments. This enhances isolation and security.
-
Automation: Automate the creation and management of IAM roles and policies using Terraform or other infrastructure-as-code tools.
-
Documentation: Clearly document your AssumeRole setup, including the roles, policies, and trust relationships involved.
Troubleshooting:
-
Access Denied Errors: Double-check your IAM role policies, trust relationships, and the permissions granted to the entity assuming the role.
-
Credential Expiration: If you encounter issues with credentials expiring, ensure that your Terraform code is configured to automatically refresh credentials.
-
AWS STS Endpoints: In some cases, you might need to configure specific AWS STS endpoints if you are working in a restricted environment.
Alternatives to AssumeRole:
-
Cross-Account Access with IAM Users: While less secure, you can create IAM users in one account and grant them permissions to access resources in another account.
-
AWS Organizations: For managing multiple AWS accounts centrally, AWS Organizations provides a more comprehensive solution for cross-account access and governance.
This table summarizes using AWS AssumeRole to manage resources in a different AWS account than where your Terraform code runs:
Step |
Description |
Security & Best Practices |
1. Define IAM Role in Target Account |
Create an IAM role in the target account with the specific permissions your Terraform code needs. |
Principle of Least Privilege: Grant only the necessary permissions to this role. |
2. Grant AssumeRole Permissions |
In the target account's IAM role policy, specify who (user, role, service) can assume this role. |
|
3. Configure AWS Provider in Terraform |
In your Terraform code, configure the AWS provider to use AssumeRole by providing the ARN of the target account's IAM role. |
|
4. Terraform Assumes Role |
When executed, Terraform uses the provided ARN to request temporary credentials from AWS STS. |
|
5. Terraform Manages Target Account |
Using the temporary credentials, Terraform can now provision and manage resources in the target AWS account. |
|
Additional Considerations:
-
Instance Profiles: Simplify credential retrieval by associating the IAM role with an EC2 instance using an instance profile.
-
Skip Metadata API Check: Use the
skip_metadata_api_check
flag in the AWS provider configuration cautiously, as it can have security implications.
Benefits:
-
Enhanced Security: Adhere to the principle of least privilege by granting only necessary permissions.
-
Increased Flexibility: Manage resources across different AWS accounts seamlessly.
AWS AssumeRole is a powerful feature for managing AWS resources across multiple accounts securely and efficiently with Terraform. By leveraging temporary credentials, you can adhere to the principle of least privilege, enhancing the overall security posture of your infrastructure. By understanding the steps involved in setting up AssumeRole, configuring your Terraform code, and following best practices, you can streamline your infrastructure management workflows while maintaining a high level of security. Remember to carefully consider the permissions granted to your IAM roles and utilize tools like the AWS Policy Simulator to validate your configurations. As you adopt more complex infrastructure setups, exploring advanced AssumeRole features like external IDs and session tags can further enhance your security and governance practices. By embracing these principles and techniques, you can confidently manage your AWS resources across multiple accounts using Terraform, ensuring a secure and well-organized cloud environment.
-
aws_iam_role | Resources | hashicorp/aws | Terraform | Terraform ... | This resource will take over exclusive management of the role's respective policy types (eg, both policy types if both arguments are used).
-
amazon web services - can i assume-role over an aws ec2 instance ... | Aug 20, 2018 ... looks like the special-sauce for my particular use case is Terraform's aws provider skip_metadata_api_check flag, which apparently inhibits ...
-
Docs overview | hashicorp/aws | Terraform | Terraform Registry | When the AWS Provider is running on an EC2 instance with an IAM Instance Profile set, the provider can source credentials from the EC2 Instance Metadata Service ...
-
Use AssumeRole to provision AWS resources across accounts ... | AWS AssumeRole allows you to grant temporary credentials with additional privileges to users as needed, following the principle of least privilege.
- ![MalformedPolicyDocument: Invalid principal in policy: "AWS" Only ... [MalformedPolicyDocument: Invalid principal in policy: "AWS" Only ... | #1388 The documentation specifically says this is allowed: https://www.terraform.io/docs/providers/aws/d/iam_policy_document.html#example-with-multiple-principals data "aws_caller_identity" "caller...
-
Backend Type: s3 | Terraform | HashiCorp Developer | Endpoints set for specific services will override the base endpoint configured in the profile. Assume Role Configuration. Assuming an IAM Role can be configured ...
-
How do you handle AWS permissions for terraform user? : r/Terraform | Posted by u/LexRivera - 13 votes and 22 comments
-
AWS EC2 Assume Role with Terraform | e-Zest | Nowadays, it is an ideal practice to keep different AWS accounts for IAM users and a different account for running production infrastructure. Also, Terraform is used to manage and provision cloud infrastructure. To create infrastructure in one account while users reside in another, the user needs to assume the role of that account. To provision resources using Terraform, which executes on an EC2 instance in the AWS account where users reside, we need to assume the role by saving credentials of resources account on the EC2 instance.
-
AWS assume role not working · Issue #472 · hashicorp/terraform ... | This issue was originally opened by @hkalyana as hashicorp/terraform#11270. It was migrated here as part of the provider split. The original body of the issue is below. Hi there, Thank you for open...