[小ネタ] 再起動を伴うSSM Run Commandの書き方

小ネタです。
基本的にドキュメントを見れば一発の話なのですが、軽い解説と実践的なサンプルを紹介します。

スクリプトからのマネージドインスタンスの再起動

再起動を伴う AWS Systems Manager Run Command(SSM Run Command)の記述方法は以下のドキュメントにばっちり記載されています。

このドキュメントから要点を抜き出します。

スクリプトの戻り値

SSM Run Commandでは特定の戻り値(Windowsの場合3010、Linuxの場合194)でスクリプトが終了した場合にインスタンスを再起動し、再起動後にスクリプトを再実行します。

ここでWindowsで採用されている3010という値はMSIインストーラー(msiexec.exe)が再起動を伴う終了となった場合の戻り値(ERROR_SUCCESS_REBOOT_REQUIRED)と同じ値が採用されています。
Windowsの自動セットアップスクリプトを良く書く人にとってはピンとくる戻り値ですね。

また、Linuxの194という値については正直なぜこの値が選ばれたのかわからなかったのですが、Bashで予約済みの戻り値から外れる値を選んでいる様に見受けられます。

スクリプトはべき等に

スクリプトが再起動後再実行される場合に特別な引数が付与されるといったことは一切無く、単純に同じスクリプトがもう一度実行されます。
このため再起動を伴うスクリプトはべき等に作る必要があります。

再実行されたスクリプトが再起動後に必要な処理だけを実施し、再起動前の処理を二重に呼び出さない様にすることはスクリプト実装者の責務です。

スクリプト例

本記事では少し実践的なスクリプト例(Windowsの場合)を書いてみます。

Windows Server 2012 R2以降でSMBv1を無効化にするスクリプト

2年ほど前にWannaCryといったランサムウェアが猛威を振るい、Windows環境においてSMBv1を無効にする方法がマイクロソフトから公開されるといったことがありました。

SMBv1を無効にする方法はOSによって異なりますが、Windows Server 2012 R2以降であればすべてPowerShellから行え、手順としては、

  • Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocolを実行し再起動
    • これはRemove-WindowsFeature -Name FS-SMB1でも良い

行えば良いです。
また、Windows Server 2012においては、

  • Set-SmbServerConfiguration -EnableSMB1Protocol $falseを実行

も記載されており、Windows Server 2012 R2以降でもこの設定は可能なのとDisable-WindowsOptionalFeatureだけだとEnableSMB1Protocol = Trueのままだったので念のためにこのコマンドレットも実行しておいたほうがよさそうです。
これら2つのコマンドを実行し、再起動後に正しくSMBv1が無効にされているか確認するスクリプトを以下に用意しました。

# 現在および再起動後の設定を取得
Write-Host 'Current SMB configurations.'
Write-Host '  Is SMB 1.0 protocol enabled...'
$config = Get-SmbServerConfiguration | Select-Object EnableSMB1Protocol
$config | Out-String
if ($config.EnableSMB1Protocol) {
    # 設定変更
    Write-Host 'Disable SMB 1.0 protorol...'
    Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force | Out-String
}
Write-Host '  Is SMB 1.0 feature installed...'
$feature = Get-WindowsFeature -Name FS-SMB1
$feature | Select-Object Name, DisplayName, Installed | Out-String
if ($feature.Installed) {
    # 設定変更
    Write-Host 'Disable SMB 1.0 feature...'
    Remove-WindowsFeature -Name FS-SMB1 | Out-String
    # 再起動
    Write-Host 'Reboot computer...'
    exit 3010
} else {
    exit 0
}

適当に用意したWindows Server 2016インスタンスに対してSSM Run CommandのAWS-RunPowerShellScriptコマンドにこのスクリプトを記述して実行してみます。

(今回SSMを実行するためのEC2インスタンスの設定などの部分は端折ります)

実行結果は以下の様になります。

すべての出力を以下に抜き出し、解説してきます。
( # で始まる部分は本記事による注釈です)

# ↓ スクリプトの開始 : 最初のSMBv1の状態を取得して表示しています
Current SMB configurations.

# ↓ Get-SmbServerConfiguration | Select-Object EnableSMB1Protocol を実行した最初の判定
Is SMB 1.0 protocol enabled...

EnableSMB1Protocol

------------------

True

# ↓ Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force を実行
Disable SMB 1.0 protorol...

# ↓ Get-WindowsFeature -Name FS-SMB1 を実行した最初の判定
Is SMB 1.0 feature installed...

Name DisplayName Installed

---- ----------- ---------

FS-SMB1 SMB 1.0/CIFS File Sharing Support True

# ↓ Remove-WindowsFeature -Name FS-SMB1 を実行
Disable SMB 1.0 feature...

WARNING: You must restart this server to finish the removal process.

Success Restart Needed Exit Code Feature Result 

------- -------------- --------- -------------- 

True Yes SuccessRest... {SMB 1.0/CIFS File Sharing Support} 

# ↓ SMBv1の機能を削除し、ここで最初の呼び出しが終了(exit 3010)
Reboot computer...

# ↓ 再起動後、2回目のスクリプトの開始 
Current SMB configurations.

# ↓ Get-SmbServerConfiguration | Select-Object EnableSMB1Protocol を実行した2回目の判定
Is SMB 1.0 protocol enabled...

EnableSMB1Protocol

------------------

False

# ↓ SMBv1プロトコルは無効にしたので何もせず続行

# ↓ Get-WindowsFeature -Name FS-SMB1 を実行した2回目の判定
Is SMB 1.0 feature installed...

Name DisplayName Installed

---- ----------- ---------

FS-SMB1 SMB 1.0/CIFS File Sharing Support False

# SMBv1の機能はアンインストールされているのでそのまま正常終了(exit 0)

こんな感じ再起動を伴うSSM Run Commandを実行できます。

おまけ

最後におまけとして以下の様なスクリプトを実行するとどうなるか試してみます。
現在時刻を記録だけして3010を返すスクリプトです。

Write-Output ("{0:yyyy/MM/dd HH:mm:ss} : Start script..." -f (Get-Date))
exit 3010

これまでの説明を踏まえると無限に再起動を繰り返すハズです。
このためタイムアウト時間は短めにしておきます。

実行結果は予想通りタイムアウトとなりました。

出力は以下の通り。

2019/06/09 15:03:55 : Start script...
2019/06/09 15:05:41 : Start script...
2019/06/09 15:07:32 : Start script...

タイムアウト時間を短めにしたのでそこまで多く再起動しませんでしたが、気を付けないと無限に再起動してしまうことはわかりました。
みなさんも再起動を伴うSSM Run Commandを実施する際はご注意ください。