カスタム UEFI 安全ブート キーを使用して Linux AMI を作成する
このステップでは、UEFI 安全ブート およびカスタムメイドのプライベートキーを使用して Linux AMI を作成する方法を示します。Amazon Linux は、AL2023 リリース 2023.1 から UEFI セキュアブートをサポートしています。詳細については、「AL2023 ユーザーガイド」の「UEFI 安全ブート」を参照してください。
重要
次の手順は、上級ユーザーのみを対象としています。これらの手順を使用するには、SSL および Linux ディストリビューションのブートフローに関する十分な知識が必要です。
前提条件
-
以下のツールを使用します。
-
OpenSSL – https://www.openssl.org/
-
efivar – https://github.com/rhboot/efivar
-
efitools – https://git.kernel.org/pub/scm/linux/kernel/git/jejb/efitools.git/
-
-
Linux インスタンスは、UEFI ブートモードをサポートする Linux AMI で起動され、不揮発性データを使用している必要があります。
UEFI 安全ブート キーを使用せずに新規で作成されたインスタンスには、SetupMode
が適用されます。この状態で、独自のキーを登録することが可能です。一部の AMI では UEFI 安全ブート が事前設定されており、既定のキーを変更することはできません。AMI のキーを変更する場合は、その AMI をベースに、新らたな AMI を作成する必要があります。
変数ストア内のキーを伝達するには 2 つの方法があり、それぞれを、以下の オプション A とオプション B の中で説明します。オプション A では、実際のハードウェアのフローを模倣することで、インスタンス内からこれを行う方法について説明します。オプション B では、AMI の作成時に base64 でエンコードされたファイルとして渡される、バイナリ BLOB を作成する方法について説明します。どちらのオプションでも、最初に、信頼チェーンに使用するためのキーペアを 3 つ作成する必要があります。
UEFI 安全ブート をサポートする Linux AMI を作成するには、まず 3 つのキーペアを作成し、オプション A またはオプション B のいずれかを実行します。両方は実行しません。
UEFI 安全ブート は、プラットフォームキー (PK)、キー交換キー (KEK)、署名データベース (db) という 3 つのキーデータベースに基づいおり、これらのデータベースは信頼チェーンで使用されます。
インスタンスでは、これらの各キーを作成する必要があります。UEFI 安全ブート 標準が有効な形式でパブリックキーの準備を行うには、それぞれのキー用に証明書を作成します。DER
では SSL 形式 (バイナリエンコード用の形式) を定義しています。その後、各証明書を UEFI 署名リストに変換します。このリストはバイナリ形式で、UEFI 安全ブート による解析が可能です。最後に、関連するキーで各証明書に署名します。
トピック
キーペアの作成を準備するには
キーペアを作成する前に、キー生成処理で使用するための、グローバルで一意の識別子 (GUID) を作成します。
-
シェルプロンプトで、次のコマンドを実行します。
uuidgen --random > GUID.txt
キーペア 1: プラットフォームキー (PK) を作成します。
PK は UEFI 安全ブート インスタンスの信頼のルートです。プライベート PK は KEK を更新するために使用されます。このキーはその後、認証されたキーを署名データベース (db) に追加するためにも使用されます。
キーペアの作成には、X.509 標準が適用されます。標準の詳細については、ウィキペディアで「X.509
PK を作成するには
-
キーを作成します。変数
PK
に名前を付ける必要がありますopenssl req -newkey rsa:4096 -nodes -keyout PK.key -new -x509 -sha256 -days 3650 -subj "/CN=
Platform key
/" -out PK.crt以下の各パラメータが指定されます。
-
-keyout PK.key
– プライベートキーファイル。 -
-days 3650
– 証明書が有効な日数。 -
-out PK.crt
– UEFI 変数の作成に使用される証明書。 -
CN=
– キーの共通名 (CN)。ここでは、Platform key
プラットフォームキー
の代わりに組織の独自の名前を入力できます。
-
-
証明書を作成します。
openssl x509 -outform DER -in PK.crt -out PK.cer
-
証明書を UEFI 署名リストに変換します。
cert-to-efi-sig-list -g "$(< GUID.txt)" PK.crt PK.esl
-
UEFI 署名リストに (自己署名の) プライベート PKで署名します。
sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt PK PK.esl PK.auth
キーペア 2: キー交換キー (KEK) を作成します
プライベート KEK は db にキーを追加するために使用されます。このデータベースは、システム上で起動が許可された署名のリストです。
KEK を作成するには
-
キーを作成します。
openssl req -newkey rsa:4096 -nodes -keyout KEK.key -new -x509 -sha256 -days 3650 -subj "/CN=Key Exchange Key/" -out KEK.crt
-
証明書を作成します。
openssl x509 -outform DER -in KEK.crt -out KEK.cer
-
証明書を UEFI 署名リストに変換します。
cert-to-efi-sig-list -g "$(< GUID.txt)" KEK.crt KEK.esl
-
プライベート PK で署名リストに署名します。
sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt KEK KEK.esl KEK.auth
キーペア 3: 署名データベース (db) を作成します
db リストには、システム上で起動することが認証されているキーが記載されています。このリストを変更する場合は、プライベート KEK が必要です。ブートイメージは、このステップで作成したプライベートキーで署名されます。
db を作成するには
-
キーを作成します。
openssl req -newkey rsa:4096 -nodes -keyout db.key -new -x509 -sha256 -days 3650 -subj "/CN=Signature Database key/" -out db.crt
-
証明書を作成します。
openssl x509 -outform DER -in db.crt -out db.cer
-
証明書を UEFI 署名リストに変換します。
cert-to-efi-sig-list -g "$(< GUID.txt)" db.crt db.esl
-
プライベート KEK を使用して署名リストに署名します。
sign-efi-sig-list -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db db.esl db.auth
ブートイメージ (カーネル) にプライベートキーで署名する
Ubuntu 22.04 の場合、以下のイメージに署名が必要です。
/boot/efi/EFI/ubuntu/shimx64.efi
/boot/efi/EFI/ubuntu/mmx64.efi
/boot/efi/EFI/ubuntu/grubx64.efi
/boot/vmlinuz
イメージに署名するには
イメージに署名するには、以下の構文を使用します。
sbsign --key db.key --cert db.crt --output
/boot/vmlinuz
/boot/vmlinuz
注記
署名は、すべての新しいカーネルに対して行う必要があります。通常、
は、最近インストールしたカーネルへのシンボリックリンクとなります。/boot/vmlinuz
ブートチェーンおよび必要なイメージは、ディストリビューションのドキュメントで確認してください。
¹ ArchWiki コミュニティの皆さんから提供された、すべての作業に感謝します。PK の作成、KEK の作成、DB の作成、およびイメージへの署名のためのコマンドは、Creating keys
3 つのキーペアの作成が完了すると、以下のステップにより、インスタンスに接続し、インスタンス内から変数ストアにキーを追加できるようになります。
オプション A のステップ:
ステップ 1: UEFI 安全ブート をサポートするインスタンスを起動する
次の前提条件の下でインスタンスを起動することで、UEFI 安全ブート をサポートするようにインスタンスを構成する準備が整います。インスタンスでの UEFI 安全ブート のサポートは、起動時にみ有効化が可能で、その後に有効にすることはできません。
前提条件
-
AMI - Linux AMI では、UEFI ブートモードをサポートする必要があります。AMI が UEFI ブートモードをサポートしていることを確認するには、AMI ブートモードパラメータで uefi を指定する必要があります。詳細については、「Amazon EC2 AMI のブートモードパラメータを確認する」を参照してください。
AWS では、重力子 ベースのインスタンスタイプ向けに UEFI をサポートするように構成された Linux AMI のみを提供します。AWS では、UEFI ブートモードをサポートする x86_64 Linux AMI を提供していません。すべてのアーキテクチャで UEFI ブートモードをサポートするように独自の AMI を構成できます。UEFI ブートモードをサポートするように AMI を設定するには、独自の AMI に対して、複数の設定ステップを実行する必要があります。詳細については、「Amazon EC2 AMI のブートモードを設定する」を参照してください。
-
インスタンスタイプ — UEFI をサポートするすべての仮想インスタンスタイプは、UEFI 安全ブート もサポートします。ベアメタルインスタンスタイプは UEFI 安全ブート をサポートしていません。UEFI 安全ブート をサポートするインスタンスタイプについては、UEFI ブートモードの要件 を参照してください。
-
UEFI 安全ブート の立ち上げ後に、インスタンスの起動を行います。UEFI 安全ブート のサポートが可能なのは、2022 年 5 月 10 日 (UEFI 安全ブート リリース日) より後に起動されたインスタンスのみです。
インスタンスを起動したら、UEFI データが存在するかどうかを調べ、UEFI 安全ブート のサポートを設定できる状態であることを確認します (ステップ 2 に進みます)。UEFI データが見つかれば、不揮発性データが保持されていることになります。
インスタンスがステップ 2 に進める状態かどうかを確認するには
get-instance-uefi-data
aws ec2 get-instance-uefi-data --instance-id
i-0123456789example
出力に UEFI データが含まれていれば、そのインスタンスはステップ 2 に進める状態です。空の出力が表示される場合、そのインスタンスで UEFI 安全ブート をサポートする設定は行えません。この状態は、UEFI 安全ブート サポートが利用可能になる前に起動されたインスタンスで発生します。この場合、新しいインスタンスを起動して再試行します。
ステップ 2: UEFI 安全ブート をサポートするようにインスタンスを設定する
インスタンスの UEFI 変数ストアにキーペアを登録します。
警告
ブートイメージへの署名は、キーの登録後に行う必要があります。そうしないと、インスタンスを起動できなくなります。
署名済みの UEFI 署名リスト (PK
、KEK
、および db
) は、作成後に UEFI ファームウェアに登録する必要があります。
PK
変数に対する書き込みは、以下の場合にのみ行うことができます。
-
SetupMode
変数が1
の場合、PKはまだ登録されていない。これは、次のコマンドを使用して確認します。1
または0
のどちらかが出力されている。efivar -d -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-SetupMode
-
新しい PK が、既存の PK のプライベートキーによって署名されている。
UEFI 変数ストアにキーを登録するには
インスタンスで以下のコマンドを実行する必要があります。
SetupMode が有効 (値が 1
) になっていれば、インスタンスで以下のコマンドを実行することでキーを登録できます。
[ec2-user ~]$
efi-updatevar -f db.auth db
[ec2-user ~]$
efi-updatevar -f KEK.auth KEK
[ec2-user ~]$
efi-updatevar -f PK.auth PK
UEFI 安全ブート が有効になっていることを確認するには
UEFI 安全ブート が有効であることを確認するには、「Amazon EC2 インスタンスで UEFI 安全ブート が有効化されているかどうかを確認する」に示したステップに従います。
この段階で、get-instance-uefi-data
ステップ 3: インスタンスから AMI を作成する
インスタンスから AMI を作成するには、コンソールまたは CreateImage
API、CLI、または SDK を使用します。コンソールでのステップについては、「アマゾン EBS-バック AMI を作成する」を参照してください。API でのステップについては、「CreateImage」を参照してください。
注記
CreateImage
API は、インスタンスの UEFI 変数ストアを AMI に自動的にコピーします。コンソールは CreateImage
API を使用します。この AMI を使用してインスタンスを起動した場合、インスタンスにも AMI と同じ UEFI 変数ストアが含まれます。
3 つのキーペアの作成後、事前に値が設定され UEFI 安全ブート キーが指定された変数ストアを含む、バイナリ BLOB を作成できます。
警告
ブートイメージには、キーを登録する前に署名を行う必要があります。そうしないと、インスタンスを起動できなくなります。
ステップ 1: 変数ストアを新規で作成するか既存の変数ストアを更新する
python-uefivars ツールを使用すると、インスタンスを実行せずに変数ストアをオフラインで作成できます。このツールでは、キーから新しい変数ストアを作成できます。現在、このスクリプトでは、EDK2 形式、AWS 形式、および上位レベルのツールで編集しやすい JSON 表現がサポートされています。
インスタンスを実行せずに変数ストアをオフラインで作成するには
-
次のリンクからツールをダウンロードします。
https://github.com/awslabs/python-uefivars
-
次のコマンドを実行して、キーから新しい変数ストアを作成します。これにより、base64 でエンコードされたバイナリ BLOB が、
your_binary_blob
bin として作成されます。このツールでは、-I
パラメータ経由でバイナリ BLOB を更新することもできます。./uefivars.py -i none -o aws -O
your_binary_blob
.bin -P PK.esl -K KEK.esl --db db.esl --dbx dbx.esl
ステップ 2: AMI の作成時にバイナリ BLOB をアップロードする
register-image--uefi-data
パラメータではバイナリ BLOB を指定し、また --boot-mode
パラメータでは uefi
を指定します。
aws ec2 register-image \ --name uefi_sb_tpm_register_image_test \ --uefi-data $(cat
your_binary_blob
.bin) \ --block-device-mappings "DeviceName=/dev/sda1,Ebs= {SnapshotId=snap-0123456789example
,DeleteOnTermination=true}" \ --architecture x86_64 \ --root-device-name /dev/sda1 \ --virtualization-type hvm \ --ena-support \ --boot-mode uefi