Microsoft Azure Attestation による Remote Attestation を試した(AMD SEV-SNP 編)

azure
Published: 2023-07-24

はじめに

Confidential Computing では、アプリケーションが動いている環境が Confidential Computing な環境であることをする検証できる仕組みが必要です。そのための仕組みが Attestation です。Attestation には、Local Attestation と Remote Attestation が存在します。Local Attestation は Confidential Computing で保護された環境の中で、自身の環境が Confidential Computing な環境であることを検証する手法です。Remote Attestation は、Confidential Computing な環境で動作している通信先が本当に Confidential Computing な環境であることを外部から検証する手法です。

Remote Attestation の場合には、3つの登場人物が存在します。1つ目が Attester です。Attester は、自分が Confidential Computing な環境であることを証明したい人です。2つ目が Relying Party です。Relying Party は、相手が Confidential Computing な環境かどうかを確認したい人です。最後が Verifier です。Verifier は Attester と Relying Party によるやりとりの仲介役として、Attester が信頼できるかを評価する人です。Azure では Verifer の役割を担う Microsoft Azure Attestation というサービスが存在します。

さらに、Remote Attestation にはパスポートモデルとバックグラウンドチェックモデルという2つの方式が存在します。評価の流れは次の通りです。

パスポートモデルの流れ

自分が Confidential Computing な環境であることを証明したい Attester が、Verifer に対して検証を要求して証明を取得する方式です。

  1. Attester は Verifer に対して自身が Confidential Computing な環境であることの証拠を提示する
  2. Verifer は提示された証拠を検証して、Attester に対して Confidential Computing な環境であることの証明を提示する
  3. Attester は Verifer から受け取った証明を Relying Party に提示する
  4. Relying Party は、Attester が提示した証明を確認して、Attester が Confidential Computing な環境かどうかを判断する

Attester を国民、Verifer を外務省、Relying Party を入国審査官と置き換えると、パスポートモデルと呼ばれる理由が分かります。国民(Attester)が外務省(Verifer)に対して身分証明書や住民票などの証拠を提示することで、国民であることの証明であるパスポートを発行してもらいます。そして、入国審査で自分が国民であることを証明する際に、国民(Attester )は入国審査官(Relying Party)にパスポートを提示して国民であることを判断してもらいます。Remote Attestation の流れがパスポートの発行と入国審査と同じです。

バックグラウンドチェックモデルの流れ

相手が Confidential Computing な環境であることを確認したい Relying Party が、Verifer に対して検証を要求して証明を取得する流れです。

  1. Attester は、Relying Party に対して自身が Confidential Computing な環境であることの証拠を提示する
  2. Relying Party は、Verifer に対して Attester から受け取った証拠を提示する
  3. Verifer は、Relying Party から受け取った証拠を検証して、証拠を提示した Attester が Confidential Computing な環境であることの証明を提示する
  4. Relying Party は、Verifer が提示した証明を確認して Attester が Confidential Computing な環境かどうかを判断する

Attester を社員、Relying Party を会社、Verifer を調査会社と置き換えると、バックグラウンドチェックモデルと呼ばれる理由が分かります。社員(Attester)は経歴を確認したい会社(Relying Party)に対して各種証明書を証拠として提示します。会社(Relying Party)は、社員(Attester)から受けとった証拠を調査会社(Verifer)に提示します。調査会社(Verifer)は入手した証拠をもとに経歴が正しいかどうかを検証して、結果をレポートとして会社(Relying Party)に提示します。そして会社(Relying Party)は、受け取ったレポートをもとに、社員(Attester)の経歴が正しいかどうかを判断します。Remote Attestation の流れがバックグラウンドチェックと同じです。

参考

やってみた

Confidential Computing を扱う機会が増えてきているにも関わらずこのサービスを全く触ったことがなかったので、ドキュメントを見ながら試してみました。ちょうど東日本リージョンで AMD SEV-SNP をサポートする DCadsv5 シリーズが使えるようになっていたので、今回のシナリオは、私が通信している仮想マシンが AMD の SEV-SNP を利用した環境で動作している、つまり通信する相手がホスト OS や他のゲスト VM から隔離されている環境で動作していることを確認する形とします。方式はバックグラウンドチェックモデルとします。

検証のイメージは次の通りです。

検証のイメージ図

参考

証拠の提示

まずは、Attester である仮想マシンが Relying Party である私に証拠を提示する必要があります。Relying Party と Attester 間で証拠をやり取りする仕組みが必要になりますが、今回の環境にはそのような仕組みがないので、私自身がサーバにログインして証拠を集めることにします。

私が Microsoft Azure Attestation に提示しなければならない証拠は次の内容です。

{
  "report": "",
  "runtimeData": {
    "data": "",
    "dataType": "JSON"
  }
}

参考:Attestation - Attest Sev Snp Vm

“report” の値は次の JSON を Base64 URL エンコードしたものになります。ただの Base64 エンコードだと Azure Remote Attestation による検証は失敗します。

{
  "SnpReport" : "",
  "VcekCertChain" : ""
}

“SnpReport” には vTPM NVRAM から取得できる SNP 構成証明レポートの内容を記載します。“SnpReport” の内容は次のコマンドで取得できます。

base64url::encode () { base64 -w0 | tr '+/' '-_' | tr -d '='; }
sudo tpm2_nvread -C o 0x01400001 > ./snp_report.bin
dd skip=32 bs=1 count=1184 if=./snp_report.bin of=./attestation_report.bin
cat attestation_report.bin | base64url\:\:encode

参考:Decode/encode base64url with common unix tools

SnpReport の内容は、ADM のチップごとにユニークな秘密鍵である Versioned Chip Endorsement Key によって電子署名されています。SnpReport が改ざんされていないこと、SnpReport の作成者が信頼できる事を Verifer が検証するためには、電子署名を検証するための公開鍵(証明書)が必要です。その情報を VcekCertChain に記載します。取得するコマンドは次の通りです。

curl -H Metadata:true http://169.254.169.254/metadata/THIM/amd/certification > vcek
jq -r '.vcekCert , .certificateChain' >vcek.pem <vcek
base64 -w 0 vcek.pem

最後が “runtimeData.data” です。RuntimeData.data には SNP 構成証明レポート内に含まれる REPORT_DATA の内容を記載します。必要な内容は次のコマンドで取得できます。

dd skip=1236 bs=1 if=snp_report.bin | tr -d '\0' >runtimedata
base64 -w 0 runtimedata

証拠を集め終わったら、Microsoft Azure Attestation に証拠を提示して検証してもらいます。

$token = (Get-AzAccessToken -ResourceUrl 'https://attest.azure.net').Token 
$headers = @{Authorization="Bearer $token"}
$data = @"
{
  "report": "<上で確認した値>",
  "runtimeData": {
    "data": "<上で確認した値>",
    "dataType": "JSON"
  }
}
"@
$res = Invoke-RestMethod -Method POST -Headers $headers -Uri 'https://ymattestation.jpe.attest.azure.net/attest/SevSnpVm?api-version=2022-08-01' -body $data -ContentType 'application/json'

検証に失敗するとエラーが返ってきます。実際に遭遇したエラーのサンプルは次の通りです。

{“error”:{“code”:“InvalidParameter”,“message”:“Parameter binding failed: Unexpected end when deserializing object. Path ‘runtimeData’, line 6,

{ “error”: { “code”: “InvalidQuote”, “message”: “Attestation Enclave operation failed with 65534(中略)‘No data was provided.'\r\nDecoded SnpReport Payload size is invalid 0x480, expected 0x4a0: 0xfffe:}}

検証結果の確認

検証に成功すると Azure Remote Attestation から構成証明トークンが返ってきます。トークンは JWT なので、パースして中身を確認します。

$res

token
-----
eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8veW1hdHRlc3RhdGlvbi5qcGUuYXR0ZXN0LmF6dXJlLm5ld

Install-Module JWT
Get-JwtHeader $token       
{"alg":"RS256","jku":"https://ymattestation.jpe.attest.azure.net/certs","kid":"neZ4c5ykC6ReyXcgaU4PZignsJFTd5OryFashL9/xcg=","typ":"JWT"}
Get-JwtPayload $token
{"exp":1690218223,"iat":1690189423,"iss":"https://ymattestation.jpe.attest.azure.net","jti":"03c54c27cb442a8d46cbb4a1dc6c3ae5a0c163e03d6b3d052ba8367864f064e2","nbf":1690189423,"x-ms-attestation-type":"sevsnpvm","x-ms-compliance-status":"azure-compliant-cvm","x-ms-policy-hash":"9NY0VnTQ-IiBriBplVUpFbczcDaEBUwsiFYAzHu_gco","x-ms-runtime":{"keys":[{"e":"AQAB","key_ops":["encrypt"],"kid":"HCLAkPub","kty":"RSA","n":"hFI8XwAAS7IMndf3dsd9reBoQa0Two8_pgcetTyoI_n3y_1psc8TcOBVoBtkA96Jgz1Wqa6y8Poq6wwEJofF1vDybGuJkv23v4ZSMAUnGb6WUkYv4G_tcDm2lDGmSMUFCLarLL3NcoKQewXQRc0AtsaVn2oicHujOgXMrM9wWpoiwfgDTDdTAn40kOICGSSHJcylTy-ezDXtGG3XL1eke4Fh3pk-fyUj2WFGZYgN-XmONc-aczdSmsNSxTLxe8ZAILyqFj3UljtswVG9r-QTwcmUSbUa9WqTRth6IXt8rJOjiA3ijHVeE5-PswpO8JjT_jp1ecJjY7XZ337I7E9orw"}],"vm-configuration":{"console-enabled":true,"current-time":1690179305,"secure-boot":true,"tpm-enabled":true,"vmUniqueId":"8E877AD8-7EFC-4E7E-AD69-A2611E627259"}},"x-ms-sevsnpvm-authorkeydigest":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","x-ms-sevsnpvm-bootloader-svn":3,"x-ms-sevsnpvm-familyId":"01000000000000000000000000000000","x-ms-sevsnpvm-guestsvn":5,"x-ms-sevsnpvm-hostdata":"0000000000000000000000000000000000000000000000000000000000000000","x-ms-sevsnpvm-idkeydigest":"0356215882a825279a85b300b0b742931d113bf7e32dde2e50ffde7ec743ca491ecdd7f336dc28a6e0b2bb57af7a44a3","x-ms-sevsnpvm-imageId":"02000000000000000000000000000000","x-ms-sevsnpvm-is-debuggable":false,"x-ms-sevsnpvm-launchmeasurement":"43abf28f1124609aa3d187952d2a1a74f703f0bce6a4f7d7d0206459604707cf8b5f8b360c57c4b176461d5f542e2b06","x-ms-sevsnpvm-microcode-svn":115,"x-ms-sevsnpvm-migration-allowed":false,"x-ms-sevsnpvm-reportdata":"8eba38742537eac70788a1b00bc704c99c890f06330bb3028194d88418c254d40000000000000000000000000000000000000000000000000000000000000000","x-ms-sevsnpvm-reportid":"ec7113d6145fd46b3d71273b466b83acda3e25ca7e0a3e7a43e0bf0800aeba14","x-ms-sevsnpvm-smt-allowed":true,"x-ms-sevsnpvm-snpfw-svn":8,"x-ms-sevsnpvm-tee-svn":0,"x-ms-sevsnpvm-vmpl":0,"x-ms-ver":"1.0"}

参考:Decode JWT access and id tokens via PowerShell

JWT 内の “x-ms-attestation-type"には構成証明のタイプを示す文字列が含まれます。“sevsnpvm"となっているので、意図したとおり SEV-SNP な環境かどうかが検証されています。そして、“x-ms-compliance-status” が “azure-compliant-cvm” となっているので、証拠を提出した仮想マシンが Azure 上の SEV-SNP が有効なホスト上で動いていることを証明しています。

For CVMs, is there a way to validate that this is an Azure VM by only looking at the ‘x-ms-sevsnpvm’ fields? You can use the x-ms-compliance-status = azure-compliant-cvm claim. This claim should only be checked in a CVM guest attestation token. This presence of this claim in guest attestation token proves that the CVM is running on SEV-SNP host on Azure with platform version that Microsoft deems healthy.

引用元:For CVMs, is there a way to validate that this is an Azure VM by only looking at the ‘x-ms-sevsnpvm’ fields?

まとめ

見よう見まねで、Microsoft Azure Attestation を利用して、仮想マシンが AMD SEV-SNP が有効なホスト上で動作していることを検証してみました。今回の Microsoft Azure Attestation を利用した Remote Attestation の場合、Microsoft Azure Attestation は Confidential Computing において信頼の対象となります。もし Microsoft Azure Attestation を信頼できない場合は、AMD が提供しているツールを利用して、集めた証拠を自分自身で検証する必要があります。Confidential Computing のキモは「何を信頼するか」だと思いますので、要件にあった Attestation の方法を検討しましょう。

Note

  • 当サイトは個人のブログです。このブログに示されている見解や意見は個人的なものであり、所属組織の見解や意見を表明するものではありません。
  • 公開情報を踏まえて正確な情報を掲載するよう努めますが、その内容の完全性や正確性、有用性、安全性、最新性について一切保証しません。
  • 添付文章やリンク先などを含む本サイトの内容は作成時点でのものであり、予告なく変更される場合があります。