- AWS CLI利用時のMFA認証突破をラクにするOSS「Jimon-s/awsmfa」の紹介記事
- 日頃のめんどくさいにコミットする設計
- AWS STS GetSessionToken API、AssumeRole APIの両方に対応しています
毎日やらなくてはいけないものの、操作が割と煩雑で、手動でやりつづけるにはちょっとつらい「CLI利用時のMFA」。
今回は、こんな日々のめんどくさいをラクにしてくれるOSS「Jimon-s/awsmfa」をリリースしたのでご紹介します。
ざっくり、どんなものかは以下のGIFをみていただけばと!
リポジトリはこちらです。
スポンサーリンク
インストール
homebrew
$ brew tap Jimon-s/awsmfa
$ brew install awsmfa
The others
リポジトリをClone後、
$ go install
or
Go 1.16以降
$ go install github.com/Jimon-s/awsmfa@latest
補完を効かせたい場合は、以下も実行
For zsh
$ echo "autoload -U compinit; compinit" >> ~/.zshrc
↑はすでに追記済みであれば不要
$ awsmfa completion zsh > "${fpath[1]}/_awsmfa"
For bash
$ awsmfa completion bash > /usr/local/etc/bash_completion.d/awsmfa
セットアップ
「使いたいprofile名」+「–before-mfa」のprofileを~/.aws/credentialsと~/.aws/configに追記します。
が、まっさらから書くのはめんどうなので、スケルトン生成機能を搭載してます。
以下を叩いて、~/.aws/credentialsと~/.aws/configにひな形を追記しましょう。
$ awsmfa --generate-credentials-skeleton get-session-token >> ~/.aws/credentials
$ awsmfa --generate-config-skeleton get-session-token >> ~/.aws/config
※AssumeRole APIを使いたい場合は、get-session-tokenをassume-roleに置換してください。
で、追記されたひな形をエディタで埋めていきます。
GetSessionTokenを使う場合は、こんなイメージ。
AssumeRoleの場合は、こんな感じです。
極力aws cli v2のデフォルトのkey名が、そのまま使えるように設計してあります。
(どうしても無理だったものは、prefixがawsmfa-xxxxとなっています)
使い方
$ awsmfa --profile 使いたいprofile名
を実行すると、
- MFAコードの入力画面
- リクエストパラメータ
- パラメータの出どころ
が出てきます。問題なければ、そのままコードを入力すればOK。
これで、~/.aws/credentialsに一時クレデンシャルが自動追記されるので、あとは普段通りawsコマンドを使っていただければOKです。
$ aws s3 ls --profile 使いたいprofile名
応用編:デフォルトパラメータ
「profile名毎回入れるのめんどう」「全profileで共通のパラメータを使いたい」というケースもありますよね。
こういったケースに対応できるよう、awsmfaは独自の設定ファイルも保持しています。
$ awsmfa --generate-configuration-file true
で、~/.awsmfa/configurationにビルドインのデフォルト値が記載されたファイルが生成されるので、中身を書き換えてください。
パラメータの読み込み優先順位は、
- cliオプション
- 環境変数
- shared credentialsファイル (~/.aws/credentials)
- shared configファイル (~/.aws/config)
- カスタム設定ファイル (~/.awsmfa/configuration)
- ビルドインのデフォルト値
となっているので、カスタム設定ファイルが意図せずパラメータを上書きしにくくしています。
設計思想
MFAでやらなきゃいけないこと
MFAが設定されているIAMユーザーでCLIを利用する場合、
もともと払い出したアクセスキー&シークレットキーで、
- AWS STS GetSessionToken API + with MFAコード
- AWS STS AssumeRole API + with MFAコード
のどちらかを実行
↑のレスポンスで、色々なAPIへアクセスできる一時的な
- アクセスキー
- シークレットキー
- セッショントークン
が返ってくるので控える
控えたクレデンシャルを
- 環境変数
- Shared credentialsファイル(~/.aws/credentials)
のどちらかに登録して、aws cliの各種コマンド実行
のフローを取ります。
ただ、CLIコマンドを叩くたびに、毎度オプションが大量についた長めのコマンドを実行するのはなかなかにめんどくさいですし、~/.aws/credentialsを手作業で毎回メンテするのはつらみがありすぎですね。
「コマンド都度実行」のつらみをあげると
もう少し詳しく分解してみると、まずコマンドの打ち込み&実行フェーズでは、
- 打ち込むコマンドがMFA認証コード–token-codeまで含めた「長めなコマンド」になるので、見通しが悪い
- ↑をコピペで解決しようにも、MFAコード部分を毎回書き換えなくてはならないので、カーソル移動が発生してめんどくさい
- さらに–profileまで指定していると、変更箇所2倍でさらにめんどくさい
があるかなと。特に3番目は、僕のような複数のAWS環境をいったりきたりしている人にとっては、–profileはほぼ必須(ポカよけでdefaultは使わないようにしている)なので死活です。
さらに返ってきた一時クレデンシャルを保存するフェーズでは、
- レスポンスのJSON文字列から、アクセスキー、シークレットキー、セッションキーを個別に抜き出す必要がある
- 抜き出した情報を毎回エディタで~/.aws/credentialsに書かなくてはいけない
のがつらいですね。
これを回避するよくある方法は「環境変数に保存するワンライナーを書く」だと思うんですが、先の理由と同様にポカよけで環境変数も使わないようにしている僕にはマッチせず。
「credentialsファイルの書き換えまで、ワンライナー化すればいいじゃん!」と言われそうですが、(特にprofileを指定した書き換えまでやろうと思うと)なかなかに複雑な作りになってしまい、将来の自分に嫌われそうな雰囲気がただよっていたので、その線はなしにしました。
また、ちょっと本筋とは離れますが、aws cliのパラメータの読み込み順序って、結構複雑じゃないですか。例えば、cliオプション、環境変数、~/.aws/credentials、~/.aws/configの全部にリージョン書いたらどこが最優先になるかパッといえますか?
特に、STS APIはオプションが多く、記述があっちこっちに散らばりがちなので、このあたりも見える化したいなと。
他のOSSもあるけれど
自作する前段階で既存を探してはみたんですが、
- ~/.aws/credentials、~/.aws/configにaws cliのデフォルトとは違う独自キーのパラメータを書かなくてはいけない
- 一時クレデンシャルの有効期限の指定ができない
- GetSessionToken APIとAssumeRole APIの切り替えがブラックボックス化されてる
- ↑を叩きにいくリージョン指定ができない
- どこに書いたパラメータが優先されたか不明瞭
なものが多く、僕のユースケースにぴったりハマるものがみつけられず。探すよりも作ったほうがはやいのでは、となった次第です。
なので目指したのは
- コマンド実行時にカーソル移動をしなくてよい
- ~/.aws/credentialsの書き換えまで自動でやってくれる
- 使っているパラメータの出どころが明確
- ~/.aws/credentials、~/.aws/configに書く独自パラメータは最小限
- 一時クレデンシャルの有効期限、叩き先リージョンのような細かな部分まで指定できる
- GetSessionToken APIとAssumeRole APIの切り替えができる
贅沢ですが、これを全て叶える全部入りを目指しました。
できあがったもの
で、完成したのがこちら!
まさしく全部入り!という感じです。
あとがき
割といろんなユースケースに耐える作りになっていると思いますので、お気軽にお試しくださいー!
最後までご覧いただきありがとうございました。
Jimon(@jimon_s)でした。