[アップデート] SSM Run Commandでパラメーターの値を環境変数に設定可能になりました
しばたです。
先日AWSより「Systems Manager Run Command now supports interpolating parameters into environment variables」というタイトルの更新がアナウンスされました。
こちら、どちらかというとSSM Run CommandよりSSM AgentとSSM Documentに対する機能追加な気もするのですが、あまり深く考えずに解説していきたいと思います。
更新内容
今回の更新はSSM Documentスキーマ定義の最新バージョンであるVer.2.2に対する機能追加となり、ドキュメントのパラメーターにinterpolationType
属性を指定することでその内容をSSM Run Command実行時に環境変数に設定可能になるというものです。
環境変数の名前はSSM_<パラメーター名>
になります。
Run Command実行時の処理はSSM Agentが担うため、SSM Agentのバージョンが本日時点で最新のVer.3.3.2746.0以上である必要があります。
Ver.3.3.2746.0未満の場合はinterpolationType
属性は無視されます。(従来の挙動)
AWSによればこの機能によりユーザーによる意図せぬコマンドインジェクションを防ぎやすくなるとのことです。
設定例
ここからは具体的な設定例を基に解説していきます。
従来の方式
例として簡単なSSM Documentを用意すると、従来Run Command用のスクリプト内でパラメーターを使うには{{}}
で囲って定義する必要がありました。
---
schemaVersion: "2.2"
description: "Sample Document 1"
parameters:
Message:
type: "String"
description: "Example parameter"
default: "Hello World"
mainSteps:
- action: "aws:runShellScript"
name: "example"
inputs:
runCommand:
- # 従来のパラメーターは {{}} で囲う必要があり、これは単純なプレースホルダー (Run Command実行時に置換される)
- echo "{{Message}}"
これは単純なプレースホルダーであり、Run Command実行時にはその内容が置換された状態のスクリプト(_script.sh
)がインスタンス内部に保存されたうえで実行されます。
# コマンドが実行されるインスタンス内部では文字列置換後のスクリプトが実行される
echo "Hello World"
単純な置換なので容易にコマンドインジェクションを起こせてしまいます。
パラメーターの値をHello World
からコマンドを実行する値、たとえば$(curl -s https://checkip.amazonaws.com)
にするだけでRun Command中にcurl
コマンドを差し込めます。[1]
意図的にコマンドインジェクションしてみる
結果はこの通りcurl
コマンドを実行した後の値になります。
curlコマンドにより取得されたIPアドレスが表示されている
これはインスタンス内部で実行されるスクリプトが下記となるためです。
echo "$(curl -s https://checkip.amazonaws.com)"
この様なかたちでコマンドインジェクションが可能ではあるものの、悪意を持った人物がコマンドインジェクションをするには事前にAWSアカウントを侵害する必要があるため悪意を持ってSSM Run Commandのパラメーターを細工するという事態はそこまで多くないと思います。[2]
ただ、アナウンスの通りユーザーの操作ミス等により意図しない形でコマンドインジェクションを起こしてしまう可能性はあるでしょう。
今回の更新はこの事態を防ぐための機能の様です。
新方式
続けて今回の更新によりパラメーター(Message
)に新たにinterpolationType
属性を増やし値をENV_VAR
することで環境変数SSM_Message
が使える様になります。
---
schemaVersion: "2.2"
description: "Sample Document 2"
parameters:
Message:
type: "String"
description: "Example parameter"
default: "Hello World"
# ↓ interpolationType 属性の指定によりパラメーターの値を環境変数に
interpolationType: "ENV_VAR"
mainSteps:
- action: "aws:runShellScript"
name: "example"
inputs:
runCommand:
- # interpolationType の指定により SSM_Message 環境変数が使える様になる
- echo "$SSM_Message"
インスタンスのSSM AgentのバージョンがVer.3.3.2746.0未満の場合は「単純にSSM_Message
環境変数が無い」扱いになるのでRun Commandの結果は何も表示されずに終わります。
SSM Agentのバージョンが古い場合 : 環境変数が無い扱いとなる
パラメーターの置換も発生しないのでインスタンス内部で実行されるスクリプトはこの通りです。
echo "$SSM_Message"
SSM AgentのバージョンをVer.3.3.2746.0にしてやるとSSM_Message
環境変数が増えるのでRun Commandの実行結果も変わります。
SSM Agentのバージョンを上げると環境変数に値が設定される
この状態で前述のコマンドインジェクションを試みても、
再度コマンドインジェクションを試みる
今度は単純に環境変数の文字列して扱われるのでcurl
コマンドは実行されません。
無事コマンドインジェクションを防ぐことができる
いい感じですね。
余談 : PowerShellも対応しています
本記事ではBash(runShellScript
)を例示していますがPowerShellの場合(runPowerShellScript
)も対応しています。
PowerShell版のドキュメントはこんな感じになり、環境変数の参照方法がシェルに応じた形になるだけです。
---
schemaVersion: "2.2"
description: "Sample Document 3"
parameters:
Message:
type: "String"
description: "Example parameter"
default: "Hello World"
interpolationType: "ENV_VAR"
mainSteps:
- action: "aws:runPowerShellScript"
name: "example"
inputs:
runCommand:
- # interpolationType の指定により SSM_Message 環境変数が使える様になる
- Write-Output "$env:SSM_Message"
最後に
以上となります。
シンプルですがスクリプトの安全性が高まる良い更新ですね。
これからSSM Documentを作る際は積極的に採用するとよいでしょう。