Unable to create an IAM role in AWS China Ningxia region

Viewed 900

I'm trying to use terraform to create an IAM role in AWS China Ningxia region.

Here's my folder structure

.
├── main.tf
└── variables.tf

Here's the content of main.tf

provider "aws" {
  access_key = var.access_key
  secret_key = var.secret_key
  region  = var.region
}

resource "aws_iam_role" "role" {
  name               = "TestRole"
  assume_role_policy = data.aws_iam_policy_document.policy_doc.json
}

data "aws_iam_policy_document" "policy_doc" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

And here's the variables.tf file:

variable "access_key" {}
variable "secret_key" {}
variable "region" {}

After running the following command

terraform apply \
  -var 'access_key=<my_access_key>' \
  -var 'secret_key=<my_secret_key>' \
  -var 'region=cn-northwest-1'

I got an error saying Error: Error creating IAM Role TestRole: MalformedPolicyDocument: Invalid principal in policy: "SERVICE":"ec2.amazonaws.com".

This terraform script works correctly in other regions of AWS (Tokyo, Singapore, ...). It seems like that AWS China is a little bit different from other regions.

Here's the message before I type yes to terraform:

Terraform will perform the following actions:

  # aws_iam_role.role will be created
  + resource "aws_iam_role" "role" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ec2.amazonaws.com"
                        }
                      + Sid       = ""
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + max_session_duration  = 3600
      + name                  = "TestRole"
      + path                  = "/"
      + unique_id             = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

Does anyone know how to create an IAM role like mine with terraform in AWS China?

3 Answers

I use aws iam get-account-authorization-details to view the current IAM roles in my AWS China accounts, which are created using AWS console.

Then I found lines containing "Service": "ec2.amazonaws.com.cn".

So using ec2.amazonaws.com.cn to replace ec2.amazonaws.com works without any problem.

I mean the content of main.tf should be

provider "aws" {
  access_key = var.access_key
  secret_key = var.secret_key
  region  = var.region
}

resource "aws_iam_role" "role" {
  name               = "TestRole"
  assume_role_policy = data.aws_iam_policy_document.policy_doc.json
}

data "aws_iam_policy_document" "policy_doc" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com.cn"]
    }
  }
}

Like so much in AWS, it is all fully documented... but the real challenge is in finding the documentation.

As you wrote, Brian, the answer is to use ec2.amazonaws.com.cn instead of ec2.amazonaws.com when working in China. But I thought the documentation above might be helpful since it includes all mappings.


Also, highly related:

If you use Terraform and you need to manage resources both in China and outside, you can use the data source aws_partition to help you generalize across China and non-China:

data "aws_partition" "current" {
}

data "aws_caller_identity" "current" {
}

Then later if you have something like:

    principals {
      type        = "AWS"
      identifiers = ["arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:role/my_cool_role"]
    }

Then it will evaluate the ARN as follows:

  • China: arn:aws-cn:iam::<my China account number>:role/my_cool_role
  • Anywhere else: arn:aws:iam::<my other account number>:role/my_cool_role

Note that in China it's aws-cn whereas it is aws otherwise.

This does assume that you have properly set up the two regions, so that "current" reflects back to the Chinese and non-Chinese accounts.

Related