AgentSkillsCN

Remote State Boundaries

按环境、账户和域名划分状态隔离模式,有效缩小攻击面

SKILL.md
--- frontmatter
name: Remote State Boundaries
description: State isolation patterns by environment, account, and domain to reduce blast radius

Remote State Boundaries

Overview

Terraform state should be isolated to reduce blast radius and enable independent deployments. This skill covers state organization patterns for multi-environment, multi-account setups.

mermaid
graph TB
    subgraph "State Organization"
        subgraph "By Environment"
            DevState[dev/terraform.tfstate]
            StagingState[staging/terraform.tfstate]
            ProdState[prod/terraform.tfstate]
        end
        
        subgraph "By Layer"
            Foundation[foundation/terraform.tfstate]
            Platform[platform/terraform.tfstate]
            Workloads[workloads/terraform.tfstate]
        end
    end

State Isolation Strategies

StrategyUse CaseBlast Radius
MonolithicSmall projectsHigh
Per-EnvironmentSingle teamMedium
Per-LayerPlatform teamLow
Per-Layer-Per-EnvEnterpriseVery Low

Best Practices

  1. Never share state across accounts - Security boundary
  2. Separate by blast radius - What can break together?
  3. Use locking - DynamoDB for S3 backend
  4. Limit access - Least privilege to state
  5. Encrypt state - Contains sensitive values
  6. Version state bucket - Recovery from corruption

Example 1: Terraform - S3 Backend with Isolation

State per environment and layer with proper locking.

📁 Location: terraform/examples/remote-state/

Backend Configuration

hcl
# backend.tf
terraform {
  backend "s3" {
    bucket         = "mycompany-terraform-state"
    key            = "layers/foundation/prod/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
    
    # Workspace-based key pattern
    workspace_key_prefix = "env"
  }
}

State Bucket Setup

hcl
# state-bucket/main.tf
resource "aws_s3_bucket" "state" {
  bucket = "${var.org_name}-terraform-state-${data.aws_caller_identity.current.account_id}"
}

resource "aws_s3_bucket_versioning" "state" {
  bucket = aws_s3_bucket.state.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "state" {
  bucket = aws_s3_bucket.state.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.state.arn
    }
  }
}

resource "aws_dynamodb_table" "locks" {
  name         = "terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

Example 2: CDK - Isolated Pipelines

CDK stacks with isolated state per stage.

📁 Location: cdk/examples/remote-state/

Pipeline Stages

typescript
// Each environment has isolated synth/deploy
const pipeline = new pipelines.CodePipeline(this, 'Pipeline', {
  synth: new pipelines.ShellStep('Synth', {
    commands: ['npm ci', 'npm run build', 'npx cdk synth'],
  }),
});

// Dev stage - independent state
pipeline.addStage(new MyApplicationStage(this, 'Dev', {
  env: { account: DEV_ACCOUNT, region: 'us-east-1' },
}));

// Prod stage - requires manual approval
pipeline.addStage(new MyApplicationStage(this, 'Prod', {
  env: { account: PROD_ACCOUNT, region: 'us-east-1' },
}), {
  pre: [new pipelines.ManualApprovalStep('PromoteToProd')],
});

Naming Convention

code
s3://{org}-terraform-state-{account}/
├── foundation/{env}/terraform.tfstate
├── platform/{env}/terraform.tfstate
└── workloads/{app}/{env}/terraform.tfstate

Validation Checklist

  • State bucket versioning enabled
  • State encrypted with KMS
  • DynamoDB locking configured
  • State access restricted (IAM policies)
  • Separate state per environment
  • Cross-account access via assume role

Related Skills