はじめに
こんばんは、mirukyです。
わりとあるあるかな、と思うのですがCloucWatchのログに、意図せず個人情報を垂れ流しにしちゃいがちじゃないですか。開発者しか見ないから大丈夫かと思われるかもしれませんが、ともすればインシデントになりかねない結構危険な状態です。
今回はCloudWatch Logsのデータ保護ポリシーを使い、ロググループへ取り込まれたメールアドレスを自動でマスクしてみようと思います。AWSマネジメントコンソールだけを使い、設定前後の違い、権限を持つ担当者による元値の確認、作成したリソースの削除まで確かめましょう!
目次
1. CloudWatch Logsのデータ保護とは
CloudWatch Logsのデータ保護は、ロググループへ取り込まれる文字列を検査し、指定した種類の機密データをアスタリスク(*)へ置き換える機能です。AWSが用意するマネージドデータ識別子には、メールアドレス、クレジットカード番号、AWSシークレットアクセスキー、国別の識別番号などがあります。
通常のログ閲覧、CloudWatch Logs Insights、メトリクスフィルター、サブスクリプションフィルターなどから出ていく値にもマスクが適用されます。元の値を読むには、閲覧者へ明示的にlogs:Unmaskを許可しなければなりません。
ポリシーはロググループ単位とアカウント単位で設定でき、両方がある場合は対象の識別子が累積して働きます。今回は、ほかのロググループへ影響させないよう、検証用Lambdaのロググループだけを対象にします。このあたりはPJ次第ですね。
2. 今回確かめること
データ保護ポリシーは、作成後に取り込まれたログへ適用されます。作成前のログまで遡ってマスクするものでは無いことに注意が必要です。同じロググループへ、次の順で架空のメールアドレスを送ります。
-
before@example.comを記録する -
EmailAddressを対象にする -
after@example.comを記録する - 2件を比較する
- 必要な権限で元値を確かめる
入力には予約済みドメインexample.comを使います。実在するメールアドレスや個人情報は使いません。
3. マネジメントコンソールで試す
3-1. 前提と料金を確認する
リージョンはアジアパシフィック(東京)です。Lambdaが自動作成するStandardログクラスで試します。2026年3月からInfrequent Accessでも機密データの検出とマスクを利用できますが、ログの取得方法などに機能差があるため、本記事はStandardで進めます。
操作するIAMユーザーまたはロールには、検証用Lambda関数と実行ロールの作成・削除、CloudWatch Logsの閲覧・削除、logs:PutDataProtectionPolicyを許可してください。元値も確かめる場合はlogs:Unmaskが必要です。権限は検証用リソースへ絞ります。
東京リージョンのデータ保護検査料金は、2026年8月11日にAWS公式料金ページで確認した時点で0.12 USD/GBでした。今回は数KB規模のログを2回出すため、この検証だけの従量料金は0.01 USD未満の見込みです。LambdaとCloudWatch Logsの料金、ほかの利用分、価格改定は別に考えてください。
比較を始める前に、アカウント単位のポリシーがEmailAddressを対象にしていないことを確かめます。対象になっている環境では設定前のログも伏字になるため、共有設定には触れず、影響のない検証環境を使ってください。
画面にはデータ保護アカウントポリシーと設定なしが表示されています。この条件なら、ロググループ側のポリシーを作る前後を比較できます。
3-2. 比較用Lambda関数を作る
Lambdaで「一から作成」をクリックします。検証ではqiita-cw-mask-20260811-131751という名前にしました。手元で試すときは日時部分を変えて、片付けまで同じ名前を使ってください。
関数名とランタイムを間違えないよう、作成前の値を確かめます。
画面には関数名qiita-cw-mask-20260811-131751とランタイムNode.js 24.xが表示されています。
今回は追加のネットワーク接続や暗号化設定を使いません。初期値を使う部分も確かめます。
画面ではARM64 アーキテクチャとカスタム実行ロールがオフです。そのため、x86_64と基本的なLambdaアクセス許可を持つ新しいロールが使われます。
この条件で関数を作ります。処理が終わったことまで確かめてから、次へ進みます。
通知には関数qiita-cw-mask-20260811-131751が正常に作成されたことが表示されています。
3-3. 設定前のログを出す
Lambda関数のindex.mjsを次の内容へ置き換えます。
export const handler = async (event) => {
const phase = event.phase === "after" ? "after" : "before";
// 予約済みドメインの架空メールアドレスだけを検証ログへ出します。
const email = phase + "@example.com";
console.log("phase=" + phase + " customer_email=" + email);
return {
statusCode: 200,
body: "ok"
};
};
反映前に、貼り付けたコードと変更の有無を確かめます。
画面では、DEPLOY部分にコード反映前を示すUndeployedが表示されています。Deployで変更を反映します。
反映処理が終わったことも確かめます。
通知には関数が正常に更新されたことが表示され、コード領域はCurrentになっています。
Lambdaのテスト機能で新しいイベントを作り、イベントJSONへ次を入れます。
{
"phase": "before"
}
テストを実行し、返り値のbodyがokになることを確かめます。これでbefore@example.comを含むログが作られました。
3-4. ロググループへポリシーを設定する
CloudWatch Logsの/aws/lambda/qiita-cw-mask-20260811-131751へ移り、ロググループ単位のデータ保護ポリシーを作ります。指定する値は次のとおりです。
| 項目 | 値 |
|---|---|
| マネージドデータ識別子 |
EmailAddressのみ |
| 監査先 | なし |
今回はマスクの差だけを確かめるため、監査結果の送信先は作りません。監査先がなくてもマスクは働きます。作成後の内容を確かめます。
画面には作成成功の通知があり、ステータスはオン、マネージドデータ識別子はEmailAddress、監査先は-です。この結果を確かめてからLambdaへ戻ります。
3-5. 設定後のログを出して比較する
同じLambdaのテスト機能で、今度はafterを渡します。入力内容を確かめましょう。
画面のイベント JSONには"phase": "after"が入力されています。この内容でテストを実行します。
処理が終わり、関数呼び出し自体に問題がないことを確かめます。
画面には実行中の関数: 成功と表示されています。これで設定後のログも同じロググループへ入りました。
CloudWatch Logsでphase=を含むログイベントを絞り、2件を比べます。
画面ではbefore@example.comが平文のまま残り、設定後のメールアドレスがアスタリスクへ変わっています。データ保護ポリシーは取り込み時に働き、過去ログへ遡らないことを同じ条件で確かめられました。
3-6. 必要な担当者だけ元値を確認する
logs:Unmaskを許可された利用者だけ、保護された値を一時的に読めます。元値が必要な担当者と用途を絞ったうえで、同じログイベントに対してマスク解除を実行します。
画面ではafter@example.comまで元値で表示されています。確認が終わったら再度マスクし、通常の閲覧へ戻します。検証のためだけに閲覧者全員へlogs:Unmaskを付けないでください。
3-7. お片付けっと
検証後は、Lambda関数、ロググループ、実行ロールの順に片付けます。まず、Lambda関数の削除確認まで進めます。
ダイアログには、関数コードが完全に削除され、関連するログとロールは保持されるという警告が表示されています。確認欄へ確認を入れ、削除を確定します。
関数名で完全一致検索し、対象が残っていないことを確かめます。
通知にはLambda関数が正常に削除されたこと、検索結果には0件の一致が表示されています。
関数を消してもロググループは残ります。次に、対象ロググループの削除確認まで進めます。
ダイアログには削除対象/aws/lambda/qiita-cw-mask-20260811-131751が表示されています。対象名が合っていることを確かめ、削除を確定します。
同じロググループ名で完全一致検索し、片付いたことを確かめます。
通知にはロググループが削除されたこと、完全一致の検索結果には0 matchesが表示されています。
最後に、IAMの実行ロールを削除し、同じ名前が残っていないことまで確かめます。3か所を別々に片付ける理由は、Lambda関数だけを削除してもロググループと自動作成ロールが残るためです。
おわりに
ここまでお付き合いいただきありがとうございます。
CloudWatch Logsのデータ保護ポリシーを使うと、取り込み後の通常閲覧や転送先で、検出したメールアドレスを伏字にできます。今回の検証では、設定前のログは平文のまま、設定後のログだけがマスクされました。元値はlogs:Unmaskを持つ担当者に限定できます。
ではまた、お会いしましょう。














