ある研究者の手記

セキュリティとかゲームとかプログラミングとかそのへん

CLIの環境変数をいい感じに管理するツールを作った

表題のとおりですが altenv というツールを作りました。 Alter environment の略です。

github.com

モチベーション

業務上、大小様々なツールやらシステムやら(これとかこれとか)を開発をすることが多いのですが、あつかうプロジェクトが多くなると開発やデプロイなどに使う設定値の管理がだんだん煩雑化していくという課題を感じていました。特に一部のツールは外部公開もしているので、実装と設定をちゃんと分離しようとすると(特にローカルでの開発に関する設定の場合)数ヶ月たった後に作業をしようとすると「どの設定値を使うんだっけ、、」というのがちょいちょいありました。単純にちゃんと管理しておけという話ではあるものの、そういった設定値を統一的に扱えるものがあると便利だなと思って作ったのがこのツールです。

端的に言うと、オプションや設定ファイルに記載された内容に応じて環境変数を読み込み、その環境変数とともに指定されたコマンドを実行するというだけのツールです。イメージとしては以下の通り。

$ cat test.env
DBNAME=hoge
$ altenv -e test.env npm run server
# running npm server with environment variable DBNAME=hoge

ユースケース

細かい利用方法はレポジトリの方に書いたつもりなので、ざっくりとユースケースごとの使い方を書いておきたいと思います。コマンドラインのオプションでいろいろ指定することもできますが、デフォルトで $HOME/.altenv という設定ファイルを読み込むので、そちらの設定を交えて紹介したいと思います。

プロジェクトのディレクトリごとに環境変数をわける

wordir.xxx というテーブルがあり、これを使って作業ディレクトリごとの環境変数を定義できます。( xxx はただのラベル)

[workdir.proj1]
dirpath = "/Users/mizutani/.ghq/github.com/xxx/project1"
define = ["DB_NAME=mydb1"]

[workdir.proj2]
dirpath = "/Users/mizutani/.ghq/github.com/yyy/project2"
define = ["DB_NAME=mydb2"]

CWDが dirpath 以下にあるとそのテーブル内に記載された設定が有効化されます。具体的には以下のようになります。( -r dryrun で読み込まれた環境変数一覧が表示されます)

$ cd /Users/mizutani/.ghq/github.com/xxx/project1
$ altenv -r dryrun
DB_NAME=mydb1
$ cd ../../yyy/project2
$ altenv -r dryrun
DB_NAME=mydb2

外部のレポジトリやファイル共有サービスから参照する

define環境変数を定義するやり方だと全ての環境変数$HOME/.altenv に書く必要があり、チーム内で共有するのが難しくなってしまいます。なので、外部ファイルを参照することで、gitレポジトリやファイル共有サービス(Google File StreamやDropboxなど)を使って環境変数を共有できます。(ただし、gitレポジトリは自分で最新ファイルをpullしてくることを想定しています)

[workdir.proj1]
dirpath = "/Users/mizutani/.ghq/github.com/xxx/project1"
envfile = ["/Users/mizutani/Google Drive File Stream/Shared drives/MyTeam/config/project1.env"]

[workdir.proj2]
dirpath = "/Users/mizutani/.ghq/github.com/yyy/project2"
envfile = ["/Users/mizutani/.ghq/github.com/yyy/configs/project2.env"]

このように設定することにより、project1 のディレクトリにいる際にはGoogleドライブのShared Drive内にあるファイルが、project2のディレクトリにいるときはconfig管理用レポジトリ内のファイルが参照されるようになります。

Staging / Production などの切り替えをする

例えば同じディレクトリでもステージング環境とプロダクション環境の両方にアクセスする場合、利用する環境変数の切り替えが必要になります。 profile.xxx というテーブルを用意することにより、利用したい設定を都度選択できるようになります。profileにおける xxx はそのままプロファイル名になります。

[profile.proj1-stg]
envfile = ["/path/to/proj1/stg.env"]

[profile.proj1-prd]
envfile = ["/path/to/proj1/prd.env"]

このように設定しておくと、 -p オプションによって読み込まれる環境変数を切り替えることができます。

$ altenv -p proj1-stg ./deploy.sh
# ステージング用の環境変数が読み込まれた上で deploy.sh が実行される

秘匿値を環境変数に使う(macOSのみ)

macOSが提供しているKeychainに環境変数を保存しておくことで、ファイルなどに平文保存するより安全にAPIキーなどの認証情報を管理できます。基本的には envchain の機能をベースに実装しています。

-r update-keychain -w <namespace> というオプションをつけることで、読み込んだ環境変数をKeychainに書き出します。<namespace> は任意の名前空間を指定できます。例えばすでに平文でファイル保存していた場合は以下のようにしてKeychainへの書き出しができます。

$ altenv -e credential.env -r update-keychain -w mycred

あるいはすでに環境変数に読み込まれている場合は以下のようにしてKeychainへ書き出すこともできます。例としてAWSで利用する環境変数 を保存してみます。

$ env | grep -e "^AWS_ " | altenv -i env -r update-keychain -w aws-cli

また、コピー&ペーストにより1つずつ書き出すこともできます。

$ altenv --prompt AWS_SECRET_ACCESS_KEY -r update-keychain -w aws-cli
Enter AWS_SECRET_ACCESS_KEY Value:
# 秘匿値を想定しているため入力した値は表示されない

呼び出すときは -k <namespace> オプションで保存した環境変数を呼び出せます。

$ altenv -k aws-cli -r dryrun
AWS_SECRET_ACCESS_KEY=xxxxxxx
AWS_ACCESS_KEY_ID=xxxx
$ altenv -k aws-cli aws s3 ls
2019-11-21 19:02:20 mybucket-1
2019-11-21 19:02:22 mybucket-2
...