AWS Systems Manager Automation を使って CFnスタック展開の承認フローを作ってみる

SSMオートメーションと仲良くなりたい
2021.02.18

はじめに

以下のような 承認/作成フローを Systems Manager(SSM) オートメーションを使って実現してみます。

img

大まかな流れは以下のとおり

  1. 開発者は CFnスタック作成に必要なパラメータを入力して、SSMオートメーションを実行する
  2. SSMオートメーションは 管理者の承認 ステップに入る
  3. 管理者は SSMオートメーションの内容を確認して、承認する
  4. SSMオートメーションは CFnスタック作成 ステップに入る
  5. SSMオートメーションは入力パラメータを元に CFnスタックを作成する

前提知識

SSMドキュメント

多くの人が知っているとおり、 AWS Systems Manager(SSM) でできることはとても多いです。 例えば 「EC2インスタンスに対して特定のコマンドを実行する」Run Command や 「一連のAWSアクションを自動化する」Automation などがあります。

これら SSM 各種機能で実施する定型アクションは AWS Systems Manager(SSM) ドキュメント の構文に従って書かれています。

SSMドキュメントの主な特徴は以下の通り

  • YAML もしくは JSONで記述
  • 異なるバージョンの作成や比較が可能
  • アカウント間の共有が可能
  • タイプ が存在して、タイプに合わせた スキーマバージョンを指定する必要がある
    • 例えば Run Command の SSMドキュメントは Command タイプ。 スキーマバージョンは 1.2, 2.0, 2.2 が使用できる
    • 例えば Automation の SSMドキュメントは Automation タイプ。 スキーマバージョンは 0.3 を使用する必要がある

SSMドキュメントはマネジメントコンソールの AWS Systems Manager > Documents から参照できます。 SSMドキュメントは自身で作成することも可能ですが、 AWSで提供されている SSMドキュメントも豊富にあります。

SSMオートメーション

Systems Manager(SSM) オートメーション は EC2インスタンスや他AWSリソースに関連する 一連の運用作業を自動化するための機能です。

前述の SSMドキュメント(スキーマタイプ Automation)を活用しています。 Automation で使われる SSMドキュメントは ランブック(runbook) と呼ばれます。

「承認プロセスを含んだ EC2インスタンスの起動/停止フロー」や 「承認プロセスを含んだ CFnスタック作成フロー」などがユースケースです。

もし AWS Config の修復機能を触ったことがある方は、 SSMオートメーションに馴染みがあるかもしれません。 Configルールの「修復アクション」の実態は SSMオートメーションです。

参考: 【AWS Config】EC2インスタンスに特定アプリケーションがインストールされているかチェックして通知する | DevelopersIO

構築

今回の検証で作る必要のあるリソースは以下の 4つです。

img

  • SSMドキュメント: 「承認→CFnスタック作成」フローを記述するために必要です
  • SNSトピック: 「承認」ステップで管理者に SNSトピック経由でメール通知を行います
  • CFnテンプレート: 「CFnスタック作成」ステップで使うテンプレートです
  • IAMロール: SSMオートメーションの実行ロールです

手間の掛からない順番に説明します。

SNSトピック

適宜作成して、管理者へメールが通知されるようにサブスクリプション設定を済ませます。

CFnテンプレート

今回は バケット名/Projectタグをパラメータとした S3バケットを作成するシンプルなテンプレートを使います。

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  BucketName:
    Type: String
  ProjectName:
    Type: String
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties: 
      BucketName: !Ref BucketName
      Tags: 
        - Key: Project
          Value: !Ref ProjectName

これを S3バケットに格納しておきます。

IAMロール

SSMオートメーションの実行ロールです。以下を行う権限を付与します。

  • SNSトピックに送信(Publish)する
    • 後述する aws:approve アクションで必要な権限です
  • CFnスタックを作成する
    • 後述する aws:createStack アクションで必要な権限です
  • S3バケットを作成する
    • 同じく aws:createStack アクションで必要な権限ですが、 CFnテンプレートで作るリソースに依ります

今回は以下のように CFnテンプレートを使って作成しました。

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  RoleName:
    Type: String
    Default: ssm-automation-role-for-creating-stack
Resources:
  IamRole:
    Type: AWS::IAM::Role
    Properties: 
      RoleName: !Ref RoleName
      Description: "role for ssm automation: create stack"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement: 
          - Effect: "Allow"
            Principal: 
              Service: "ssm.amazonaws.com"
            Action: "sts:AssumeRole"
      Policies: 
        - PolicyName: policy-for-ssm-automation
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              # SNSトピックに送信(Publish)する
              - Sid: approval
                Effect: "Allow"
                Action: "sns:Publish"
                Resource: "*"
              # CFnスタックを作成する
              - Sid: createStack
                Effect: "Allow"
                Action:
                  - "sqs:*"
                  - "cloudformation:CreateStack"
                  - "cloudformation:DescribeStacks"
                  - "s3:GetObject"
                Resource: "*"
              # S3バケットを作成する
              - Sid: createBucket
                Effect: "Allow"
                Action:
                  - "s3:CreateBucket"
                  - "s3:PutBucketTagging"
                Resource: "*"

SSMドキュメント

以下のような SSMドキュメントを作成しました。 ハイライト部分を適宜書き換えてください。

schemaVersion: "0.3"
description: "create a new S3 bucket with approval"
assumeRole: "{{AssumeRole}}"
parameters:
  AssumeRole:
    description: "(Required) Automation Role."
    type: String
    default: "(先程作ったIAMロールのARN)"
    allowedValues:
    - "(先程作ったIAMロールのARN)"
  SnsTopic:
    description: "(Required) The SNS topic ARN used to send pending approval notification."
    type: String
    default: "(先程作ったSNSトピックのARN)"
    allowedValues:
    - "(先程作ったSNSトピックのARN)"
  TemplateURL:
    description: "(Required) CFn TemplateURL"
    type: String
    default: "(先程作ったCFnテンプレートの格納先 URL)"
    allowedValues:
    - "(先程作ったCFnテンプレートの格納先 URL)"
  StackName:
    description: "(Required) CFn StackName"
    type: String
  BucketName:
    description: "(Required) Parameter: BucketName"
    type: String
  ProjectName:
    description: "(Required) Parameter: ProjectName"
    type: String
mainSteps:
  - name: "approve"
    action: "aws:approve"
    onFailure: Abort
    inputs:
      NotificationArn: "{{SnsTopic}}"
      Message: "Approval required to createStack: {{StackName}} (BucketName: {{BucketName}}, ProjectName: {{ProjectName}})"
      MinRequiredApprovals: 1
      Approvers:
      - "(管理者のIAMロールARN)"
  - name: "createStack"
    action: "aws:createStack"
    onFailure: Abort
    inputs:
      StackName: "{{StackName}}"
      TemplateURL: "{{TemplateURL}}"
      Parameters:
        - ParameterKey: BucketName
          ParameterValue: "{{BucketName}}"
        - ParameterKey: ProjectName
          ParameterValue: "{{ProjectName}}"

これを登録していきます。

マネコンの SSMドキュメント のページに行き、 オートメーションを作成する を選択します。 名前を適当に記入(例えば CreateNewS3BucketWithApproval ) して、 ドキュメントエディタに貼り付けてオートメーションを作成します。

img

SSMドキュメント詳細

作成した SSMドキュメントの内容解説です。

「SSMドキュメントの構文や SSMオートメーションで使用可能なアクションを知りたい人」向けです。 必要ない場合は次章 "検証(利用の流れ)" をご覧ください。

全体構成

schemaVersion: "0.3"
description: "create a new S3 bucket with approval"
assumeRole: "{{AssumeRole}}"
parameters:
  AssumeRole:
    description: "(Required) Automation Role."
    type: String
    default: "(先程作ったIAMロールのARN)"
    allowedValues:
    - "(先程作ったIAMロールのARN)"
  (略)
mainSteps:
  - name: "approve"
    action: "aws:approve"
    (略)
  - name: "createStack"
    action: "aws:createStack"
    (略)

大枠部分の構文は以下ドキュメントを読めば分かります。

schemaVersion は使用するスキーマバージョンです。 Automation ドキュメントは 0.3 を指定する必要があります。

description はドキュメントの説明です。

assumeRole は SSMオートメーションの実行ロールを指定します。 後述のパラメータ AssumeRole を参照しています。

parameters でパラメータを定義します。おおよそ CFnのパラメータと同じような使い方です。 "{{ParameterName}}" といった形で他セクションで参照できます。

mainSteps で実行するアクションを連ねていきます。 「承認→作成」フローを書くセクションです。詳細は後述。

mainSteps#1(aws:approve)

# "approve" ステップ
- name: "approve"
  # 実行するアクション
  action: "aws:approve"
  # 失敗時の行動。Abotr(中止), Continue(続行), step:xxx(別ステップへ遷移)
  onFailure: Abort
  inputs:
    # 通知先SNSトピック
    NotificationArn: "{{SnsTopic}}"
    # メッセージ
    Message: "Approval required to createStack: {{StackName}} (BucketName: {{BucketName}}, ProjectName: {{ProjectName}})"
    # 必要な承認の最小数
    MinRequiredApprovals: 1
    # 承認できるプリンシパルのリスト
    Approvers:
    - "(管理者のIAMロールARN)"

まず SSMオートメーションで実行可能なアクションのリファレンスは以下リンクから辿れます。

最初のステップでは aws:approve を使います。 指定した承認者から、必要数の承認を得られた場合に次のステップに進めます。

必要に応じて MinRequiredApprovals (必要な承認の最小数) や Approvers (承認できるプリンシパルのリスト)を変更しましょう。

mainSteps#2(aws:createStack)

# "createStack" ステップ
- name: "createStack"
  # 実行するアクション
  action: "aws:createStack"
  # 失敗時の行動。Abotr(中止), Continue(続行), step:xxx(別ステップへ遷移)
  onFailure: Abort
  inputs:
    # スタック名
    StackName: "{{StackName}}"
    # テンプレートURL
    TemplateURL: "{{TemplateURL}}"
    # CFnパラメータ
    Parameters:
      - ParameterKey: BucketName
        ParameterValue: "{{BucketName}}"
      - ParameterKey: ProjectName
        ParameterValue: "{{ProjectName}}"

このステップでは aws:createStack を使います。 テンプレートを指定して新しい CFnスタックを作成するアクションです。

検証(利用の流れ)

[開発者] オートメーションを実行する

開発者は SSMのマネコンから、作成したドキュメントを選択します。

img

"オートメーションを実行する" を選択します。

img

デフォルトの "シンプルな実行" を選択したままで、 以下のようにパラメータを入力します。 AssumeRole, SnsTopic, TemplateURL は固定値にしているので、 開発者はスタック名と CFnパラメータ(作成したバケットの名前とプロジェクト名)を入力します。

img

内容確認して "実行" します。

[管理者] 承認する

SNS経由で管理者へメール通知されます。以下のような内容です。

img

Approve のリンクへ移動します。以下のような承認/拒否画面になります。

img

メッセージからリクエストされた情報(スタック名やパラメータ)を確認し、 承認を選択して "送信" します。

スタック作成を確認

スタック作成が成功する場合は、以下のように全ステップ "成功" となります。

img

CFnスタック、および スタックリソース(S3バケット)も確認できました。

おわりに

シンプルですが SSMオートメーションを使った CFnスタック展開の承認フローを作ってみました。

最近登場した Systems Manager Change Manager (変更管理のプロセス、承認フロー作成の機能) の 実態は オートメーションです。 Change Manager を触る前に、 今回みたいにオートメーションを軽く触ることでスムーズに理解が進むのではないでしょうか。

参考