最近の記事

埋め込み属性をできるだけ使用しない

ルール

Do not use embedded attributes as much as possible. (e.g., ingress/egress within security groups)

(埋め込み属性をできるだけ使用しない(例: セキュリティグループ内の ingress/egress))

解説

埋め込み属性は可読性が悪い・ループなどの操作がしづらい・更新時に一時的に削除されることがあるなど、使いづらさが目立つため、極力使わないようにします。

サンプルコード

resource "aws_security_group" "web" {
  name        = "${var.environment}-${var.project}-web-sg"
  description = "Webサーバー用セキュリティグループ"
  vpc_id      = var.vpc_id
}

resource "aws_security_group_rule" "web_https_ingress" {
  type              = "ingress"
  from_port         = 443
  to_port           = 443
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.web.id
}

resource "aws_security_group_rule" "web_egress" {
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.web.id
}

参考リンク

Infrastructure 開発ガイドライン Coding Standards

すべての.tfファイルにterraform fmtを適用する

ルール

Apply terraform fmt to all .tf files.

(すべての.tfファイルにterraform fmtを適用する)

解説

「フォーマッタが正しい」これをプロジェクトのルールにします。

個人のスタイルの違いが出ないよう、ツールにすべて任せます。

サンプルコード

# terraform fmt 実行前
resource "aws_instance" "web" {
instance_type="t3.micro"
  ami=data.aws_ami.ubuntu.id
    tags={
  Name="web-server"
    }
}

# terraform fmt 実行後
resource "aws_instance" "web" {
  instance_type = "t3.micro"
  ami           = data.aws_ami.ubuntu.id

  tags = {
    Name = "web-server"
  }
}

参考リンク

Infrastructure 開発ガイドライン Coding Standards

重要なリソースとデータは常にバックアップする。DR戦略はバックアップ&リストアレベル

ルール

Always backup important resources and data. DR strategy is at backup & restore level

(重要なリソースとデータは常にバックアップする。DR戦略はバックアップ&リストアレベルとする)

解説

重要なリソースとは自社保有の暗号鍵など、データとはデータベース上のレコードなどです。 これらの消失はサービス存続にも関わる大損害をもたらすため、必ずバックアップします。

ここではコスト面を重視しDR(災害対策)はバックアップ&リストア方式を採用していますが、プロジェクトの性格次第でそれ以外の戦略を取ってももちろんかまいません。

サンプルコード

なし

参考リンク

Infrastructure 開発ガイドライン Design

TFLintを導入してAWSベストプラクティス違反と未使用宣言を検出する

ルール

Introduce TFLint to detect AWS best practice violations and unused declarations.

(TFLintを導入してAWSベストプラクティス違反と未使用宣言を検出する)

解説

人間のレビューを受ける前に機械的なチェックで済ませられることを極力済ませておきます。

これは人間のレビュー負荷軽減に貢献します。

サンプルコード

$ tflint

参考リンク

Infrastructure 開発ガイドライン Coding Standards

terraform validateで構文検証を実行する

ルール

Perform syntax validation with terraform validate.

terraform validateで構文検証を実行する)

解説

生成AIが最初に出したコードには時折構文エラーが含まれます。 これらを自動的に検出し、自動で修正させるため、ツールによるバリデーションを行います。

人間のレビュー負荷軽減のための施策の一つです。

サンプルコード

# 構文検証の実行
$ terraform validate

参考リンク

Infrastructure 開発ガイドライン Coding Standards

terraform.tfvars.jsonはルートモジュールに配置する

ルール

Place terraform.tfvars.json in the root module (the module where terraform apply is executed) instead of submodules.

terraform.tfvars.jsonはルートモジュールに配置し、サブモジュールには配置しない)

解説

混乱防止のため、terraform.tfvars.jsonは必ずルートモジュールに置くルールです。

サンプルコード

# ディレクトリ構造
#
# terraform/
#   production/
#     main.tf
#     variables.tf
#     terraform.tfvars.json    # ← ここに配置
#   modules/
#     networking/
#       main.tf
#       variables.tf
#       # terraform.tfvars.json は配置しない

Infrastructure 開発ガイドライン Coding Standards

terraform.tfvars.jsonには再利用値と機密情報を格納する

ルール

In the root module, ensure terraform.tfvars.json stores: 1) values that other modules might also reuse, 2) sensitive information that must never be hard-coded (e.g., private keys).

(ルートモジュールのterraform.tfvars.jsonには、1) 他のモジュールでも再利用する値、2) ハードコードしてはならない機密情報を格納する)

解説

平文の機密情報はなるべくTerraformを通さずに利用したいところですが、利用せざるを得ないケースもあります。その場合はコード内にハードコーディングせず、terraform.tfvars.jsonに記述してsopsで暗号化します。

なおこのアプローチをとる場合、そのリポジトリでCursorやClaudeCodeなどクラウドタイプのAIを利用してはいけません。

サンプルコード

# terraform.tfvars.json(良い例)
{
  "environment": "production",
  "project": "myapp",
  "region": "ap-northeast-1",
  "db_password": "encrypted_password_here",
  "ssl_certificate_private_key": "encrypted_key_here"
}

# variables.tf
variable "environment" {
  type        = string
  description = "Environment name"
}

variable "project" {
  type        = string
  description = "Project name"
}

variable "db_password" {
  type        = string
  sensitive   = true
  description = "Database password"
}

# main.tf
module "database" {
  source = "../modules/database"

  environment = var.environment
  project     = var.project
  password    = var.db_password
}

module "networking" {
  source = "../modules/networking"

  environment = var.environment
  project     = var.project
}

Infrastructure 開発ガイドライン Coding Standards

Nameタグを識別子として使用するリソースには必ずNameタグを設定する

ルール

Always set Name tags for resources that use Name tags as identifiers.

(Nameタグを識別子として使用するリソースには必ずNameタグを設定する)

解説

EC2インスタンスなど、Nameタグが事実上のリソース名として用いられるリソースがいくつかあります。

これらはNameタグが適切につけられていないと管理運用が難しくなるため、必ずセットします。

サンプルコード

resource "aws_instance" "api" {
  tags = {
    Name = "${var.environment}-${var.project}-api"
  }
}

参考リンク

Infrastructure 開発ガイドライン Coding Standards

共通タグはaws_default_tagsのみで設定する

ルール

Common tags such as Environment and Service must be set only in aws_default_tags. Do not define them in any individual resource block.

EnvironmentServiceなどの共通タグはaws_default_tagsのみで設定する。個別のリソースブロックで定義しない)

解説

すべてのAWSリソースに共通して付与すべきタグはaws_default_tagsで一元管理します。個々のリソースブロックで設定してはならないのですが、AIはやりがちのため、明示的に禁止しています。

サンプルコード

# providers.tf
provider "aws" {
  region = "ap-northeast-1"

  default_tags {
    tags = {
      Environment = var.environment
      Service     = var.service
    }
  }
}

# main.tf - 個別リソースでは共通タグを定義しない
resource "aws_s3_bucket" "main" {
  bucket = "${var.environment}-${var.service}-data"
  # Environment、Serviceタグは自動的に付与される
}

Infrastructure 開発ガイドライン Coding Standards

variableブロックはvariables.tfに定義する

ルール

Define variable blocks in variables.tf.

(variableブロックはvariables.tfに定義する)

解説

variableブロックの置き場所を定めておくことで可読性を向上させます。

サンプルコード

# variables.tf
variable "environment" {
  type        = string
  description = "Environment name (e.g., production, staging)"
}

variable "vpc_cidr" {
  type        = string
  description = "CIDR block for VPC"
}

variable "enable_nat_gateway" {
  type        = bool
  description = "Whether to create NAT Gateway for private subnets"
}

参考リンク

Infrastructure 開発ガイドライン Coding Standards