前回の記事では、AWSコンソール上でRun Commandを実行するところまでを書きましたが、実際にプロジェクトで実行しようと思っていることはこれではまだ中途半端な状態でした。
実際にお客様がサーバーを運用していくために、VSS Snapshotの取得を実施するたびにWebコンソールで実施するわけにはいかないので、CloudWatchEventなどで定期実行をすることが考えられますが、今回の要件ではとあるシステム管理ツールを利用する前提となっていたのです。そのため、WindowsServer上のコマンドプロンプト(バッチ)か、PowerShellで実行できるようにするところがゴールとなります。
#今回実施したこと
今回も以下のようなことをやりました。
・WindowsServer上のコマンドプロンプト上でCLIからSSMを実行できるか調べる
・Windowsはないことがわかる
・とりあえずLinuxコマンドでやってみる
・エラー出る(JSON関連)
・解決する
・エラー出る(ポリシー関連)
・解決する
今回はSSMのコンソールと、同僚に教えてもらったこちらのドキュメント、また、ググって見つけたQiitaを参考にして解決することができました。
やったぜ!これぞ集合知!インターネットの醍醐味ですね。
早速行ってみましょう。
#WindowsServer上のコマンドプロンプト上でCLIからSSMを実行できるか調べる
SSMコンソールのRun Commandを実行する画面の一番下に、CLIで今実行しようとすることと同じコマンドを表示する機能があります。それをまずは参考にしてみましょう。
↓これこれ、こんな感じで見ることができます。これはLinuxやMacの場合ですね。
次にWindowsを見てみましょう。
これこれ。これです。
ちゃんと「Windwows command prompt」「Windows Power shell」の二パターンが用意されていますね。
見てみましょう。
・・・ぉ、ぉぅ。ドンマイ。
そういうこともあるよね~。「not yet」だからそのうち対応するのかな~?
気を取り直して、Power Shellは?
ブルータス、お前もか。
##Windowsはないことがわかる
トホホ。
途方にくれますね。
うーん、ないなら仕方ない。出来ないのであれば素直に諦らめましょうかね。
と、同僚に愚痴ったら、「Linuxのコマンドそのまま打ったら行けないかな?」とのお言葉。おおっ?!確かに!
基本的にAWS CLIはどのプラットフォームでも同じ使い方のはずなので、いけるかもしれない。
##とりあえずLinuxコマンドでやってみる
そのままLinuxコマンドでやってみました。
C:\Users\Administrator>aws ssm send-command --document-name "AWSEC2-CreateVssSnapshot" --document-version "6" --targets '[{"Key":"InstanceIds","Values":["i-017d77c8973d7c953"]}]' --parameters '{"ExcludeBootVolume":["False"],"description":[""],"AmiName":[""],"CreateAmi":["False"],"CopyOnly":["False"],"tags":["Key=Name,Value="],"NoWriters":["False"]}' --timeout-seconds 600 --max-concurrency "50" --max-errors "0" --region ap-northeast-1
Error parsing parameter '--targets': Expected: '=', received: ''' for input:
'[{Key:InstanceIds,Values:[i-017d77c8973d7c953]}]'
^
#エラー出る(JSON関連)
はい、エラーが出ましたね。
いや、まだだ、まだ慌てるときじゃない。
とりあえずよくわかりませんが、JSONの表示に関わるエラーみたいですね。「'」が悪さをしている?
よくわからないまま「'」を外して実行してみましょう。
C:\Users\Administrator>aws ssm send-command --document-name "AWSEC2-CreateVssSnapshot" --document-version "6" --targets [{"Key":"InstanceIds","Values":["i-017d77c8973d7c953"]}] --parameters '{"ExcludeBootVolume":["False"],"description":[""],"AmiName":[""],"CreateAmi":["False"],"CopyOnly":["False"],"tags":["Key=Name,Value="],"NoWriters":["False"]}' --timeout-seconds 600 --max-concurrency "50" --max-errors "0" --region ap-northeast-1
Expecting property name enclosed in double quotes: line 1 column 3 (char 2)
はい、エラーが出ましたね。
いやいや、まだだ、まだ慌てるときじゃない。
まぁよくわからないまま「'」を外して実行してみちゃうのはよくないですね。基本的にアホなので。
このエラーメッセージでググってみたところ、JSONの記法に関することでエラーが出ているみたいですね。
困った。
コマンドプロンプト上では「'」を含めて、JSON記法がうまく認識されない呪いにでもかかっているのでしょう。
これは無理だなあ。。。と、また同僚にぼやいたところ「じゃ、パラメーターを別ファイルで渡すこともできるから試してみたら?」と、また蜘蛛の糸的な助言をいただきました!
やってみましょう。
#解決する
とりあえず、「--targets」と「--parameters」のオプションパラメーターがJSONになっているようなので、こちらのAWSドキュメントを参考に記述しなおしてみました。
それぞれのファイルの中身は以下の通りです。
[{"Key":"InstanceIds","Values":["i-*****************"]}]
{"ExcludeBootVolume":["False"],"description":[""],"AmiName":[""],"CreateAmi":["False"],"CopyOnly":["False"],"tags":["Key=Name,Value="],"NoWriters":["False"]}
実行してみましょう。
#エラー出る(ポリシー関連)
C:\Users\Administrator>aws ssm send-command --document-name "AWSEC2-CreateVssSnapshot" --document-version "6" --targets file://C:\Users\Administrator\targets.json --parameters file://C:\Users\Administrator\parameters.json --timeout-seconds 600 --max-concurrency "50" --max-errors "0" --region ap-northeast-1
An error occurred (AccessDeniedException) when calling the SendCommand operation: User: arn:aws:sts::************:assumed-role/TEST-SSM-ROLE/i-***************** is not authorized to perform: ssm:SendCommand on resource: arn:aws:ec2:ap-northeast-1:************:instance/i-*****************
はい、エラーが出ましたね。
いやいやいや、まだだ、まだ慌てるときじゃない。
とりあえず「not authorized to perform: ssm:SendCommand」って書いてあるので、SSMコマンドの権限がないってことは想像できます。なるほど、ロールが足りていないのかと想像できたところが、何となく自分が成長している気がします。解決はしていませんけど。
ググったところ、Lambdaで実行しようとしているという点は異なりますが、参考にできそうな素晴らしいQiita記事を発見しました。
早速ロールにポリシーを追加してみましょう。
#解決する
「AmazonSSMMaintenanceWindowRole 」という、Windows上でSSM Run Commandを実行するのに必要なポリシーが当然必要になるので、アタッチします。
ポリシーがアタッチできました!
これでどうでしょうか。
実行!
お???
おおおお?
何かいろいろJSONっぽいのが画面に出てきました。
これは実行結果ですね。
Systems Managerのコンソール画面でRun Commandの実行結果を確認してみましょう。
ヨシ!
成功しています。
これで、WindowsServer上のコマンドプロンプトからVSS Snapshotの取得を実行するというゴールを達成することができました。