それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

GNOMEログイン画面でユーザ一覧を消す

GNOMEのログインのユーザー名を消す。

ユーザー名一覧を消して、ユーザーを指定するようにする。

セキュリティ的な懸念からユーザ名は表示しないほうが絶対に良い。総当りの危険性が減るわけですし。

f:id:takuya_1st:20220109054249p:plain

方法1 lightdm を使う。

sudo apt install lightdm

まぁlightdmでデスクトップ・マネージャを買えちゃうのが一番楽だと思うんですけどね。それをしちゃうと、Xrdpが・・・

方法2 gnomeの設定を変える。

gnome 設定を書き換えて、ログインスクリーンの設定で、ユーザー名一覧を出さないようにする。

/etc/dconf/profile/gdm

gdm の設定を書いて、dconf のプロファイルを有効にします。

cat <<EOF  > tmp-gdm
user-db:user
system-db:gdm
file-db:/usr/share/gdm/greeter-dconf-defaults
EOF
sudo mv tmp-gdm /etc/dconf/profile/gdm

/etc/dconf/db/gdm.d/00-login-screen

ログイン・スクリーン(ログイン画面)の設定を追加する。 ここで、ユーザ一覧の表示を禁止します。

sudo mkdir -p  /etc/dconf/db/gdm.d
cat <<__EOF__ > tmp-login-screen
[org/gnome/login-screen]
# Do not show the user list
disable-user-list=true

__EOF__
sudo mv tmp-login-screen /etc/dconf/db/gdm.d/00-login-screen

update && refresh

dconf の設定を反映する。そして再起動して設定を読み込ませる。

sudo dconf update
sudo systemctl restart gdm

出来上がり

f:id:takuya_1st:20220109054249p:plain:w200

っていうか、なんでこの程度のことがデスクトップの設定からできないんだろう。。。

参考資料

https://help.gnome.org/admin/system-admin-guide/stable/login-userlist-disable.html.en

clevis initramfs でtpm を使ってルートの自動アンロックをやる

clevis が ubuntu で対応してた。

clevis ツールでdrucat を使わなくても initramfs で、起動時にLUKSのアンロックができるようになってたらしい。

これは便利ですね。

参考資料にしたブログがよく書いてくれてるので、とても簡単だった。

準備

  • /boot のバックアップ
  • tpm/2.0 デバイス
  • clevis-initramfs
  • 作業用のSSHアンロック
  • 作業用のserialポート

clevis が動作しないときに備えて、シリアル・ポートとSSHアンロックを最初に準備しておく。

実験環境を作る

いきなり、PCでやるとミスったときに initramfsを書き戻すのが手間なので、実験用に、Nested VMで、ホスト側でswtpm 有効化して、ゲスト側でtpm2 を使った仮想マシンを作成して実験をすることにする。

ttyS0 をgrub 起動でやる

以前やって試しておいた、grub でシリアル・コンソールを有効にする方法で、grub を有効にする。これでシリアルケーブルを繋いだraspiを挿しておけば、万が一のときリモートからアンロックができる。

bootのバックアップ

やかしたら面倒なので、バックアップをとっておく。

sudo tar cvzf boot.tgz /boot

luksのssh のアンロック

これも以前やって試しておいた。起動時にdm-cryptをSSHでリモートアンロックする方法で、clevis が動作しないときに、リモートから何とかできる経路を用意しておく。

clevis のインストール

clevis を使った initramfs と clevis のtpm2対応パッケージを入れておく

sudo apt install clevis clevis-tpm2 clevis-initramfs

アンロック対象の暗号ブロックデバイスの確認

アンロックの対象になる、ブロックデバイスの名前を確認しておく。

takuya@u0201:~$ lsblk
vda                         252:0    0   40G  0 disk
├─vda1                      252:1    0  512M  0 part  /boot/efi
├─vda2                      252:2    0    1G  0 part  /boot
└─vda3                      252:3    0 38.5G  0 part
  └─dm_crypt-0              253:0    0 38.5G  0 crypt
    └─ubuntu--vg-ubuntu--lv 253:1    0   20G  0 lvm   /

今回は、仮想マシンで行っているので /dev/vda が対象で、EFIブートなので対象パーティション/dev/vda3 になる。

PCR (Platform Configuration Registers) の確認

PCR を使って、TPMに登録してハッシュ値を計算した結果から、データ改竄をチェックするのに必要。ここではTPMバイスで使える暗号学的ハッシュ関数を確認しておく

takuya@u0201:~$ sudo tpm2_getcap pcrs
[sudo] password for takuya:
selected-pcrs:
  - sha1: [ ]
  - sha256: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 ]
  - sha384: [ ]
  - sha512: [ ]

sha256が使えるとわかる。

clevis に鍵設定する

clevis に鍵を設定する。ここではパスフレーズを使う。

takuya@u0201:~$ sudo clevis luks bind -d /dev/vda3 tpm2 '{"pcr_bank":"sha256","pcr_ids":"7"}'
Enter existing LUKS password:
## ちょっと時間かかる

登録されたかチェック

takuya@u0201:~$ sudo clevis luks list -d /dev/vda3
1: tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha256","pcr_ids":"7"}'

ここ出てくる 1 という番号は cryptsetyp luksDump /dev/vda3 で 確認できるキースロットの番号に対応している。

initramfs を更新する

sudo update-initramfs -u -k 'all'

再起動してチェック

takuya@u0201:~$ sudo reboot

initramfs に clevis が登録されたかチェック

lsinitramfs で initramfs の中身を見れる。

takuya@u0201:~$ sudo lsinitramfs /boot/initrd.img-$(uname -r) | grep clevis
scripts/local-bottom/clevis
scripts/local-top/clevis
usr/bin/clevis
usr/bin/clevis-decrypt
usr/bin/clevis-decrypt-sss
usr/bin/clevis-decrypt-tang
usr/bin/clevis-decrypt-tpm2
usr/bin/clevis-luks-common-functions
usr/bin/clevis-luks-list

削除

clevis 側の設定を削除する

sudo clevis luks unbind -d /dev/vda3 -s 1
The unbind operation will wipe a slot. This operation is unrecoverable.
Do you wish to erase LUKS slot 1 on /dev/vda3? [ynYN] y

tpm 側で削除する.tpmをまっさらにしたら全部消える。tpm側で削除しても clevis 側に残るので注意

sudo tpm2_clear

やってみた結果

めっちゃ手軽になってて感動した。

2022-01-07 追記

Debian/11 でも問題なく同じ手順で動くことを確認した。

luks の自動unlock が動いてたときのcryttab は本当に何もしてないシンプルな構成。これでdm-cryptとtpm2さえあれば安心ができますね。

takuya@d0201:~$ cat /etc/crypttab
vda3_crypt UUID=276f641e-c6cd-489b-8b5b-33e65c6405e6 none luks,discard

2022/01/07 追加

initramfs がだいぶサイズが大きくなるので、/boot が200MBでは容量不足になった。注意が必要。

takuya@:~$ sudo update-initramfs -u -k 'all'
update-initramfs: Generating /boot/initrd.img-5.10.0-10-amd64
setupcon: The keyboard model is unknown, assuming 'pc105'. Keyboard may be configured incorrectly.
pigz: abort: write error on <stdout> (No space left on device)
E: mkinitramfs failure pigz 28
update-initramfs: failed for /boot/initrd.img-5.10.0-10-amd64 with 1.

2022-01-09 追記

最終的に出来上がった initrd は 75Mになった。ブート時に使うには、相当でかいパッケージです。

takuya@:~$ ll -lh /boot/initrd.img-5.10.0-10-amd64
-rw------- 1 root root 75M  1月  9 01:47 /boot/initrd.img-5.10.0-10-amd64

/boot に最低2つのinitradのブートイメージが用意される。万が一のためにカレントと1世代前のinitrdが2つ用意される。これで、75MB✕2=150MBが消費される。

更新時は、新しくinitrdを作って、mvで旧来のファイルを置き換えるので、 +75MBが追加で必要。

さらに、update-initramfs -c -k all したときには、1世代前のinitradも再構成されるので、+75Mが必要

つまり、clevis化した/bootには、最低でも4つにカーネルが入るだけの容量が必要で、最低でも 300Mが必要になる。

古いカーネルなど複数バージョンのカーネルを持ってる場合はもっと必要になるかもしれません。

なので、 /bootには1GBくらい割り当てないと詰むと思います。

今回、私は見事に、ここで容量不足で詰んでしまいました。luks化された領域ディスク内で開始セクタを簡単に動かせないので、バックアップをとってSSDをまっさらにして/boot を1GB確保する羽目になり、時間が思い切り溶けました。

でも、これでTPM化されて安心です。

参考資料

QEMUがtpm サポートしてたので nested vm で tpm デバイスを実験する

TPMバイス仮想マシンに追加しようとすると・・・

libvirtd の virt-managerTPMに対応してたので、それを追加しようとしたら、エラーになる。

f:id:takuya_1st:20220106161535p:plain

パススルー or swtpm

仮想ホスト側にあるTPMをパススルーでゲスト仮想マシンに渡すか、swtpm でエミュレートしたものを仮想マシンtpmに見せかける事ができるようです。

仮想ホスト側に swtpm が必要

swtpm つまり、ソフトウェアでモックされたTPMが必要になるってことですね。

構成について

ホスト側に、何らかの形でTPMバイスを作る必要がある。 f:id:takuya_1st:20220106163535p:plain

実は、この仮想マシンのホストは、物理マシンではなく、仮想マシンである。仮想マシン上に仮想マシンを構成した nested vm にしてある。

その理由は、ubuntu/debian だと swtpm が apt に存在しないのと、swtpm 関連は不具合を引き起こすと公式サイトに記載があったためである。

そのため、nested vm にしてswtpm を構成している。

ホスト側にswtpm を作成する

debian/ubuntu の場合は相当めんどくさい。そのうちにapt で入るようになるんだろうけど、現在(2022-01-06)は 公式パッケージが存在しない。

libtpm / swtpm をインストール

libtpm をインストール

git clone https://github.com/stefanberger/libtpms
cd libtpms/
sudo apt-get -y install automake autoconf libtool gcc build-essential libssl-dev dh-exec pkg-config gawk
./autogen.sh --with-openssl
sudo make dist
mv debian/source debian/source.old
dpkg-buildpackage -us -uc -j4
cd ..
sudo dpkg -i libtpm*.deb

swtpm をインストール

cd 
git clone https://github.com/stefanberger/swtpm.git
cd swtpm
sudo apt-get -y install dpkg-dev debhelper libssl-dev libtool net-tools libfuse-dev libglib2.0-dev libgmp-dev expect libtasn1-dev socat python3-twisted gnutls-dev gnutls-bin  libjson-glib-dev python3-setuptools softhsm2 libseccomp-dev gawk libtpms-dev
dpkg-buildpackage -us -uc -j$(nproc)
cd ..
sudo dpkg -i swtpm*.deb

インストールの確認

takuya@u02:~$ type swtpm
swtpm is /usr/bin/swtpm

swtpm が追加される。

tpmバイスを追加する。

kvm+qemu+virt-manager

ホスト側にtpmができたので、それを仮想マシンに追加してやる

f:id:takuya_1st:20220106161305p:plain

tpmバイスが追加されたことを確認

仮想マシンをインストールして、起動して、tpm が生えたことを確認する。 f:id:takuya_1st:20220106161350p:plain

takuya@u0201:~$ dmesg | grep -i tpm
[    0.000000] efi:  SMBIOS=0x7ebd8000  TPMFinalLog=0x7db10000  ACPI=0x7ebfa000  ACPI 2.0=0x7ebfa014  MEMATTR=0x7df45018  MOKvar=0x7df47000  TPMEventLog=0x7d085018
[    0.012720] ACPI: TPM2 0x000000007D9EE000 00004C (v04 BOCHS  BXPCTPM2 00000001 BXPC 00000001)
[    0.012731] ACPI: Reserving TPM2 table memory at [mem 0x7d9ee000-0x7d9ee04b]
[    1.874567] tpm_tis MSFT0101:00: 2.0 TPM (device-id 0x1, rev-id 1)
takuya@u0201:~$ cat /proc/keys
249913f0 I--Q---     1 perm 1f3f0000  1000 65534 keyring   _uid_ses.1000: 1
343a1bb4 I--Q---     3 perm 1f3f0000  1000 65534 keyring   _uid.1000: empty
3ac179bd I--Q---     7 perm 3f030000  1000  1000 keyring   _ses: 1

使ってみる

sudo apt install tpm2-tools
takuya@u0201:~$ sudo tpm2_getcap pcrs
[sudo] password for takuya:
selected-pcrs:
  - sha1: [ ]
  - sha256: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 ]
  - sha384: [ ]
  - sha512: [ ]

動作チェック / sha256 でハッシュHEXを作ってみる。

takuya@u0201:~$ echo $(echo hello | sudo tpm2_hash --hash-algorithm=sha256 --hex )
5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03
takuya@u0201:~$ echo $(echo hello | sha256sum )
5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03 -

ふむ、ちゃんと動いてるようだ。

参考資料