はじめに
前回、CloudFormation Hookを試用してみました。
今回は自作Lambdaを使うケースを、簡単な例で作ってみました。
概要
今回は"S3の名前をチェックするCloudFormation Hook"を作ります。
- Lambdaを作成
- 権限は、Lambdaを実行するだけなので、CloudWatch Logsに出力するもののみです
- 作成するS3名は、入力からとってこれます
- 権限は、Lambdaを実行するだけなので、CloudWatch Logsに出力するもののみです
- CloudFormation Hookを作成
- 権限は、先ほど作ったLambdaを実行するもののみです
参考
やってみた
Lambda作成
S3名をチェックするLambdaを作成します。今回は簡単に、"プレフィックスにsales|hr|infraが指定"されていることをチェックする関数にしました。
権限は、他リソースは呼び出さないので、最低限のログ出力のみです。
import json
import re
def validate_bucket_name(bucket_name):
if not bucket_name:
return False
pattern = r"^(sales|hr|infra)-"
return re.match(pattern, bucket_name) is not None
def lambda_handler(event, context):
properties = event.get("requestData", {}).get("targetModel", {}).get("resourceProperties", {})
bucket_name = properties.get("BucketName")
print("BucketName:", bucket_name)
if not validate_bucket_name(bucket_name):
return {
"hookStatus": "FAILED",
"message": "Bucket name must start with 'sales-', 'hr-', or 'infra-'.",
"clientRequestToken": event.get("clientRequestToken"),
"errorCode": "NonCompliant"
}
return {
"hookStatus": "SUCCESS",
"message": "Bucket name passed validation.",
"clientRequestToken": event.get("clientRequestToken")
}
テストで使用した、想定される入力eventのJSONは以下になります。
{
"awsAccountId": "123456789012",
"stackId": "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/TestStack/example-id",
"changeSetId": null,
"hookTypeName": "Company::S3::Naming",
"hookTypeVersion": "00000001",
"hookModel": {
"LambdaFunction": "arn:aws:lambda:ap-northeast-1:123456789012:function:CheckS3BucketName"
},
"actionInvocationPoint": "CREATE_PRE_PROVISION",
"requestData": {
"targetName": "AWS::S3::Bucket",
"targetType": "AWS::S3::Bucket",
"targetLogicalId": "TestBucket",
"targetModel": {
"resourceProperties": {
"BucketName": "hr-acme-dev-test-12345"
},
"previousResourceProperties": {}
}
},
"requestContext": {
"invocation": 1,
"callbackContext": null
},
"clientRequestToken": "local-test-token"
}
Pythonをローカルでチェックした際、以下のコードを入れて行いました。先のeventは同ディレクトリにevent.jsonというファイルで保存しておきます。
def main():
with open("event.json", "r", encoding="utf-8") as file:
event = json.load(file)
result = lambda_handler(event, None)
print("=== result ===")
print(json.dumps(result, indent=2, ensure_ascii=False))
if __name__ == "__main__":
main()
CloudFormation Hookを作成
先に作ったLambdaを使うCloudFormation Hookを作ります。
今回の環境では、デフォルトロールを作成を選択すると先に進ませんでした。他の指定項目が問題なくても動かず、ここだけ別のロールを使用にしたら通るようになりました。エラーにもなりませんでしたので、注意ください。
専用のロールを作るため、設定値を埋めていきます。

Hookの名前も指定して、専用のロールにできます。


モードを変更しつつ、実行を確認してみました。正常に動いているようです。

おわりに
今回はチェックに自作Lambdaを使ったCloudFormation Hookを作ってみました。
組織独自のチェックが必要なケースもあるかと思います、そういった際を想定して記事を作成してみました。
この記事がどなたかのお役に立てれば幸いです。



