コンテンツにスキップ

Phase 5a:静的解析(tflint / checkov)

目標

apply の前に、ツールでコードの問題を自動的に見つけます。

ツール チェック対象
tflint Terraform の書き方:バージョン制約、未使用の変数、description の欠落など
checkov セキュリティ設定:暗号化、メタデータ・サービス、ネットワークの公開範囲など

インストール

winget install --id TerraformLinters.tflint -e       # 新しく開いた shell でないと PATH が反映されない
python -m pip install --user checkov                 # exe が PATH にない → python -m checkov.main で実行

OCI には公式の tflint ruleset がありません → Terraform 言語自体のルール(plugin "terraform"、組み込み)だけを使います。

実行

tflint --recursive --config "$PWD\.tflint.hcl"
$env:PYTHONUTF8 = '1'                                  # ← 必須。下のハマりどころを参照
python -m checkov.main -d . --framework terraform --compact

指摘内容と対処(Phase 4 のコードに対して)

ツール 指摘 対処
tflint モジュール(module)に required_version / provider のバージョン制約がない モジュールには下限(>= 9.0)だけを書き、具体的なバージョンは呼び出し側(~> 9.0)で決める
tflint output に description がない 追記
checkov CKV_OCI_5 旧バージョンのメタデータ・サービス(IMDS v1)が無効化されていない instance_options { are_legacy_imds_endpoints_disabled = true }
checkov CKV_OCI_4 ブート・ボリューム(Boot Volume)の転送中暗号化が有効になっていない launch_options { is_pv_encryption_in_transit_enabled = true }
checkov CKV_OCI_21 NSG(ネットワーク・セキュリティ・グループ)の ingress ルールが stateless ではない 変更しない。skip コメントで理由を明記
  • IMDS v1 はトークン不要のため、SSRF 攻撃で悪用されやすい(AWS の IMDSv2 と同じ問題)
  • 修正後:tflint 0 件、checkov 成功 18 / 失敗 0 / skip 3

意図的に変更しないものは skip コメントを書く

resource "oci_core_network_security_group_security_rule" "lb_http_from_my_ip" {
  #checkov:skip=CKV_OCI_21:Low traffic lab; stateful rules are simpler and sufficient
  ...
}

stateless ルールでは戻りトラフィック用のルールを別に書く必要があり(ルール数が倍になり、設定ミスもしやすい)、メリットが出るのは大量トラフィックのときだけです。 skip コメント = 「リスクを理解したうえで、意図的に変更しない」という判断と理由をコードに残すこと。レビュー時に見えますし、checkov の結果にも理由が表示されます。

学んだこと

静的解析が通る ≠ 安全

checkov は次の点を指摘しませんでした:要塞(Bastion)の 0.0.0.0/0、ADB のパブリック・エンドポイント(public endpoint)、LB が HTTP のみ。 OCI のルールは AWS よりかなり少ないため、設計レベルの問題はやはり人によるレビューが必要です。

checkov が認識する書き方は 1 つだけ

is_pv_encryption_in_transit_enabled は oci_core_instance のトップレベルにも launch_options の中にも書けます。 トップレベルに書いても provider は正常に動きますが、checkov は失敗と判定します → checkov のソースコードを見ると、launch_options の中しかチェックしていませんでした。

apply 時に起きたこと

  • plan:0 to add, 2 to change(in-place、プライベート IP は変わらない)
  • しかし VM が再起動されました → apply 直後に LB にアクセスすると 502 Bad Gateway(2 台が同時に再起動し、どちらもヘルスチェックに通らない)。数十秒後に復旧
  • 本番環境では 1 台ずつ変更します:-target で 2 回に分けて apply する、または先に LB のバックエンドから外す

in-place ≠ 無停止

~(in-place)は OCID が変わらないことを示すだけで、再起動しないという意味ではありません。どの属性の変更で再起動が発生するかは、provider のドキュメントを確認するか、先にテスト環境で試します。

ハマりどころ

checkov:UnicodeDecodeError: 'cp932' codec can't decode

checkov はデフォルトで Windows のシステム・エンコーディング(日本語 Windows では cp932)でファイルを読むため、UTF-8 で書いた日本語・中国語のコメントがあるとエラーになります。 → $env:PYTHONUTF8 = '1'(Python の UTF-8 モード)。

tflint --recursive で設定ファイルが見つからない

サブディレクトリに .tflint.hcl がない → --config で絶対パスを指定します。