[新機能]AWS CloudFormationでAWS Systems ManagerパラメータストアのSecureStringがサポートされました

AWS CloudFormationでAWS Systems ManagerパラメータストアのSecureStringがサポートされたので実際に使ってみました。
2018.08.18

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。サービスグループの武田です。

AWSにはAWS Systems Managerパラメータストア(以下、SSMパラメータストア)という、設定データ管理と機密管理のための安全な階層型ストレージを提供するサービスがあります。SSMパラメータストアは、パラメータ値をString/StringList(平文)またはSecureString(暗号化されたデータ)として保存できます。

これまでAWS CloudFormationでは、SSMパラメータストアのString/StringListデータは参照できましたが、SecureStringデータは参照できませんでした。今回のアップデートで、CloudFormationでSSMパラメータストアのSecureStringがサポートされたので実際に使ってみました。ちなみにこの機能はDynamic referencesというらしいです。

AWS CloudFormation Supports AWS Systems Manager Secure String Parameters in CloudFormation Templates

CloudFormationでDynamic referencesの使い方

  • スタックテンプレートに含められるDynamic referencesは60個まで
  • cn-north-1cn-northwest-1リージョンは未サポート
  • テンプレート内の書式は{{resolve:service-name:reference-key}}
  • 現在サポートされているservice-namessmssm-secureの2つ
  • SSMパラメータストアのString/StringListの参照は{{resolve:ssm:parameter-name:version}}
  • SSMパラメータストアのSecureStringの参照は{{resolve:ssm-secure:parameter-name:version}}
  • parameter-nameは大文字と小文字を区別する(case-sensitive)
  • versionは必須
  • 最新のバージョン を参照という指定は不可

現在ssm-secureをサポートしているのは次のリソースのみです。

Resource Property Type Properties
AWS::DirectoryService::MicrosoftAD Password
AWS::DirectoryService::SimpleAD Password
AWS::ElastiCache::ReplicationGroup AuthToken
AWS::IAM::User LoginProfile Password
AWS::KinesisFirehose::DeliveryStream RedshiftDestinationConfiguration Password
AWS::OpsWorks::App AppSource Password
AWS::OpsWorks::Stack CustomCookbooksSource Password
AWS::OpsWorks::Stack RdsDbInstances DbPassword
AWS::RDS::DBCluster MasterUserPassword
AWS::RDS::DBInstance MasterUserPassword
AWS::Redshift::Cluster MasterUserPassword

やってみた

それでは実際にCloudFormationテンプレートを用意してSSMパラメータストアのデータを参照してみます。まずはSSMパラメータストアにパラメータ値をセットします。

$ aws ssm put-parameter --name plaintext-password --value jugemujugemugokounosurikire --type String
$ aws ssm put-parameter --name secure-password --value 'P@ssW%rd#123' --type SecureString

$ aws ssm get-parameter --name plaintext-password
{
    "Parameter": {
        "Name": "plaintext-password",
        "Type": "String",
        "Value": "jugemujugemugokounosurikire",
        "Version": 1
    }
}

$ aws ssm get-parameter --name secure-password
{
    "Parameter": {
        "Name": "secure-password",
        "Type": "SecureString",
        "Value": "AQICAHhoU3dH8gG618tMtQTGML7F40J6GS3uxzeVcB1fm+PZ1wGXv+cRZAPFPYdWBmTiDW83AAAAajBoBgkqhkiG9w0BBwagWzBZAgEAMFQGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMK8sT/8JMqPeg6aPEAgEQgCd0cG5p0sxp7CZyUkP6vj3WXxGSFwsZ66q5mE8D//P3/30ZPAfe004=",
        "Version": 1
    }
}

次にCloudFormationテンプレートを用意します。今回はssm-pstest.template.ymlというファイル名で用意しました。

ssm-pstest.template.yml

---
AWSTemplateFormatVersion: '2010-09-09'
Description: SSM Parameter Store test template.
Parameters:
  ParamPlaintextPassword:
    Type : AWS::SSM::Parameter::Value<String>
    Default: ''
Resources:
  IAMUser:
    Type: AWS::IAM::User
    Properties:
      UserName: test-user
      LoginProfile:
        Password: '{{resolve:ssm-secure:secure-password:1}}'
Outputs:
  ParamPlaintextPassword:
    Value: !Ref ParamPlaintextPassword
  DynamicRefPlaintextPassword:
    Value: '{{resolve:ssm:plaintext-password:1}}'

テンプレートの要点を簡単に解説します。

  • 6行目
  • 以前からサポートされていたSSMパラメータストアの参照形式です(String/StringListのみ)
  • スタック作成時のパラメータ(引数)でキー名を指定すると、SSMパラメータストアのパラメータ値が取得できます
  • 今回のアップデートには関係ありません
  • 17行目
  • AWS::SSM::Parameter::Valueのパラメータを参照しています
  • Ref組込み関数などで参照すると値が取得できます
  • 14行目
  • secure-passwordというキー名のSecureStringを参照しています
  • 前述した、サポートされているリソースでのみ使用できます
  • 今回のアップデートの目玉機能です
  • 19行目
  • plaintext-passwordというキー名のStringを参照しています
  • これによってAWS::SSM::Parameter::Value以外の参照方法ができるようになりました

それでは用意したテンプレートを使用してスタックを作成してみます。

$ aws cloudformation create-stack \
  --stack-name ssm-pstest \
  --template-body file://ssm-pstest.template.yml \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameters \
    ParameterKey=ParamPlaintextPassword,ParameterValue=plaintext-password

出力を確認してみます。従来の参照方法と、今回のDynamic referencesどちらでも取得できています。

$ aws cloudformation describe-stacks | jq '.Stacks[] |select(.StackName == "ssm-pstest") | .Outputs[]'
{
  "OutputKey": "DynamicRefPlaintextPassword",
  "OutputValue": "jugemujugemugokounosurikire"
}
{
  "OutputKey": "ParamPlaintextPassword",
  "OutputValue": "jugemujugemugokounosurikire"
}

続いて、マネジメントコンソールから作成したIAMユーザーでログインしてみます。もちろんパスワードはsecure-passwordでセットした値です。

無事にログインできました!

確認できたらさくっとスタックは削除しておきましょう。

パラメータ(引数)としてキー名を受け取ってみる

先ほどのテンプレートでは、パスワードのキー名をテンプレート内にハードコーディングしていました。これをスタック作成時のパラメータ(引数)で受け取って動作するか確認してみました。

ssm-pstest.template.yml

---
AWSTemplateFormatVersion: '2010-09-09'
Description: SSM Parameter Store test template.
Parameters:
  PassKey:
    Type: AWS::SSM::Parameter::Name
Resources:
  IAMUser:
    Type: AWS::IAM::User
    Properties:
      UserName: test-user
      LoginProfile:
        Password: !Sub '{{resolve:ssm-secure:${PassKey}:1}}'

ポイントは5-6行目でキー名を取得している点。そして13行目でキー名を参照してDynamic referencesを構築している点です。

画面キャプチャは省きますが、次のコマンドでスタックを作成でき、マネジメントコンソールからのログインもできました。これは熱いですね!

$ aws cloudformation create-stack \
  --stack-name ssm-pstest \
  --template-body file://ssm-pstest.template.yml \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameters \
    ParameterKey=PassKey,ParameterValue=secure-password

もしかして従来の方法でもSecureString参照できる?

できません。 次のようなテンプレートを用意してスタック作成をしてみましたが、エラーで失敗しました。

ssm-pstest.template.yml

---
AWSTemplateFormatVersion: '2010-09-09'
Description: SSM Parameter Store test template.
Parameters:
  ParamSecurePassword:
    Type : AWS::SSM::Parameter::Value<String>
    Default: ''
Resources:
  IAMUser:
    Type: AWS::IAM::User
    Properties:
      UserName: test-user
Outputs:
  ParamSecurePassword:
    Value: !Ref ParamSecurePassword
$ aws cloudformation create-stack \
  --stack-name ssm-pstest \
  --template-body file://ssm-pstest.template.yml \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameters \
    ParameterKey=ParamSecurePassword,ParameterValue=secure-password

An error occurred (ValidationError) when calling the CreateStack operation: Parameters [secure-password] referenced by template have types not supported by CloudFormation.

SecureStringも出力できるんじゃない?

できません。 次のようなテンプレートを用意してスタック作成をしてみましたが、エラーで失敗しました。前述したサポートされているリソース以外ではエラーとなるようです。

ssm-pstest.template.yml

---
AWSTemplateFormatVersion: '2010-09-09'
Description: SSM Parameter Store test template.
Resources:
  IAMUser:
    Type: AWS::IAM::User
    Properties:
      UserName: test-user
Outputs:
  DynamicRefSecurePassword:
    Value: '{{resolve:ssm-secure:secure-password:1}}'
$ aws cloudformation create-stack \
  --stack-name ssm-pstest \
  --template-body file://ssm-pstest.template.yml \
  --capabilities CAPABILITY_NAMED_IAM

An error occurred (ValidationError) when calling the CreateStack operation: SSM Secure reference is not supported in: [Outputs/DynamicRefSecurePassword/Value]

まとめ

これまでCloudFormationで参照したいデータをSSMパラメータストアに保存する場合、暗号化して保存できませんでした。今回のアップデートによって、よりセキュアにデータが保存できるようになりました。地味ですがうれしいアップデートですね!