[profile dev] region = ap-northeast-1 output = json
[profile prod] region = ap-northeast-1 output = json
[sso-session my-sso] sso_start_url = https://example.awsapps.com/start sso_region = ap-northeast-1 sso_registration_scopes = sso:account:access aws sso login --sso-session my-sso aws sso logout --sso-session my-sso PKCE authorization (default since AWS CLI v2.22.0) Recommended for desktop/mobile access; provides secure OAuth 2.0 flow Automatic token refresh without re-authentication Requires AWS CLI v2.9.0+ or v1.27.10+; sso-session configuration enables token refresh support Use SSO with sso-session for human users; use IAM roles for services
.github/workflows/deploy.yml
permissions: id-token: write contents: read
jobs: deploy: runs-on: ubuntu-latest steps: - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole aws-region: ap-northeast-1 No long-term credentials stored in CI/CD; temporary credentials via STS Validate OIDC thumbprints and restrict ClientIDList to prevent misconfiguration
Wait for EC2 instance to reach running state aws ec2 wait instance-running --instance-ids i-1234567890abcdef0 Wait for CloudFormation stack creation aws cloudformation wait stack-create-complete --stack-name my-stack
provider "aws" { region = "ap-northeast-1" }
assume_role { role_arn = "arn:aws:iam::987654321098:role/TerraformRole" session_name = "terraform-session" external_id = "unique-external-id" } }
provider "aws" { region = "us-east-1" alias = "virginia" }
resource "aws_s3_bucket" "tokyo_bucket" { provider = aws.tokyo bucket = "my-tokyo-bucket" }
resource "aws_s3_bucket" "virginia_bucket" { provider = aws.virginia bucket = "my-virginia-bucket" }
default_tags { tags = { Environment = "dev" ManagedBy = "terraform" Project = "my-project" } } }
attribute { name = "LockID" type = "S" } }
tags = { Name = "main-vpc" } }
resource "aws_subnet" "public" { count = 2 vpc_id = aws_vpc.main.id cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index) availability_zone = data.aws_availability_zones.available.names[count.index] map_public_ip_on_launch = true
tags = { Name = "public-subnet-${count.index + 1}" } }
resource "aws_internet_gateway" "main" { vpc_id = aws_vpc.main.id }
ingress { from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] }
egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } }
assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "lambda.amazonaws.com" } } ] }) }
resource "aws_iam_role_policy_attachment" "lambda_basic" { role = aws_iam_role.lambda_role.name policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" }
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = ["ffffffffffffffffffffffffffffffffffffffff"] }
resource "aws_iam_role" "github_actions" { name = "github-actions-role"
assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Principal = { Federated = aws_iam_openid_connect_provider.github.arn } Action = "sts:AssumeRoleWithWebIdentity" Condition = { StringEquals = { "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com" } StringLike = { "token.actions.githubusercontent.com:sub" = "repo:org/repo:*" } } } ] }) } Always restrict sub claim to specific repos/branches
resource "aws_s3_bucket_versioning" "main" { bucket = aws_s3_bucket.main.id versioning_configuration { status = "Enabled" } }
resource "aws_s3_bucket_server_side_encryption_configuration" "main" { bucket = aws_s3_bucket.main.id
rule { apply_server_side_encryption_by_default { sse_algorithm = "AES256" } } }
resource "aws_s3_bucket_public_access_block" "main" { bucket = aws_s3_bucket.main.id
block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true }
filename = "lambda.zip" source_code_hash = filebase64sha256("lambda.zip")
environment { variables = { ENV = "production" } } }
setting { name = "containerInsights" value = "enabled" } }
resource "aws_ecs_task_definition" "app" { family = "my-app" network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] cpu = "256" memory = "512" execution_role_arn = aws_iam_role.ecs_execution.arn task_role_arn = aws_iam_role.ecs_task.arn
container_definitions = jsonencode([ { name = "app" image = "nginx:latest" portMappings = [ { containerPort = 80 hostPort = 80 } ] } ]) }
db_name = "mydb" username = "admin" password = var.db_password
vpc_security_group_ids = [aws_security_group.rds.id] db_subnet_group_name = aws_db_subnet_group.main.name
backup_retention_period = 7 skip_final_snapshot = false final_snapshot_identifier = "my-database-final"
tags = { Name = "my-database" } }
output "account_id" { value = data.aws_caller_identity.current.account_id }
output "region" { value = data.aws_region.current.name }
filter { name = "name" values = ["al2023-ami-*-x86_64"] } }
cidr_block = "10.0.0.0/16" name = "main" }
name = "my-vpc" cidr = "10.0.0.0/16"
azs = ["ap-northeast-1a", "ap-northeast-1c"] private_subnets = ["10.0.1.0/24", "10.0.2.0/24"] public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true single_nat_gateway = true }