把气隙引入走完整
目标
制作导入包,用清单验证,打成归档再解开,再搭建软件仓库,并仅凭它完成安装。一次走完整个隔离网络导入流程。
为什么重要
导入介质中不能只放 rpm。rpm、repodata、GPG 密钥、清单、校验和、安装步骤说明这六样必须齐全,而实际上最常缺的是清单和 GPG 密钥。
而且验证必须是双向的。清单中的所有文件是否都在介质上(遗漏检查),以及介质上是否有清单中没有的文件(多余检查)。遗漏会很快以安装失败的形式暴露出来,但多出来的文件会在无人察觉的情况下溜过去——从导入评审的角度看,这一边更危险。
步骤
- 创建目录
/root/airgap/rpms,并把tree和nano连同所有依赖(包括已安装的)一起下载到该目录。 - 创建
/root/airgap/MANIFEST.tsv。第一行是NAME EPOCH VERSION RELEASE ARCH SHA256 FILE表头(以制表符分隔),并为每个 rpm 各填一行对应的值。没有 epoch 的软件包请填0。 - 把
rpms目录和清单打包为/root/airgap/bundle.tar.gz,并把该归档的 sha256 保存到/root/airgap/bundle.sha256。 - 把归档解压到
/root/airgap/unpacked/,把清单中的校验和与实际文件对照的结果保存到/root/airgap/verify.txt。并把不在清单中却存在于目录里的文件的数量写成一行数字,保存到/root/airgap/extra.txt(必须为 0)。 - 在
/root/airgap/unpacked/rpms中创建元数据,并编写/etc/yum.repos.d/airgap.repo。仓库 ID 为airgap-local,name中要有snapshot和日期,并且要包含baseurl=file:///root/airgap/unpacked/rpms、enabled=1、gpgcheck=0、metadata_expire=-1。 - 在关闭其他所有软件仓库、只开启
airgap-local的状态下重新安装tree,并把输出保存到/root/airgap/install.txt。 - 留下状态记录。把模块列表保存到
/root/airgap/state-modules.txt,把用户安装列表保存到/root/airgap/state-userinstalled.txt。 - 把
/root/airgap/report.txt写成下面这 6 行。BUNDLE_ID=airgap-<오늘 날짜 YYYY-MM-DD>/PACKAGES=<rpms 안 .rpm 개수>/MANIFEST_LINES=<매니페스트의 헤더 제외 줄 수>/VERIFY=OK/EXTRA=0/INSTALLED_FROM=airgap-local(前三项的占位符依次为当天日期 YYYY-MM-DD、rpms 中 .rpm 的数量、清单中除表头之外的行数)
参考
- 下载用
dnf download --resolve --alldeps --destdir=/root/airgap/rpms tree nano。 - 提取 NEVRA:
rpm -qp --queryformat '%{NAME}\t%|EPOCH?{%{EPOCH}}:{0}|\t%{VERSION}\t%{RELEASE}\t%{ARCH}' <파일>(占位符为文件名) - 查找清单中没有的文件:
comm -13 <(정렬된 매니페스트 파일명) <(정렬된 실제 파일명)(占位符依次为排序后的清单文件名、排序后的实际文件名) - 只使用一个软件仓库:
dnf --disablerepo='*' --enablerepo=airgap-local install -y tree(如果已经安装,不要用install --reinstall,而要使用reinstall子命令——在这个 dnf 中,前一种形式会报错) - 常见错误 1:在第 2 步中,epoch 被写成
(none)。请用三元表达式补上 0。 - 常见错误 2:在第 4 步中,把清单做成了绝对路径,导致在其他目录中对照失败。
收集导入包
创建目录 /root/airgap/rpms,并把 tree 和 nano 连同所有依赖(包括已安装的)一起下载到该目录。
需要一种选项组合:既下载依赖,又不跳过已安装的软件包。
生成清单
创建 /root/airgap/MANIFEST.tsv。第一行是 NAME EPOCH VERSION RELEASE ARCH SHA256 FILE 表头(以制表符分隔),并为每个 rpm 各填一行对应的值。没有 epoch 的软件包请填 0。
同时写入 NEVRA 和校验和。对于没有 epoch 的软件包,有一种填 0 的写法。
打包为归档
把 rpms 目录和清单打包为 /root/airgap/bundle.tar.gz,并把该归档的 sha256 保存到 /root/airgap/bundle.sha256。
制作可放进介质的单一对象。归档本身的校验和也要留下。
解压并验证
把归档解压到 /root/airgap/unpacked/,把清单中的校验和与实际文件对照的结果保存到 /root/airgap/verify.txt。并把不在清单中却存在于目录里的文件的数量写成一行数字,保存到 /root/airgap/extra.txt(必须为 0)。
解压到另一个路径,再对照校验和。也要确认是否有清单中没有的文件。
配置软件仓库
在 /root/airgap/unpacked/rpms 中创建元数据,并编写 /etc/yum.repos.d/airgap.repo。仓库 ID 为 airgap-local,name 中要有 snapshot 和日期,并且要包含 baseurl=file:///root/airgap/unpacked/rpms、enabled=1、gpgcheck=0、metadata_expire=-1。
创建元数据,再写 .repo 文件。由于是隔离网络,请调整过期设置。
仅用该软件仓库安装
在关闭其他所有软件仓库、只开启 airgap-local 的状态下重新安装 tree,并把输出保存到 /root/airgap/install.txt。
关闭其他所有软件仓库,只开启导入软件仓库,然后安装。
记录模块状态
留下状态记录。把模块列表保存到 /root/airgap/state-modules.txt,把用户安装列表保存到 /root/airgap/state-userinstalled.txt。
留下模块列表和用户安装列表。它们是导入记录的一部分。
导入报告
把 /root/airgap/report.txt 写成下面这 6 行。
BUNDLE_ID=airgap-<오늘 날짜 YYYY-MM-DD> / PACKAGES=<rpms 안 .rpm 개수> / MANIFEST_LINES=<매니페스트의 헤더 제외 줄 수> / VERIFY=OK / EXTRA=0 / INSTALLED_FROM=airgap-local(前三项的占位符依次为当天日期 YYYY-MM-DD、rpms 中 .rpm 的数量、清单中除表头之外的行数)
汇总导入包信息和验证结果。值必须是实际确认的结果。