IaCセキュリティとベストプラクティス
ストーリー
「IaCで自動化できたからといって、セキュリティを疎かにしていいわけじゃない」
木村先輩が警告した。
「むしろIaCだからこそ、セキュリティの問題がコードに残る。 セキュリティグループを
0.0.0.0/0で全開放するコードが レビューをすり抜けてapplyされたら、大事故だ」「コードレビューで見つけられませんか?」
「人間の目だけに頼るな。自動化できるものは自動化する。 セキュリティスキャンツールをCIに組み込むんだ」
IaCのセキュリティリスク
よくあるセキュリティ問題
| リスク | 例 | 影響 |
|---|---|---|
| 過度に緩い権限 | SG で 0.0.0.0/0 を全ポート許可 | 不正アクセス |
| シークレットのハードコード | パスワードを .tf に直接記述 | 認証情報漏洩 |
| 暗号化の未設定 | S3/EBS/RDS の暗号化なし | データ漏洩 |
| パブリックアクセス | S3バケットのパブリック公開 | データ漏洩 |
| ログ未設定 | CloudTrail/VPC Flow Logs なし | 監査不能 |
セキュリティスキャンツール
tfsec
Terraformコードのセキュリティスキャンツールです。
bash
# インストール
brew install tfsec
# スキャン実行
tfsec .
# 出力例
Result #1 CRITICAL Security group rule allows ingress from public internet
Resource: aws_security_group.web
File: main.tf:45-52
Reason: Security group rule allows ingress from 0.0.0.0/0 on port 22
55 | ingress {
56 | from_port = 22
57 | to_port = 22
58 | protocol = "tcp"
59 | cidr_blocks = ["0.0.0.0/0"] ← SSH を全世界に公開
60 | }checkov
包括的なIaCセキュリティスキャナーです。
bash
# インストール
pip install checkov
# スキャン実行
checkov -d .
# 特定のチェックをスキップ
checkov -d . --skip-check CKV_AWS_18CIへの組み込み
yaml
# .github/workflows/terraform-security.yml
name: Terraform Security
on:
pull_request:
paths:
- 'infrastructure/**'
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: tfsec scan
uses: aquasecurity/tfsec-action@v1.0.3
with:
working_directory: infrastructure/
soft_fail: false
- name: checkov scan
uses: bridgecrewio/checkov-action@v12
with:
directory: infrastructure/
framework: terraform
quiet: true
soft_fail: falseセキュアなTerraformコーディング
1. セキュリティグループ:最小権限
hcl
# NG: 全ポートを全世界に公開
resource "aws_security_group" "bad" {
ingress {
from_port = 0
to_port = 65535
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # 全世界からアクセス可能
}
}
# OK: 必要なポートのみ、必要なソースから
resource "aws_security_group" "good" {
ingress {
description = "HTTP from ALB only"
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [aws_security_group.alb.id] # ALBからのみ
}
}2. S3バケット:パブリックアクセスブロック
hcl
# 全てのS3バケットにパブリックアクセスブロックを設定
resource "aws_s3_bucket_public_access_block" "this" {
bucket = aws_s3_bucket.this.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}3. 暗号化の徹底
hcl
# S3
resource "aws_s3_bucket_server_side_encryption_configuration" "this" {
bucket = aws_s3_bucket.this.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
# EBS
resource "aws_instance" "web" {
root_block_device {
encrypted = true
}
}
# RDS
resource "aws_db_instance" "this" {
storage_encrypted = true
}4. シークレットの外部管理
hcl
# NG: パスワードをハードコード
resource "aws_db_instance" "bad" {
password = "MyP@ssw0rd123" # コードに直接記述
}
# OK: 変数で注入(CI/CDから渡す)
resource "aws_db_instance" "good" {
password = var.db_password # 変数で外部から注入
}
# さらに良い: AWS Secrets Managerを使用
data "aws_secretsmanager_secret_version" "db_password" {
secret_id = "myapp/db-password"
}
resource "aws_db_instance" "best" {
password = data.aws_secretsmanager_secret_version.db_password.secret_string
}5. ログの有効化
hcl
# VPC Flow Logs
resource "aws_flow_log" "vpc" {
vpc_id = aws_vpc.this.id
traffic_type = "ALL"
iam_role_arn = aws_iam_role.flow_log.arn
log_destination = aws_cloudwatch_log_group.flow_log.arn
}
# S3 アクセスログ
resource "aws_s3_bucket_logging" "this" {
bucket = aws_s3_bucket.this.id
target_bucket = aws_s3_bucket.logs.id
target_prefix = "s3-access-logs/"
}Terraformコーディング規約
ファイル構成
| ファイル | 内容 |
|---|---|
main.tf | メインのリソース定義 |
variables.tf | 入力変数 |
outputs.tf | 出力値 |
providers.tf | プロバイダ設定 |
backend.tf | Stateバックエンド設定 |
locals.tf | ローカル変数 |
data.tf | データソース |
versions.tf | バージョン制約 |
命名規則
| 対象 | 規則 | 例 |
|---|---|---|
| リソース名 | snake_case | aws_instance.web_server |
| 変数名 | snake_case | var.instance_type |
| モジュール名 | snake_case | module.vpc |
| タグ | PascalCase or kebab-case | Name = "web-server" |
コードレビューチェックリスト
Terraform PRレビューチェックリスト
[ ] terraform fmt が適用されている
[ ] terraform validate が通る
[ ] tfsec / checkov でセキュリティスキャン済み
[ ] plan の出力で意図しない削除(-)がない
[ ] シークレットがハードコードされていない
[ ] 暗号化が有効になっている
[ ] タグが適切に設定されている
[ ] 削除保護が必要なリソースに prevent_destroy がある
まとめ
| ポイント | 内容 |
|---|---|
| セキュリティスキャン | tfsec / checkov をCIに組み込む |
| 最小権限 | SG、IAMは必要最小限の権限のみ |
| 暗号化 | S3、EBS、RDS の暗号化を必須化 |
| シークレット | コードにハードコードせず外部管理 |
チェックリスト
- IaCのセキュリティリスクを説明できる
- tfsec / checkov のCIへの組み込み方法を理解した
- セキュアなTerraformコーディングパターンを把握した
- PRレビューでのセキュリティチェックポイントを理解した
次のステップへ
次のセクションでは、学んだ知識を全て使って、フルスタックIaCを構築する演習に挑戦します。
推定読了時間: 30分