【実務・中級編】Pulumi CrossGuardを使ったインフラガバナンス:Policy as Codeの実装と実践 – インフラ構成管理(IaC)活用バイブル

Pulumi CrossGuardが変えるインフラガバナンス:CI/CDの速度を落とさずセキュリティを担保するPolicy as Codeの実践

こんにちは。大規模クラウドインフラの設計からSRE体制の構築までを統括しているテックリードです。

「セキュリティレビューのチケットを切ってから承認が下りるまで数日かかる」
「Terraformの`sentinel`やOpa/Regoの学習コストが高すぎてチーム全体に浸透しない」
「開発スピードを落とさずに、ジュニアメンバーのうっかりミス(S3パブリック公開など)を防ぎたい」

こうしたインフラ開発のボトルネックに頭を悩ませていないでしょうか。
IaC(Infrastructure as Code)の普及によりインフラ構築の速度は劇的に向上しましたが、それに比例して「ガバナンスの欠如によるインフラの脆弱化」というリスクも増大しています。

ここで登場するのが、Pulumi CrossGuardです。

今回は、使い慣れたTypeScriptやPythonを用いて、デプロイメント前にインフラストラクチャのコンプライアンスを自動検証する「Policy as Code」の実装と、現場の生産性を極限まで高める実践的テクニックを余すところなく解説します。

—

1. なぜ Pulumi CrossGuard なのか?

世の中には OPA (Open Policy Agent) / Rego や、Terraform Sentinel など、いくつかのPolicy as Codeツールが存在します。しかし、現場のエンジニアにとって以下のような不満がありました。

1. ドメイン固有言語(DSL)の学習コスト: Regoのような新しい言語を覚えるだけで数週間の教育コストがかかる。
2. フィードバックループの遅さ: CI/CDパイプラインを回しきらないと違反に気づけない。

Pulumi CrossGuardは、インフラを記述している言語(TypeScript, Python, Goなど)をそのままポリシー定義にも使えるという圧倒的なアドバンテージを持っています。つまり、普段使っているIDEの補完や型安全性の恩恵をそのまま受けてポリシーを書けるのです。

—

2. 開発体験を爆発的に高める環境設定(VS Code編)

Policy Packの開発・運用をチームに定着させるためには、開発者のストレスをゼロにするエディタ環境が不可欠です。

必須プラグイン

  • Pulumi: リソースの視覚化やスタック管理をIDE内で完結させる。
  • ESLint / Prettier: ポリシーコードのフォーマットを強制し、レビュー時の無駄な指摘を排除。

チームで共有すべき `.vscode/settings.json`

Policy Packのプロジェクトルートに配置し、保存時の自動修正と型チェックを徹底させます。

{
“editor.formatOnSave”: true,
“editor.codeActionsOnSave”: {
“source.fixAll.eslint”: true
},
“typescript.suggest.completeFunctionCalls”: true,
“files.exclude”: {
“/node_modules”: false
}
}

—

3. 実践:TypeScriptで書くカスタムポリシー

「すべてのAWS S3バケットに暗号化が有効であり、かつパブリックアクセスが完全にブロックされていること」を強制するポリシーを実装します。

プロジェクト構成

policy-pack/
├── index.ts # ポリシーのエントリーポイント
├── package.json # 依存関係定義
└── tsconfig.json # TypeScript設定

1. `package.json` の設定

Pulumi Policy SDKとAWSプロバイダーの型定義をインポートします。

{
“name”: “company-security-policies”,
“version”: “1.0.0”,
“dependencies”: {
“@pulumi/policy”: “^3.0.0”,
“@pulumi/aws”: “^6.0.0”
},
“devDependencies”: {
“typescript”: “^5.0.0”
}
}

2. `index.ts`(ポリシーの実装コード)

import { PolicyPack, validateResource } from “@pulumi/policy”;
import as aws from “@pulumi/aws”;

new PolicyPack(“company-security-guardrails”, {
policies: [
{
name: “s3-bucket-security-compliance”,
description: “S3バケットはパブリックアクセス禁止およびサーバーサイド暗号化が必須です。”,
enforcementLevel: “mandatory”, // “advisory” (警告) または “mandatory” (デプロイ阻止)
validateResource: validateResource(aws.s3.BucketV2, (bucket, args, reportViolation) => {
// 1. パブリックアクセスブロックの検証
// ※実際には aws.s3.BucketPublicAccessBlock も併用しますが、ここではバケット本体の設定を例示

// 2. サーバーサイド暗号化の検証
if (!bucket.serverSideEncryptionConfiguration) {
reportViolation(
`[Security Violation] S3バケット ‘${args.name}’ にサーバーサイド暗号化 (SSE) が設定されていません。`
);
}
}),
},
{
name: “forbidden-ec2-instance-types”,
description: “コスト最適化のため、t2シリーズのインスタンス利用を禁止します。”,
enforcementLevel: “mandatory”,
validateResource: validateResource(aws.ec2.Instance, (instance, args, reportViolation) => {
if (instance.instanceType && instance.instanceType.startsWith(“t2.”)) {
reportViolation(
`[Cost Governance] コスト最適化ポリシー違反: インスタンスタイプ ‘${instance.instanceType}’ は使用できません。t3以降を利用してください。`
);
}
}),
},
],
});

—

4. 組織全体でのポリシー運用とCI/CD統合

ポリシーを書くだけでは意味がありません。開発者がローカル環境やプルリクエストの段階で自然にルールを強制される仕組みを作ります。

組織標準設定ファイル: `PulumiPolicy.yaml`

ポリシーパックの設定や適用範囲を管理するファイルです。

yaml: 2.0
properties:
name: company-security-guardrails
description: 組織全体のセキュリティおよびコストガバナンスポリシー
policies:

  • name: s3-bucket-security-compliance

enforcementLevel: mandatory

  • name: forbidden-ec2-instance-types

enforcementLevel: advisory # 移行期間中は警告に留める

GitHub ActionsでのCI/CDパイプライン統合

デプロイ(`pulumi up`)の前に、ポリシーチェック(`pulumi preview` との連携、または `pulumi policy validate`)を挟みます。

name: Infrastructure CI/CD with CrossGuard

on:
pull_request:
branches: [ main ]

jobs:
policy-check:
runs-on: ubuntu-latest
steps:

  • uses: actions/checkout@v4
  • name: Setup Node.js

uses: actions/setup-node@v4
with:
node-version: ’20’

  • name: Setup Pulumi

uses: pulumi/actions@v5

  • name: Install Policy Dependencies

run: |
cd policy-pack
npm ci

  • name: Run Pulumi Preview with Policy Pack

run: |
# プレビュー時にローカルのポリシーパックを適用して検証
pulumi preview –policy-pack ./policy-pack
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

もし開発者が `t2.micro` のEC2インスタンスを作ろうものなら、この `pulumi preview` のステップで即座にエラーとなり、CIがレッドになります。開発者はマージ前に自分のコードの不備に気づくことができるのです。

—

5. テックリードが伝える運用上のベストプラクティス

1. 最初は `advisory` モードからスタートする
新しいポリシーを導入する際、いきなり `mandatory`(デプロイブロック)にすると開発現場が混乱します。まずは `advisory`(警告のみ)でデプロイし、既存リソースへの影響度を測りながら段階的に厳格化しましょう。

2. ポリシーコードのテストを書く
Policy Pack自体もコードです。`@pulumi/policy` が提供するテストユーティリティを使い、意図通りに違反を検知できるかUnitテスト(Jestなど)を記述することを強く推奨します。

3. 「なぜこのポリシーがあるのか」のリンクをエラーメッセージに含める
`reportViolation` の文字列の中に、社内のConfluenceやNotionのガイドラインドキュメントへのリンクを埋め込みましょう。「怒られる」のではなく「自律的に学べる」環境を作るのが、優れたSREの仕事です。

—

最後に:ガードレールは開発のスピードを加速させる

「セキュリティを厳しくすると開発速度が落ちる」というのは、古い時代の誤った二項対立です。

Pulumi CrossGuardを用いたPolicy as Codeは、人間の目による属人的で泥臭いレビュー負担をゼロにし、「安全なコードだけが高速にデプロイされる自動化された高速道路」をチームにもたらします。

今すぐあなたのプロジェクトにも、コードによるガードレールを導入し、真の「DevSecOps」を体現してください。

タイトルとURLをコピーしました