こんにちは!クラウドインフラ・SREの世界へようこそ。
今日は、日々のインフラ管理を劇的に安全でスマートにしてくれる「Pulumi(プルミ)」のお話です。
「IaCといえばTerraform」という時代から、TypeScriptやPythonなどの使い慣れたプログラミング言語でインフラを書けるPulumiへ移行するチームが急増しています。これをマスターすれば、JSONやHCLの独自構文に悩まされることなく、条件分岐やループ、関数といったおなじみのプログラミングパラダイムでインフラを自在に操れるようになり、毎日の作業が劇的に楽になりますよ。
今回はその中でも、「本番運用で絶対に避けて通れないインフラの核心」である、Pulumiのステート(状態)管理と暗号化キーローテーションの安全な運用手順について、現場の生きた知見を交えて徹底解説します。
—
1. なぜ「ステート管理と暗号化」がSREの命運を握るのか?
IaCツールを使う上で最も重要な概念が「ステート(State)」です。ステートとは、今クラウド上にどんなリソースが作られているかの「現在地」を記録した台帳のこと。
デフォルトの状態(Pulumi Serviceを使う場合)では、この台帳はPulumi社のマネージドクラウドに安全に保存されます。しかし、企業のセキュリティポリシーやデータ主権(コンプライアンス)の観点から、「自分たちのAWSアカウントやGCSバケット(セルフホストバックエンド)にステートを閉じ込めたい」という要件に必ず直面します。
さらに、ステートファイルの中身には、データベースのパスワードやAPIトークンなどの機密情報(Secrets)が暗号化されて含まれています。つまり、ステートの保存場所を守るだけでなく、それを暗号化する鍵(KMS)の管理、そしてコンプライアンス要件で義務付けられる「鍵の定期的なローテーション(更新)」を、デプロイ障害を起こさずにやり切るスキルが、一流のSREには求められるのです。
—
2. 環境構築と基礎セットアップ
まずは、手元のマシンでPulumiを動かせる状態を作りましょう。ここでは最も一般的なMac/Linux環境をベースに解説します(Windowsの場合はWSL2推奨です)。
ターミナルでのインストール
macOSの場合 (Homebrew)
brew install pulumi
または公式のインストールスクリプトを使用する場合
curl -fsSL https://get.pulumi.com | sh
インストールができたら、バージョンを確認してみましょう。
pulumi version
デフォルトから「セルフホストバックエンド(S3)」への切り替え
Pulumiのデフォルト(Pulumi Service)から、自分たちの管理するAWS S3バケットへとバックエンドを切り替えます。環境変数 `PULUMI_BACKEND_URL` を設定するのが最もクリーンで冪等性の高い方法です。
S3バケットをバックエンドとして指定する場合
export PULUMI_BACKEND_URL=”s3://my-company-pulumi-state-bucket-production?region=ap-northeast-1″
このコマンドを叩くだけで、あなたのPulumiはマネージドサービスを離れ、完全自社管理のS3をステートの保存先として認識し始めます。
—
3. AWS KMSを用いたステート暗号化とバックエンド構成
セルフホストS3を使う場合、S3側のデフォルト暗号化(SSE-S3)だけでなく、AWS KMS(Key Management Service)のカスタマー管理キー(CMK)を使用することを強く推奨します。なぜなら、鍵のローテーションやアクセス監査を完全にコントロールできるからです。
AWS KMSキーの作成(TerraformやAWS CLIなど)
まずはKMSキーを作成し、そのARN(例: `arn:aws:kms:ap-northeast-1:123456789012:key/your-kms-key-uuid`)を控えておきます。
PulumiでこのKMSキーを使ってシークレットを暗号化・復号するには、スタックの初期化時にシークレットプロバイダとして指定します。
KMSをシークレットプロバイダに指定してスタックを新規作成
pulumi stack init production \
–secrets-provider=”awskms://arn:aws:kms:ap-northeast-1:123456789012:key/your-kms-key-uuid?region=ap-northeast-1″
これで、このスタック内で扱われる機密情報は、AWS KMSによってガチガチに暗号化されてS3に保存されるようになります。
—
4. 【極限の知見】キーローテーションでデプロイ障害を起こさないためのベストプラクティス
さて、ここからが本題です。セキュリティ監査などで「KMSキーを年1回(あるいは四半期ごとに)ローテーションしなさい」と言われたとき、適当にキーを差し替えるとどうなるでしょうか?
「古いキーで暗号化された過去のステートファイルが、新しいキーでは復号できなくなり、次回の `pulumi up` で全リソースがロストまたはデプロイ不能になる」という、SREの悪夢(P0インシデント)を引き起こします。
これを完全に防ぐための、現場で実証された安全なキーローテーション手順を授けましょう。
ベストプラクティス手順:AWS KMSの「自動ローテーション」と「マルチキーポリシー」
AWS KMSには、キー自体のIDを変えずに内部のマテリアル(実体の鍵)だけを定期更新する「自動キーローテーション機能」があります。しかし、Pulumiのシークレットプロバイダとして利用する場合、より確実なのは「エイリアス(Alias)を用いたシームレスな移行」です。
以下の手順を厳守してください。
1. 新しいKMSキーの作成と、古いキーの残置
新しいKMSキー(Key B)を作成します。ただし、古いKMSキー(Key A)を絶対に削除(または無効化)してはいけません。
2. KMSキーポリシー(権限)の拡張
新しいキー(Key B)のポリシーにおいて、Pulumiを実行するIAMロール/ユーザーに対し、「encrypt / decrypt」権限を付与することは当然として、古いキー(Key A)の「decrypt(復号)」権限もIAMロールに保持させ続けます。
(なぜなら、過去のステートを読むときは古いキーが必要になるためです)
3. シークレットプロバイダの参照をエイリアス(Alias)に向ける(超重要)
KMSキーのハードコードされたUUID(例: `key/1234abcd-…`)ではなく、AWS KMSのエイリアス(例: `alias/pulumi-state-key`)をPulumiのシークレットプロバイダに指定するように設計します。
# よくない例(UUID直書きはローテーション時に死ぬ)
–secrets-provider=”awskms://arn:aws:kms…:key/old-uuid”
# 良い例(エイリアスを使用する)
–secrets-provider=”awskms://arn:aws:kms:ap-northeast-1:123456789012:alias/pulumi-state-key?region=ap-northeast-1″
4. AWS側でエイリアスの向き先を切り替える
AWS KMSのコンソールまたはIaCで、`alias/pulumi-state-key` が指す実体のキーを「Key A」から「Key B」へと付け替えます。
- これにより、新規に暗号化されるデータはすべて新しい「Key B」で処理されます。
- 一方で、既存のステートファイルにアクセスする際は、AWS KMSが自動的に過去のバージョン(Key A)を特定して復号するため、デプロイエラーが1ミリも発生しません。
—
5. 精度高いHelloWorld的動作確認:実際にデプロイして確かめる
理論が分かったところで、実際にS3バックエンドとKMS暗号化が正しく機能しているか、シンプルなTypeScriptのコードで動作確認をしてみましょう。
プロジェクトの作成
mkdir pulumi-demo && cd pulumi-demo
pulumi new aws-typescript –dir . –stack production –yes
コードの記述 (`index.ts`)
機密情報(Secret)を含むリソース(例:ランダムなパスワード)を定義し、ちゃんと暗号化されてステートに保存されるか確認します。
import as pulumi from “@pulumi/pulumi”;
import as random from “@pulumi/random”;
// 機密情報(Secret)としてランダムなパスワードを生成
// これがPulumiによってKMSで暗号化され、S3のステートに書き込まれます
const dbPassword = new random.RandomPassword(“db-password”, {
length: 16,
special: true,
});
// エクスポート(出力値も自動的にマスクされます)
export const passwordResult = dbPassword.result;
デプロイの実行
pulumi up
実行後、AWS S3バケットの中身を覗いてみてください。`.pulumi/stacks/production.json` のようなパスにステートファイルが保存されており、その中のシークレット値がAWS KMSによって綺麗に暗号化されていることが確認できます。
—
まとめ
いかがでしたでしょうか?
Pulumiのセルフホストバックエンド(S3)とAWS KMSを組み合わせた堅牢なステート管理、そしてキーローテーション時の罠を回避するベストプラクティスをマスターすれば、エンタープライズレベルの厳格なセキュリティ要件を持つ環境でも、安心して高速なデプロイを回し続けることができます。
「インフラをコードで書く」ことの楽しさと美しさを、ぜひあなたの現場でも実感してください。あなたのインフラライフが、より劇的で快適なものになることを応援しています!