SORACOM CLIの認証情報を安全に保管する

2022/06/07に公開

SORACOM CLIで認記情報を安全に保管するための機能追加のプルリクを送っていたのですが、2022/06/07に無事にマージされたのでその機能について紹介したいと思います。

SORACOM CLIの認証情報

SORACOM CLIでは、利用時に認証情報を与える必要があります。
認証情報は以下の種類があり、soracom configureコマンドでインタラクティブに設定することができます。

  • 認証キー (認証キーIDおよび認証キーシークレット)
  • ルートユーザーのメールアドレスとパスワード
  • SAM ユーザーの認証情報

ここで入力された情報は~/.soracom/default.json(または--profileオプションでプロファイル名を指定した場合は~/.soracom/指定したプロファイル名.json)に保存されます。
このファイルには認証情報が平文で掲載されています。パーミッションは600(自分だけが読める)ではありますが、パスワードやシークレットが平文なのはちょっと不安になります。

また、認証情報を複数の端末で共有する場合、各端末ごとに個別で設定する必要があります。

1password CLI

私は各種シークレット情報の保存に1passwordを使っているのですが、1passwordを使うことでシークレットを安全に保存し、複数の端末で(スマートフォンなどでも)参照できます。また、家族やグループでシークレットを共有することも可能です。

そして、1passwordにはCLIがあります。これを使えば、SORACOM CLIの認証情報を1passwordに保存することで安全に保管や共有ができるのではないか?と思いつきました。

やってみた

SORACOM CLIはソースコードが公開されていますので、実現可能かどうかforkして実装してみることにしました。

1password CLIとjqを組み合わせると、

op item get soracom-cli --format json | jq '{authKeyId:.fields[0].value,authKey: .fields[1].value}'

としてやると、

{
  "authKeyId": "soracom-cli-auth-key-id",
  "authKey": "soracom-cli-auth-key"
}

というJSONになりますので、これを外部コマンドから読み込めるようにします。

golangはほとんど触ったことないのですが、見よう見まねで書いて、とりあえず動くだけの所までは数時間でできました。当時、喜び勇んでこんなツイートしています。

https://twitter.com/show_m001/status/1506628232023461888

その後、プルリクを作成して、レビューいただいて2022/06/07に無事masterブランチに取り込まれました。
レビューでのやり取りは大変勉強になりました。マージされたときは本当に嬉しかったです。

使ってみる

まず、SORACOM CLIのver 0.12.0以降をインストールします。

次に、外部から認証情報(プロファイル)を渡してあげるコマンドを準備します。コマンドはプロファイルのJSONを標準出力に出すようなものであればいいので、動作検証ということであればひとまず

cat ~/.soracom/default.json 

でも問題ありません。以下に、1password CLIを使った場合の手順を記載しますが、他のコマンドを使う場合は「プロファイルの設定」まで読み飛ばしてください。

1passwordの準備

1password CLIと、ワンライナーで使うjqをインストールします。

1passwordに「soracom」というアイテムを追加し、ユーザ名に認証キーID、パスワードに認証キーシークレットを入力します。

1password CLIで認証を行います。bashの場合は

eval $(op signin --account my.1password.com)

と入力し、パスワードを入れます。powershellであれば

Invoke-Expression $(op signin --account my.1password.com)

とします。

認証できたら、先ほど作ったアイテムの情報がcliで取得できるか確認しましょう。

% op item get soracom-cli --format json
{
  "id": "****************",
  "title": "soracom",
  "version": 2,
  "vault": {
    "id": "****************"
  },
  "category": "LOGIN",
  "last_edited_by": "****************",
  "created_at": "yyyy-mm-ddTHH:MM:ssZ",
  "updated_at": "yyyy-mm-ddTHH:MM:ssZ",
  "fields": [
    {
      "id": "username",
      "type": "STRING",
      "purpose": "USERNAME",
      "label": "username",
      "value": "keyId-*******************"
    },
    {
      "id": "password",
      "type": "CONCEALED",
      "purpose": "PASSWORD",
      "label": "password",
      "value": "secret-*******************",
      "password_details": {
        "strength": "FANTASTIC"
      }
    },
    {
      "id": "notesPlain",
      "type": "STRING",
      "purpose": "NOTES",
      "label": "notesPlain"
    }
  ]
}

こんな感じでfieldsという配列の要素の1番目に認証キーID、2番目に認証シークレットが入っています。もし配列の順番が違う場合は、ワンライナーのfields[0]fields[1]の添え字を変えてください。

プロファイルの設定

外部コマンドが準備できましたので、このコマンドをプロファイルに設定します。例として、~/.soracom/test.jsonに以下のようにprofileCommand要素に記述します。

{"profileCommand":"/bin/sh -c \"op item get soracom --format json | jq '{email:.fields[0].value,password:.fields[1].value}'\""}

パイプを使ったワンライナーや引数が必要なコマンドを渡す場合は、上記のように/bin/sh -cに引数で渡してあげてください。エスケープが複雑になってしまう場合は適当なシェルスクリプトを作成して、それを指定するといいです。

Windowsであれば以下のようなバッチファイルを作成して、それを指定すればOKです。

@c:\path-to-command\op item get soracom-cli --format json | c:\path-to-command\jq "{authKeyId:.fields[0].value,authKey: .fields[1].value}"

バッチをgetSoracomProfile.batという名前で保存した場合、プロファイルでの指定はこうなります。

{"profileCommand":"c:\path-to-command\getSoracomProfile.bat"}

実行する

では、実行してみましょう。例としてSIMの一覧を表示してみます。

soracom --profile test sims list

SIMの一覧が表示されれば成功です。

また、コマンドをプロファイルに記載せずに、コマンドラインオプション--profile-commandで指定することも可能です。

soracom --profile-command="/bin/sh -c \"op item get soracom-cli --format json | jq '{authKeyId:.fields[0].value,authKey: .fields[1].value}'\"" sims list

この例では認証キー(認証キーIDおよび認証キーシークレット)での認証を使っていますが、ルートユーザーのメールアドレスとパスワード、SAMユーザーの認証情報での認証も可能です。それらを含めたJSONを渡すようなコマンドにするだけでOKです。

まとめ

外部コマンドを使ってプロファイル情報を渡す機能をSORACOM CLIに実装しました。これを使って、安全に認証情報を保管することができますので皆さん是非お試しください。

また、SORACOM CLIに機能改善案などがあれば皆さんもぜひご自身でプルリクエストを送ってみてはいかがでしょうか。

GitHubで編集を提案

Discussion