跳至主要内容

AWS instance identity documents

· 閱讀時間約 3 分鐘
Ivan Tsai
Backend engineer

Instance Metadata Service

Instance metadata 是 AWS 對你的 EC2 提供的資訊,包含 Host Name, Public IP ... 等等的資訊都可以從 Metadata Service 獲取。每個 EC2 中都能存取到位於 169.254.169.254 的 API,這個位址是 Link-local address,只有從 EC2 內部才可以存取的到。例如,我們可以由下面這個 API 獲得目前的 Public IP:

curl http://169.254.169.254/latest/meta-data/public-ipv4

Instance identity documents

Instace identity documents 是一種動態的 instance metadata,他會在每次機器啟動、重啟等等的狀況重新產生,它包含了很多重要的資訊:

名稱描述
marketplaceProductCodesAWS marketplace 提供的 product codes,可以驗證機器是否是由 AWS Marketplace 訂閱並啟動的。
imageId機器所使用的 AMI ID
instanceIdEC2 instance id

獲取的方式很簡單,一樣藉由 Metadata Service 就可以了:

curl -s http://169.254.169.254/latest/dynamic/instance-identity/document

{
"accountId" : "xxxxxxx",
"architecture" : "x86_64",
"availabilityZone" : "ap-northeast-1d",
"billingProducts" : null,
"devpayProductCodes" : null,
"marketplaceProductCodes" : null,
"imageId" : "ami-xxxxx",
"instanceId" : "i-xxxxxx",
"instanceType" : "t3a.small",
"kernelId" : null,
"pendingTime" : "2022-10-15T13:45:28Z",
"privateIp" : "10.100.2.202",
"ramdiskId" : null,
"region" : "ap-northeast-1",
"version" : "2017-09-30"
}

作為身分驗證的方法

那 Instance identity 可以拿來做身分驗證 (Authentication) 嗎? 答案是可以的,Vault 就有提供類似的驗證方法

不過,要進行身分驗證,可不是拿著上面的 JSON 資料就能算數,AWS 除了提供上面的資料以外,也會使用 AWS public certificate 做簽名,我們收到來自 EC2 Instace 送過來簽名過後的資料後,比對 AWS Public Key,這麼一來我們就能確定 Instance 的身分了。

Auto workflow with instance identity document

驗證 Identity Document

我們需要取得 AWS 的 Public Key,這把公鑰在各個 Region 是不同的,需要到官方文件中查看,之後只要對 Signature 做驗證就可以了,下面是以 NodeJS 做的簡單範例:

const crypto = require("crypto");

// Signature from http://169.254.169.254/latest/dynamic/instance-identity/signature
const signature = Buffer.from(`MVIZxx....`, "base64");

// Document from http://169.254.169.254/latest/dynamic/instance-identity/document
const doc = Buffer.from(
`{
"accountId" : "xxxxxxx",
"architecture" : "x86_64",
"availabilityZone" : "ap-northeast-1d",
"billingProducts" : null,
"devpayProductCodes" : null,
"marketplaceProductCodes" : null,
"imageId" : "ami-xxxxx",
"instanceId" : "i-xxxxxxx",
"instanceType" : "t3a.small",
"kernelId" : null,
"pendingTime" : "2022-10-15T13:45:28Z",
"privateIp" : "10.100.2.202",
"ramdiskId" : null,
"region" : "ap-northeast-1",
"version" : "2017-09-30"
}`,
"utf-8"
);

const result = crypto.verify(
"SHA256",
doc,
// AWS public key (Other AWS Regions)
`
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCHvRjf/0kStpJ248khtIaN8qkD
N3tkw4VjvA9nvPl2anJO+eIBUqPfQG09kZlwpWpmyO8bGB2RWqWxCwuB/dcnIob6
w420k9WY5C0IIGtDRNauN3kuvGXkw3HEnF0EjYr0pcyWUvByWY4KswZV42X7Y7XS
S13hOIcL6NLA+H94/QIDAQAB
-----END PUBLIC KEY-----
`,
signature
);

console.log(result);

References