[ハマりまとめ]Session ManagerでAWS CLIを設定してRun Commandで実行しようとした話

「Session Manager」で「AWS CLI」をセットアップして「Run Command」で「AWS CLI」を実行したら見事ハマったので、経緯・原因・解決策をまとめました。
2019.10.31

世間はハロウィンで盛り上がっておりますね。そしてハロウィンの翌日と言えばそう、Developers.IO 2019 TOKYOです!

▲ お祭りはまだ続きますよ!ワッショイ

今年も気になるセッションが目白押しです。参加される皆さまにおかれましては、楽しい1日をお過ごし下さいませ。
生憎行けないよ!という方も、後日(という程時間を空けずに)セッションレポートが上がると思われますのでそちらでお祭りを一緒に楽しんで頂ければ幸いです。

こんにちは、AWS事業本部のShirotaです。早速、10月最後のブログに参りましょう。

今回やりたかった事/やってみた事

今回はタイトルの通り、「Session ManagerでAWS CLIを設定してRun Commandで実行しようとした」時にハマった事をお話ししたいと思います。
まずはやりたかった事を簡単に箇条書きでまとめると、次のようになります。

  • AWSコンソールだけを操作してAWS CLIの設定・実行を完結させたい
    • EC2インスタンスにSSH接続せずにAWS CLIのセットアップをして実行したい
  • AWS CLIの実行結果を保存したい

上記を実現する為に、私がやろうと考えた事が以下になります。

  • AWS Systems Manager Session Managerを用いてAWS CLIをセットアップする
  • AWS Systems Manager Run Commandをコンソール上で用いてAWS CLIを実行、実行結果を記録する

これならSSH接続を使わずコンソール上でAWS CLIを実行し、かつ実行結果を保存する事ができると考え、試してみる事にしました。
これを考えた時には、ハマるとは露ほども思っていなかったのです。

やろうとしてハマった事/原因/解決策をまるっとお話しします

まずは、やりたい事の為に用意した環境についてお話しします。

準備したもの

「AmazonEC2RoleforSSM」ポリシーをつけたIAMRole

EC2からAWS Systems Managerを使用できるようにするには、「AmazonSSMManagedInstanceCore」ポリシーを含むIAMRoleのアタッチが必須となっております。
「AmazonEC2RoleforSSM」だと許可されている権限が広い為、「AmazonSSMManagedInstanceCore」ポリシーをベースとしたカスタムポリシーを作成して使用する事が推奨されてきているのですが、今回はやりたい事を手っ取り早く実現する為にAWS側で用意されていた「AmazonEC2RoleforSSM」ポリシーを利用しました。
これについては、弊社中川の以下ブログにて分かり易く解説しておりますので良かったらご参照下さい。

新ポリシー AmazonSSMManagedInstanceCore がサポートされました

作業用のIAMUser

AWS CLIで、サービスに対して実行したい権限をつけたIAMUserを用意しました。
これも、やりたい事が定まっている場合は権限を絞り込み、必要な権限だけつけるのがベターです。

上記IAMRoleをアタッチした作業用のEC2インスタンス

今回、EC2に対してSession ManagerとRun Commandを実行する事になる為、上記で準備したIAMRoleをアタッチしました。

やってみる

Session ManagerでEC2インスタンスにログインして、AWS CLIをセットアップしました。

▲ 対話式でIAMUserのプロファイルを登録する

作業用のIAMUserのプロファイルを登録しました。

▲ ちゃんと登録できました

この画像を よく覚えておいて下さい 。テストには出ませんがこのブログの後の方に出てきます。

準備は整ったので、Run Commandで早速AWS CLIを実行してみます。

今回は、 AWS-RunShellScript を選択し、以下のコマンドを入力しました。

aws ec2 copy-image --region ap-northeast-1 --source-region us-west-2 --source-image-id ami-XXXXXXXXXXXX --name ami-copy-test

これは、AMIを別リージョンにコピーするコマンドです。
今回は、オレゴンリージョンから東京リージョンへAMIコピーを実行してみました。
さて、Run Commandを実行してみます。

▲ 瞬殺

瞬殺されました。時間にして1秒でした。

ハマったので調べた

もう一度、Session Managerに戻り設定を確認しました。試しに、aws s3 lsが動くかを確認してみましたところ、正常に動きました。
そこで、Run Commandでもaws s3 lsを実行してみたところ、以下のようになりました。

▲ 瞬殺その2

……ここでようやく気付いて、私は以下のコマンドをAWS-RunShellScriptで実行しました。

whoami
aws configure list

▲ 久々に合間見えたSuccessの緑が目に沁みた

原因

私がSession Managerで実行していた環境とRun Commandで実行していた環境について、簡単に比較できるように表にまとめてみました。

Session Manager Run Command
コマンド実行ユーザー ssm-user root
クレデンシャルの出どころ IAMUser EC2にアタッチしたIAMRole
与えていたポリシー PowerUser AmazonEC2RoleforSSM

そもそものコマンド実行ユーザーが違った事でSession Managerで準備した設定が反映されていなかった為、想定通りの動きがRun Commandで見られずにハマっていたという訳です。

解決してみた

原因が分かれば、後は解決策を考えるだけです。
いくつか考えてみたので、それぞれについて検討してみました。

1.Run Command実行時にssm-userでコマンドを実行させる

設定をどこも変更せず、問題を解決できたのはこれでした。Shellライクな解決手段です。
Run Commandの実行を、想定したクレデンシャルが設定されているssm-userユーザで実行します。

sudo -u ssm-user aws ec2 copy-image --region ap-northeast-1 --source-region us-west-2 --source-image-id ami-XXXXXXXXXXXX --name ami-copy-test

▲ 実行結果。想定通りコマンドが実行されていた

この場合は、恒久的にこの問題を解決するには若干面倒である点に留意してコマンドを実行してもらう必要があるかと思います。

2.Run Commandで用意したIAMUserのクレデンシャルを設定する

そもそも、Run Commandは対話的な動きをさせる為には以下エラーに見られるように「ヒアドキュメント」を使う必要があります。

▲ ヒアドキュメントしろよと怒られた図

ヒアドキュメントを用いてIAMUserのクレデンシャルを設定してみました。これもShellライクな解決方法ですが、この場合はもう少し恒久的な解決方法になります。

aws configure --profile iamuser << EOF
アクセスキー
シークレットキー
デフォルトリージョン

EOF

今回、アウトプットフォーマットの指定は省略しています。
これでRun Commandを実行したところ、設定できました。
以降は、profileで「iamuser」を指定すれば、用意したIAMUserの権限でAWS CLIを実行できるようになります。
ただ、profileが増える事による操作ミスが発生する可能性がある為、rootユーザに複数のクレデンシャルを与える際には十分気をつけましょう。

3.EC2インスタンスにアタッチするIAMRoleに実行したい権限を追加する

この方法だと、これ以上Run Commandで設定を追加する必要性が無く、そもそもIAMUserを用意したりSession Managerで設定する必要が無くなります。これまでの説明ェ
ただし、EC2インスタンスそのものに権限を増やしていく形になる為、EC2のインスタンスに与える権限を極力増やしたくない場合にはそもそもむいておらず、また権限を追加する際には必要な権限を選んで設定する必要があります。
AWS CLIの実行に対してピンポイントに権限を与えたいのか、EC2そのものに権限を付与しても問題無い環境なのかは事前に良く考えた上で実行して貰えれば大丈夫かと思います。

Run CommandでAWS CLIを実行できるようになると嬉しい事も増える

「何でこんな遠回りな事をしているんだろう」と思われたでしょうか。実際、私はハマっていた時そう思いました。
ですが、Run CommandでAWS CLIを実行できるようになると嬉しい事も増えます。

はじめに私が実現しようとしていた、Run Commandの出力を保存する事もその一つですし、Run Commandは実行結果をSNSで通知させる事もオプションで簡単にできる為、時間のかかるAWS CLIの処理などは終了の通知をSNSに任せてコンソールを閉じる事もできるようになります。

▲ 「成功」した事や成功した「時刻」を通知してもらえる

ハマったけど、その分できるようになった事も増えたから良かった という前向きな気持ちも得られたので、このブログを読んでくれた方にも前向きな気持ちがおすそ分けできれば幸いです。