GPG + Expect で複数のパスワードを共通管理
お仕事のソフトウェア開発は複数の会社(日本 + 海外)で共同で行っている。そのため、必然的に海外のマシンに接続する必要が出てくる。バグ管理システム(Bugzilla)やビルドマシンは言うに及ばず、開発チームの wiki やテスト管理システム(Testopia)、Subversion レポジトリなどなど…とにかくリモートから色々なサービスを利用することになる。
このリモート間での作業を効率化するため、このたび OpenVPN が開通した。これであたかもリモートのマシンが内部のネットワークにいるかのごとく作業できる。
ただ、その度に悩むのがパスワードの管理。システム管理者から「あなたの OpenVPN パスワードはこれよん」という GPG メールが送られてくるのだが、他にもいろいろあって覚えきれない。そこで複数のアプリに使用するパスワードを共通のパスフレーズで一元管理できないか考えてみた.
1. まず、各種パスワード(例として OpenVPN 用、マシンA の root 用、mysql 用)をそれぞれのテキストファイルに保存する(ここではサンプルなので mkpasswd を使っている)。
$ cat "BwJRjKvqlZeOc" > pass.openvpn $ cat "ltubEfK.ZKxJ6" > pass.machineAroot $ cat "Jzq.XM5OwhUsQ" > pass.mysql
2. 次にこの 3 つのパスワードファイルを gpg を使って共通のパスフレーズ「hirake, goma」で暗号化する。暗号化した後は、元の平文ファイルを削除する。
$ ls pass.machineAroot pass.mysql pass.openvpn $ echo "hirake, goma" | gpg --force-mdc --passphrase-fd 0 --batch -c pass.openvpn $ echo "hirake, goma" | gpg --force-mdc --passphrase-fd 0 --batch -c pass.machineAroot $ echo "hirake, goma" | gpg --force-mdc --passphrase-fd 0 --batch -c pass.mysql $ ls pass.machineAroot pass.mysql pass.openvpn pass.machineAroot.gpg pass.mysql.gpg pass.openvpn.gpg $ rm pass.openvpn pass.machineAroot pass.mysql $ ls pass.machineAroot.gpg pass.mysql.gpg pass.openvpn.gpg
3. 最後にこの暗号化されたパスワードファイルからパスワードを読み取り各種処理(OpenVPN スタート、scp, mysql の DB データ抽出など)を実行するスクリプトを作成する。どのスクリプトにも共通のパスフレーズである「hirake, goma」を唱えると gpg がパスワードファイルを復号化してパスワードを Expect に渡すようにしている。
#!/bin/bash DECRYPT_PASSWORD=`gpg -d pass.openvpn.gpg` expect -c " spawn startopenvpn.sh expect password: send $DECRYPT_PASSWORD\n expect eof"
#!/bin/bash DECRYPT_PASSWORD=`gpg -d pass.machineAroot.gpg` expect -c " spawn scp -rp src machineA:/tmp # rsync など各種処理 ... expect password: send $DECRYPT_PASSWORD\n expect eof"
#!/bin/bash DECRYPT_PASSWORD=`gpg -d pass.mysql.gpg` expect -c " spawn mysql -u root -p expect password: send $DECRYPT_PASSWORD\n # データ抽出など各種処理 expect eof"
古典的な「環境変数にパスワードを保存 + Expect で渡す」方法だと確かに全自動でラクなのだが、メモリ上に残るため、set や declare -x などで閲覧が可能なところがなんとなく気持ちが悪い。上記の方法ならば画面にも出てこないし、メモリにも各種スクリプト(プロセス)の動作時のみなので安心。