Service Catalogでスタックをネストした製品を起動してみた
Service Catalogでは製品を起動すると内部でCloudFormationによってスタックが作成されますが、スタックをネストして製品を起動できるのか試してみました。
やってみる
構成
以下の構成でやってみました。製品にはVPCとそこからネストしてサブネットを作成するものを用意しました。
テンプレート
VPCスタック
サブネットスタックをネストしていて、subnet.yamlをS3に保存してオブジェクトURLを指定しています。
AWSTemplateFormatVersion: 2010-09-09 Parameters: Env: Type: String Default: dev AllowedValues: - prod - stg - dev VpcCidr: Type: String Default: 10.0.0.0/16 TemplateSubnet: Description: "Object URL for Subnet Template" Type: String Default: https://{bucketname}.s3.ap-northeast-1.amazonaws.com/Vpc-Portfolio/subnet.yaml Resources: # VPC Vpc: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCidr EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: !Sub ${Env}-vpc # Subnet Stack Subnet: Type: AWS::CloudFormation::Stack Properties: TemplateURL: !Ref TemplateSubnet Parameters: Env: !Ref Env VpcId: !Ref Vpc Outputs: Vpc: Value: !Ref Vpc Export: Name: !Sub ${AWS::StackName}-Vpc VpcCidr: Value: !Ref VpcCidr Export: Name: !Sub ${AWS::StackName}-VpcCidr
Subnetスタック
VPCスタックからネストされて作成されるスタックです。任意のS3バケットに保存しておきます。
AWSTemplateFormatVersion: 2010-09-09 Parameters: Env: Type: String Default: dev AllowedValues: - prod - stg - dev VpcId: Description: "VPC id of Subnet" Type: String SubnetAZ1Cidr: Type: String Default: 10.0.0.0/24 SubnetAZ2Cidr: Type: String Default: 10.0.1.0/24 Resources: # Subnets ## Subnets SubnetAZ1: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Select - 0 - Fn::GetAZs: !Ref "AWS::Region" VpcId: !Ref VpcId CidrBlock: !Ref SubnetAZ1Cidr Tags: - Key: Name Value: !Sub ${Env}--subnet1 SubnetAZ2: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Select - 1 - Fn::GetAZs: !Ref "AWS::Region" VpcId: !Ref VpcId CidrBlock: !Ref SubnetAZ2Cidr Tags: - Key: Name Value: !Sub ${Env}--subnet2
製品の作成
Service Catalogのコンソールから製品(VPC)を作成します。
今回はテンプレートが手元にあるので、アップロードして作成しました。
製品を作成したら適当なポートフォリオを作成するか紐付けしてください。アクセス権をポートフォリオに付与して準備完了です。
製品の起動
それでは製品を起動してみます。
起動すると、リソースにVPCとサブネットのネストされたスタックが表示されていました。Service Catalogでもスタックをネストして利用するのは問題なさそうです。
共有されたポートフォリオからクロスアカウントで起動
単一のアカウント内では問題なくネストできたので、次にポートフォリオを共有してクロスアカウントでネストしたスタックが起動できるか試してみます。
ポートフォリオの共有
検証している環境はOrganizations環境のため、組織内に共有して試してみます。
共有先のアカウントで製品を起動すると、予想通りエラーとなりました。
CloudFormationで詳細を確認してみると、S3バケットへのアクセスが拒否されたとあります。
ここでエラーとなるのは、共有先アカウントでSubnetスタックを作成するためのテンプレートが取得できないためです。
バケットポリシーの変更
現状を整理すると、このような形になっています。共有先アカウントからみると共有元アカウントのS3バケットを参照しているため、クロスアカウントでの許可が必要です。
そのため、共有先アカウントのネストスタックでもテンプレートを取得できるように、共有元アカウントでS3バケットのバケットポリシーを変更します。
今回は組織内に共有しているため、同じ組織であれば取得を許可しました。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": [ "arn:aws:s3:::bucketname", "arn:aws:s3:::bucketname/*" ], "Condition": { "StringEquals": { "aws:PrincipalOrgID": "o-xxxxxxxxxx" } } } ] }
バケットポリシーを変更したので、もう一度製品を起動してみると正常に作成できました。
起動制約を利用しない場合は、製品を起動するユーザー(ロール)にs3:GetObject
の権限が必要なので注意しましょう。
おわりに
Service Catalogでネストしたスタックを使ってみました。内部的にはCloudFormationを動かしているだけなので、Service Catalogが分かれば直感的に使えそうですね。
マルチアカウントで利用する場合も、バケットポリシーで上手く制御してあげることでテンプレートの管理を共有元だけでできそうです。