Go製パスワードマネージャー gopass でパスワード管理をやってみる

Written by @ryysud

Apr 1, 2019 19:30 · 4268 words · 9 minutes read #go #tool

TL;DR

  • gopass は pass をベースに追加機能を Go で実装したパスワードマネージャー
  • GPG を利用してパスワードの 暗号化/復号化 を行い Git でバージョン管理を行う
  • パスワードの操作は以下のコマンドで実行可能(主要コマンドのみ抜粋)
コマンド 説明
gopass init パスワードストアの初期化
gopass list パスワードの一覧表示
gopass show パスワードの表示
gopass insert 任意の文字列をパスワードとして追加
gopass generate ランダムな文字列をパスワードとして追加
gopass edit パスワードの変更
gopass rm パスワードの削除
gopass mv パスワードの移動
gopass cp パスワードのコピー
gopass config gopass の設定確認
gopass sync リモートパスワードストア(Git リモートリポジトリ)との同期

gopass とは?

gopass は、UNIX哲学 に従ったシンプルなパスワードマネージャー pass を Go で rewrite したものです。クロスプラットフォームでの利用と追加機能の実装を目的に Go で rewrite がなされたようです。今回は gopass の基本的な機能を紹介した上で、使い方をまとめていこうと思います。

https://github.com/gopasspw/gopass

gopass を実行するための前準備

前置き

後述の説明は全て Mac での利用を想定したものとなっておりますので、他の OS を利用の際には公式ドキュメントを参照ください。

CLI のインストール

gopass は GPG と Git に依存しているので、それら全てを brew でインストールします。

brew install gnupg2 git
brew install gopass

今回利用する各CLIのバージョンは以下です。

  • gpg 2.2.14
  • git 2.16.1
  • gopass 1.8.4

パスワードの 暗号化/復号化 に使う GPG Key Pair の作成

gopass は GPG を用いて、パスワードの 暗号化/復号化 を行うため、予めそれらの処理に利用する GPG Key Pair を作成しておく必要があります。

gpg --list-keys を実行して、既に GPG Key Pair が存在している場合には、こちらの作業はスキップしてください。GPG Key Pair が存在していない場合には gpg --gen-key もしくは gpg --full-generate-key を実行して作成を行います。

実行すると作成するためのオプションを問われるので、自由に入力してください。

$ gpg --full-generate-key
gpg (GnuPG) 2.2.14; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

# Key 種別はデフォルトの "RSA and RSA" で良いので未入力で Enter
Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection?

# Key サイズはデフォルトの "2048" で良いので未入力で Enter
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 bits

# Key 有効期限はデフォルトの "無期限" で良いので未入力で Enter
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y

# Git で利用するユーザーとメールアドレスと一致している必要があります(一致しないとエラーとなります)
# わからない人は git config -l で user.name や user.email などを参照してください
GnuPG needs to construct a user ID to identify your key.

Real name: ryysud
Email address: ryysud@example.com
Comment:
You selected this USER-ID:
    "ryysud <ryysud@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O

# ここまでの入力を終えるとパスワードを求められるので任意の文字列を入力してください
# ここで設定したパスワードが gopass で利用するマスターパスワードとなります

# Key が作成された旨のメッセージが出力される
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key 67625320783C98C3 marked as ultimately trusted
gpg: revocation certificate stored as '/Users/yoshida/.gnupg/openpgp-revocs.d/F6D0DC0AB0470AF7587294B167625320783C98C3.rev'
public and secret key created and signed.

pub   rsa2048 2019-04-01 [SC]
      F6D0DC0AB0470AF7587294B167625320783C98C3
uid                      ryysud <ryysud@example.com>
sub   rsa2048 2019-04-01 [E]

GPG Key Pair が作成されました。

# 公開鍵
$ gpg --list-keys
/Users/yoshida/.gnupg/pubring.kbx
---------------------------------
pub   rsa2048 2019-04-01 [SC]
      F6D0DC0AB0470AF7587294B167625320783C98C3
uid           [ultimate] ryysud <ryysud@example.com>
sub   rsa2048 2019-04-01 [E]

# 秘密鍵
$ gpg --list-secret-keys
/Users/yoshida/.gnupg/pubring.kbx
---------------------------------
sec   rsa2048 2019-04-01 [SC]
      F6D0DC0AB0470AF7587294B167625320783C98C3
uid           [ultimate] ryysud <ryysud@example.com>
ssb   rsa2048 2019-04-01 [E]

以下のコマンドが正常に動作することが確認できたら、次のステップに進みます。上手くいかない場合には、ここまでの手順が誤っていないか再度確認してください。

mkdir some-dir
cd some-dir
git init
touch foo
git add foo
git commit -S -m "test"

余談ですが、ドキュメントで「GPG を使うことに慣れていなければ、以下の資料が参考になるよー」という案内がされていて、とても親切で好印象でした。

実際に gopass を実行しながら基本機能を理解していく

パスワードストアの初期化( gopass init )

gopass init を実行することでパスワードストアの初期化が可能です。
※ パスワードストアは gopass が管理するパスワード置き場の参照先

$ gopass init

# パスワードの 暗号化/復号化 に使う GPG Key Pair を選択
[init] Initializing a new password store ...
Please select a private key for encrypting secrets:
[0] gpg - 0x67625320783C98C3 - ryysud <ryysud@example.com>
Please enter the number of a key (0-0, [q]uit) [0]: 0
[init] Initializing git repository (gitcli) ...

# パスワードストアで利用する Git Config を選択
Use ryysud (ryysud@example.com) for password store git config? [Y/n/q]: Y
[init] git initialized at /Users/yoshida/.password-store
[init] git configured at /Users/yoshida/.password-store
[init] Git initialized
[init] Password store /Users/yoshida/.password-store initialized for:
[init]   0x67625320783C98C3 - ryysud <ryysud@example.com>

~/.password-store に Git リポジトリが作成されたことがわかります。

$ ls -al ~/.password-store
total 16
drwx------   6 yoshida  staff   204B Apr  1 19:47 .
drwxr-xr-x+ 65 yoshida  staff   2.2K Apr  1 19:50 ..
drwx------  10 yoshida  staff   340B Apr  1 19:50 .git
-rw-------   1 yoshida  staff    15B Apr  1 19:47 .gitattributes
-rw-------   1 yoshida  staff    19B Apr  1 19:47 .gpg-id
drwx------   3 yoshida  staff   102B Apr  1 19:47 .public-keys

パスワードの追加( gopass insert/generate )

任意の文字列を追加する場合

gopass insert path/to/password を実行することで、任意の文字列をパスワードとして追加することが可能です。今回は golang.org/gopher というパスに “password” というパスワードを追加します。

$ gopass insert golang.org/gopher

# "password" という文字列を入力します
Enter password for golang.org/gopher:
Retype password for golang.org/gopher:

# 暗号化に使う Key が出力される
Warning: Password is too common / from a dictionary
gopass: Encrypting golang.org/gopher for these recipients:
- F6D0DC0AB0470AF7587294B167625320783C98C3 - 0x67625320783C98C3 - ryysud <ryysud@example.com>

# 最後に確認がなされてパスワードの追加が完了する
Do you want to continue? [Y/n/q]: Y
Warning: git has no remote. Ignoring auto-push option
Run: gopass git remote add origin ...

ランダムな文字列を追加する場合

gopass generate path/to/password を実行することで、ランダムな文字列をパスワードとして追加することが可能です。今回は golang.org/gopher-random というパスにランダムな文字列のパスワードを追加します。

$ gopass generate golang.org/gopher-random

# ランダムで生成するパスワードの長さを選択可能(デフォルトで良ければ未入力で Enter)
How long should the password be? [24]:
Do you have strict rules to include different character classes? [y/N/q]: y
gopass: Encrypting golang.org/gopher-random for these recipients:
- F6D0DC0AB0470AF7587294B167625320783C98C3 - 0x67625320783C98C3 - ryysud <ryysud@example.com>

# 最後に確認がなされてパスワードの追加が完了する
Do you want to continue? [Y/n/q]: Y
Warning: git has no remote. Ignoring auto-push option
Run: gopass git remote add origin ...

# 生成されたパスワードは45秒間だけクリップボードにコピーされる
✔ Copied golang.org/gopher-random to clipboard. Will clear in 45 seconds.

ワンタイムパスワードを追加する場合

ワンタイムパスワードを追加することも可能となっておりますが、今回は割愛します。
詳細は こちら を参照ください。

パスワードの変更( gopass edit )

gopass edit path/to/password を実行することで、パスワードの変更が可能です。今回は golang.org/gopher というパスにある “password” というパスワードを “edit-password” に変更します。

# 変更前
$ gopass show golang.org/gopher
password

# パスワードの変更(エディタが開かれるので値を "edit-password" に変更)
$ gopass edit golang.org/gopher
gopass: Encrypting golang.org/gopher for these recipients:
- F6D0DC0AB0470AF7587294B167625320783C98C3 - 0x67625320783C98C3 - ryysud <ryysud@example.com>

Do you want to continue? [Y/n/q]: Y
Warning: git has no remote. Ignoring auto-push option
Run: gopass git remote add origin ...

# 変更後
$ gopass show golang.org/gopher
edit-password

パスワードの一覧表示( gopass list )

gopass list を実行することで、パスワードの一覧表示が可能です。

$ gopass list
gopass
└── golang.org
    ├── gopher
    └── gopher-random

-f オプションでパスをフラットに表示することが可能です。パスワードの表示を行う際には、フラットなパスを入力する必要があるので、このオプションはとても有用だと思います。

$ gopass list -f
golang.org/gopher
golang.org/gopher-random

パスワードの表示( gopass show )

gopass show path/to/password を実行することで、パスワードの表示が可能です。こちらのコマンドを実行する際には、パスワードストアの初期化で選択した GPG Key Pair のパスワードを入力する必要があります。gopass の設定にもよりますが、デフォルトだと一度入力すれば一定時間はパスワードの入力がスキップされます。

$ gopass show golang.org/gopher
edit-password

$ gopass show golang.org/gopher-random
U*x@>19]`WjDnC*/fZc<h7Rc

パスワードの削除( gopass rm )

gopass rm path/to/password を実行することで、パスワードの削除が可能です。

$ gopass list
gopass
└── golang.org
    ├── gopher
    └── gopher-random

$ gopass rm golang.org/gopher-random
Are you sure you would like to delete golang.org/gopher-random? [y/N/q]: y

$ gopass list
gopass
└── golang.org
    └── gopher

パスワードの移動( gopass mv )

gopass mv src-path/to/password dest-path/to/password を実行することで、パスワードの移動が可能です。

$ gopass list
gopass
└── golang.org
    └── gopher

$ gopass mv golang.org/gopher golang.org/gopher-mv
gopass: Encrypting golang.org/gopher-mv for these recipients:
- F6D0DC0AB0470AF7587294B167625320783C98C3 - 0x67625320783C98C3 - ryysud <ryysud@example.com>

Do you want to continue? [Y/n/q]: Y
Warning: git has no remote. Ignoring auto-push option
Run: gopass git remote add origin ...

$ gopass list
gopass
└── golang.org
    └── gopher-mv

パスワードのコピー( gopass cp )

gopass cp src-path/to/password dest-path/to/password を実行することで、パスワードのコピーが可能です。

$ gopass list
gopass
└── golang.org
    └── gopher-mv

$ gopass cp golang.org/gopher-mv golang.org/gopher
gopass: Encrypting golang.org/gopher for these recipients:
- F6D0DC0AB0470AF7587294B167625320783C98C3 - 0x67625320783C98C3 - ryysud <ryysud@example.com>

Do you want to continue? [Y/n/q]: Y
Warning: git has no remote. Ignoring auto-push option
Run: gopass git remote add origin ...

$ gopass list
gopass
└── golang.org
    ├── gopher
    └── gopher-mv

gopass の設定確認( gopass config )

gopass config を実行することで、gopass の設定確認が可能です。また gopass config param custom-value で設定の変更も可能です。

$ gopass config
root store config:
  askformore: false
  autoclip: true
  autoimport: true
  autosync: true
  check_recipient_hash: false
  cliptimeout: 45
  concurrency: 1
  editrecipients: false
  nocolor: false
  noconfirm: false
  nopager: false
  notifications: true
  path: gpgcli-gitcli-fs+file:///Users/yoshida/.password-store
  safecontent: false
  usesymbols: false

パスワードストアをリモートで管理して複数人で利用する

故意に既存のリモートパスワードストア(Git リモートリポジトリ)を追加しない限りは、ローカルパスワードストア(Git ローカルリポジトリ)の利用となるので、ローカルで閉じた個人での利用が前提となります。

なので、複数人で同じパスワードストアを利用したい場合には、リモートでの管理が必要となります。今回は、複数人での利用を想定して GitHub で管理する手順を紹介します。パスワードストアも結局のところ実体は Git リポジトリなので、Git の基本操作で簡単に設定可能です。

Git リモートリポジトリの設定を追加

gopass git remote add origin を実行して Git リモートリポジトリを追加します。

$ gopass git remote add origin https://github.com/ryysud/hello-gopass.git

~/.password-store に移動して Git リモートリポジトリを確認すると、設定が適用されていることがわかります。

$ cd ~/.password-store
$ git remote -vvv
origin  github.com:ryysud/hello-gopass.git (fetch)
origin  github.com:ryysud/hello-gopass.git (push)

リモートパスワードストアへのデータ同期を行う

gopass sync を実行することで、リモートパスワードストアへのデータ同期が可能です。実行結果にあるように、実処理は git pull と git push と GPG Key Pair の操作のようです。

gopass sync
Sync starting ...
[<root>]
   git pull and push ...
OK (no changes)
   importing missing keys ... OK
   exporting missing keys ... OK
   done
All done

以上で、パスワードストアをリモートで管理して複数人で利用することが可能となります。

他の人が利用を開始する際には Cloning an Existing Password Store の手順に従い、リモートパスワードストアのクローンを行う必要があります。また、複数人で利用するのに単一の GPG Key Pair をコピーして利用するのは、リスクが大きいので Managing Recipients の手順に従い、利用者全員の GPG Key Pair の追加を行ってください。

ちょっとした Tips1

デフォルトだと、パスワードの操作が行われた後にリモートパスワードストアとの自動同期が実行されるので、事故を防ぐためにも gopass config autosync false を実行して、自動同期を無効化しておいたほうが良さそうです。

# デフォルトは自動同期が有効
$ gopass config autosync
autosync: true

# 自動同期を無効に設定
$ gopass config autosync false
autosync: false

設定を忘れて誤ってパスワードを 変更/削除 してしまっても、パスワードストアの実体は Git リポジトリなので、Git を操作して revert すれば良いと思います。

ちょっとした Tips2

パスワードの変更をチームなどでレビューする際には、パスワードストアのブランチを切り替えて gopass sync を実行した後に PR を作成すれば良さそうです。

cd ~/.password-store
git checkout -b update-password
gopass insert new-password
gopass sync

最後に

今回初めてパスワードマネージャーなるものを使ってみたのですが、複数人でパスワードを共有したい場合に gopass は非常に有用なツールであることがわかりました。

今回紹介したコマンド郡は最上部の TL;DR にまとめてあります。また、今回紹介した以外にも gopass では多くの機能が提供されているので、気になる方は以下をチェックしてみてください。

https://github.com/gopasspw/gopass/blob/master/docs/features.md

おしまい。