Dynamic Terraform Roles
This document describes the Dynamic Terraform Roles feature and its benefits, and, for users of the previous architecture, how to migrate to it. The AWS Access Control Architecture documentation assumes this feature is enabled and describes how to use it. The AWS Access Control Evolution documentation describes the feature in more detail.
The Dynamic Terraform Roles feature is not just about Terraform. It is part of a larger effort to normalize the roles and permissions in all accounts. As such, it includes not just updates to various components, but it includes a recommended restructuring of "teams" and "team roles". This restructuring makes a clear distinction (via naming conventions) between the IAM roles that represent teams and the IAM roles that team members can assume. The migration portion of this document includes instructions on how to migrate to the new " team" and "team role" names and configuration.
This document alone is a lot of information. Combined with the above links and specific migration instructions in the affected components, it could take days to fully read, understand, and implement. Please prepare yourself accordingly.
Background
Cloud Posse's current reference architecture includes a feature we call
"Dynamic Terraform Roles". This is in contrast to our previous implementation,
where we used a single, static role per account for all Terraform operations. In
the old implementation, access to Terraform was all-or-nothing (per account)
and based on whether or not the user was allowed to assume the static role. This
approach had some difficulties, including problems supporting AWS Identity
Center Permission Sets (which are implemented by dynamic roles), and an
inability to allow users to run terraform plan for drift detection or to
validate that their changes at least did not introduce any syntax errors,
without also allowing them to run terraform apply. It is also did not allow
for a "least privilege" approach to access control in the target accounts,
because the Terraform role requires full AdminAccess to the account, and there
was no way to give users more restricted access and still allow them to use
Terraform. The feature (or, more accurately, set of features) we call "Dynamic
Terraform Roles" addresses these issues.
Features and Benefits
In this section we describe the features and benefits of the Dynamic Terraform Roles feature at a high level. For a more detailed description, see AWS Access Control Evolution -> Dynamic Terraform Roles....
Freed from the requirement that all users use the same, single, static IAM role for all Terraform operations, we can now implement a more fine-grained access control policy.
- Full access: This was the only option under the previous architecture. With full access, users are allowed to assume the Terraform role in some or all accounts, and that role can be used for all Terraform operations. As before, users can be limited to only certain accounts, but before, when limited, they would have no Terraform access at all to the accounts to which they were not granted full access. Now there are other options for giving users something less than full access but more than no access.
- Plan-only access: Users can be granted access to a role that allows
only
terraform planoperations, but does not allow any modifications to the infrastructure. This is particularly useful for automated users like Spacelift or GitHub actions to perform drift detection on critical security settings without giving them the necessary authority to make changes (which would make them a very attractive target for malicious users). This is also useful, for example, for developers who want to see what changes their pull requests would make to infrastructure in production. Typically, DevOps and CI users would be granted full access in most accounts and plan-only access in the most sensitive ones, while developers would get full access only in development and sandbox accounts. - Individual Per-Account Terraform Users: Users can be granted access to
custom roles in each account, allowing them to modify some infrastructure
while not being able to modify other infrastructure, using ordinary IAM
policies. For example, developers could be allowed to deploy applications to
EKS without being allowed to modify the EKS cluster itself. As of this
writing, such individual roles need to be explicitly granted access to the
Terraform state via the configuration in the
tfstate-backendcomponent, but we could add attribute-based access control (ABAC) allowing access via tags on roles and thus eliminate the current requirement to thetfstate-backendcomponent to grant access to new roles every time there is a change. Contact Cloud Posse Professional Services if you are interested in this feature.
Direct Access versus Assume Role
In the previous architecture, users would be required to assume a role in
the identity account, and then Terraform would automatically assume the role
in the target account. This meant for every possible access pattern, there
needed to be a corresponding role in the identity account and users needed to
be granted access to that role, which would then be assumed in the target
account. This was a complex and unwieldy configuration, and it had an additional
downside: For users who were focused on working in a single account, they would
have to switch back and forth, using the identity
account role to perform Terraform operations in the target account, and then
switching back to their original role to perform AWS CLI or kubectl
operations in the target account.
Now it is possible to grant users a single role in the target account, and enable that role to be used for all Terraform operations. This simplifies both role assignments and user workflows.
Reduced Need for SuperAdmin and Other Special Configurations
In both the current and the previous architecture, a special "SuperAdmin" role
is created in the root (organization owner) account with full Admin
privileges. This role is needed to create the infrastructure that supports
creating the IAM roles that are used for ordinary operations. For example,
SuperAdmin is required to create the accounts and initial IAM roles themselves.
In the previous architecture, anything that ever needed to be done by the SuperAdmin role would always need to be done by the SuperAdmin role. This caused a lot of friction, because the SuperAdmin role was accessed by static API keys which had to be protected, manually rotated, and manually activated, and there was always a greater risk of these keys being leaked, since they were long-lived.
In the previous and current implementations, there was and is a single static
role that is used to access the Terraform state backend, and all Terraform users
except SuperAdmin were required to assume this role to access the Terraform
state, a prerequisite for running Terraform. In the previous architecture,
SuperAdmin was not allowed to assume this role because the role did not exist in
the early stages of bringing up a set of accounts. This limitation required
special configurations, such as var.privileged and backend.s3.role_arn: null in the Terraform configuration. In the new architecture, SuperAdmin can
assume the same static role as everyone else, so these special configurations
are only necessary for a small number of components, and to the extent an
organization desires, nearly all operations can be performed by the
root-admin role.
Enabling the root-admin role to do all the things that previously required the
SuperAdmin role converts the SuperAdmin role into more of a backup "break glass
in case of emergency" role, which allows for tighter access control, including
disabling or deleting access keys after use. Typically, whereas in the previous
architecture we only had the identity-admin role and greatly restricted what
the root-admin role could do, in the new architecture we add an
identity-devops role that matches roughly what the old identity-admin
role could do, and does not have access to the root-admin or
root-terraform roles. This would be the role that would be used for day-to-day
operations by senior DevOps engineers.
In this setup, the identity-admin is removed, to reduce confusion with
the *-admin roles in other accounts. A new role,
identity-managers, is added for those people who are trusted with full access
to the root account. From that role users would have access to the
root-terraform role to be able to run Terraform in the root account, and can
assume theroot-admin role, which could be used for most purposes that
previously required the SuperAdmin role.
Configuration and Usage
To understand how access control works using Dynamic Terraform Roles, see AWS Access Control Architecture, especially the section on Terraform Support.
The instructions below provide a thorough overview of the migration steps, but you should always refer to the latest documentation for each component to see if anything has changed since this was written.
Migrating to Dynamic Terraform Roles, pt. 1, preparation
This section describes how to start using Dynamic Terraform Roles if you are
already using the previous implementation. Customers who are new to Cloud Posse,
or who started using Cloud Posse's reference architecture after the release of
version 1.242.0 of the terraform-aws-components module, should not need to do
anything, it should already be enabled.
Phased Migration
The migration to Dynamic Terraform Roles can be done in a single step, but doing so would have the effect of locking everyone (except SuperAdmin) out of all accounts, and then you would have to reconfigure your IdP to allow people to log into the new roles. This is a significant disruption, so we recommend a phased approach:
- Ensure prerequisites are met
- Add the new roles to the
aws-teamsconfiguration - Migrate users to the new roles
- Remove the old roles from the
aws-teamsconfiguration and deployaws-team-rolesto theidentityaccount
This phased approach is laid out in the following sections. If you want to do it all at once, you can just go through all the phases without doing any commits or apply operations until the end, at which point, as SuperAdmin, apply the components in the following order:
tfstate-backendaccount-mapaws-teamsaws-team-roles
Prerequisites
This migration guide assumes your current configuration already meets the following prerequisites. If it does not, you may be able to find instructions adequate to upgrade your configuration to meet the prerequisites in the AWS Access Control Evolution documentation and/or the change logs for the individual components. If you cannot find the information you need there, please contact Cloud Posse Professional Services for assistance.
You must be using version 1.242.0 or later of these terraform-aws-components
components:
account-mapaws-team-rolesaws-teamstfstate-backendrootfs/usr/local/bin/aws-config
You must also have upgraded the providers.tf file in all your Terraform
components to the v1.238.0 version or later. This means if the component is
older than that version, you can either upgrade it to that version or later, or
you can just cherry-pick the providers.tf file (and any other providers for
those components that have multiple providers configured) from the v1.238.0
version.
All of the above components are backwards compatible with the old configurations
via legacy_* feature flags that are set to "legacy mode" by default. This
means you can upgrade the components first and then migrate your configuration
at your own pace.
You must have access to the SuperAdmin user. Although after the migration, you
may have little use for SuperAdmin, two areas where it should always be used
are when updating tfstate-backend and when updating the
aws-team-roles in the root account. During the migration, all Terraform
operations should be performed by SuperAdmin.
You must have already configured your Atmos stacks to use a
backend.s3.role_arn whose name ends in tfstate (or at least is not
terraform), created by the tfstate-backend component.
In older versions of the Cloud Posse reference architecture,
the root-terraform
role was used (assumed) by all users to access the Terraform state, and had
extremely limited permissions. In the new architecture, the root-terraform
role has full AdminAccess permissions and is used to perform all Terraform
operations in the root account, and therefore access to it should be highly
restricted.
It is therefore critical to ensure the following configuration is already in place:
- Your
tfstate-backendcomponent and Atmos stacks use abackend.s3.role_arnthat does not end interraform. - If a
terraformrole exists in therootaccount, only individuals authorized to use Terraform to modify therootaccount have access to it.
Failing to meet these requirements could result in users
- losing access to the Terraform state, or
- obtaining full AdminAccess to the
rootaccount
depending on the specific configuration.
Migrating to Dynamic Terraform Roles, pt. 2, Add the New Stuff
Configure the new teams
Because of some automatic configuration done in the new architecture, you need
to update all of your aws-teams and aws-team-roles stacks before applying
any Terraform changes.
Refresher: What are "teams" and "team roles"?
Cloud Posse, based on recommendations from Google and AWS, uses a hub-and-spoke
architecture for access control. In this architecture, we create a hub account
we call identity, and spoke accounts, which are all the other accounts in the
organization. There are no AWS Resource deployed in or owned by the identity
account other than IAM resources. Through various mechanisms, users and
automated services are granted IAM Roles in the
identity account. We call these roles "teams", and they are analogous to
"groups" in conventional access control systems. We call the IAM Roles in the
spoke accounts "team roles", and they grant access to the resources in those
accounts. Teams are granted or denied access to accounts by configuring the team
roles in those accounts to allow or deny the team to assume them.
Add the new teams to aws-teams
The configuration described below enables "managers" to have full Admin access
to the root account, largely replacing the SuperAdmin user, meaning that
access to the role should be as highly restricted as was access to the
SuperAdmin role. The configuration adds a "devops" team that has admin access to
all accounts other than root and identity, to take the place of
identity-admin in the previous configuration (which had limited access to
root and identity via other restrictions).
This is the configuration most popular with our customers, but obviously, other configurations are reasonable, trading off convenience for security. Adjust your configuration to suit your organization's needs.
In the configuration below, we include trusted_permission_sets for
organizations using AWS Identity Center (previously AWS SSO). If you are not
using the Cloud Posse aws-sso component, just remove the
trusted_permission_sets entries.
In much older versions of the Cloud Posse architecture, using the component
iam-primary-roles rather than aws-teams, the Permission Sets intended to
correspond to what we now call "teams" had names that ended with RoleAccess.
In the new architecture, these Permission Sets have names that end
with TeamAccess. We recommend you use the new names, but if you find that such
migration is too difficult, you can continue to use the old names. To use the
earlier convention, create
a account-map/modules/roles-to-principles/variables_override.tf
file in which you set variable
overridable_team_permission_set_name_pattern to default to
"Identity%sRoleAccess"
As a first step, we add the new teams and roles to the stacks. In the
aws-teams configuration, add the new teams:
managers:
<<: *user-template
role_description: "Team with AdministratorAccess to all accounts **including** `root`"
role_policy_arns:
- "arn:aws:iam::aws:policy/AdministratorAccess"
aws_saml_login_enabled: true
trusted_teams: [ "managers" ]
trusted_permission_sets: [ "IdentityManagersTeamAccess" ]
# The devops team is the normal team for DevOps personnel.
# It has full access to all accounts except `iam` and `root`.
devops:
<<: *user-template
role_description: "Team with PowerUserAccess permissions in `identity` and AdministratorAccess to all other accounts except `root`"
# Limit `devops` to Power User to prevent accidentally destroying the `devops` role itself
# Use SuperAdmin to administer IAM access
role_policy_arns:
- "arn:aws:iam::aws:policy/PowerUserAccess"
aws_saml_login_enabled: true
# list of roles in primary that can assume into this role in delegated accounts
# primary admin can assume delegated admin
trusted_teams: [ "managers", "devops" ]
trusted_permission_sets: [ "IdentityManagersTeamAccess", "IdentityDevopsTeamAccess" ]
In the old architecture, "teams" and "team roles" had the same name, and were
both referred to as roles. Access to a role in any account was automatically
granted by having access to the role of the same name in the identity account.
This was done to simplify configuration and implementation, before we
had Atmos, but it was very confusing and inflexible, and
violated our preference that the same role name should mean the same thing in
every account.
In the new architecture, teams have names distinct from team
roles, (team names are plural, while team role names are singular), and team
roles get deployed to the identity
account via aws-team-roles, just like every other account.
In the first phase of our multiphase migration, you leave the team roles
in aws-teams and do not deploy aws-team-roles to identity. This preserves
the ability to use the old roles for a transition period. However, if you can
afford the disruption and can run as SuperAdmin, you can remove the team roles
from aws-teams and deploy
aws-team-roles to identity at the same times as you make all the other
changes.
aws-teamsAt some point (see warning below) you want to remove these roles from the
aws-teams configuration:
adminpoweruserobserverreadersupportbillingbilling_adminhelmterraform
Most of those roles will be restored, because in the new architecture, we
deploy aws-team-roles to the identity account, too. For now, in the phased
migration approach, you should leave them in the configuration. Especially, you
should leave the terraform role in the identity account with full
AdminAccess, and enable the new managers team (and whatever other teams you
want to be able to use Terraform to make changes in the
identity account)
to assume it.
If you remove these roles from the aws-teams configuration before deploying
the new teams and giving people access to them, everyone but SuperAdmin will
lose access to all accounts.
You may want to add one or more teams for users that need some AWS access in some accounts, but not full Admin Access everywhere. As an example, here is how to create a new team for developers, who will have less access than DevOps personnel:
developers:
<<: *user-template
role_description: "Team with view permissions in `identity` and limited access to all other accounts"
role_policy_arns:
- "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"
- team_role_access
aws_saml_login_enabled: true
trusted_teams:
- managers
- devops
- developers
trusted_permission_sets:
- IdentityManagersTeamAccess
- IdentityDevopsTeamAccess
- IdentityDevelopersTeamAccess
The extra entries under trusted_teams and trusted_permission_sets allow
people on the managers and devops teams to assume the developers role in
identity, thereby allowing them to test out the permissions that developers
will have in other accounts.
identity accountYou may have been wondering about the team_role_access entry under
role_policy_arns in the developers team configuration above.
The identity account is an account that has no resources other than IAM roles
and policies. It is used to manage access to other accounts. Therefore, there is
not much that is needed to be done and few people need IAM permissions to do
anything in this account. We recommend in general minimizing permissions in
the identity account.
However, the prime function of the "teams" (implemented as IAM Roles) in the
identity account is to allow users to assume roles in other accounts. This
requires they have the IAM permissions to assume roles. Therefore, the
aws-teams component ships with a team_role_access policy that allows this.
Formally, all teams should have this policy, but in practice, it is redundant
for some users and can be omitted.
We recommend you add, at a minimum, these teams to the aws-teams:
managers: Full AdminAccess to all accounts. This is the role that mostly replaces the SuperAdmin role. You may want to give this role to just one or two people, or you may want to disable access to this role entirely, enabling access only when needed. In theidentityaccount, this role has fullAdministratorAccess.devops: Terraformplanner(ReadOnlyAccess) access in therootand theidentityaccount and AdminAccess to all other accounts. This is the role that most DevOps engineers will use for day-to-day operations. In theidentityaccount, this role hasPowerUserAccess, which is access to almost anything other than IAM.
You may want to add these teams:
developers: (See above) Configured viaaws-team-rolesto have whatever access you want developers to have in whatever accounts. Inidentity, we recommendViewOnlyAccessandteam_role_access.helpdesk: A team that has access to thesupportrole in all accounts. This is useful for troubleshooting and for performing routine maintenance tasks.bookkepers: A team that has access to thebillingrole in all accounts. This is useful for reading billing invoice and tracking payments.controllers: A team that has access to thebilling_adminrole in all accounts. This is useful for managing billing, budgets, and creating reports.
Configure the new roles: pt. 1: The defaults
You should have default settings for aws-team-roles in your stacks. Review
the default settings and make the following changes.
Add the planner role
In the aws-team-roles configuration, add a planner role:
# The planner role allows use of `terraform plan` but does not allow any changes to be made
planner:
# This assumes you have &user-template defined earlier in the YAML file
<<: *user-template
enabled: true
role_description: "Role for running terraform plan"
role_policy_arns:
- "arn:aws:iam::aws:policy/ReadOnlyAccess"
- "eks_viewer"
# You may want to add other teams here, e.g. helpdesk
# If you have a CI/CD team, you may want to add it here, too
trusted_teams: [ "managers", "devops", "developers" ]
trusted_permission_sets: [ "IdentityManagersTeamAccess", "IdentityDevopsTeamAccess", "IdentityDevelopersTeamAccess" ]
terraform and plannerThis guide assumes you are using Cloud Posse's naming conventions for roles,
specifically, terraform for Terraform-managed infrastructure modifications
and planner for Terraform plan-only access. You can use different names if
you want to, but you will need to create roles with some name that fulfill
these purposes, and you will need to configure account-map (specifically,
terraform_role_name_map) with the names you choose.
Configure access to the planner role
One major point of this whole migration is to enable users to run terraform plan without being able to make changes. Give those users access to the
planner role via trusted_teams, trusted_permission_sets, or both.
Further limit the planner role (optional, not recommended)
You can further restrict the planner role, for example by removing the
eks_viewer policy, and replacing ReadOnlyAccess with a more restrictive
policy such as arn:aws:iam::aws:policy/job-function/ViewOnlyAccess in certain
accounts. However, this will probably cause terraform plan to fail for some
components. This may be acceptable if you are allowing Spacelift or some other
automated process access to the full terraform role in those accounts, but if
you are restricting those, too, (as you should for the
root and identity accounts), then you will lose the ability to perform drift
detection on those components.
You might want to make such changes in only a subset of accounts, such as
security or audit accounts, or production accounts. Although this goes
against the rule of having the same role mean the same thing in every account,
it is a tradeoff the architecture designers made in order to have consistent
automatic access to the appropriate role via Terraform.
Remove outdated roles
You might want to remove outdated roles such as helm and cicd if you
have them in your configuration. You can add them back later if you need
them. At the time of this writing, the standard set of roles from Cloud
Posse is:
admin: Full access to all resourcesbilling: Read-only access to AWS billing informationbilling_admin: Full access to AWS billing informationsupport: Access to AWS support resourcespoweruser: Full access to all resources except IAMobserver: View-only access to non-sensitive resourcesreader: Read-only access to all resourcesterraform: Used by Terraform to make changes to the infrastructure viaapplyoperationsplanner: Used by Terraform when the user does not have access to theterraformrole, with the intention that this role be allowed to perform plan operations without being able to make changes
We also include a disabled role called template that is used to establish the
default settings for roles to help keep things DRY.
Outdated Cloud Posse roles include:
helm: Previously we usedhelmandhelmfilefor deploying Helm charts to Kubernetes. We now use Terraform exclusively (using thehelmandkubernetesproviders). If you are still using Helm, you may want to keep this role.cicdandspacelift: These were the roles used by automated processes. We now recommend they assume a team inidentity, and that team be allowed to assume the roles in other accounts as usual.
You are more than welcome to add additional roles that suit your purposes,
but if you find a role that is not in this list and not one you added,
such as helm or spacelift, then you can delete it now.
Add custom roles
For all accounts, including root and identity, add your standard set of team
roles and remove outdated roles. Remember, we strongly recommend that the roles
in each account have exactly the same permissions, so that the same role name
means the same thing everywhere. However, you can and probably should have
different trusted_teams and trusted_permission_sets for the same role in
different accounts. For example, in a "sandbox" account, you might be OK with
giving developers access to the admin role, but in a production account, you
might want to restrict them to the planner role or even the
observer role.
This difference in who can assume the role in different accounts is the chief
benefit of the new architecture. By changing who has access to the
terraform or planner role in each account, you can restrict who can do what
via Terraform in each account. We recommend that only managers
should have access to terraform and admin in root and identity. As you
update the team roles, you should review and adjust who has access to them in
each account.
If you need a role in some account with different permissions, give it a
different name. For example, maybe give Developers a developer role in some
accounts where admin
or poweruser is not appropriate, but only deploy that role in those accounts
where you want developers to have that level of access, and in other accounts,
create a triage role or use the
support role so that developers can have some more restricted access. Do not
create a developer role in every account and then change what IAM policies are
attached to that role in each account, because we have seen in practice that
this leads to confusion and mistakes.
Enable access to the roles from the new teams
In the aws-team-roles configuration, add the new teams to the trusted_teams
list for all the roles, as appropriate. For example, add managers to all
the roles, maybe add devops to all the roles (to be overridden in the
root and identity accounts), and add helpdesk to the support role
Later, you will remove the old roles from trusted_teams, but you want to
wait until everyone is using the new teams before you do that.
Configure the new roles: pt. 2: The exceptions
You should have customized settings for aws-team-roles for the root and
identity accounts. Update the settings for those accounts as follows.
Fully normalize the terraform role, pt. 1
As discussed under Prerequisites above, the terraform role
in much older versions of the Cloud Posse reference architecture was used to
access the Terraform state backend, and had extremely limited permissions.
You should have already updated your configuration to use a backend.s3.role_arn
that does not end in terraform, but it is possible you simply removed
or disabled the terraform role from the root account and left the
configuration using the admin role to perform Terraform operations in the
root and identity accounts.
We will prepare to undo this wart in the configuration by giving the
terraform role in root and identity full AdminAccess, and restricting
access to them to the managers team.
In the root account:
In the aws-team-roles stack configuration for the root account, ensure that
the terraform role is enabled and has full AdminAccess. This is the default
configuration for aws-team-roles, so it may have already been inherited by
default and then simply disabled, in which case you can just enable it now.
You will, however, want to restrict access to the terraform role to the
managers team. This is done by setting the trusted_teams list to
["managers"]. (In Atmos, maps are merged, but lists are replaced.)
While you are there, you may want to modify the planner role, giving
the devops team access to it, and perhaps including the CI/CD team(s).
In the identity account:
In the identity account, the terraform role should currently be
controlled by the aws-teams configuration. You should have already added
managers the trusted_teams list for the terraform role via aws-teams,
but double-check now.
Later, you will deploy the aws-team-roles stack to the identity account,
and move control of the role from aws-teams to aws-team-roles. At that
point you will want to ensure the same non-default access controls for
identity that you established above for root.
Migrate your current customizations
You may have customized access to any of the aws-team-roles roles in
certain accounts. We have already discussed root and identity, but you
may have also customized the roles in production accounts, or security or
audit or other sensitive accounts. You should review and update these
customizations to ensure that the new teams (managers, devops,
developers, etc.) have the appropriate access to the roles in those
accounts.
Apply phase 1 changes to account-map
At this point, your aws-teams and aws-team-roles configurations should be
updated to include the new teams and roles, and the new teams should be given
access to the roles in the aws-team-roles configuration.
Update your account-map configuration to toggle the features:
legacy_terraform_uses_admin: true
terraform_dynamic_role_enabled: true
Optionally, have Atmos validate the syntax of your configuration:
atmos validate stacks
Fix any issues, then apply the changes (you will need to be SuperAdmin to do this). Adjust the stack name as necessary to match your configuration.
atmos terraform apply account-map -s core-gbl-root
Update tfstate-backend
Your configuration for the tfstate-backend component should already be set up
to manage the role that is used to access the Terraform state and specified
in your backend.s3.role_arn configuration. Update that configuration to include
the new teams, plus root-admin and SuperUser.
access_roles:
default: &access-template
write_enabled: true
allowed_roles:
# Everyone who uses Terraform, even for planning, needs read/write access.
# Add the new teams to the list, e.g "managers", "devops", "developers"
# that currently looks something like this:
core-identity: ["admin", "cicd", "ops", "platform", "poweruser", "spacelift"]
# Add a new entry to allow the root-admin role to access the Terraform state
core-root: ["admin"]
# Add a new entry to allow the SuperUser role to access the Terraform state
# Replace existing `allowed_principal_arns` empty list with a list containing
# the ARN of the SuperUser role, substituting your root account ID for <root-account-ID>
allowed_principal_arns: [arn:aws:iam::<root-account-ID>:user/SuperAdmin]
If you have a read-only role, make the same additions, being careful not to remove any access.
Apply that configuration, adjusting the stack name as necessary to match your
configuration. Note that unlike the other components we are changing, whose
stacks are in the global gbl "region", tfstate-backend is deployed to
your primary region, so you will need to adjust that part of the stack name
accordingly.
Note that you will need to be SuperAdmin to do this.
atmos terraform apply tfstate-backend -s core-usw2-root
Apply phase 1 changes to aws-teams and aws-team-roles
Now you are ready to apply the changes to aws-teams and aws-team-roles.
Deploy the aws-teams stack to the identity account:
atmos terraform apply aws-teams -s core-gbl-identity
Deploy the aws-team-roles stack all the other accounts except identity:
atmos terraform apply aws-team-roles -s <tenant>-gbl-<stage>
Update aws-config-teams
Check your Dockerfile to see if you are using the aws-config-teams file to
configure the AWS SDK. Look for this line:
ENV AWS_CONFIG_FILE=/etc/aws-config/aws-config-teams
If you are not using that exact configuration, consider starting to use it now (more below).
It is managed by the aws-config script, which is installed in your Git
repository in the rootfs/usr/local/bin directory. You can install or
update it from
terraform-aws-components.
You can then update the aws-config-teams file by running the aws-config
script:
aws-config teams > rootfs/etc/aws-config/aws-config-teams
Note that the script depends on files in
the components/terraform/account-map/account-info/ and
components/terraform/aws-team-roles/iam-role-info/ directories that are
generated by account-map and aws-team-roles (plus aws-teams),
respectively. Make sure all the files in those directories are checked into Git
and updated. If you did not have the aws-config script installed before, you
will probably need to add these files to your repository.
If you are using something other than aws-config-teams to configure the
AWS SDK, now would be a good time to start using it. Unlike earlier
solutions, aws-config is automatically maintained by the Terraform
components, so after making changes to the aws-teams and aws-team-roles,
you just need to run account-map and then aws-config to update the AWS
configuration.
The aws-config script also can generate the configuration for the browser
plugin AWS Extend Switch Roles,
via the switch-roles subcommand. If you are using that plugin, update that
configuration now, too:
aws-config switch-roles > rootfs/etc/aws-config/aws-extend-switch-roles
You may also want to generate a configuration for Spacelift or other CICD.
aws-config spacelift > rootfs/etc/aws-config/aws-config-spacelift
The spacelift subcommand generates a configuration appropriate for
Spacelift, but it is likely to be a useful starting for other CICD systems,
too. All you likely need to do is change the role_arn and
role_session_name for the <namespace-identity> profile.
Run aws-config with no arguments to list all the subcommands.
Migrating to Dynamic Terraform Roles, pt. 3, switch over to the new stuff
Somehow you are currently giving users access to roles in the identity
account, perhaps via AWS Identity Center (previously AWS SSO) Permission Sets,
perhaps via a SAML IdP. However you are doing that, you need to switch users
over to using the new teams: managers, devops, developers, etc.
We leave those details up to you. Once you have everyone switched over to using the new teams, you can move on to the next step.
Migrating to Dynamic Terraform Roles, pt. 4, clean up
Remove the old teams from aws-teams
Remove all the old teams from the aws-teams configuration.
identityOnce you remove the terraform role from the aws-teams configuration,
ordinary Terraform usage in the identity account will be broken. However,
the goal of the identity is to have no resources other than IAM roles and
thus no ordinary Terraform operations should be necessary. The SuperUser
will continue to be able to deploy aws-teams and aws-team-roles, and
after making the changes, ordinary Terraform operations will be restored.
Remove the following teams from the aws-teams configuration:
adminbillingbilling_adminsupportpoweruserobserverreaderterraformhelm
You may also want to remove teams like ops, cicd, and spacelift, but
check first to make sure they are not still needed.
Apply the changes to the aws-teams stack in the identity account:
atmos terraform apply aws-teams -s core-gbl-identity
Remove the old access from aws-team-roles
Go through the aws-team-roles configurations and remove the old teams
(like admin) from the trusted_teams list for all the roles. Note that in
the new configuration, no team roles have the same name as teams, so if you
see a team role's own name in the trusted_teams list (previously standard
configuration, now outdated), you should remove it.
Fully normalize the terraform role, pt. 2
In earlier versions of the Cloud Posse reference architecture, the terraform
role in the identity account was managed by aws-teams, and
aws-team-roles was not deployed to the identity account. Now that you have
cleaned out the old teams from aws-teams, you can and should deploy
aws-team-roles to the identity account. It should be configured in the
same way you have aws-team-roles configured for the root account.
Deploy aws-team-roles to the all accounts
Deploy the aws-team-roles stack to all the accounts, including identity:
atmos terraform apply aws-team-roles -s <tenant>-gbl-<stage>
Apply final changes to account-map
Update your account-map configuration to toggle the features:
legacy_terraform_uses_admin: false
terraform_dynamic_role_enabled: true
Update account-map (Adjust the stack name as necessary to match your
configuration.)
atmos terraform apply account-map -s core-gbl-root
Normalize Terraform State Backend Access
Search your stacks for backend and remote_state_backend configurations
that have role_arn: null or var.privileged: true. You can remove these
settings, and if those are the only backend or remote_state_backend
settings being overridden, remove the entire configuration section.
Update config files (optional)
If you want to, you can use the aws-config script to update the various files
generated earlier. This is optional, as all it will do is remove the old
teams and roles no longer in use.