Technical Blog テクニカルブログ
  1. HOME
  2. テクニカルブログ
  3. 【NIC x Ops(にこぷす)通信】(Terraform編)【連載】本当に買い?HCP Terraform Premiumをゆるっと検証 〜気になる「運用自動化」と「ガバナンス」ってぶっちゃけどうなの?(全6回)

【NIC x Ops(にこぷす)通信】(Terraform編)【連載】本当に買い?HCP Terraform Premiumをゆるっと検証 〜気になる「運用自動化」と「ガバナンス」ってぶっちゃけどうなの?(全6回)

投稿者:種田

【第6回】セキュリティはCI(Checkov)で、その他はSentinelで!ガードレール設計とSentinel検証

目次

  1. はじめに:セキュリティとコスト、ガードレールはどこで仕込む?
  2. ガードレールの全体像とチームでの設計
  3. 【検証】Sentinelで「コスト&命名規約ガードレール」を動かしてみた
  4. Policy as Code(PaC)導入のまとめ:安全とスピードを両立する運用へ
  5. 【総まとめ】HCP Terraform Premiumは結局「買い」なのか?
  6. おわりに

皆さま、こんにちは!
このテックブログでは、IT運用に関する内容を連載、「にこぷす通信」をお届けしています。

「NIC x Ops(にこぷす)」とは?

NIC x Ops(にこぷす)』とは、
私たちの会社であるNTTインテグレーション(NI+C)の運用ノウハウと、
IBMさんの強力なソリューションを
Collaboration(コラボレーション)させた、IT運用高度化シリーズ(Ops)のニックネームなんです。

現代のIT運用の現場は、システムの複雑化や人手不足など、課題が山積みです。そんな現場を少しでも楽に、そしてエンジニアの皆さんが笑顔で「攻めの運用」ができるように支えたい。そんな想いがこの「にこぷす」には込められています。

「にこぷす」には、Instana(可観測性)のほかにも、Turbonomic(リソース最適化)Terraform(インフラ自動化)など、IT運用を劇的に変える製品がたくさんあります。

これからもこの通信を通して、「IT用語は難しいけれど、中身を知ればこんなに便利で面白いんだ!」というテクニカルな内容をご紹介していきますので、どうぞよろしくお願いします。

1. はじめに:セキュリティとコスト、ガードレールはどこで仕込む?

皆さん、こんにちは!全6回に渡って連載してきた「運用自動化」と「ガバナンス」の最終回となります。

これまでドリフト検知やAuto-destroyによる「放置リソース対策」を検証してきましたが、クラウド運用で切っても切り離せないのが「ガバナンスとセキュリティの自動化」です。

  • 「開発環境にオーバースペックなインスタンスがデプロイされ、思わぬ高額請求が来た……」
  • 「設定ミスでストレージバケットが外部に公開されそうになった……」
  • 「タグや命名規約がバラバラで、誰の何のリソースか分からない……」

こうしたトラブルを防ぐために有効なのが「Policy as Code(PaC)」です。 HCP Terraform で使える Sentinel を導入すれば、セキュリティチェックから、コストの抑制、必須ラベルの強制、命名規約の統一まで、インフラ運用に必要なガードレールを幅広く自動化できます。

しかし実務においては、「これらをすべてSentinelで守るべきか」「他のレイヤーとどう組み合わせるべきか」というガードレールの配置や使い分けで悩むケースも少なくありません。

そこで今回は、まず「ガードレールをどこでどう効かせるべきか」という全体像を整理したうえで、Sentinel での実機検証をお届けします!

最後には連載全体の総まとめも用意していますので、ぜひ最後までお付き合いください。

2. ガードレールの全体像とチームでの設計例

インフラの「守り」を固めるにあたり、私たちのチームでは「どのタイミングで・何を使って・何を防ぐか」を整理し、以下のようなガードレールを組みました。

場所(タイミング) 採用した仕組み 主なターゲット(防ぎたいこと)
1開発端末(ローカル) pre-commit (gitleaks) 機密情報の誤コミット(APIキーや認証情報の直書き)
2CI/CD(PR作成時) GitHub Actions (Checkov) コード単体のセキュリティ設定ミス(バケット公開、暗号化漏れ等)
3HCP Terraform(Plan後) Sentinel コスト・命名規約(オーバースペックVM、ラベル/名前のルール違反)
4クラウド基盤(デプロイ先) GCP 組織ポリシー 全社共通のNGルール違反(VM外部IP付与、SAキー作成など)

機密情報は手元(ローカル)で即座に止め、一般的なセキュリティ問題は PR 時に CI(Checkov)で早期発見・修正させる(シフトレフト)。

そして、予算や命名規約といった運用ルールは Apply 直前の Sentinel で捕まえて人間が最終判断し、全社共通の「絶対NG」ルールは GCP 組織ポリシーで物理的にブロックする。という役割分担です。

ポイントは、各レイヤーの「例外スルーの権限レベル」を変えている点にあります。ローカルやCI(Checkov)でのスキップは開発者自身の手元で簡単に行えてしまうため PR レビューでチェックし、Sentinel や GCP 組織ポリシーでのスルーは「管理者の承認や設定」を必須にすることで、開発の柔軟性と組織の安全性を両立させています。

💡 コラム:Validation や precondition は「コーディング規約」、Sentinel は「セーフティネット」

Terraform 標準の validationprecondition をコード(リソースレベル)に仕込んでおくのは、手戻りを減らすためのベストプラクティスとして非常に有効です。

ただし、これらは「開発者がコードに書き忘れないこと」が前提となります。 コーディング規約(Validation等)で開発者自身に手元で素早く気づかせつつ、万が一の書き忘れや直書きをシステム側(Sentinel等)で一律キャッチする。この「運用ルール(標準)× システム制御(仕組み)」の組み合わせこそが、現実的なガバナンスの形です。


3. 【検証】Sentinelで「コスト&命名規約ガードレール」を動かしてみた

今回は Sentinel を使って、Google Cloud(GCE / GCS)に対する以下のルールを強制するポリシーを作成・検証しました。

  1. マシンタイプの制限: 指定したサイズ(e2-micro, e2-small, e2-medium 等)以外は拒否
  2. 必須ラベルと値の検証: env(値は dev, stg, prd のみ)と owner ラベルを強制
  3. リソース命名規約の強制: [システム名]-[環境]-[リソース種別]-[任意名] の形式を正規表現でチェック

今回の検証構成(同一リポジトリ運用と専用リポジトリの推奨)

今回は手軽に検証を進めるため、1つの Git リポジトリ内に Terraform コードと Sentinel ポリシーを同居させて VCS 連携を行いました。

ただし、本番運用においてはポリシー専用リポジトリ(例: tf-sentinel-policies)へ分離して VCS 連携するのがベストプラクティスです。インフラ開発者が自らポリシーコードを書き換えてルールを無効化するのを防ぎ(権限分離)、組織共通のルールとして全 Workspace に一括適用できるようにするためです。

📁 ディレクトリ構成
.
├── policy_sets/                  # Sentinel ポリシーの定義
│   ├── sentinel.hcl              # Sentinel 設定ファイル
│   └── policies/
│       ├── enforce-mandatory-labels.sentinel  # 必須ラベルの検証
│       ├── enforce-naming-convention.sentinel  # 命名規則の検証
│       └── restrict-gce-machine-type.sentinel  # マシンタイプの制限
│
└── terraform/                    # ポリシーの対象となる Terraform コード
    ├── main.tf                   # GCEインスタンスの作成定義
    ├── variables.tf              # 変数の定義
    ├── dev.auto.tfvars           # 開発環境用の設定値(テスト用)
    └── README.md                 # モジュール個別のドキュメント

ポリシーの定義(sentinel.hcl)と強度設定

Sentinel では、ポリシーごとに3つの強度(Enforcement Level)を設定できます。今回は「絶対修正」「管理者承認で通過可」「警告のみ」の3段階を定義しました。

📄 sentinel.hcl(クリックで展開)
# ① 命名規約:絶対に修正が必要(Hard-Mandatory)
policy "enforce-naming-convention" {
  source            = "./policies/enforce-naming-convention.sentinel"
  enforcement_level = "hard-mandatory"
}

# ② マシンタイプ制限:原則ブロックだが管理者承認で一時スルー可(Soft-Mandatory)
policy "restrict-gce-machine-type" {
  source            = "./policies/restrict-gce-machine-type.sentinel"
  enforcement_level = "soft-mandatory"
}

# ③ 必須ラベル:警告ログのみでデプロイは止めない(Advisory)
policy "enforce-mandatory-labels" {
  source            = "./policies/enforce-mandatory-labels.sentinel"
  enforcement_level = "advisory"
}

Sentinel ポリシーコード

tfplan/v2 インポートを使用し、Apply 前の変更予定(after)に対して各ルールを評価します。

このポリシーをセットすることで、無許可の巨大インスタンス作成や、命名ルール違反のバケット作成を全社レベルで防止できます。

📄 Sentinel ポリシーコード(クリックで展開)
import "tfplan/v2" as tfplan

# Policy settings
allowed_machine_types = ["e2-micro", "e2-small", "e2-medium"]

# Helper function
get_resources = func(type) {
  resources = {}
  for tfplan.resource_changes as address, rc {
    if rc.type is type and rc.mode is "managed" and (rc.change.actions contains "create" or rc.change.actions contains "update") {
      resources[address] = rc
    }
  }
  return resources
}

# Check logic
check_machine_types = func() {
  valid = true
  instances = get_resources("google_compute_instance")
  for instances as addr, rc {
    machine_type = ""
    if rc.change.after.machine_type is not null {
      machine_type = rc.change.after.machine_type
    }
    if machine_type not in allowed_machine_types {
      print("❌ [マシンタイプエラー]", addr, ": '", machine_type, "' は不可。許可一覧:", allowed_machine_types)
      valid = false
    }
  }
  return valid
}

# Execution & Main rule
# すべてのGCEインスタンスが、許可されたマシンタイプのみを使用していることを確認します。
main = rule { check_machine_types() }
import "tfplan/v2" as tfplan

# Policy settings
allowed_envs    = ["dev", "stg", "prd"]
required_labels = ["env", "owner"]

# Helper function
get_resources = func(type) {
  resources = {}
  for tfplan.resource_changes as address, rc {
    if rc.type is type and rc.mode is "managed" and (rc.change.actions contains "create" or rc.change.actions contains "update") {
      resources[address] = rc
    }
  }
  return resources
}

# Check logic
check_labels = func(type) {
  valid = true
  resources = get_resources(type)
  for resources as addr, rc {
    labels = {}
    if rc.change.after.labels is not null {
      labels = rc.change.after.labels
    }
    
    # Check for required label keys
    for required_labels as req {
      if req not in keys(labels) {
        print("❌ [ラベルエラー]", addr, ": 必須ラベル '", req, "' がありません。")
        valid = false
      }
    }
    
    # Check for env label value
    if "env" in keys(labels) and labels["env"] not in allowed_envs {
      print("❌ [ラベル値エラー]", addr, ": env の値 '", labels["env"], "' は不可。許可一覧:", allowed_envs)
      valid = false
    }
  }
  return valid
}

# Execution
gce_labels_ok = check_labels("google_compute_instance")
gcs_labels_ok = check_labels("google_storage_bucket")

# Main rule
# すべてのGCEインスタンスとGCSバケットに必須ラベルが付与されていることを確認します。
main = rule { gce_labels_ok and gcs_labels_ok }
import "tfplan/v2" as tfplan

# Policy settings
name_patterns = {
  "google_compute_instance": "^[a-z0-9]+-(dev|stg|prd)-gce-[a-z0-9-]+$",
  "google_storage_bucket":   "^[a-z0-9]+-(dev|stg|prd)-gcs-[a-z0-9-]+$",
}

# Helper function
get_resources = func(type) {
  resources = {}
  for tfplan.resource_changes as address, rc {
    if rc.type is type and rc.mode is "managed" and (rc.change.actions contains "create" or rc.change.actions contains "update") {
      resources[address] = rc
    }
  }
  return resources
}

# Check logic
check_naming = func(type, pattern) {
  valid = true
  resources = get_resources(type)
  for resources as addr, rc {
    name = ""
    if rc.change.after.name is not null {
      name = rc.change.after.name
    }
    if name not matches pattern {
      print("❌ [命名規約エラー]", addr, ": リソース名 '", name, "' がパターン違反です。(規約:", pattern, ")")
      valid = false
    }
  }
  return valid
}

# Execution
gce_naming_ok = check_naming("google_compute_instance", name_patterns["google_compute_instance"])
gcs_naming_ok = check_naming("google_storage_bucket", name_patterns["google_storage_bucket"])

# Main rule
# すべてのGCEインスタンスとGCSバケットが、定義された命名規則に従っていることを確認します。
main = rule { gce_naming_ok and gcs_naming_ok }

HCP Terraform での設定

Sentinel ポリシーコードが準備できたら、最後に HCP Terraform の画面から VCS(Git)リポジトリを連携してポリシーを適用します。

1. Policy Sets の作成

HCP Terraform の [Settings] > [Policy Sets] を開き、画面右上にある [+ Create policy set] ボタンをクリックします。

2. ポリシーリポジトリ(VCS)の連携

Policy set の作成画面(Choose source)が開いたら、ポリシーの管理方法として [Version control system (VCS) provider] を選択して右下の [Next] をクリックします。

3. ポリシーセットの基本設定(Configure settings)

Configure settings 画面が開いたら、ポリシーセットの基本情報と適用対象を設定します。

  • Policy framework: [Sentinel] を選択します。
  • Policy set name: 任意のポリシーセット名(例: sc-26q2-04-policy-as-code)を入力します。
  • Policy set description: 必要に応じてポリシーの用途などの説明(例: Sentinel 検証用ポリシー)を入力します。
  • Scope of policies: ポリシーを適用する対象(特定の Workspace やプロジェクトなど)を指定します。

入力が完了したら、次へ進んで VCS(GitHub等)との連携設定を行います。

4. ポリシーリポジトリ(VCS)の連携(Connect to VCS provider)

Connect to a VCS provider 画面が開いたら、Sentinel ポリシーを管理しているリポジトリや各種パス情報を設定します。

  • Organization / Repository: 連携する VCS 組織および対象のリポジトリ(例:your-organization/showcase-2026)を選択します。
  • Policies path: リポジトリ内で sentinel.hcl が配置されているディレクトリパス(例: /terraform/sc-26q2-04-policy-as-code/policy_sets)を指定します。
  • VCS branch: 参照する対象ブランチ(例: main)を指定します。
  • Policy update patterns: ポリシーコードの変更を自動検知して更新するためのパスルール(例: terraform/sc-26q2-04-policy-as-code/policy_sets/**)を設定します。

設定内容を確認し、右下の [Next](または作成完了)をクリックして接続を完了させます。これにより、該当 Workspace の Plan 実行時にリポジトリ内の Sentinel ポリシーが自動的に読み込まれて評価されるようになります。

動作確認

1. 初回 Plan 実行(ポリシー違反の発生)

テスト用コードで terraform plan(または VCS 経由の自動 Plan)を実行すると、Sentinel が即座に起動し、設定したルールに従ってチェックが行われます。

今回はあえて全ルールに違反するコードを流したため、以下のように Apply がブロックされました。

2. 命名規約エラーの解消(コード修正)

命名規約ルール(enforce-naming-convention.sentinel)は Hard-Mandatory に設定しているため、HCP Terraform 画面から管理者が上書き承認(Override)することはできません。

そのため、開発者が Terraform コード(main.tf)側のリソース名を正しい命名規則(app-dev-gce-01 など)に修正し、Git へコミット&プッシュして再度 Plan を走らせます。

3. マシンタイプエラーの承認(Override 実行)

コード修正後、命名規約のエラーは解消されましたが、依然としてマシンタイプ制限(Soft-Mandatory)の違反で Plan が一時停止しています。

今回は「一時的なベンチマークテストのために一時許可する」という想定で、権限を持つ管理者が HCP Terraform の画面上から [Override and Continue] をクリックします。

4. デプロイ(Apply)の完了

上書き承認(Override)が完了すると、Plan ステータスが通過状態(Overridden)に変わり、無事に terraform apply が実行可能になります。

なお、必須ラベルの警告(Advisory)はログに表示されたままでしたが、デプロイ自体を阻止することなく無事に処理が完了しました。

4. Policy as Code(PaC)導入のまとめ:安全とスピードを両立する運用へ

今回の検証を通して、Sentinel を活用した Policy as Code(PaC)の強力さと、クラウド運用における有用性が実感できました。最後に、PaC を導入・運用する上での重要なポイントをまとめます。

1. 「お願いベース」の運用から「システムによる自動ガードレール」へ

「ドキュメントに書いてある規約を守る」「レビューで人間がチェックする」といった運用は、組織やシステムが拡大するにつれて必ず限界がきます。PaC を導入することで、コスト超過につながる設定や命名ルールの違反を Apply 直前にシステムが自動で検知・ブロックできるようになります。

2. 開発スピードを殺さない「ガードレール」を作る

ガバナンスを効かせすぎると「開発のスピード感が失われる」と思われがちですが、PaC の本質は開発者を縛ることではありません。「万が一ミスをしても Sentinel が止めてくれる」という安心感があるからこそ、開発者は恐れずにスピード感をもってインフラを構築できます。

3. 役割に応じた「適切なレイヤーでの制御」が成功の鍵

すべてのルールを Sentinel だけで守ろうとする必要はありません。

  • CIツール(Checkov等): コード記述段階での標準的なセキュリティ違反を早期発見(シフトレフト)
  • Sentinel: 組織独自のコスト上限・命名規約・承認フローの制御(HCP Terraform上)
  • クラウド組織ポリシー: 絶対に許容しない最上位ルールの制御(クラウド基盤側)

このように適切なレイヤーでガードレールを敷き、例外処理(Override)のルールも設計しておくことで、安全性と柔軟性を両立したクラウド運用が実現します。

次の章では、これまでの連載(ドリフト検知・Auto-destroy・Sentinel)を踏まえ、HCP Terraform Premium が結局「買い」なのかどうかを総合的に判定します!


5. 【総まとめ】HCP Terraform Premiumは結局「買い」なのか?

全6回の検証を通して、Standard プラン(無料枠/小規模向け)と Premium プランの機能を評価してきました。最終的な総括をお伝えします!

全6回の振り返り

  1. 【第1回】スモールスタートするのが普通な中で、なぜ最初からHCP Terraform Premiumを評価しているのか?
  2. 【第2回】プレミアムの画面、全部見せます!Premiumプラン限定機能ツアー
  3. 【第3回】コード書かずにインフラ作れる?「No-Code Provisioning」をポチポチしてみた
  4. 【第4回】コンソールから勝手に弄った奴は誰だ。ドリフト検知で「野良変更」は許さないよ
  5. 【第5回】消し忘れよ、さようなら。時間が来たら自動で消える「自動削除機能」が超便利だった

これまでの連載では、HCP Terraform Premium が持つさまざまな運用自動化・ガバナンス機能を実機で検証してきました。

  • 標準化(第3回): GUIから簡単に標準化インフラをデプロイできる 「No-Code Provisioning」
  • 検知(第4回): コンソールからの手動変更(野良変更)を自動でキャッチする 「ドリフト検知」
  • コスト削減(第5回): 検証環境の消し忘れを防ぎ、放置リソースを自動抹消する 「Auto-destroy」
  • ガバナンス(第6回): コスト超過や命名規約違反を Apply 前にブロックする 「Sentinel(PaC)」

単に機能が豊富なだけでなく、「運用の現場がどれだけ楽になり、無駄なコストやセキュリティリスクを削減できるか」 という実践的な視点で検証を重ねてきました。

これらを踏まえ、最後に「HCP Terraform Premium は結局どんな組織にとって『買い』なのか」を判定します!

結論:「買い」になる組織、不要な組織

  • Premiumが「買い」な組織(元が取れる組織)
    • 開発・検証環境が多く、消し忘れや巨大インスタンスの放置で毎月定額以上の無駄コストが発生している組織
    • マルチチーム・複数プロジェクトで運用しており、共通のセキュリティ・命名ルールを強制したいプラットフォームチーム・クラウド管理部門がある組織
    • ドリフト検知や安全なデプロイフローで、運用障害の対応工数を削減したい組織
  • Standardや無料枠で十分な組織
    • 1〜2名の少人数で単一プロジェクトを管理しており、手動の通知やレビューで十分目が届く規模。

6. おわりに

「お願い」や「注意書きルール」に頼ったクラウド運用は、組織が大きくなるほど必ず破綻します。

HCP Terraform Premium が提供する Auto-destroySentinel などの機能は、開発者の自由度を奪うものではなく、「安全なガードレールの中で、開発者が安心してスピード感をもって挑戦できる環境」を作るための強力なパートナーでした。

全6回にわたる「にこぷす通信 Terraform編」をお読みいただき、本当にありがとうございました!皆さまの現場でのツール選定や運用改善の参考にしていただければ幸いです。

「にこぷす通信」について

「NIC × Ops(にこぷす)通信」は、隔週で皆さまに情報をお届けします。
このシリーズでは、Instana(可観測性)をはじめ、Turbonomic(リソース最適化)やTerraform(インフラ自動化)など、IT運用を劇的に変える製品をピックアップしていきます。
これからも最新の技術検証をチームで継続し、皆さまの現場ですぐに役立つ「有益な知見」を全力で共有していきます。 次回の連載もお楽しみに!

ページのトップへ