CFnでSSMパラメータストアの値を利用する方法

# この記事でわかること
CFnテンプレート内に設定する値をSSMパラメータストアから拾ってくる方法。

# 留意事項
1. CFnテンプレートの記載はyamlを想定しています。
2. SSMパラメータストアの動的参照は、SSMパラメータ側でSecureStringを設定している場合は記載方法が若干違います。
3. 本記事では、Standardを設定しているものに主眼を置きます。
4. 後述しますが、SecureStringは、SSMパラメータストアの動的参照に対応しているリソースが少ないようです。（2024/03/30現在）
# テンプレート上の記載
結論から言うと基本的な記載方法は、下記のとおりです。
```yaml: 
'{{resolve:ssm:parameter-name:}}'
```
バージョン指定をしたい場合は下記のような記載になりますが、<font color="Red">バージョン指定なしの場合は最新バージョンを拾ってくれる</font>ようなので、基本的にバージョンは指定しないのが良いと思います。
```yaml: 
'{{resolve:ssm:parameter-name:version}}'
```
# やってみた
## VPCの作成
### テンプレート・SSMパラメータストアの準備
今回はVPCを作成してみます。
テンプレートの内容は以下の通りです。（今回はSSMパラメータのバージョン番号も指定）
・CIDRブロック
・Nameタグ
```yaml: CFn_Template.yml
AWSTemplateFormatVersion: "2010-09-09"

Description: Create VPC

Resources:
    TestVPC:
        Type: 'AWS::EC2::VPC'
        Properties:
            CidrBlock: '{{resolve:ssm:/CreateVPC/CidrBlock:1}}'
            Tags: 
              - 
                Key: '{{resolve:ssm:/CreateVPC/Tag/NameTag/Key:1}}'
                Value: '{{resolve:ssm:/CreateVPC/Tag/NameTag/Value:1}}'
```

SSMパラメータストアにはそれぞれ下記のように設定します。
```yaml: パラメータストアの設定値
/CreateVPC/CidrBlock #VPCのCIDRブロック
- 10.0.0.0/16
/CreateVPC/Tag/NameTag/Key #Nameタグのキー
- Name
/CreateVPC/Tag/NameTag/Value #作成するVPCの名前
- TestVPC
```
### スタックの実行と結果の確認
Cfnテンプレートを実行し、作成したVPCを確認します。
しっかりと設定したCIDRブロックとVPCの名前が反映されていました。
![実行結果1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759299/e408e341-0fdb-8928-e7dd-ee531befe3a3.png)


## 更新
### パラメータストアの値の更新
今回は最初に実行したテンプレートでバージョン番号を指定していた都合上、テンプレートを更新する必要があります。
今後は自動的にSSMパラメータストアに格納した最新版の値をとってくるように、バージョン指定をしない記法に変更しました。
```yaml: CFn_Template.yml（更新）
AWSTemplateFormatVersion: "2010-09-09"

Description: Create VPC

Resources:
    TestVPC:
        Type: 'AWS::EC2::VPC'
        Properties:
            CidrBlock: '{{resolve:ssm:/CreateVPC/CidrBlock}}'
            Tags: 
              - 
                Key: '{{resolve:ssm:/CreateVPC/Tag/NameTag/Key}}'
                Value: '{{resolve:ssm:/CreateVPC/Tag/NameTag/Value}}'
```
SSMパラメータストアはVPCのNameタグの値のみ修正します。
```yaml: パラメータストアの設定値
/CreateVPC/Tag/NameTag/Value #作成するVPCの名前
- TestVPC_ver2 #TestVPC → TestVPC_ver2に変更
```
### 結果の確認
CFnから変更セットを実行し、Nameタグが変更されていることを確認します。
しっかりと最新バージョンの値が設定されていました。
![実行結果2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759299/4d9f994c-3aae-86bf-32ca-f13a06c52b13.png)

# SecureStringのSSMパラメータストアを参照する場合
SecureString場合は、記載方法は以下の通りになります
```yaml: 
'{{resolve:ssm-secure:parameter-name}}' #バージョン指定なし
'{{resolve:ssm-secure:parameter-name:version}}' #バージョン指定あり
```
ただし、サポートしているリソースが少ないため、注意が必要です。
| 2024/03/30時点で対応しているリソース |
| :--- |
| AWS::DirectoryService::MicrosoftAD |
| AWS::DirectoryService::SimpleAD |
| AWS::ElastiCache::ReplicationGroup |
| AWS::IAM::User |
| AWS::KinesisFirehose::DeliveryStream |
| AWS::OpsWorks::App |
| AWS::OpsWorks::Stack |
| AWS::OpsWorks::Stack |
| AWS::RDS::DBCluster |
| AWS::RDS::DBInstance |
| AWS::Redshift::Cluster |
# 所感
1. CFnテンプレートを修正せずに、SSMの修正だけでテンプレートを修正できるので、
テンプレート内部で管理する場合や、テンプレートのパラメータセクションで管理する場合よりも、今回試してみた方法でパラメータを管理するほうが運用上望ましいのではないかと感じました。<br><br>
2. SSMの値をSecureStringに設定している場合、参照できるリソースが少ないのが残念です。DB等は対応しているので、パラメータにPW等の機密情報が必要になるリソースはSecureString対応しないとまずいか、、的な発想なのでしょうか。プロジェクトでSSMは全部SecureStringで管理する方針になっている場合はSSMの動的参照を諦めるか、方針を変えてもらうようにゴネてみるかの2択になるかと思います。<br><br>

3. こういった内容の記事はすでに複数あると思いますが、自分で調べて動作確認を実施して結果をアウトプットできてよかったです。

# 参考
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/dynamic-references.html<br>