Gunosy Tech Blog

Gunosy Tech Blogは株式会社Gunosyのエンジニアが知見を共有する技術ブログです。

(awsctx) AWS profile のコンテキストマネージャーを作ってみた

はじめに

こんにちは、DR&MLOps チームの hyamamoto です! 最近犬と一緒に生活するようになり、Slack やら Twitter やらで犬のことばかり書いています。

今回は AWS profiles のコンテキストマネージャーを作成したので、会社のブログを使って宣伝したいと思います。 github.com

端的にこのツールは

$ gcloud config set project ${project_name}
$ kubectl config set-context ${context_name}

と同じような感覚で AWS の profile を切り替えられるようにすることを目的にしたものです。

背景

まず、このツールを作るにあたった背景や既存の AWS の認証情報周りの辛い点についてお話します。

AWS の認証情報について

AWS のサービスを awscli や sdk を使ったコードから利用する場合、手元の環境で認証を通す必要があり、 その認証情報は $HOME/.aws/credentials にあるファイル(以降 credentials)に記述されます。

credentials は複数の認証情報を保存することができ、各認証情報は profile という名前を key にして管理されています。 また、default profile という予約された profile があり、これは名前の通りデフォルトで参照される profile になります。 詳しい説明は下記のドキュメントに書かれています。

docs.aws.amazon.com

profile の切り替え

default profile 以外の profile を切り替えて利用する方法として次のような方法があります。

  • AWS_PROFILE という環境変数を上書きする
  • awscli の場合 --profile option で profile を指定する

しかしながら、この方法には一定の不便さが残ります

AWS_PROFILE を上書きする場合、それぞれ実行しているシェルで設定する必要があります。 direnv を使えば多少緩和される部分もありますが、dev, stg などの環境で profile を切り替える必要がある場合は、あまり効果的とは言えません。 また、credentials を volume mount してコンテナで利用している場合は、 コンテナにも AWS_PROFILE を環境変数として渡す必要がありやや手間です。 特にコンテナ実行するためのスクリプトが用意されているプロジェクトの場合、 毎回そのスクリプトを書き換えてまでAWS_PROFILE を渡す設定にするかというと、ハードルが高いようにも思います。

awscli における --profile option は毎回渡すべき引数が増えてしまうため正直面倒です。

そこで、以前までは認証時に名前付き profile に保存するのではなく、default profile を上書きするという方法をとっていました。 しかし、過去認証していた profile 情報が上書きにより消えてしまうため、profile の移動のたびに再度認証作業が必要になっていました。 特に弊チームでは環境ごとに異なる profile を用意していたり、横断チームであるため他のプロダクトの profile を利用することが度々あり、1 日の中でこのスイッチ作業はかなりストレスでした。

そこで今回 gcloudkubectl の機能を参考に、 awsctx というツールを開発し、

$ awsctx use-context -p ${profile_name}

と打つことで、default profile を名前付き profile で上書きできるようにしました。 これによって上書きによる揮発を避けつつ default profile として名前付き profile を扱うことができ、 上記のようなツラミを抱えることなく、profile 間の行き来が容易になりました。

機能紹介

ここでは現在私がよく使っている機能をご紹介します。

profile の切り替え

1 つ目は先程もご紹介した profile の切り替えです。

$ awsctx use-context -p ${profile_name}

シェルの A マークの横に現在の default profile に相当する profile (以降 active profile)が表示されており、 profile の中身が切り替わっていることが確認できます*1

また、引数なしのコマンドを実行することで fuzzy finder を用いた profile の選択をすることができます*2

$ awsctx

認証コマンドのエイリアス設定

2 つ目は profile ごとに認証コマンドのエイリアスを追加して利用する機能です。 この機能は 1 度設定しておくと、単一のシンプルなコマンドで、profile の更新から active profile への反映ができる点で便利です。 エイリアスの設定になるので、profile ごとに複雑な認証コマンドを記憶したり history を辿る必要もありません。 それでは使い方を見ていきます。

まず、awsctx を初回に実行すると $HOME/.awsctx/configs.yaml が生成されます。 その中に auth_commands というブロックがあり、profile を key として認証のためのコマンドを登録しておくと、 後に紹介するサブコマンドで呼び出しが行われます。

ここでは、デモとして下記のような設定ファイルを用意し、挙動を確認していきたいと思います。 より実運用的な説明は README を参照していただけると幸いです。

auth_commands:
  foo: &command |
    echo "credentials updated for (profile: {{profile}})"
  bar: *command

上記の設定ファイルにおいて下記の性質があります。

  • {{profile}} が予約語として template 化可能で、key になっている profile 名で置換することができる
  • 同一のコマンドであればアンカーで共通化可能

これらの挙動について実際に動かしながら確認していきます。

auth コマンド

auth コマンドは上記のエイリアスを使って profile の credentials を更新し、更新した認証情報を default profile に反映するものです。

$ awsctx auth -p ${profile_name}

上記の gif から、設定してる echo 文が実行されていることや、template 化された {{profile}} が指定した profile 名で置換されていることがわかると思います。

refresh コマンド

refresh コマンドは現在 active な profile に対してエイリアスを実行し、改めて default profile に反映する機能です。 有効期限付きの credentials で期限が切れた場合に利用すると便利なものになっています。

$ awsctx refresh

まとめ

最初は Rust の勉強ついでに、普段感じている自分のツラミを少しでも解消できたらいいなと思って書いたツールで、初期の頃はかなり雑なコードを用意していました。 ふとしたことで、メンバーが同じようなツラミを抱えているのを知り紹介したところ、実際に使ってみて Bug Fix や機能追加の PR を出してくれたことがきっかけで、OSS として体裁を整える活力が湧き今の形に至ります。

今では CI/CD も production 環境に持っていけるぐらいには十分なものを整備できたと思いますし、 codecov によるカバレッジレポートや Homebrew によるインストール機能も整えるに至りました。 この辺りは社内で既に Rust による CLI を作って公開しているメンバーがおり、 ブログやコードを参考にしたり、Slack の times で助言を頂いたりで、環境面に助けられたなとも思っています。 改めて会社の方々には感謝です。 yuutookun.hatenablog.com

おそらく 1 人で使っているだけだと、ここまで時間をかけて整備する気にはならなかったと思うので、改めてアウトプットする大事さを感じました。 また、コードの勉強がてらオモチャを作ることはしばしばありますが、普段困っているところで導入すると更新を続けるきっかけが生まれやすいので、題材としていいなと思いました。

もしここまでの内容で、便利そうだなと思われた方は、ぜひこちらに従って導入していただけると幸いです。 よろしくおねがいします!

*1:これは awsctx active-context というサブコマンドを使って表示しています

*2:この変更は同じチームの id:m-hamashita さんからの PR でした、圧倒的感謝...!