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が分かれば直感的に使えそうですね。
マルチアカウントで利用する場合も、バケットポリシーで上手く制御してあげることでテンプレートの管理を共有元だけでできそうです。