我一直在使用 Terraform 在其中创建一个 AWS 组织和三个额外的帐户。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
cloud {
hostname = "app.terraform.io"
organization = "MyOrg"
workspaces {
name = "MyWorkspace"
}
}
}
provider "aws" {
region = var.aws_region
}
resource "aws_organizations_organization" "organization" {
}
resource "aws_organizations_account" "users" {
name = "users"
email = "users@example.com"
role_name = "Admin"
}
resource "aws_organizations_account" "staging" {
name = "staging"
email = "staging@example.com"
role_name = "Admin"
}
resource "aws_organizations_account" "production" {
name = "production"
email = "production@example.com"
role_name = "Admin"
}
provider "aws" {
assume_role {
role_arn = "arn:aws:iam::${aws_organizations_account.users.id}:role/Admin"
}
alias = "users"
region = var.aws_region
}
provider "aws" {
assume_role {
role_arn = "arn:aws:iam::${aws_organizations_account.users.id}:role/Admin"
}
alias = "staging"
region = var.aws_region
}
provider "aws" {
assume_role {
role_arn = "arn:aws:iam::${aws_organizations_account.users.id}:role/Admin"
}
alias = "production"
region = var.aws_region
}
resource "aws_iam_group" "self_managing" {
name = "SelfManaging"
provider = aws.users
}
resource "aws_iam_group_policy_attachment" "iam_read_only_access" {
group = aws_iam_group.self_managing.name
policy_arn = "arn:aws:iam::aws:policy/IAMReadOnlyAccess"
provider = aws.users
}
resource "aws_iam_group_policy_attachment" "iam_self_manage_service_specific_credentials" {
group = aws_iam_group.self_managing.name
policy_arn = "arn:aws:iam::aws:policy/IAMSelfManageServiceSpecificCredentials"
provider = aws.users
}
resource "aws_iam_group_policy_attachment" "iam_user_change_password" {
group = aws_iam_group.self_managing.name
policy_arn = "arn:aws:iam::aws:policy/IAMUserChangePassword"
provider = aws.users
}
resource "aws_iam_policy" "self_manage_vmfa" {
name = "SelfManageVMFA"
policy = file("${path.module}/data/self_manage_vmfa.json")
provider = aws.users
}
resource "aws_iam_group_policy_attachment" "self_manage_vmfa" {
group = aws_iam_group.self_managing.name
policy_arn = aws_iam_policy.self_manage_vmfa.arn
provider = aws.users
}
module "developer_role_staging" {
source = "./modules/developer-role"
trusted_entity = "arn:aws:iam::${aws_organizations_account.users.id}:root"
providers = {
aws = aws.staging
}
}
module "developer_role_production" {
source = "./modules/developer-role"
trusted_entity = "arn:aws:iam::${aws_organizations_account.users.id}:root"
providers = {
aws = aws.production
}
}
module "developer_group_staging" {
source = "./modules/developer-group"
group_name = "DevelopersStaging"
assume_role_arns = [
module.developer_role_staging.role_arn,
]
providers = {
aws = aws.users
}
}
module "developer_group_production" {
source = "./modules/developer-group"
group_name = "DevelopersProduction"
assume_role_arns = [
module.developer_role_production.role_arn
]
providers = {
aws = aws.users
}
}
我运行 Terraform 的用户没有完全正确的权限。组织和帐户已创建,但状态似乎不包含它们。如果我运行terraform apply
,则表明它将添加它们。但是,一旦接受该计划,每个帐户都会出现以下错误:-
Error: Error waiting for account request (car-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx) to become available: EMAIL_ALREADY_EXISTS
我阅读了aws_organizations_account 资源的文档,其中状态我可以terraform import aws_organizations_account.my_org 111111111111
用来将其导入状态。但是,当我运行时,我得到了几个:-
Error: Invalid provider configuration
│
│ on path-to\main.tf line 42:
│ 42: provider "aws" {
│
│ The configuration for provider["registry.terraform.io/hashicorp/aws"].users depends on values that cannot be determined until apply.
我真的被困住了,希望能得到一些指点。
更新
根据要求,我添加了输出terraform plan
Terraform v1.1.0
on linux_amd64
Configuring remote state backend...
Initializing Terraform configuration...
aws_organizations_organization.organization: Refreshing state... [id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
<= read (data resources)
Terraform will perform the following actions:
# aws_iam_group.self_managing will be created
+ resource "aws_iam_group" "self_managing" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "SelfManaging"
+ path = "/"
+ unique_id = (known after apply)
}
# aws_iam_group_policy_attachment.iam_read_only_access will be created
+ resource "aws_iam_group_policy_attachment" "iam_read_only_access" {
+ group = "SelfManaging"
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/IAMReadOnlyAccess"
}
# aws_iam_group_policy_attachment.iam_self_manage_service_specific_credentials will be created
+ resource "aws_iam_group_policy_attachment" "iam_self_manage_service_specific_credentials" {
+ group = "SelfManaging"
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/IAMSelfManageServiceSpecificCredentials"
}
# aws_iam_group_policy_attachment.iam_user_change_password will be created
+ resource "aws_iam_group_policy_attachment" "iam_user_change_password" {
+ group = "SelfManaging"
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/IAMUserChangePassword"
}
# aws_iam_group_policy_attachment.self_manage_vmfa will be created
+ resource "aws_iam_group_policy_attachment" "self_manage_vmfa" {
+ group = "SelfManaging"
+ id = (known after apply)
+ policy_arn = (known after apply)
}
# aws_iam_policy.self_manage_vmfa will be created
+ resource "aws_iam_policy" "self_manage_vmfa" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "SelfManageVMFA"
+ path = "/"
+ policy = jsonencode(
{
+ Statement = [
+ {
+ Action = [
+ "iam:CreateVirtualMFADevice",
+ "iam:EnableMFADevice",
+ "iam:ResyncMFADevice",
+ "iam:DeleteVirtualMFADevice",
]
+ Effect = "Allow"
+ Resource = [
+ "arn:aws:iam::*:mfa/${aws:username}",
+ "arn:aws:iam::*:user/${aws:username}",
]
},
+ {
+ Action = [
+ "iam:DeactivateMFADevice",
]
+ Condition = {
+ Bool = {
+ aws:MultiFactorAuthPresent = "true"
}
}
+ Effect = "Allow"
+ Resource = [
+ "arn:aws:iam::*:mfa/${aws:username}",
+ "arn:aws:iam::*:user/${aws:username}",
]
+ Sid = "AllowUsersToDeactivateTheirOwnVirtualMFADevice"
},
+ {
+ Action = [
+ "iam:ListMFADevices",
+ "iam:ListVirtualMFADevices",
+ "iam:ListUsers",
]
+ Effect = "Allow"
+ Resource = "*"
},
]
+ Version = "2012-10-17"
}
)
+ policy_id = (known after apply)
+ tags_all = (known after apply)
}
# aws_organizations_account.production will be created
+ resource "aws_organizations_account" "production" {
+ arn = (known after apply)
+ email = "production@example.com"
+ id = (known after apply)
+ joined_method = (known after apply)
+ joined_timestamp = (known after apply)
+ name = "production"
+ parent_id = (known after apply)
+ role_name = "Admin"
+ status = (known after apply)
+ tags_all = (known after apply)
}
# aws_organizations_account.staging will be created
+ resource "aws_organizations_account" "staging" {
+ arn = (known after apply)
+ email = "staging@example.com"
+ id = (known after apply)
+ joined_method = (known after apply)
+ joined_timestamp = (known after apply)
+ name = "staging"
+ parent_id = (known after apply)
+ role_name = "Admin"
+ status = (known after apply)
+ tags_all = (known after apply)
}
# aws_organizations_account.users will be created
+ resource "aws_organizations_account" "users" {
+ arn = (known after apply)
+ email = "users@example.com"
+ id = (known after apply)
+ joined_method = (known after apply)
+ joined_timestamp = (known after apply)
+ name = "users"
+ parent_id = (known after apply)
+ role_name = "Admin"
+ status = (known after apply)
+ tags_all = (known after apply)
}
# module.developer_group_production.data.template_file.assume_role will be read during apply
# (config refers to values not yet known)
<= data "template_file" "assume_role" {
+ id = (known after apply)
+ rendered = (known after apply)
+ template = (known after apply)
}
# module.developer_group_production.aws_iam_group.this will be created
+ resource "aws_iam_group" "this" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "DevelopersProduction"
+ path = "/"
+ unique_id = (known after apply)
}
# module.developer_group_production.aws_iam_group_policy_attachment.assume_role will be created
+ resource "aws_iam_group_policy_attachment" "assume_role" {
+ group = "DevelopersProduction"
+ id = (known after apply)
+ policy_arn = (known after apply)
}
# module.developer_group_production.aws_iam_policy.assume_role will be created
+ resource "aws_iam_policy" "assume_role" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "DevelopersProductionAssumeRole"
+ path = "/"
+ policy = (known after apply)
+ policy_id = (known after apply)
+ tags_all = (known after apply)
}
# module.developer_group_staging.data.template_file.assume_role will be read during apply
# (config refers to values not yet known)
<= data "template_file" "assume_role" {
+ id = (known after apply)
+ rendered = (known after apply)
+ template = (known after apply)
}
# module.developer_group_staging.aws_iam_group.this will be created
+ resource "aws_iam_group" "this" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "DevelopersStaging"
+ path = "/"
+ unique_id = (known after apply)
}
# module.developer_group_staging.aws_iam_group_policy_attachment.assume_role will be created
+ resource "aws_iam_group_policy_attachment" "assume_role" {
+ group = "DevelopersStaging"
+ id = (known after apply)
+ policy_arn = (known after apply)
}
# module.developer_group_staging.aws_iam_policy.assume_role will be created
+ resource "aws_iam_policy" "assume_role" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "DevelopersStagingAssumeRole"
+ path = "/"
+ policy = (known after apply)
+ policy_id = (known after apply)
+ tags_all = (known after apply)
}
# module.developer_role_production.data.template_file.trust_relationship will be read during apply
# (config refers to values not yet known)
<= data "template_file" "trust_relationship" {
+ id = (known after apply)
+ rendered = (known after apply)
+ template = (known after apply)
}
# module.developer_role_production.aws_iam_role.this will be created
+ resource "aws_iam_role" "this" {
+ arn = (known after apply)
+ assume_role_policy = (known after apply)
+ create_date = (known after apply)
+ force_detach_policies = false
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "Developer"
+ name_prefix = (known after apply)
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
+ inline_policy {
+ name = (known after apply)
+ policy = (known after apply)
}
}
# module.developer_role_production.aws_iam_role_policy_attachment.administrator_access will be created
+ resource "aws_iam_role_policy_attachment" "administrator_access" {
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
+ role = "Developer"
}
# module.developer_role_staging.data.template_file.trust_relationship will be read during apply
# (config refers to values not yet known)
<= data "template_file" "trust_relationship" {
+ id = (known after apply)
+ rendered = (known after apply)
+ template = (known after apply)
}
# module.developer_role_staging.aws_iam_role.this will be created
+ resource "aws_iam_role" "this" {
+ arn = (known after apply)
+ assume_role_policy = (known after apply)
+ create_date = (known after apply)
+ force_detach_policies = false
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "Developer"
+ name_prefix = (known after apply)
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
+ inline_policy {
+ name = (known after apply)
+ policy = (known after apply)
}
}
# module.developer_role_staging.aws_iam_role_policy_attachment.administrator_access will be created
+ resource "aws_iam_role_policy_attachment" "administrator_access" {
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
+ role = "Developer"
}