top of page

AWS Systems Manager(SSM)のAutomation機能でDB特権ユーザーの利用を承認制にする

  • yeda1343
  • 9月5日
  • 読了時間: 8分
ree


目次




   はじめに


私の参画しているプロジェクトでは、AWS上にデータを集約管理する「データ管理基盤」の構築を行っています。


DBの特権ユーザーについて、利用された場合に管理者に通知する仕組みはあるものの、パスワードを知っている人であればいつでも利用可能となっており、特権ユーザーを申請に基づいて一時的に有効化する仕組みがありませんでした。


AWS Systems ManagerのAutomationを用いて、DB特権ユーザーの利用を承認制にし、特権ユーザーのログイン有効化/無効化を自動化する承認フローを実装したので、紹介していきます。



   AWS Systems Manager(SSM)とは


AWS Systems Manager(SSM)は、AWSクラウド、オンプレミス、マルチクラウド環境にまたがるサーバーや仮想マシン(ノード)を一元的に管理・運用できるマネージドサービスです。



SSMの主な機能


SSMは多機能な運用管理サービスであり、その主な機能は大きく以下の4つのカテゴリに分類されます。

  • アプリケーション管理

  • ノード管理

  • 運用管理

  • 変更管理


具体的にはこのような構成になっています。

AWS Systems Manager(SSM)
├── アプリケーション管理
│   ├── Parameter Store(パラメータ管理)
│   ├── AppConfig(アプリケーション設定管理)
│   └── Application Manager(アプリケーションリソース管理)
├── ノード管理
│   ├── Fleet Manager(ノード一元管理)
│   ├── Session Manager(リモート接続)
│   ├── Run Command(リモートコマンド実行)
│   ├── Patch Manager(パッチ管理)
│   ├── Inventory(インベントリ収集)
│   ├── State Manager(状態管理)
│   ├── Compliance(コンプライアンス管理)
│   ├── Distributor(ソフトウェア配布)
│   └── Hybrid Activations(オンプレミス連携)
├── 運用管理
│   ├── Incident Manager(インシデント管理)
│   ├── Explorer(運用ダッシュボード)
│   ├── OpsCenter(運用課題管理)
│   └── CloudWatch Dashboards(運用可視化)
└── 変更管理
    ├── Automation(自動化ワークフロー)
    ├── Document(SSMドキュメント)
    ├── Quick Setup(初期セットアップ自動化)
    ├── Maintenance Windows(メンテナンススケジューリング)
    ├── Change Manager(変更管理)
    └── Change Calendar(変更カレンダー)


SSMのAutomationとは


これらの機能の中で、今回の承認フロー構築において大きな役割を果たすのがAutomationです。これは、AWSリソースの運用・管理タスクを自動化するための機能を指します。


Automationでは「Runbook」と呼ばれるワークフロー定義(JSON/YAML)を利用し、複数のAWSリソースに対して一連の操作を自動的に実行できます。


実行方法は以下の4つから選択できます。

  • シンプルな実行(Simple execution) 1回の実行、単一または少数リソース向け

  • レート制御(Rate control) 複数リソースに対し同時実行数・エラー閾値を制御

  • マルチアカウント・リージョン(Multi-account and Region) 複数AWSアカウント・リージョンをまたぐ一括実行

  • 手動実行(Manual execution) ステップごとに進行を手動で制御、確認しながら実行



SSMのRunbookとは


RunbookはDocumentの一種であり、AWS Systems Manager(SSM)の「Automation」機能で利用される自動化手順書のことです。


Automation Runbookとも呼ばれ、AWSリソースやマネージドインスタンスに対して実行する一連のアクション(手順)を定義します。


Runbookには以下の2種類があります。

  • AWSが提供する事前定義済みRunbook

  • 独自のカスタムRunbook


Runbookの主な構成要素は以下の通りです。

Runbook
├── description: Runbookの説明文
├── schemaVersion: Runbookのスキーマバージョン(例: 0.3)
├── parameters: Runbook実行時に入力するパラメータ群
│    ├── パラメータ名
│    │    ├── type: パラメータの型(例: String, StringList, Map)
│    │    ├── required: 必須かどうか(true/false)
│    │    ├── default: デフォルト値(省略可)
│    │    └── description: パラメータの説明
│    └── ...(複数パラメータを定義可能)
├── mainSteps: Runbookのメイン処理ステップ群
│    ├── ステップ名
│    │    ├── action: 実行するアクション(例: aws:runCommand等)
│    │    ├── name: ステップの名前
│    │    ├── inputs: ステップで使用する入力値
│    │    └── onFailure: 失敗時の挙動(オプション)
│    └── ...(複数ステップを定義可能)
└── outputs: Runbook実行後に返す出力値の定義(オプション)

【例】AWS-StopEC2Instanceの事前定義済みRunbook

ree


   承認フローの構築


それでは、これらの知識を踏まえて実際に承認フローを構築してみましょう。


今回は、ユーザーが申請した使用開始・終了時刻に基づき、一時的にDB特権ユーザーを利用可能にする承認フローを作成します。



構築イメージ(Runbookの全体像)


以下はデザインモード(GUI)で表示した場合のRunbookです。今回はコードで作成しますが、Runbookの全体像の理解にご利用ください。


ree

Step1:承認/否認

Step2:待機秒数計算

Step3:待機処理(利用開始)

Step4:特権ユーザー有効化

Step5:待機処理(利用終了)

Step6:特権ユーザー無効化

Step4及び6では、踏み台サーバーからpsqlコマンドでDB特権ユーザーの利用可否(LOGIN/NOLOGIN)を制御します。

※psqlはPostgreSQL に接続するクライアントコマンドです。コマンドラインからデータベースに接続し、SQLコマンドやpsql独自のメタコマンドを実行できます



Runbookの作成 ①Parametersセクション


まずは、申請に必要なパラメータをコードで定義します。

デフォルト値を設定することでユーザーの申請負荷を減らすことができます。

parameters:
  Approvers:
    type: StringList
    description: 承認者(IAMユーザーもしくはIAMロール)
    default:
      - arn:aws:iam::<アカウントID>:role/aws-reserved/sso.amazonaws.com/<リージョン>/<ロール名>
  SnsTopicArn:
    type: String
    description: SNS通知先
    default: arn:aws:sns:<リージョン>:<アカウントID>:<トピック名>
  EC2InstanceId:
    type: String
    description: psql実行用EC2インスタンスID
  DBUser:
    type: String
    description: 特権DBユーザー名
  DBName:
    type: String
    description: データベース名
  StartTime:
    type: String
    description: '利用開始時刻(ISO8601、例: 2025-05-29T09:00:00Z)'
  EndTime:
    type: String
    description: '利用終了時刻(ISO8601、例: 2025-05-29T10:00:00Z)'

※承認者のパラメータはIAMユーザーの直接指定(リスト形式)もしくはIAMロールとなります



Runbookの作成 ②mainStepsセクション


続いて、各処理ステップをコードで定義します。

mainSteps:

 #1.承認/否認
  - name: approve
    action: aws:approve
    nextStep: calcSleepSeconds
    isEnd: false
    onFailure: Abort
    inputs:
      NotificationArn: '{{SnsTopicArn}}'
      Message: 特権ユーザー利用の承認依頼
      Approvers: '{{Approvers}}'
      MinRequiredApprovals: 1

 #2.待機秒数計算
  - name: calcSleepSeconds
    action: aws:executeScript
    nextStep: sleepUntilStart
    isEnd: false
    inputs:
      Runtime: python3.10
      Handler: main
      Script: |
        import datetime

        def parse_iso8601(s):
            return datetime.datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ")

        def main(events, context):
            start = parse_iso8601(events['StartTime'])
            end = parse_iso8601(events['EndTime'])
            now = datetime.datetime.utcnow()
            sleep_to_start = int((start - now).total_seconds())
            sleep_to_end = int((end - now).total_seconds())
            if sleep_to_start < 0:
                sleep_to_start = 0
            if sleep_to_end < 0:
                sleep_to_end = 0
            return {
                "SleepToStart": str(sleep_to_start),
                "SleepToEnd": str(sleep_to_end)
            }
      InputPayload:
        StartTime: '{{StartTime}}'
        EndTime: '{{EndTime}}'
    outputs:
      - Name: SleepToStart
        Selector: $.Payload.SleepToStart
        Type: String
      - Name: SleepToEnd
        Selector: $.Payload.SleepToEnd
        Type: String

 #3.待機処理(利用開始)
  - name: sleepUntilStart
    action: aws:sleep
    nextStep: enableLogin
    isEnd: false
    inputs:
      Duration: PT{{calcSleepSeconds.SleepToStart}}S

 #4.特権ユーザー有効化
  - name: enableLogin
    action: aws:runCommand
    nextStep: sleepUntilEnd
    isEnd: false
    inputs:
      DocumentName: AWS-RunShellScript
      InstanceIds:
        - '{{EC2InstanceId}}'
      Parameters:
        commands:
          - |
            # Parameter StoreからDB接続情報を取得
            export PGPASSWORD=$(aws ssm get-parameter --name '/db/password' --with-decryption --query 'Parameter.Value' --output text)
            export PGHOST=$(aws ssm get-parameter --name '/db/endpoint' --query 'Parameter.Value' --output text)
            # 特権ユーザーのログイン権限を付与
            psql -h $PGHOST -U usr_dbmgr -d {{DBName}} -c "ALTER ROLE {{DBUser}} LOGIN;"

 #5.待機処理(利用終了)
  - name: sleepUntilEnd
    action: aws:sleep
    nextStep: disableLogin
    isEnd: false
    inputs:
      Duration: PT{{calcSleepSeconds.SleepToEnd}}S

 #6.特権ユーザー無効化
  - name: disableLogin
    action: aws:runCommand
    isEnd: true
    inputs:
      DocumentName: AWS-RunShellScript
      InstanceIds:
        - '{{EC2InstanceId}}'
      Parameters:
        commands:
          - |
            # Parameter StoreからDB接続情報を取得
            export PGPASSWORD=$(aws ssm get-parameter --name '/db/password' --with-decryption --query 'Parameter.Value' --output text)
            export PGHOST=$(aws ssm get-parameter --name '/db/endpoint' --query 'Parameter.Value' --output text)
            # 特権ユーザーのログイン権限を剥奪
            psql -h $PGHOST -U usr_dbmgr -d {{DBName}} -c "ALTER ROLE {{DBUser}} NOLOGIN;"

これで承認フローの作成は完了です。続いて動作確認にうつりましょう。


※実環境実装時の留意点

  • DBパスワード管理 今回はDBパスワード管理にSSM Parameter StoreのSecureStringsを採用しています。 より厳密に管理したい場合はSecrets Manager等の利用を検討してください。

  • 各ステップのエラー処理 今回はコード簡略化のため、各ステップのエラー処理を組み込んでいません。 実環境で実装する際は、各ステップのエラーハンドリングを適切に処理してください。


エラー処理を組み込んだ例(GUI)

ree

AWSプロジェクトの人手不足でお困りではありませんか?

高い技術力を持つAWSエンジニアが、貴社の課題を解決します。



   承認フローの動作確認


Automationの実行(承認申請)


パラメータを指定して実行します。


GUI

ree

CLI

aws ssm start-automation-execution `
  --document-name "<Runbook名>" `
  --parameters "DBUser=<特権ユーザー名>,DBName=<データベース名>,StartTime=<利用開始時刻>,EndTime=<利用終了時刻>"


承認依頼メールの受信


SNSトピックに登録されているメール(メーリングリスト)宛に承認依頼メールが送信されます。

ree


承認オペレーション


承認者として指定されているIAMユーザーもしくは承認者ロールを持つIAM Identity Centerのワークフォースユーザー等で承認します。


CLI

aws ssm send-automation-signal `
--automation-execution-id <Automation ID>  `
--signal-type Approve `
--payload Comment=OK


DB接続時の挙動確認


ポートフォワーディングでSQLクライアント(A5M2等)から繋いだ場合の挙動を確認します。


承認中

ree

承認外

ree

上の画像のように、

  • 承認中はDB特権ユーザーでDBにアクセスできる

  • 承認外はDB特権ユーザーでDBにアクセスできない(ログイン権限がない旨のエラーメッセージが表示される)

となれば、想定通りです!



   まとめ


ご紹介した通り、SSM Automationで簡易的な承認フローを作成できます。自動化により運用ミスも回避できるため、一時的な特権付与・剥奪などの権限制御に有用です。


【SSM Automationを用いた承認フローの主なユースケース】

GRANT/REVOKE rds_superuser FROM <DBユーザー>;

  • DB特権ユーザーの一時的な利用許可(ログイン権限付与) psqlの-cオプションにて下記SQL文で制御

ALTER ROLE <DB特権ユーザー> LOGIN/NOLOGIN;

今回は3つ目の方法を解説しました。 皆さまの業務やアイデアにもご活用いただければと思います。


AWSプロジェクトの人手不足でお困りではありませんか?

高い技術力を持つAWSエンジニアが、貴社の課題を解決します。



ree