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 で絶対パスを指定します。