Skip to content

필사 모드: 閉域網の運用プレイブック — セキュリティパッチに追随し、ロールバックし、CVE 遅延を管理する

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

はじめに — 遅延はなくせませんが、管理はできます

接続網サーバーのセキュリティ対応はこうです。勧告が出て、その日に dnf update --security を回して、終わりです。

閉域網はこうです。勧告が出て、次の持ち込み周期を待ち、外側でパッケージを取得し、審査に上げ、媒体を持ち込み、リポジトリを更新し、サーバーに適用します。速くて数日、普通は数週間です。

この遅延は構造から出てきます。手順をどれだけ磨いても 0 にはなりません。ですから今回の目標は遅延をなくすことではなく、測定可能にし、緊急経路を別に用意し、その事実を組織に知らせること です。

まず確認すること — updateinfo は生きているか

運用編の大部分は dnf updateinfo から出発します。ところが閉域網では、このコマンドが何も出力しないことが非常によくあります。

# 何が滞留しているかを数えてみる
dnf updateinfo --summary

# 何も出てこないなら、たいていはリポジトリ側の問題です

理由は第 5 回のモジュール問題と同じ構造です。どのパッケージがどの勧告に属するかは、rpm ファイルの中ではなくリポジトリメタデータに あります。createrepo_c が rpm から生成するのは primary、filelists、other であり、勧告情報は rpm の中にないので作り出すことができません。createrepo_c の man ページに --keep-all-metadata("Keep additional metadata during update (default)") が別途あるのも、この付加メタデータが別個の存在だからです。

そこでこう分かれます。

  • dnf reposync --download-metadata で取得したなら勧告情報も一緒に来ます。この場合、持ち込み後に createrepo_c を再実行しないでください。作り直すと失われます
  • dnf download で rpm だけを集めて createrepo_c でリポジトリを作ったなら勧告情報はありません。このリポジトリでは --security 系がすべて無意味になります

2 番目の状態で dnf update --security を回すと、エラーなしで「やることなし」と出ます。静かに何もしないという点が危険です。持ち込み手順の検証段階に、この 1 行を入れておいてください。

# 持ち込みリポジトリが勧告情報を持っているか確認 — 0 なら手順が間違っている
dnf updateinfo --summary | tail -5

何が滞留しているかを数えます

勧告情報が生きているなら、現状把握はコマンド数行です。RHEL 9 公式セキュリティドキュメントの表記をそのまま使います。

# まだ適用していないセキュリティ更新の一覧
dnf updateinfo list updates security

# すでに適用済みのセキュリティ更新 (監査対応用)
dnf updateinfo list security --installed

# 特定の勧告の詳細 (CVE 番号と説明を含む)
dnf updateinfo info RHSA-2019:0997

# CVE を参照する勧告だけを絞り込む
dnf updateinfo list --with-cve

ドキュメント基準で --with-cve は "print only advisories referencing a CVE"、--with-bz は "print only advisories referencing a bugzilla" です。可用性の指定子は --available(デフォルト)、--installed--updates--all の 4 つです。

RHEL 9 セキュリティドキュメントにある dnf updateinfo list updates security の出力はこういう形です。

RHSA-2019:0997 Important/Sec. platform-python-3.6.8-2.el8_0.x86_64
RHSA-2019:0997 Important/Sec. python3-libs-3.6.8-2.el8_0.x86_64
RHSA-2019:0990 Moderate/Sec.  systemd-239-13.el8_0.3.x86_64

2 列目が深刻度です。これで持ち込みの優先順位を決められます。

適用します

# 利用可能なセキュリティ更新をすべて適用
sudo dnf update --security

# 特定の勧告だけを適用
sudo dnf update --advisory=RHSA-2019:0997

# 特定の勧告を最小のバージョン変更だけで適用
sudo dnf upgrade-minimal --advisory=RHSA-2019:0997

# 特定の CVE だけを指定して適用
sudo dnf update --cve=CVE-2019-9636

# 深刻度で範囲を絞る
sudo dnf update --sec-severity=Important

dnf ドキュメントの定義では、--security が "Includes packages that provide a fix for a security issue"、--advisory=<advisory> が "Include packages corresponding to the advisory ID"、--cve=<cves> が "Include packages that fix a CVE ID"、--sec-severity=<severity> が "Includes packages that provide a fix for an issue of the specified severity" です。

upgrade-minimal は閉域網で特に有用です。ドキュメントの説明は "Updates each package to the nearest available version that provides a bugfix, enhancement or a fix for security issue" です。セキュリティ修正は受け取りつつ、バージョンの変化を最小に保つ ので、変更範囲が狭くなって審査を通しやすく、回帰のリスクも減ります。閉域網の定期パッチのデフォルトにする価値があります。

適用のあとに残る作業が 1 つあります。

# 再起動が必要なプロセスを確認
dnf needs-restarting

RHEL 9 ドキュメントはこのコマンドに重要な但し書きを付けています。このコマンドはプロセスだけを列挙し、サービスではないので "you cannot restart processes listed using the systemctl utility" です。出力に出たものをそのまま systemctl に渡してはいけない、という意味です。

2 つのスナップショットの差分を審査資料にします

定期持ち込みでいちばん面倒なのが、「今回は何が変わりますか」という質問に答えることです。dnf repodiff がその仕事をします。ドキュメントの定義は "repodiff is a program which will list differences between two sets of repositories" です。

# 前回の持ち込みスナップショットと今回のものを比較する
dnf repodiff \
  --repofrompath=old,/srv/repo-snapshots/2026-07-14/baseos \
  --repofrompath=new,/srv/repo-snapshots/2026-08-15/baseos \
  --repo-old=old --repo-new=new \
  --archlist=x86_64 \
  --size

# 1 行の要約形式で (審査文書に添付しやすい)
dnf repodiff \
  --repofrompath=old,/srv/repo-snapshots/2026-07-14/baseos \
  --repofrompath=new,/srv/repo-snapshots/2026-08-15/baseos \
  --repo-old=old --repo-new=new \
  --archlist=x86_64 --simple --downgrade

ここで必ず知っておくべきデフォルトがあります。ドキュメントは "Note that by default only source packages are compared" と明記しています。--archlist を指定しなければバイナリパッケージは比較されません。ドキュメントは --archlist-a を "Add architectures to change the default from just comparing source packages. Note that you can use a wildcard * for all architectures" と説明しています。

残りのオプションは、--size-s が "Output additional data about the size of the changes"、--simple が "Output a simple one line message for modified packages"、--downgrade が "Split the data for modified packages between upgraded and downgraded packages"、--compare-arch が名前だけでなくアーキテクチャまで比較対象に入れるオプションです。

この出力を持ち込み審査の添付にそのまま使えば、審査する側が「何が変わるのか」を根拠を持って判断できます。

ミラー容量を管理します

持ち込みを繰り返すとリポジトリは大きくなり続けます。かといって古いバージョンをすべて消せばロールバックが不可能になります。dnf repomanage がこの均衡を取ってくれます。ドキュメントの説明は "repomanage prints newest or older packages in a repository specified by <path> for easy piping to xargs or similar programs" です。出力するだけで削除はしないという点が重要です。

# 各パッケージの最新 2 バージョンだけ残し、残りを確認する
dnf repomanage --old --keep 2 /srv/repo/rhel9-baseos

# 実際に削除する (一覧を先に目で確認したあとだけ)
dnf repomanage --old --keep 2 /srv/repo/rhel9-baseos | xargs -r rm -v

# 整理後にメタデータを作り直す
sudo createrepo_c --update /srv/repo/rhel9-baseos

ドキュメント基準で --old は "Show older packages (for a package or a stream show all versions except the newest one)"、--new は "Show newest packages"、-k--keep は "Limit the resulting set to newest <keep-number> packages" です。

いくつ残すかが、そのままロールバック可能な範囲になります。持ち込み周期が月 1 回で 3 つ残すなら、およそ 3 か月分のロールバックが可能です。容量とロールバック範囲を同じ天秤に載せて決めてください。

ロールバック — 戻せるものと戻せないもの

パッチ後に問題が起きたときの手順です。

# トランザクション履歴を確認
dnf history

# 特定のトランザクションの内容を確認
dnf history info 42

# そのトランザクション 1 つだけを戻す
sudo dnf history undo 42

# 指定時点以降をすべて戻す (指定したトランザクション自体は維持)
sudo dnf history rollback 41

RHEL 9 ドキュメントは undo の動作をこう説明します。トランザクションがパッケージをインストールしていれば削除し、削除していれば再インストールし、更新されたパッケージについては以前のバージョンが まだ利用可能な場合にかぎり ダウングレードを試みます。そして "If an older package version is not available, the downgrade by using the dnf history undo command fails" と明記しています。

閉域網では、この一文がそのまま前節の保管ポリシーにつながります。古いパッケージを消していればロールバックは失敗します。

そして必ず守るべき境界が 1 つあります。RHEL 9 ドキュメントはこう警告しています。

"Downgrading RHEL system packages to an older version by using the dnf history undo and dnf history rollback command is not supported. This concerns especially the selinux, selinux-policy-*, kernel, and glibc packages, and dependencies of glibc such as gcc."

つまりカーネル、glibc、SELinux ポリシーは履歴の巻き戻しで扱ってはいけません。こうしたものの回帰対応は、ロールバックではなく 別の経路 で準備しておく必要があります。カーネルなら以前のカーネルで起動する方法があり、それ以外はスナップショットやシステムイメージのレベルでの復旧が現実的な答えです。この境界を手順書に明記しておけば、事故が起きた時点での判断が速くなります。

持ち込み周期を設計します

ここが今回の核心となる設計です。経路を 1 つしか用意しないと必ず失敗します。2 つ用意します。

区分定期持ち込み緊急持ち込み
周期月 1 回など固定事由が発生したとき
発動条件スケジュール深刻度 Critical の勧告、または組織が定めた CVE 基準
範囲リポジトリ全体のスナップショット該当勧告に関係するパッケージのみ
適用コマンドdnf upgrade-minimal --securitydnf update --advisory=<ID>
審査標準手順事前に合意された短縮手順
検証全体の回帰テスト該当サービスのみ

緊急経路の核心は 平時にあらかじめ合意しておくこと です。事故が起きたあとで短縮手順を作ろうと言い出すと、その議論だけで数日かかります。

遅延を測ることも忘れないでください。

#!/usr/bin/env bash
# patch-lag.sh — 滞留しているセキュリティ勧告を深刻度別に数える
set -euo pipefail

echo "== 調査時刻: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "== リポジトリスナップショット"
grep -h '^name=' /etc/yum.repos.d/airgap-*.repo || true

echo "== 滞留しているセキュリティ勧告の要約"
if ! dnf updateinfo --summary 2>/dev/null | grep -q .; then
  echo "警告: updateinfo メタデータがありません。持ち込み手順を確認してください。"
  exit 2
fi
dnf updateinfo --summary

echo "== 深刻度別の詳細"
for sev in Critical Important Moderate Low; do
  n="$(dnf updateinfo list updates security 2>/dev/null | grep -c "${sev}/Sec." || true)"
  printf '%-10s %s\n' "${sev}" "${n}"
done

この出力を定期報告に入れれば、パッチ遅延は「感覚」ではなく数字になります。数字になれば、持ち込み周期を短くしようという議論が可能になります。

Red Hat 公式セキュリティドキュメントの手順は、その多くが前提条件として "A Red Hat subscription is attached to the host" を明記しています。閉域網サーバーはこの条件を満たさない場合が多いので、勧告情報は持ち込みリポジトリのメタデータを通して入ってこなければなりません。前の第 1 節が重要な理由がここにあります。

サブスクリプションなしに Red Hat コンテンツを再配布することは契約違反になりうるので、組織のライセンス条件を先に確認してください。勧告メタデータも Red Hat コンテンツに含まれます。

運用チェックリスト

手順書のいちばん前に貼っておいて使う用途のものです。

持ち込み準備 (接続網)

  • リリースバージョンを固定したか (--releasever または /etc/dnf/vars/releasever)
  • 空の --installroot で依存関係を解決したか
  • モジュールを使うシステムなら module_platform_id を指定したか
  • reposync--download-metadata を付けたか (勧告とモジュール情報の保存)
  • dnf repoclosure が通ったか
  • MANIFEST.tsv を生成したか (NEVRA、チェックサム、スナップショット日付、releasever)
  • GPG 公開鍵をバンドルに含めたか
  • 生成コマンドを PROVENANCE.txt に記録したか
  • dnf repodiff の出力を審査資料として添付したか

持ち込み後 (閉域網)

  • マニフェストとチェックサムを突き合わせたか
  • rpmkeys --checksig がすべて通ったか
  • マニフェストにないファイルが媒体にないか確認したか
  • リポジトリメタデータを作り直す必要があるか判断したか (--download-metadata で取得したなら再生成は禁止)
  • .repo ファイルに gpgcheck=1 が明記されているか
  • dnf clean expire-cache のあと dnf repolist -v でパッケージ数を確認したか
  • dnf updateinfo --summary が空になっていないか
  • dnf repoclosure を実際のリポジトリ構成で改めて回したか

適用と事後

  • dnf upgrade-minimal --security で変更範囲を最小化したか
  • dnf needs-restarting の結果を処理したか
  • dnf history のトランザクション ID を運用記録に残したか
  • ロールバック可能な範囲 (repomanage --keep の値) を確認したか
  • カーネル・glibc・SELinux を履歴ロールバックの対象から外したか
  • パッチ遅延の数値を定期報告に反映したか

おわりに — 遅延を隠さないでください

閉域網の運用でいちばん危険な態度は、パッチ遅延を恥じて報告から外すことです。遅延は閉域網を選んだ対価であり、その選択はたいてい技術ではなく規制がしたものです。

やるべきことは、遅延を 数字にし、緊急経路をあらかじめ開けておき、その数字を定期的に見せること です。そうしてはじめて「持ち込み周期を月 1 回から隔週に短縮しよう」という議論が、勘ではなく根拠の上で行われます。

7 回分の結論は 1 つに集まります。閉域網では反復可能なものだけが生き残ります。マニフェストとチェックリストがその反復を作ります。

コマンドとオプションは 2026-08-15 に公式ドキュメントで確認しました。RHEL のバージョンによって異なるので、使用中のバージョンのドキュメントで改めて確認してください。

自分で試す

シリーズ全体

  1. 閉域網インストールが難しい本当の理由
  2. 外側で取得する — dnf download, reposync, yumdownloader
  3. ローカルリポジトリを作る — createrepo_c と GPG 鍵
  4. 持ち込み手順と完全性 — 再現可能なバンドル
  5. モジュールとバージョン固定
  6. コンテナイメージの持ち込み
  7. 運用プレイブック (この記事)

閉域網 Kubernetes の運用は Day 2 運用編 に続きます。

参考資料

현재 단락 (1/139)

接続網サーバーのセキュリティ対応はこうです。勧告が出て、その日に `dnf update --security` を回して、終わりです。

작성 글자: 0원문 글자: 9,933작성 단락: 0/139