CentOS 6 で yum localinstall が通らないときの切り分け
CentOS 6 で配布元から落としてきた RPM を yum localinstall で入れようとして、
警告: ... ヘッダ V3 RSA/SHA256 Signature, key ID xxxxxxxx: NOKEY が出たまま進まない、という詰まり方があります。
ただ、同じコマンドが通らない原因は1つではありません。 特に CentOS 6 がサポート終了してからは、署名の警告にたどり着く前に別のところで落ちているケースのほうが多い。 順番に切り分けます。
先に結論
- NOKEY は「壊れている」ではなく「署名を確認できない」。 配布元の公開鍵を
rpm --importすれば消える --nogpgcheckは署名検証そのものを止めるオプション。 鍵が手に入らないときの最後の手段で、最初に打つものではない- いまの CentOS 6 は、その前にリポジトリと TLS で止まる。
Cannot find a valid baseurl for repo: baseやproblem making ssl connectionが出ていたら、署名の話はまだ先 localinstallは互換のために残っているだけ。yum install ./xxx.rpmで同じことができる
「key ID ...: NOKEY」は何を言っているのか
署名検証の仕組み
RPM パッケージには、作った人の秘密鍵で署名が付いています。 インストール時、rpm はその署名を自分のキーリング(rpm のデータベースに登録された公開鍵の一覧)と突き合わせて、 「このパッケージは確かにその配布元が作ったもので、途中で中身が差し替わっていない」ことを確認します。
NOKEY は、署名に使われた鍵がキーリングに入っていないという意味です。 署名が壊れているわけでも、パッケージが不正だと判定されたわけでもない。「照合する相手がいないので検証できなかった」という状態です。
足りない鍵を特定する
いま入っている鍵は、こう確認できます。
# 登録済みの公開鍵を一覧
rpm -qa gpg-pubkey*
gpg-pubkey-c105b9de-4e0fd3a3
# 中身を見る(誰の鍵なのか)
rpm -qi gpg-pubkey-c105b9de-4e0fd3a3
手元の RPM が誰の署名を要求しているかは、インストールする前に単体で確認できます。
# 署名の検証だけ行う
rpm -K xxxxx.rpm
xxxxx.rpm: RSA sha1 ((MD5) PGP) md5 NOT OK (MISSING KEYS: (MD5) PGP#xxxxxxxx)
MISSING KEYS に出ている ID が、足りない鍵です。
この ID を手がかりに、配布元が公開している鍵を探すことになります。
かつて MySQL 公式のリポジトリ RPM(mysql-community-release-el6-*.noarch.rpm)を入れるときに、
この NOKEY によくぶつかりました。配布元が自前の鍵で署名していて、その鍵が CentOS 標準では入っていないからです。
いまは el6 向けの配布自体が終了しているので、同じ RPM を取得することはできません。
正攻法:鍵をインポートする
取り込んで確認する
配布元が公開鍵を出しているなら、それを取り込むのが本来の手順です。
# URL から直接取り込む
rpm --import https://example.com/RPM-GPG-KEY-example
# ファイルで受け取っている場合
rpm --import /tmp/RPM-GPG-KEY-example
# 取り込まれたか確認
rpm -qa gpg-pubkey* | wc -l
rpm -K xxxxx.rpm
xxxxx.rpm: rsa sha1 (md5) pgp md5 OK
OK に変われば、あとは普通にインストールできます。
yum install ./xxxxx.rpm
鍵の入手先に注意
鍵の入手先は 配布元の公式サイトかドキュメントに書かれている URL だけを使ってください。 検索で出てきた個人ブログに貼られた鍵や、どこかのミラーに転がっているものを取り込むと、 署名検証という仕組みの意味がなくなります。鍵を入れるのは「この配布元を信用する」という宣言なので、そこだけは横着しないほうがいい。
CentOS 自身の鍵は OS に同梱されていて、/etc/pki/rpm-gpg/ に置かれています。
CentOS-Base.repo の gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6 がそれです。
--nogpgcheck が捨てているもの
何が起きるか
--nogpgcheck を付ければ警告は出なくなり、インストールは通ります。
最後の手段
yum install --nogpgcheck ./xxxxx.rpm
ただしこれは「警告を黙らせる」のではなく、そのトランザクションの署名検証を丸ごと無効にするオプションです。 中身が配布元のものである保証を自分で外すことになります。
使ってよい場面
使ってよい場面と、やめたほうがいい場面を分けると、こうなります。
| 状況 | 判断 |
|---|---|
| 自分でビルドした、署名していない RPM を入れる | 妥当。そもそも署名がないので検証するものがない |
| 社内でビルドして社内で配っている RPM | 妥当。ただし署名を付ける運用にしたほうが後が楽 |
| 配布元が鍵を公開しているのに探すのが面倒 | やめる。rpm --import で済む |
| インターネットから落としてきた素性の不明な RPM | やめる。検証を外してよい理由がない |
リポジトリ単位で常時オフにする gpgcheck=0 も同じです。
ローカルリポジトリを自分で立てて自分のパッケージだけ置くなら実務的な選択ですが、
外部のリポジトリに対して付けるものではありません。
いまの CentOS 6 では、警告より先に止まる2か所
ここからが、2015年ごろの手順書がそのまま使えなくなっている部分です。 CentOS 6 は 2020年11月30日にサポートが終了しました。 それに伴って、デフォルトで設定されているリポジトリが実体を失っています。
1. リポジトリが消えている
yum を叩いた時点で、こう落ちます。
Loaded plugins: fastestmirror
Determining fastest mirrors
YumRepo Error: All mirror URLs are not using ftp, http[s] or file.
Eg. Invalid release/repo/arch combination/
removing mirrorlist with no valid mirrors: /var/cache/yum/x86_64/6/base/mirrorlist.txt
Error: Cannot find a valid baseurl for repo: base
mirrorlist.centos.org が CentOS 6 に対して有効なミラーを返さなくなったためです。
パッケージ自体は vault.centos.org に退避しているので、CentOS-Base.repo の参照先を差し替えます。
# 先にバックアップ
cp -p /etc/yum.repos.d/CentOS-Base.repo /tmp/CentOS-Base.repo.$(date +%Y%m%d)
各セクションを、mirrorlist をやめて baseurl を直接指定する形に書き換えます。
[base]
name=CentOS-6.10 - Base
baseurl=http://vault.centos.org/6.10/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
base だけでなく updates extras も同じ要領で直します。
バージョンは自分の環境に合わせてください(cat /etc/redhat-release で確認できます)。
6.10 以外のマイナーバージョンのままなら、そのディレクトリを指定します。
書き換えたら、キャッシュを必ず捨てます。
yum clean all
yum repolist
$releasever を使ったまま運用したい場合は /etc/yum/vars/releasever にマイナーバージョンを固定で書く手もあります。
ただ、この先もう更新されない環境なので、repo ファイルにベタ書きしてしまったほうが事故が少ないです。
2. vault に https で繋がらない
リポジトリを直したのに、今度はこうなることがあります。
http://vault.centos.org/6.10/os/x86_64/repodata/repomd.xml: [Errno 14] problem making ssl connection
Trying other mirror.
Error: Cannot retrieve repository metadata (repomd.xml) for repository: base.
CentOS 6 に入っている nss や ca-certificates が古く、いまのサーバの TLS 設定・証明書チェーンについていけていない状態です。 リダイレクトの先が https だと、ここで止まります。
この環境では curl も wget も同じ理由で使えないことが多いので、
別のマシンで必要な RPM を落としてきて転送し、rpm -Uvh で直接入れるのが早いです。
対象は TLS 周りの一式になります。
# 別の(新しい)マシンで取得して、対象サーバへ転送してから
rpm -Uvh nspr-*.rpm nss-util-*.rpm nss-softokn-freebl-*.rpm \
nss-softokn-*.rpm nss-sysinit-*.rpm nss-*.rpm \
p11-kit-*.rpm p11-kit-trust-*.rpm ca-certificates-*.rpm
これらは依存関係が絡み合っているので、1つずつ入れようとすると詰まります。まとめて渡してください。
ここを通してはじめて yum が動くようになり、localinstall の依存解決もできるようになります。
つまり、依存パッケージを引いてくる経路が死んでいる状態では、署名の警告を直しても localinstall は完走しません。 順番としては リポジトリ → TLS → 署名 です。
localinstall と install の違い
結論から言うと、いま書くなら install で構いません。yum のマニュアルにはこう書かれています。
install コマンドはファイル名を渡せばローカルインストールを行う。localinstall は過去互換のためだけに維持されている。
どちらもローカルの RPM ファイルを指定して入れられて、不足している依存パッケージは設定済みのリポジトリから取ってきます。
rpm -ivh との差はここで、rpm 単体は依存を解決せず「足りない」と言って止まるだけです。
| コマンド | ローカルの RPM | 依存解決 | 備考 |
|---|---|---|---|
rpm -ivh foo.rpm | 入れられる | しない | 足りなければエラーで停止 |
yum localinstall foo.rpm | 入れられる | する | 互換のために残っている |
yum install ./foo.rpm | 入れられる | する | いまはこちら |
なお、yum install ./foo.rpm のようにパスを明示しないと、
foo.rpm という名前のパッケージをリポジトリから探しに行って「見つからない」と言われることがあります。
カレントディレクトリのファイルを指すときは ./ を付けてください。
CentOS 7 以降の dnf でも dnf localinstall は残っていますが、これも dnf install のエイリアスです。
切り分けの順番
| 出ているもの | 原因 | 対処 |
|---|---|---|
Cannot find a valid baseurl for repo: base |
EOL でリポジトリが空 | CentOS-Base.repo を vault に向ける → yum clean all |
problem making ssl connection |
nss / ca-certificates が古い | 別マシンで RPM を取得して rpm -Uvh でまとめて更新 |
key ID ...: NOKEY |
署名した鍵が未登録 | 配布元の公式鍵を rpm --import |
Requires: ... で停止 |
依存パッケージが引けていない | 上の2つが解決済みか確認(yum repolist) |
| パッケージ名が見つからない | ファイルではなくパッケージ名として解釈されている | ./ を付けてパスで渡す |
この環境をいつまで使うか
ここまでの作業は、いずれも「動かすための一時しのぎ」です。 vault は過去のパッケージを置いてあるだけのアーカイブなので、新しい修正は出てきません。 セキュリティ更新が止まって5年以上経っているので、外向きのサーバで動かし続ける前提の話ではないです。
現実にはデータの吸い出しや、移行先での動作確認のために一時的に立ち上げる、という使い方が多いと思います。 その目的なら、ここまでの手順で十分動きます。 逆に言うと、この作業に何日もかけるくらいなら移行を進めたほうが早いということでもあります。
IIJ など国内のミラーが centos-vault を提供している場合は、そちらを baseurl に指定したほうが速いことがあります。
ただしミラーの提供状況は変わるので、作業時点で生きているかを確認してから使ってください。