🔐

Ubuntu で OpenSSH の鍵管理を gpg-agent に委譲する【たぶん決定版】

2021/01/09に公開

OpenSSH では ssh-agent を GnuPG の gpg-agent に置き換えることで鍵の管理を GnuPG 側に委譲できる。ちなみに gpg-agent は GnuPG 秘密鍵管理の中核コンポーネントで,自身はパスフレーズを一定期間キャッシュすることでユーザの鍵操作を省力化できる(秘密鍵そのものはキャッシュしない)。また,リモートの gpg-agent 同士の連携も可能である。

ただし Ubuntu を含む Debian 系ディストリビューションでは OpenSSH の鍵管理に ssh-agent を使うことを前提に構成されているため, gpg-agent に置き換えるにはいくつかの設定変更が必要なようだ。この記事では,その設定変更について簡単にまとめておく[1]

Ubuntu 設定の変更

gpg-agent サービスの確認

まずは gpg-agent がサービスとして稼働しているか確認する。

$ systemctl --user status gpg-agent
● gpg-agent.service - GnuPG cryptographic agent and passphrase cache
     Loaded: loaded (/usr/lib/systemd/user/gpg-agent.service; static)
     Active: inactive (dead)
TriggeredBy: ● gpg-agent-extra.socket
             ● gpg-agent-browser.socket
             ● gpg-agent-ssh.socket
             ● gpg-agent.socket
       Docs: man:gpg-agent(1)

上はログイン直後で gpg-agent が起動していない状態だが, TriggeredBy が示す4つのソケットへのアクセスで起動するようになっている。このソケットの中に gpg-agent-ssh.socket が含まれていれば無問題。ちなみにソケットの実体は gpgconf コマンドで確認できる。

$ gpgconf --list-dirs | grep socket
socketdir:/run/user/1000/gnupg
dirmngr-socket:/run/user/1000/gnupg/S.dirmngr
agent-ssh-socket:/run/user/1000/gnupg/S.gpg-agent.ssh
agent-extra-socket:/run/user/1000/gnupg/S.gpg-agent.extra
agent-browser-socket:/run/user/1000/gnupg/S.gpg-agent.browser
agent-socket:/run/user/1000/gnupg/S.gpg-agent

Xsession.options の変更

次に /etc/X11/Xsession.options ファイルを確認する。

/etc/X11/Xsession.options
# $Id: Xsession.options 189 2005-06-11 00:04:27Z branden $
#
# configuration options for /etc/X11/Xsession
# See Xsession.options(5) for an explanation of the available options.
allow-failsafe
allow-user-resources
allow-user-xsession
use-ssh-agent
use-session-dbus

この中の use-ssh-agent の記述を no-use-ssh-agent に差し替える。当然ながら変更には管理者権限が必要なのでご注意を。バックアップを取りながら作業してね。

gnome-keyring-ssh.desktop を autostart に入れる

/etc/xdg/autostart/ ディレクトリに gnome-keyring-ssh.desktop ファイルがあるのだが,まずはこのファイルを ~/.config/autostart/ ディレクトリにコピーする。ディレクトリがない場合は作成すること。

$ cp /etc/xdg/autostart/gnome-keyring-ssh.desktop ~/.config/autostart/

gnome-keyring-ssh.desktop ファイルの中身はテキストだが,コピーしたこのファイルの末尾に

Hidden=true

の行を追記する。

【2021-06-05 追記】 Ubuntu 21.04 の場合

2021年4月にリリースされた Ubuntu 21.04 ではこの設定ではうまく行かないようだ。この場合,とりあえず応急措置として .bashrc で

export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
dbus-update-activation-environment --systemd SSH_AUTH_SOCK

と言った感じに環境変数 SSH_AUTH_SOCK を直接指定すればよい(情報募集)。

gpg-agent.conf の設定

最後に ~/.gnupg/gpg-agent.conf ファイルに以下の内容を書き込む。 gpg-agent.conf ファイルがない場合は作成してね。

~/.gnupg/gpg-agent.conf
enable-ssh-support
default-cache-ttl-ssh 1800
max-cache-ttl-ssh 7200

下2つのオプションは任意で,以下の意味を持つ。

オプション名 内容
default-cache-ttl-ssh 直前にアクセスしたキャッシュ・エントリの有効期間を秒単位で指定する。 既定値は 1800
max-cache-ttl-ssh キャッシュ・エントリの有効期間の最大値を秒単位で指定する。 アクセスの有無にかかわらずこの期間が過ぎるとキャッシュがクリアされる。 既定値は 7200

有効期間は大きすぎると漏洩リスクが高まるのでほどほどに(笑)

これで設定は完了。念のためログインし直しておこう。

環境変数の確認

ログインし直したら環境変数を確認しておく。

$ env | grep SSH
SSH_AUTH_SOCK=/run/user/1000/gnupg/S.gpg-agent.ssh

てな感じに SSH_AUTH_SOCK 環境変数の値が gpg-agent のソケットになっていれば OK である。

GnuPG による鍵管理

既存の OpenSSH 認証鍵を登録する

上述の設定が完了していれば,既存の OpenSSH 認証鍵を GnuPG の鍵束に登録するのは ssh-add コマンドで簡単にできる。

$ ssh-add ./id_ecdsa
Enter passphrase for ./id_ecdsa: 
Identity added: ./id_ecdsa (alice@example.com)

この時 ssh-add コマンドによるパスフレーズ入力とは別に GnuPG の Pinentry によるパスフレーズの設定が行われる(確認を含めて2箇所入力する必要あり)。

Pinentry

GnuPG の鍵束に登録される認証鍵はこのパスフレーズで保護される。

大事なことなので繰り返すが,登録した秘密鍵はキャッシュされず GnuPG の鍵束(~/.gnupg/private-keys-v1.d/ ディレクトリ)に入る。また ~/.gnupg/sshcontrol ファイルに

# ECDSA key added on: 2020-06-01 14:05:35
# Fingerprints:  MD5:e4:5b:66:a6:03:9a:a4:0e:f2:1b:a5:04:72:93:f3:f0
#                SHA256:DtXgQm9rz7Dc5M5yWu/CNVo341o1rcfN9UCyYu+SZU4
A5353D587000D820669B0BD55A0B4AD6897458DB 0

という感じに追加した鍵の情報が入る。

ちなみに A5353D587000D820669B0BD55A0B4AD6897458DB は keygrip と呼ばれる値で,鍵の種類に関係なく統一的に表される ID である。また鍵束である ~/.gnupg/private-keys-v1.d/ ディレクトリに入っている鍵は A5353D587000D820669B0BD55A0B4AD6897458DB.key のように keygrip に紐付いたファイル名で格納されている。また,末尾の 0 はキャッシュ期間(秒)を指すらしい。 0 より大きければ gpg-agent.conf ファイルの指定より優先されるってことかな。

なお,行頭に ! マークを付けると鍵の使用を無効化できる。

GnuPG 鍵を OpenSSH 認証鍵として設定する

GnuPG 鍵を OpenSSH 認証鍵として設定することもできる。ただし専用の認証鍵を作る必要がある。詳しくは拙文

https://text.baldanders.info/openpgp/ssh-key-management-with-gnupg/

を参考にどうぞ。たとえば

$ gpg --list-keys --with-keygrip alice
pub   ed25519 2021-01-06 [SC] [有効期限: 2021-01-13]
      011C720B03D2E1D6BCFA98391DFF44901121B61D
      Keygrip = 97249ABEB2A2FD9E88F6723BB19D4F84B90E261A
uid           [  究極  ] Alice <alice@example.com>
sub   cv25519 2021-01-06 [E]
      Keygrip = 96CB831965E1A7EB4705577D6A7CB7F9E05C8192
sub   ed25519 2021-01-06 [A]
      Keygrip = F5C774B5B418B6E0B5B7942F93DE82BF2FEF4C8E

という鍵があるとき,最後の [A] でマークされている副鍵が OpenSSH 認証鍵として使えるのだが,この鍵の keygrip 値を ~/.gnupg/sshcontrol ファイルに登録する。

$ echo F5C774B5B418B6E0B5B7942F93DE82BF2FEF4C8E 0 >> ~/.gnupg/sshcontrol

登録した鍵の確認

登録した鍵は ssh-add -l コマンドで確認できる。公開鍵の取り出しは ssh-add -L コマンドでいいかな。 GnuPG で作成した鍵なら

$ gpg --export-ssh-key alice
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFfjejx/Saej929myfZoBQAKgusPi2iiOxdZZfpCLxh5 openpgp:0x390C3E49

でも取り出せる。

参考ページ

https://curiouslynerdy.com/gpg-agent-for-ssh-on-ubuntu/

https://text.baldanders.info/remark/2020/06/upgrade-openssh-key/

https://text.baldanders.info/openpgp/build-gnupg-in-ubuntu/

参考図書

https://www.amazon.co.jp/dp/B015643CPE

脚注
  1. Windows の場合は,古い記事で恐縮だが,拙文「GnuPG for Windows : gpg-agent について」を参照のこと。 ↩︎

GitHubで編集を提案

Discussion