アノテーション 構築チームのいたくらです。
Fn::ForEach と Fn::FindInMap を使ってセキュリティグループを作ってみました。
Fn::ForEach で出来なかった部分が Fn::FindInMap で補えていい感じです。
Fn::ForEach や Fn::FindInMap について
とてもざっくりお伝えすると Fn::ForEach はループ処理のような機能を持つ関数で、
Fn::FindInMap は Mapping セクションで定義された値を取得する関数です。
詳細は公式ドキュメントを参照ください。
あと今回は shima さんのブログも参考にさせていただきました。
まえがき
shima さんのブログを拝見し、先日書いたこちらのブログのテンプレートを Fn::FindInMap で書き直せばいけそう!と思い、やってみたら成功しました!圧倒的感謝!
セキュリティグループを作成するテンプレート例
テンプレートが長いので閉じてあります。
以下のトグルを押すとテンプレートが開きます。
先日のブログで示したテンプレートから変更した部分をハイライトにしています。
CloudFormation テンプレート
AWSTemplateFormatVersion: "2010-09-09"
Transform: 'AWS::LanguageExtensions'
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
Parameters:
VpcId:
Type: String
Default: "vpc-xxxxxxxxxxxxxxxxx" # あらかじめ作成しておいた VPC ID
SgList:
Type: List<String>
# ForEach で コレクションとして使用する値(Mappings の TopLevelKey と合わせる)
Default: "SgIngress1,SgIngress2"
# ------------------------------------------------------------#
# Mappings
# ------------------------------------------------------------#
Mappings:
SgMappings:
SgIngress1:
Cidr: "XX.XX.XX.XX/32" //自分の Global IP 等を適宜指定
FromPort: "80"
ToPort: "80"
SgIngress2:
Cidr: "XX.XX.XX.XX/32"
FromPort: "443"
ToPort: "443"
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
Resources:
SecurityGroupAlb:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Security Group for ALB"
GroupName: "test-sg-alb"
Tags:
- Key: "Name"
Value: "test-sg-alb"
VpcId: !Ref VpcId
'Fn::ForEach::LoopIngress': # LoopPort の部分はテンプレート内で一意であること
- SgIdentifier # ループ変数
- !Ref SgList # ループ変数で呼び出したい値(公式ドキュメントではコレクションと呼ぶ)
- '${SgIdentifier}': # ループで作成されるリソースの論理 ID
Type: AWS::EC2::SecurityGroupIngress
Properties:
CidrIp: !FindInMap
- SgMappings # FindInMap の引数: MapName
- !Ref SgIdentifier # FindInMap の引数: TopLevelKey
- Cidr # FindInMap の引数: SecondLevelKey
FromPort: !FindInMap
- SgMappings
- !Ref SgIdentifier
- FromPort
ToPort: !FindInMap
- SgMappings
- !Ref SgIdentifier
- ToPort
IpProtocol: "TCP"
GroupId: !Ref SecurityGroupAlb
このテンプレートで作成できたセキュリティグループがこちら。
先日のブログと違って、HTTP と HTTPS のインバウンドルールが設定できています。
疑問:複数回呼び出しできないんじゃなかったのか?
先日書いたブログのここを見ていただくと分かるように、ループ変数を複数回参照したらエラーが出ました。
でも今回のテンプレートで複数回参照しても問題なく成功したのはなぜなのでしょう。
Fn::FindInMap の引数としてループ変数が参照されているだけで、実際にオブジェクトで参照しているのは Mappings で定義した値。
ループ変数をオブジェクトで直接参照できるのは 1 回のみだけど、引数として参照するなら複数回可能、って感じなんでしょうか。
難しいですね・・・
あとがき
先日のブログで「Fn::ForEach はセキュリティグループに向いてないかもしれません」と書いてましたが、「Fn::ForEach だけだと、」に修正しました(笑)
CloudFormation 歴が浅いため、恥ずかしながら後からこんなこともできるのか!と知ることが多く、とても勉強になりました。
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。
「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。
現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。