【入門編】PulumiでAWS IAMポリシーの自動生成と静的解析:安全性を限界まで高めるセキュリティ自動化パイプライン – インフラ構成管理(IaC)活用バイブル

こんにちは!クラウドインフラの世界へようこそ。
日々、AWSの複雑なIAM(Identity and Access Management)ポリシーと格闘していませんか?

「とりあえず動かすために、`”Resource”: “”` や `”Action”: “”` を書いてしまった……」
「後で直そうと思ってそのまま本番環境にデプロイされ、セキュリティ監査で冷や汗をかいた……」

そんな経験、インフラエンジニアなら一度や二度ではないはずです。手動レビューや後からのスキャンだけに頼るのは、もう終わりにししましょう。今回は、「Pulumi」と「Policy as Code(CrossGuard)」を組み合わせて、危険なIAMポリシーが生まれる余地を完全に断つ、鉄壁のセキュリティ自動化パイプラインの作り方を解説します。

これをマスターすれば、うっかりミスによる権限過剰なリソースのデプロイをコードのコンパイル・プレビュー段階でバッツリ阻止できるようになり、毎日のインフラ作業が劇的に安心で楽しいものになりますよ。

—

1. なぜ「Pulumi」と「Policy as Code」なのか?

私たちが普段使うTerraformなどのIaC(Infrastructure as Code)でも静的解析は可能ですが、Pulumiの最大のエポックメイキングな点は、「TypeScriptやPythonといった使い慣れた汎用プログラミング言語でインフラを書ける」という点です。

プログラミング言語で書けるということは、Linterやテストフレームワーク、そして独自のバリデーションロジックをそのままインフラ定義に適用できるということ。

さらにPulumiには、デプロイやプレビューの実行時にポリシーを強制適用する「CrossGuard(Policy Packs)」という強力な仕組みが備わっています。「`”Resource”: “”` を含んでいたらデプロイを即座に失敗させる」といったルールをコードとして定義し、開発者の手元(ローカル)でもCI/CDパイプラインでも、完全に同じ基準でセキュリティを担保できるのです。

—

2. 環境構築と基礎セットアップ

まずは、手元で動かすための環境を整えましょう。今回は親しみやすく型安全性の高い TypeScript を使用します。

必要なツールのインストール

以下のツールがインストールされていることを前提に進めます。

  • Node.js (v18以上推奨)
  • Pulumi CLI
  • AWS CLI (認証設定済みであること)

プロジェクトの初期化

適当なディレクトリを作成し、Pulumiプロジェクトを初期化します。

mkdir pulumi-iam-guard
cd pulumi-iam-guard
pulumi new aws-typescript –dir . –name iam-guard-demo –stack dev –yes

コマンドが成功すると、`index.ts` や `package.json` が生成されます。
依存関係として、IAMを扱うためのAWSパッケージがすでにインストールされているはずです。

—

3. 「HelloWorld」:あえて危険なIAMポリシーを書いてみる

まずは、セキュリティ自動化の「敵」を知るために、あえてワイルドカードまみれの危険なIAMポリシーを定義するPulumiコードを書いてみましょう。

`index.ts` を以下のように書き換えてみてください。

import as pulumi from “@pulumi/pulumi”;
import as aws from “@pulumi/aws”;

// 【危険な例】あらゆるリソースに対して全権限を許可するIAMポリシー
const dangerousPolicy = new aws.iam.Policy(“dangerous-policy”, {
name: “dangerous-iam-policy”,
policy: JSON.stringify({
Version: “2012-10-17”,
Statement: [{
Effect: “Allow”,
Action: “”, // 危険!すべての操作を許可
Resource: “”, // 危険!すべてのリソースを対象に指定
}],
}),
});

// エクスポートして確認できるようにする
export const policyArn = dangerousPolicy.arn;

この状態で `pulumi preview` を実行すると、AWS上にこの危険なポリシーが作成される予定だというプレビューが表示されます。
もちろん、実際の現場ではこれをデプロイさせたくありませんよね?

ここで登場するのが、Policy as Code(CrossGuard)です。

—

4. CrossGuardによるポリシーのコード化(静的解析の導入)

それでは、先ほどのような「ワイルドカード(“)の乱用」を検出し、プレビューやデプロイを強制停止するカスタムポリシーを作成しましょう。

プロジェクトのルートに `policy` というディレクトリを作成し、その中にポリシー定義を記述します。

mkdir policy
cd policy
pulumi new policy-pack-typescript –dir . –name iam-security-pack –yes

生成された `index.ts`(ポリシーパック側のコード)を、以下のように書き換えます。ここでは、「IAMポリシーのアクションやリソースに “ が使われていないか」をチェックするルールを実装します。

`policy/index.ts`

import as policy from “@pulumi/policy”;

// ポリシーパックの定義
const noWildcardPolicies = new policy.PolicyPack(“iam-security-pack”, {
policies: [
{
name: “no-wildcard-iam-policies”,
description: “IAMポリシーでワイルドカード()の使用を禁止します。”,
enforcementLevel: “mandatory”, // 違反した場合はデプロイを強制停止する
validateResource: policy.validateResourceOfType(
// AWSのIAMポリシーリソースをターゲットにする
require(“@pulumi/aws”).iam.Policy,
(args, reportViolation) => {
//ポリシーのJSON文字列を取得
const policyDoc = JSON.parse(args.props.policy);

for (const statement of policyDoc.Statement || []) {
// Actionに “” が含まれているかチェック
const actions = Array.isArray(statement.Action) ? statement.Action : [statement.Action];
if (actions.includes(“”)) {
reportViolation(“セキュリティエラー: IAMポリシーの Action に ” を指定することは禁止されています。最小権限の原則に従ってください。”);
}

// Resourceに “” が含まれているかチェック
const resources = Array.isArray(statement.Resource) ? statement.Resource : [statement.Resource];
if (resources.includes(“”)) {
reportViolation(“セキュリティエラー: IAMポリシーの Resource に ” を指定することは禁止されています。特定のARNを指定してください。”);
}
}
}
),
},
],
});

—

5. 動作確認:セキュリティ自動化の真骨頂を見る

準備は整いました。先ほど作成した危険なインフラコードのプロジェクト(ルートディレクトリ)に戻り、このポリシーパックを適用してプレビューを実行してみましょう。

ルートディレクトリに戻り、以下のコマンドを実行します。

ルートディレクトリへ移動
cd ..

policy パックを指定して pulumi preview を実行
pulumi preview –policy-pack ./policy

さあ、実行結果はどうなるでしょうか?

コンソールには、インフラストラクチャの変更計画の代わりに、鮮やかなエラーメッセージが表示されるはずです。

Previewing update (dev):
…
pulumi:pulumi:Stack: iam-guard-demo
1 error

Diagnostics:
pulumi:providers:aws: (init)
…

aws:iam/policy:Policy (dangerous-policy):
[policy violation] no-wildcard-iam-policies: セキュリティエラー: IAMポリシーの Action に ” を指定することは禁止されています。最小権限の原則に従ってください。
[policy violation] no-wildcard-iam-policies: セキュリティエラー: IAMポリシーの Resource に ” を指定することは禁止されています。特定のARNを指定してください。

Policies:
2 violations (2 mandatory)

abekobe: 1 policy violation found. Deployment prevented.

見事にデプロイが阻止されました!
このように、コードを書いた開発者の手元であっても、CI/CDパイプラインであっても、ポリシーに違反したコードは一切インフラストラクチャに反映されなくなります。

—

6. CI/CDパイプラインでの強制適用

この仕組みをGitHub ActionsなどのCI/CDに組み込むのは極めて簡単です。プルリクエストが作成されたタイミングで `pulumi preview –policy-pack ./policy` を走らせるだけ。

name: Pulumi Security Check

on:
pull_request:
branches: [ main ]

jobs:
preview:
runs-on: ubuntu-latest
steps:

  • uses: actions/checkout@v4
  • uses: actions/setup-node@v4

with:
node-version: 18

# Pulumi CLIのインストールと認証設定(略)

  • name: Run Pulumi Preview with Policy Pack

run: |
pulumi preview –policy-pack ./policy
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}

これだけで、セキュリティ要件を満たさないプルリクエストは、レビューアが目視で指摘する前に自動的にマージ不可の状態に追い込むことができます。人間が疲れているときに起こしがちな「ヒューマンエラー」を、システムが水際で完全に防いでくれるのです。

—

おわりに:セキュリティは「仕組み」で担保する

「気をつけてコードを書いてください」というお願いや、終わりの見えない手動のセキュリティチェックシートの運用は、もうやめにしましょう。

PulumiとPolicy as Code(CrossGuard)を組み合わせれば、「安全なコードしか世の中にリリースできない世界」をエンジニア自身のの手で美しく構築できます。

これを導入したその日から、チーム全体のセキュリティ意識が自然と底上げされ、夜も安心して眠れるようになりますよ。ぜひ、あなたのプロジェクトの最初の一歩として試してみてください。あなたのインフラ開発が、より堅牢でスピーディなものになることを心から応援しています!

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