feat: add bootstrap IAM workflow and environment-scoped Terraform structure

This commit is contained in:
Haitao Pan 2025-11-16 23:54:43 +08:00
parent f7960153fe
commit 0b2050c886
18 changed files with 285 additions and 10 deletions

View File

@ -78,7 +78,17 @@ This creates:
PAY_PER_REQUEST billing mode Compatible with Terraform backend locking
## 4. Use in Terraform Backend
## 4. Bootstrap IAM Role
```
cd bootstrap-iam
terraform init
terraform apply \
-var="account_name=dev" \
-var="role_name=TerraformDeployRole-Dev"
```
## 5. Use in Terraform Backend
After both bootstrap steps are completed:
@ -92,7 +102,6 @@ terraform {
}
}
Then run:
terraform init -migrate-state

View File

@ -1,8 +0,0 @@
terraform {
backend "s3" {
bucket = "svc-plus-iac-state"
key = "sit/ec2/terraform.tfstate"
region = "svc-plus-iac-state-locks"
encrypt = true
}
}

View File

@ -0,0 +1,25 @@
# Local terraform files
.terraform/
.terraform.lock.hcl
terraform.tfstate
terraform.tfstate.backup
# Auto tfvars generated by CI/CD or sensitive data
*.tfvars
*.auto.tfvars
*.tfvars.json
# IDE / editor files
.idea/
.vscode/
*.swp
# AWS credentials — never commit
.aws/
credentials
config
# OS-specific
.DS_Store
Thumbs.db

View File

@ -0,0 +1,28 @@
resource "aws_iam_role" "terraform_deploy_role" {
name = var.role_name
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::${local.account.account_id}:root"
}
Action = "sts:AssumeRole"
}]
})
tags = merge(
{
Name = var.role_name
Environment = local.account.environment
},
local.account.tags
)
}
# Admin
resource "aws_iam_role_policy_attachment" "attach_admin" {
role = aws_iam_role.terraform_deploy_role.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}

View File

@ -0,0 +1,3 @@
output "role_arn" {
value = aws_iam_role.terraform_deploy_role.arn
}

View File

@ -0,0 +1,14 @@
terraform {
required_version = ">= 1.2"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.92"
}
}
}
provider "aws" {
region = var.region
}

View File

@ -0,0 +1,21 @@
variable "region" {
description = "AWS region"
type = string
}
variable "account_name" {
type = string
description = "Which account configuration to load (e.g., dev)"
}
variable "role_name" {
type = string
description = "IAM role name to create (e.g., TerraformDeployRole-Dev)"
}
locals {
account = yamldecode(
file("${path.root}/../config/accounts/${var.account_name}.yaml")
)
}

View File

@ -0,0 +1,20 @@
account_id: "730335654753" # 目前单账号
name: dev
environment: dev
region: ap-northeast-1
role_to_assume: arn:aws:iam::730335654753:role/TerraformDeployRole-Dev
logging_bucket: org-dev-logs
shared_vpc_account: "730335654753" # 单账号,所以保持一致
tags:
Environment: dev
Owner: Platform
CostCenter: "DEV"
backend:
bucket: svc-plus-iac-state
key_prefix: dev/
dynamodb_table: svc-plus-iac-state-dynamodb-lock

View File

@ -0,0 +1,25 @@
# Local terraform files
.terraform/
.terraform.lock.hcl
terraform.tfstate
terraform.tfstate.backup
# Auto tfvars generated by CI/CD or sensitive data
*.tfvars
*.auto.tfvars
*.tfvars.json
# IDE / editor files
.idea/
.vscode/
*.swp
# AWS credentials — never commit
.aws/
credentials
config
# OS-specific
.DS_Store
Thumbs.db

View File

@ -0,0 +1,9 @@
terraform {
backend "s3" {
bucket = "svc-plus-iac-state"
key = "account/iam/dev/terraform.tfstate"
region = "ap-northeast-1"
dynamodb_table = "svc-plus-iac-state-dynamodb-lock"
}
}

View File

@ -0,0 +1,11 @@
locals {
account = yamldecode(
file("${path.root}/../../config/accounts/dev.yaml")
)
}
# moduleiam
module "iam" {
source = "../../modules/iam"
account = local.account # << module
}

View File

@ -0,0 +1,9 @@
output "iam_role_arn" {
description = "IAM role ARN created for Terraform deployment"
value = module.iam.role_arn
}
output "iam_role_name" {
description = "IAM role name"
value = module.iam.role_name
}

View File

@ -0,0 +1,20 @@
terraform {
required_version = ">= 1.2"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.92.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
assume_role {
role_arn = "arn:aws:iam::730335654753:role/TerraformDeployRole-Dev"
session_name = "TerraformDevSession"
}
}

View File

@ -0,0 +1,25 @@
# Local terraform files
.terraform/
.terraform.lock.hcl
terraform.tfstate
terraform.tfstate.backup
# Auto tfvars generated by CI/CD or sensitive data
*.tfvars
*.auto.tfvars
*.tfvars.json
# IDE / editor files
.idea/
.vscode/
*.swp
# AWS credentials — never commit
.aws/
credentials
config
# OS-specific
.DS_Store
Thumbs.db

View File

@ -0,0 +1,18 @@
resource "aws_iam_role" "this" {
name = var.role_name
assume_role_policy = data.aws_iam_policy_document.assume.json
tags = var.tags
}
data "aws_iam_policy_document" "assume" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "AWS"
identifiers = ["*"] # OIDC provider
}
}
}

View File

@ -0,0 +1,3 @@
output "role_arn" {
value = aws_iam_role.this.arn
}

View File

@ -0,0 +1,25 @@
locals {
account = yamldecode(
file("${path.root}/../../config/accounts/dev.yaml")
)
}
terraform {
required_version = ">= 1.2"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.92.0"
}
}
}
provider "aws" {
region = var.region
assume_role {
role_arn = "local.account.role_to_assume"
session_name = "TerraformDevSession"
}
}

View File

@ -0,0 +1,18 @@
variable "account" {
type = object({
account_id = string
name = string
environment = string
region = string
role_to_assume = string
logging_bucket = string
shared_vpc_account = string
backend = object({
bucket = string
key_prefix = string
dynamodb_table = string
})
tags = map(string)
})
}