🐙
Stacksetsでデプロイ先を制御する。(ConditionsとIf関数合わせ技)
Stacksets活用術
前提
- Stacksetsを利用すると複数のアカウントに対して一斉に同一のリソースをデプロイすることができます。
- その際に、一部のアカウントのみに特定のリソースをデプロイしたい時があります。
- 一般的にはアカウント単位での制御はルールセクションで
Conditions
を利用して実現します。
- 例えばアカウント1,2に対して作成するロールを分ける際は以下のようになります。
リソース | Account1 | Account2 |
---|---|---|
RoleA | o | o |
RoleB | - | o |
Conditions
AWSTemplateFormatVersion: 2010-09-09
Description: sample
# ------------------------------------------------------------#
# Conditions
# ------------------------------------------------------------#
Conditions:
IsAccount2: !Equals [!Ref AWS::AccountId, <Account2 ID>]
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
Resources:
# IAM Role
IAMRoleA:
Type: AWS::IAM::Role
Properties:
Path : /
AssumeRolePolicyDocument:
# 略
RoleName: IAMRoleA
IAMRoleB:
Type: AWS::IAM::Role
# ★★★★★★★★
# Account2 のみにデプロイする
Condition: IsAudit
# ★★★★★★★★
Properties:
Path : /
AssumeRolePolicyDocument:
# 略
RoleName: IAMRoleB
課題
- 今回IAMロールを作って共通的なポリシーを全ロールにアタッチする構成にする際に詰まりました。
- 具体的にはポリシーのアタッチ先のロールが存在するかどうかがConditions次第(今回はアカウント次第)となっており安易に
!Ref
でメンションするとスタック構築の際に存在しないリソースをメンションしたことによるエラーが発生します。
解決策
- 条件ルールのConditions、条件関数のIf関数を合わせて利用することにより実現可能です。
Conditions+If
AWSTemplateFormatVersion: 2010-09-09
Description: sample
# ------------------------------------------------------------#
# Conditions
# ------------------------------------------------------------#
Conditions:
IsAccount2: !Equals [!Ref AWS::AccountId, <Account2 ID>]
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
Resources:
# IAM Role
IAMRoleA:
Type: AWS::IAM::Role
Properties:
Path : /
AssumeRolePolicyDocument:
# 略
RoleName: IAMRoleA
IAMRoleB:
Type: AWS::IAM::Role
# Deploy only audit account
Condition: IsAudit
Properties:
Path : /
AssumeRolePolicyDocument:
# 略
RoleName: IAMRoleB
# IAM Policy
CommonIAMPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: IAMPolicy-common
Roles:
- !Ref IAMRoleA
# ★★★★★★★★★★★★★★★★★
# アカウント2であればIAMロールBにもポリシーをアタッチする。
- !If [IsAccount2, !Ref IAMRoleB, !Ref AWS::NoValue]
# ★★★★★★★★★★★★★★★★★
PolicyDocument:
# 略
- なお、IF関数の文法としてはこんな構成になっている
まとめ
- Conditionsルールだけ利用している記事が多く、If関数との組み合わせの紹介記事を見つけられなかったので今回執筆しました。
- ご参考になればうれしいです。
2024/1/16追記
- 条件分岐の中でyamlの構成ごと挿入する場合の記述方法はこちら
- IAMポリシーなどなら正直ポリシーを分けてしまえばよいが、KMSのリソースベースポリシーなどはこのような強制分岐が有効
PolicySmaple:
Type: AWS::IAM::Policy
Properties:
PolicyName: xxx
PolicyDocument:
Version: 2012-10-17
Statement:
-
Sid: xxxx
Effect: xxxx
# 特定の条件でのみ追加するポリシー
- !If
- IsAccount2
-
Sid: xxx
Effect: Allow
Principal:
AWS:
- !Sub IAMRoleB
Action:
- xxxxxxxx
Resource: '*'
- !Ref AWS::NoValue
Discussion