TF cloud OIDC authentication to AWS organization accounts

Hi, i trying to setup terraform cloud environ and i found example to setup OIDC authentication between terraform cloud and AWS.
https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/aws-configuration

I don’t quite understand that is that OIDC supposed to install only to AWS organization root account or every sub account in organization?

I think that would be gonvient, if i could setup that only to root AWS account and then i give administrator permissions to tf-role to use those sub accounts.

Does anyone have any best practises for over mentioned thing?

Hi @juvi87,

The “dynamic credentials” (OpenID Connect) mechanism works by having Terraform Cloud produce a signed statement that your configuration is being evaluated in the context of a particular Terraform Cloud workspace, and then configuring the system you’re authenticating to (AWS in your case) to trust that signed statement.

Therefore what’s possible here depends more on what AWS allows than what Terraform Cloud allows. AWS IAM would need to offer some mechanism to use a trust relationship defined in one account to authenticate to another account.

I must admit that I’m not super famililar with all of the details of “Organization Accounts” since they are a new mechanism that was added after I stopped doing AWS infrastructure management as a regular part of my job. I hope that others will see this and offer other suggestions that might be specific to organizations, but as a starting point I’m going to share some things I know about IAM in general (ignoring “Organization Accounts”) that might approximate what you’re looking for.

The general way that roles work in IAM is that use use credentials issued from some other IAM principal (e.g. a user or another role) to call an action like sts:AssumeRole, or sts:AssumeRoleWithWebIdentity, or similar. For that to work, the target role’s “assume role policy” (or, equivalently, “trust policy”) must specify that the source principal is allowed to perform that action with a particular set of conditions.

With that in mind, one way to achieve what you described would be to set up the OpenID provider for app.terraform.io and the role for Terraform Cloud to assume in only one of your accounts. You could then configure other roles in your other accounts – but not any OpenID provider objects – and set up those secondary roles to be “assumable” by the first.

In that case then, Terraform Cloud would only deal with the first level of authentication – setting up the configuration for assuming the first role using OpenID Connect dynamic credentials. Your Terraform configuration would then configure the AWS provider to use that first set of credentials to assume a role in one of your other accounts.

For that to work, the trust policy for the role in your first account would be set up with a trust policy using sts:AssumeRoleWithWebIdentity as shown in the Terraform Cloud documentation.

The trust policy for your roles in other accounts would then be configured to allow sts:AssumeRole from the role in the first account, which would look something like this:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Principal": {
                "AWS": "arn:aws:iam::MAIN-ACCOUNT-ID:role/MAIN-ROLE-NAME"
            }
        }
    ]
}

Your Terraform configuration’s configuration for the AWS provider would need to include an assume_role block referring to the target role – the one whose trust policy is like what I showed above – so that the AWS provider will use the credentials that were automatically issued using OpenID connect to obtain session credentials for the role in the other account.

I hope that’s a helpful starting point! There’s more on the general ideas here in the following AWS tutorial:

…the only significant difference being that in the example I’ve been describing the first authentication step is done using the OpenID Connect assume role path.