1. 記事一覧 >
  2. ブログ記事
category logo

【CentOS8.3+snapd】ソースコードからrpmをビルド&SELinuxを調整でsnapdをインストール

(更新) (公開)

はじめに

2023 年 11 月の CentOS Linux release 8.3.2011 の状況を元に説明しています。OS のバージョンや時期により、状況が同じではない可能性があります。

当ブログの少し前の記事「CentOS8 に wekan をインストール(snap 編)」について、

# sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
# dnf install epel-release
# dnf -y upgrade
# dnf install -y snapd

で snapd をインストールしていますが、エラーになって、インストールできなくなっていることが分かりました。

# sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*

は当時無かった手順ですが、必要になりました。

【エラー状況】

# dnf install -y snapd
CentOS Linux 8 - AppStream                        26 kB/s | 4.3 kB     00:00
CentOS Linux 8 - BaseOS                           26 kB/s | 3.9 kB     00:00
CentOS Linux 8 - ContinuousRelease                22 kB/s | 3.0 kB     00:00
CentOS Linux 8 - Extras                           13 kB/s | 1.5 kB     00:00
Extra Packages for Enterprise Linux 8 - x86_64    8.6 kB/s | 5.6 kB     00:00
Extra Packages for Enterprise Linux 8 - x86_64    9.4 MB/s |  16 MB     00:01
Error:
 Problem: package snapd-2.58.3-1.el8.x86_64 requires snapd-selinux = 2.58.3-1.el8, but none of the providers can be installed
  - conflicting requests
  - nothing provides selinux-policy >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch
  - nothing provides selinux-policy-base >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch
(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)

NGだった手順(ページ内リンク) のように
nothing provides selinux-policy >= 3.14.3-108.el8_7.1
の呪縛から抜けられず、悶絶し、
インストールできたと思ったら、SELinux のせいで起動確認できず、
最終的には、ソースコードをビルドして、rpm を作成し、SELinux を調整することにより、snapd のインストールが完了しました。

rpm 作成ではなく、普通に make && make install でもインストール可能かもしれませんが、そちらは検証していません。


snapd インストール

全て root 権限で実行しています。そのため、sudo は省略しています。

別記事「CentOS-8.3.2011-x86_64 を VMware-workstation-16.1.1 にインストール

で OS インストールし終わった直後からの手順です。Snapインストールに必要のないことは実施しません。


epel-release リポジトリを追加して、パッケージを更新します。

# sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
# dnf install epel-release
# dnf -y upgrade

GitHub のリリースから snapd_2.53.4 の only-vendor と no-vendor をダウンロードします。

# cd ~
# curl -LO https://github.com/snapcore/snapd/releases/download/2.53.4/snapd_2.53.4.only-vendor.tar.xz
# curl -LO https://github.com/snapcore/snapd/releases/download/2.53.4/snapd_2.53.4.no-vendor.tar.xz

【no-vendor】

snapd の主要なソースコードのみが含まれており、外部の依存関係(通常は Go のライブラリやモジュールとして提供される)は含まれていません。

開発者やパッケージャーは、このアーカイブを使用して snapd をビルドする場合、必要な依存関係を別途取得する必要があります。

【only-vendor】

snapd が依存している外部のライブラリやモジュールのみが含まれています。

no-vendor のアーカイブと一緒に使用されます。


git と spectool をインストールします。

# dnf -y install git spectool

【spectool】

rpmbuild でビルド時に SPEC ファイル(ビルド時に必要な定義ファイル)からソースとパッチを展開してダウンロードするツールです。

※ソースコードを手動でダウンロードし、適切な場所に配置した場合、spectool なしで rpmbuild を実行することが可能です。


glibc-static をインストールします。

# dnf --enablerepo=powertools install glibc-static -y

【glibc-static】

C 言語プログラムのコンパイルに必要です。

【--enablerepo=powertools】

powertools リポジトリが一時的に有効化され、そのリポジトリ内のパッケージが利用可能になります。

powertools リポジトリは、開発者向けの追加パッケージを提供するためのリポジトリのためデフォルトでは無効になっています。


go-compilers-golang-compiler をインストールします。

# dnf --enablerepo=powertools install go-compilers-golang-compiler -y

【go-compilers-golang-compiler】

go 言語のコンパイルに必要です。


no-vendor を展開して、依存関係をインストールします。

# mkdir -p ~/rpmbuild/SOURCES/
# cd ~/rpmbuild/SOURCES/
# mv ~/snapd_*.tar.xz .
# ls
snapd_2.53.4.no-vendor.tar.xz  snapd_2.53.4.only-vendor.tar.xz
# xz -dc snapd_2.53.4.no-vendor.tar.xz | tar xfv -
# dnf builddep ./snapd-2.53.4/packaging/fedora/snapd.spec -y

【dnf builddep】

指定された SPEC ファイル(この場合は ./snapd-2.53.4/packaging/fedora/snapd.spec)に記述されたソフトウェアのビルドに必要なすべての依存関係を解決し、それらをインストールするためのコマンドです。


RPM パッケージを生成します。

# rpmbuild -bb ./snapd-2.53.4/packaging/fedora/snapd.spec
# cd ~/rpmbuild/RPMS/
# ls
noarch  x86_64

【rpmbuild -bb】

rpmbuild -bb コマンドを使用すると、指定した SPEC ファイルに基づいてバイナリ RPM パッケージが生成されます。

SPEC ファイル内に記述された%prep、%build、そして%install ステージを実行した後に、バイナリパッケージをビルドします。


ビルドされたものをそれぞれインストールします。(snap-confine、snapd-selinux は必須です。)

# dnf -y localinstall ./x86_64/snap-confine-2.53.4-0.el8.x86_64.rpm
# dnf -y localinstall ./noarch/snapd-selinux-2.53.4-0.el8.noarch.rpm
# dnf -y localinstall ./x86_64/snapd-2.53.4-0.el8.x86_64.rpm

【snap-confine】

snap-confine は snap アプリケーションの実行環境を構築するために snapd によって内部的に使用されるプログラムです。

特定の Snap インスタンスのために新しいマウント名前空間を作成するか、既存のマウント名前空間に参加することを試みます。

これにより、異なる Snap アプリケーションやバージョン間でのマウント名前空間の隔離が実現されます。

【マウント名前空間】

snap-confine が作成または参加する「マウント名前空間」は、Linux カーネルの機能の一部で、プロセスが見るファイルシステムのビューを制御します。

これにより、異なる Snap アプリケーションやバージョン間でのマウント名前空間の隔離が実現されます。

つまり、一つの Snap アプリケーションが見るファイルシステムは、他の Snap アプリケーションからは見えないようにすることができます。

【snapd-selinux】

SELinux が有効になっている環境で snapd が正しく動作するために必要な SELinux ポリシーモジュールを提供します。

※この後 SELinux の対処手順を紹介しますが、今回、これが不十分だった可能性があります。


snapd 自動起動を有効にし、今すぐ起動します。

# systemctl enable --now snapd.socket

classic snap サポートを有効化します。

# ln -s /var/lib/snapd/snap /snap

【classic snap サポート】

Snap アプリケーションがシステムのリソースにアクセスする方法を制御する機能です。

システムレベルの設定を変更するソフトウェア、ハードウェアデバイスにアクセスするソフトウェア等に必要です。

CentOS8 に wekan をインストール(snap 編)」について、classic snap サポートを有効化しなくても wekan 起動、アカウント登録、ログインまで可能でした。


SELinux 対処

# systemctl status snapd で正常に起動しているのが確認できるのですが、
# snap list⇒ インストールされているソフト確認
# snap install hello-world⇒ テスト用に hello-world インストール
が反応しませんでした。

# snap list
error: cannot list snaps: cannot communicate with server: timeout exceeded while waiting for response
# snap install hello-world
error: cannot communicate with server: timeout exceeded while waiting for response

/var/log/audit/audit.log に以下のエラーが出力されていました。

type=USER_AVC msg=audit(1698469714.184:195): pid=1026 uid=81 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc:  denied  { send_msg } for msgtype=method_call interface=org.freedesktop.DBus.Properties member=Get dest=org.freedesktop.timedate1 spid=2827 tpid=2871 scontext=system_u:system_r:snappy_t:s0 tcontext=system_u:system_r:timedatex_t:s0 tclass=dbus permissive=1  exe="/usr/bin/dbus-daemon" sauid=81 hostname=? addr=? terminal=?'
type=USER_AVC msg=audit(1698469714.186:197): pid=1026 uid=81 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc:  denied  { send_msg } for msgtype=method_return dest=:1.280 spid=2871 tpid=2827 scontext=system_u:system_r:timedatex_t:s0 tcontext=system_u:system_r:snappy_t:s0 tclass=dbus permissive=0  exe="/usr/bin/dbus-daemon" sauid=81 hostname=? addr=? terminal=?'

対処方法1

type=USER_AVC msg=audit(1698469714.186:197): pid=1026 uid=81 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc: denied { send_msg } for msgtype=method_return dest=:1.280 spid=2871 tpid=2827 scontext=system_u:system_r:timedatex_t:s0 tcontext=system_u:system_r:snappy_t:s0 tclass=dbus permissive=0 exe="/usr/bin/dbus-daemon" sauid=81 hostname=? addr=? terminal=?'

に注目します。 この出力は、system_u:system_r:timedatex_t:s0 ドメイン(ソースコンテキスト)のプロセスが、system_u:system_r:snappy_t:s0 ドメイン(ターゲットコンテキスト)のリソースに対して send_msg(送信メッセージ)という操作を試みたときに、SELinux がその操作を拒否したことを示しています。

拒否されたアクセスを許可する Type Enforcement ルールを表示します。

# audit2allow -a


#============= groupadd_t ==============

#!!!! This avc is allowed in the current policy
allow groupadd_t proc_t:filesystem getattr;

#============= setroubleshootd_t ==============

#!!!! This avc is allowed in the current policy
allow setroubleshootd_t proc_t:filesystem getattr;

#============= snappy_t ==============
allow snappy_t timedatex_t:dbus send_msg;

#============= timedatex_t ==============
allow timedatex_t snappy_t:dbus send_msg;

groupadd_t,setroubleshootd_t は別の内容部分を拾ってきて、現在のポリシーでは許可されています。


snappy_t、timedatex_t ドメインの対処が必要なのが分かります。 これを許可すべく、カスタムポリシーパッケージを作成します。

# vi my_custom_policy.te
module my_custom_policy 1.0.0;

require {
        type snappy_t;
        type timedatex_t;
        class dbus send_msg;
}

allow snappy_t timedatex_t:dbus send_msg;
allow timedatex_t snappy_t:dbus send_msg;

モジュールのコンパイルを行います。

# checkmodule -M -m -o my_custom_policy.mod my_custom_policy.te

ポリシーパッケージの作成を行います。

# semodule_package -o my_custom_policy.pp -m my_custom_policy.mod

カーネルへのモジュール読み込みを行います。

# semodule -i my_custom_policy.pp

再び、Type Enforcement ルールを表示します。

# audit2allow -a


#============= groupadd_t ==============

#!!!! This avc is allowed in the current policy
allow groupadd_t proc_t:filesystem getattr;

#============= setroubleshootd_t ==============

#!!!! This avc is allowed in the current policy
allow setroubleshootd_t proc_t:filesystem getattr;

#============= snappy_t ==============

#!!!! This avc is allowed in the current policy
allow snappy_t timedatex_t:dbus send_msg;

#============= timedatex_t ==============

#!!!! This avc is allowed in the current policy
allow timedatex_t snappy_t:dbus send_msg;

よさそうです。


この後、何事も無かったかのように機能します。

# snap version
snap    2.53.4-0.el8
snapd   2.53.4-0.el8
series  16
centos  8
kernel  4.18.0-348.7.1.el8_5.x86_64
# snap list
No snaps are installed yet. Try 'snap install hello-world'.
# snap install hello-world
# hello-world
Hello World!

対処方法2

この方法を選択した場合は、対処方法1不要です。

対処方法1で、snappy_t と timedatex_t ドメイン関連のときは、ログに出力して、スルーすれば良いことが分かります。

# semanage permissive -a snappy_t
# semanage permissive -a timedatex_t

でその状態が作れます。

【semanage permissive -a】

SELinux のポリシーのパーミッシブモジュールを追加します。

指定したドメインをパーミッシブ(制限なし/audit.log には出力)に設定し、そのドメインに対する SELinux の制限が解除されます。

semanage permissive -lで確認できて、

semanage permissive -dで削除できます。

操作内容を限定していないため、対処方法1より緩いと思われます。セキュリティリスクを十分に理解して実施が必要です。


確認します。

# semanage permissive -l

Builtin Permissive Types

snappy_confine_t
snappy_unconfined_snap_t
snappy_cli_t
snappy_mount_t

Customized Permissive Types

snappy_t
timedatex_t

Customized Permissive Types に snappy_t と timedatex_t が追加されているのが分かります。 この後、何事も無かったかのように機能します。

# snap version
snap    2.53.4-0.el8
snapd   2.53.4-0.el8
series  16
centos  8
kernel  4.18.0-348.7.1.el8_5.x86_64
# snap list
No snaps are installed yet. Try 'snap install hello-world'.
# snap install hello-world
# hello-world
Hello World!

まとめ

必須ではない ln -s /var/lib/snapd/snap /snap ありで、SELinuxの対象方法2でまとめると、以下です。

# sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
# dnf install epel-release
# dnf -y upgrade
# cd ~
# curl -LO https://github.com/snapcore/snapd/releases/download/2.53.4/snapd_2.53.4.only-vendor.tar.xz
# curl -LO https://github.com/snapcore/snapd/releases/download/2.53.4/snapd_2.53.4.no-vendor.tar.xz
# dnf -y install git spectool
# dnf --enablerepo=powertools install glibc-static -y
# dnf --enablerepo=powertools install go-compilers-golang-compiler -y
# mkdir -p ~/rpmbuild/SOURCES/
# cd ~/rpmbuild/SOURCES/
# mv ~/snapd_*.tar.xz .
# ls
snapd_2.53.4.no-vendor.tar.xz  snapd_2.53.4.only-vendor.tar.xz
# xz -dc snapd_2.53.4.no-vendor.tar.xz | tar xfv -
# dnf builddep ./snapd-2.53.4/packaging/fedora/snapd.spec -y
# rpmbuild -bb ./snapd-2.53.4/packaging/fedora/snapd.spec
# cd ~/rpmbuild/RPMS/
# ls
noarch  x86_64
# dnf -y localinstall ./x86_64/snap-confine-2.53.4-0.el8.x86_64.rpm
# dnf -y localinstall ./noarch/snapd-selinux-2.53.4-0.el8.noarch.rpm
# dnf -y localinstall ./x86_64/snapd-2.53.4-0.el8.x86_64.rpm
# systemctl enable --now snapd.socket
# ln -s /var/lib/snapd/snap /snap
# semanage permissive -a snappy_t
# semanage permissive -a timedatex_t
# semanage permissive -l

Builtin Permissive Types

snappy_confine_t
snappy_unconfined_snap_t
snappy_cli_t
snappy_mount_t

Customized Permissive Types

snappy_t
timedatex_t
# snap version
snap    2.53.4-0.el8
snapd   2.53.4-0.el8
series  16
centos  8
kernel  4.18.0-348.7.1.el8_5.x86_64
# snap list
No snaps are installed yet. Try 'snap install hello-world'.
# snap install hello-world
# hello-world
Hello World!

NGだった手順

# sed -i -e 's/^mirrorlist/#mirrorlist/g' -e 's/^#baseurl=http:\/\/mirror/baseurl=http:\/\/vault/g' /etc/yum.repos.d/CentOS-*repo
# dnf install epel-release
# dnf -y upgrade

実施直後からとします。


skip-broken install snapd

インストールされたように見えて、インストールされていませんでした。

# dnf -y --skip-broken install snapd
Complete!
# snap list
bash: snap: command not found...
Install package 'snapd' to provide command 'snap'? [N/y]
 * Waiting in queue...
 * Loading list of packages.... Failed to install packages: Could not depsolve transaction; 1 problem detected:
 Problem: package snapd-2.58.3-1.el8.x86_64 requires snapd-selinux = 2.58.3-1.el8, but none of the providers can be installed
  - conflicting requests
  - nothing provides selinux-policy >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch
  - nothing provides selinux-policy-base >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch

install snapd-selinux

snapd-selinux 単体もインストールできませんでした。

# dnf -y install snapd-selinux
Error:
 Problem: conflicting requests
  - nothing provides selinux-policy >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch
  - nothing provides selinux-policy-base >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch
(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)
# dnf makecache --refresh
# dnf -y install snapd-selinux
Error:
 Problem: conflicting requests
  - nothing provides selinux-policy >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch
  - nothing provides selinux-policy-base >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch
(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)

rpm -i --force

https://stackoverflow.com/questions/74960690/try-to-install-snapd-but-giving-conflicting-requests-error を参考に、yumrpm -i --force しました。

stackoverflow に投稿されている内容は、一部 Not Found になっていたため、一部変更しています。

それぞれの意味は調べていません。

# wget https://rpmfind.net/linux/centos/8-stream/BaseOS/x86_64/os/Packages/rpm-4.14.3-19.el8.x86_64.rpm
# wget https://rpmfind.net/linux/centos/8-stream/BaseOS/x86_64/os/Packages/rpm-libs-4.14.3-19.el8.x86_64.rpm
# wget http://mirror.centos.org/centos/8-stream/BaseOS/x86_64/os/Packages/selinux-policy-3.14.3-108.el8.noarch.rpm
# yum install http://mirror.centos.org/centos/8-stream/BaseOS/x86_64/os/Packages/libsemanage-2.9-9.el8.x86_64.rpm --allowerasing -y
# yum install http://mirror.centos.org/centos/8-stream/BaseOS/x86_64/os/Packages/policycoreutils-2.9-19.el8.x86_64.rpm -y
# rpm -i --force rpm-4.14.3-19.el8.x86_64.rpm
# rpm -i --force rpm-libs-4.14.3-19.el8.x86_64.rpm
# rpm -i --force selinux-policy-3.14.3-108.el8.noarch.rpm
# yum install http://mirror.centos.org/centos/8-stream/BaseOS/x86_64/os/Packages/python3-libsemanage-2.9-9.el8.x86_64.rpm -y
# yum install http://mirror.centos.org/centos/8-stream/BaseOS/x86_64/os/Packages/python3-policycoreutils-2.9-19.el8.noarch.rpm -y
# yum install http://mirror.centos.org/centos/8-stream/BaseOS/x86_64/os/Packages/policycoreutils-python-utils-2.9-19.el8.noarch.rpm -y
# yum install http://mirror.centos.org/centos/8-stream/BaseOS/x86_64/os/Packages/selinux-policy-minimum-3.14.3-108.el8.noarch.rpm -y
# yum install http://mirror.centos.org/centos/8-stream/BaseOS/x86_64/os/Packages/libseccomp-2.5.2-1.el8.x86_64.rpm -y
# yum install https://download-ib01.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/s/snapd-selinux-2.58.3-1.el8.noarch.rpm -y
snapd-selinux-2.58.3-1.el8.noarch.rpm                                    257 kB/s | 553 kB     00:02
Error:
 Problem: conflicting requests
  - nothing provides selinux-policy >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch
  - nothing provides selinux-policy-base >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch
(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)

途中までいけるかと思いましたが、おなじみのエラーになりました。


--skip-broken --nobest で先に進めます。

# dnf install --skip-broken --nobest https://download-ib01.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/s/snapd-selinux-2.58.3-1.el8.noarch.rpm -y
Complete!
# yum install snapd -y
Error:
 Problem: package snapd-2.58.3-1.el8.x86_64 requires snapd-selinux = 2.58.3-1.el8, but none of the providers can be installed
  - conflicting requests
  - nothing provides selinux-policy >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch
  - nothing provides selinux-policy-base >= 3.14.3-108.el8_7.1 needed by snapd-selinux-2.58.3-1.el8.noarch
(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)

ダメでした。


以上!

loading...