快速入門 - 適用於 JavaScript 的 Azure Key Vault 憑證用戶端程式庫
開始使用適用於 JavaScript 的 Azure Key Vault 憑證用戶端程式庫。 Azure Key Vault 是一項雲端服務,可為憑證提供安全的存放區。 您也可以安全地儲存金鑰、密碼、憑證和其他祕密。 您可以透過 Azure 入口網站建立和管理 Azure 金鑰保存庫。 在本快速入門中,您會了解如何使用 JavaScript 用戶端程式庫,從 Azure Key Vault 建立、擷取和刪除憑證。
Key Vault 用戶端程式庫資源:
API 參考文件 | 程式庫原始程式碼 | 套件 (npm)
如需有關 Key Vault 及憑證的詳細資訊,請參閱:
必要條件
- Azure 訂用帳戶 - 建立免費帳戶。
- 目前的 Node.js LTS。
- Azure CLI
- 現有的 Key Vault - 您可以使用下列工具建立 Key Vault:
- Azure 訂用帳戶 - 建立免費帳戶。
- 目前的 Node.js LTS。
- TypeScript 5+
- Azure CLI
- 現有的 Key Vault - 您可以使用下列工具建立 Key Vault:
本快速入門假設您執行 Azure CLI。
登入 Azure
執行
login
命令。az login
如果此 CLI 可以開啟您的預設瀏覽器,它會開啟瀏覽器並載入 Azure 登入頁面。
否則,請在 https://aka.ms/devicelogin 中開啟瀏覽器頁面,並輸入顯示在您的終端機中的授權碼。
請在瀏覽器中使用您的帳戶認證登入。
建立新的 Node.js 應用程式
建立一個使用金鑰保存庫的 Node.js 應用程式。
在終端機建立名為
key-vault-node-app
的資料夾,並切換至該資料夾:mkdir key-vault-node-app && cd key-vault-node-app
初始化 Node.js 專案:
npm init -y
安裝 Key Vault 套件
使用終端機,安裝適用於 Node.js 的 Azure Key Vault 祕密程式庫 @azure/keyvault-certificates。
npm install @azure/keyvault-certificates
安裝 Azure 身分識別用戶端程式庫 @azure/identity,以向 Key Vault 進行驗證。
npm install @azure/identity
授與對金鑰保存庫的存取權
若要透過角色型存取控制 (RBAC) 取得金鑰保存庫的權限,請使用 Azure CLI 命令 az role assignment create 將角色指派給「使用者主體名稱」(UPN)。
az role assignment create --role "Key Vault Certificate Officer" --assignee "<upn>" --scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.KeyVault/vaults/<your-unique-keyvault-name>"
以實際值取代 <upn>、<subscription-id>、<resource-group-name> 和 <your-unique-keyvault-name>。 您 UPN 的格式通常是電子郵件地址 (例如,username@domain.com)。
設定環境變數
此應用程式正使用金鑰保存庫端點作為稱為 KEY_VAULT_URL
的環境變數。
set KEY_VAULT_URL=<your-key-vault-endpoint>
驗證並建立用戶端
對大部分 Azure 服務的應用程式要求都必須獲得授權。 在程式碼中實作對 Azure 服務的無密碼連線時,建議使用 Azure.Identity 用戶端程式庫提供的 DefaultAzureCredential 方法。 DefaultAzureCredential
支援多個驗證方法,並在執行階段判斷應該使用哪個方法。 此方法可讓您的應用程式在不同的環境中 (本機或實際執行環境) 使用不同的驗證方法,而不需要實作環境特有的程式碼。
在本快速入門中,DefaultAzureCredential
使用已登入 Azure CLI 之本機開發使用者的認證向金鑰保存庫進行驗證。 將應用程式部署至 Azure 時,相同的 DefaultAzureCredential
程式碼可以自動探索並使用指派給 App Service、虛擬機器或其他服務的受控識別。 如需詳細資訊,請參閱受控識別概觀。
在此程式碼中,金鑰保存庫的端點會用來建立金鑰保存庫用戶端。 端點格式看起來就像 https://<your-key-vault-name>.vault.azure.net
,但主權雲端可能會變更。 如需對金鑰保存庫進行驗證的詳細資訊,請參閱開發人員指南。
程式碼範例
此程式碼會使用下列 Key Vault 憑證類別和方法:
設定應用程式架構
建立新的文字檔,並將下列程式碼貼到 index.js 檔案中。
const { CertificateClient, DefaultCertificatePolicy } = require("@azure/keyvault-certificates"); const { DefaultAzureCredential } = require("@azure/identity"); async function main() { // If you're using MSI, DefaultAzureCredential should "just work". // Otherwise, DefaultAzureCredential expects the following three environment variables: // - AZURE_TENANT_ID: The tenant ID in Azure Active Directory // - AZURE_CLIENT_ID: The application (client) ID registered in the AAD tenant // - AZURE_CLIENT_SECRET: The client secret for the registered application const credential = new DefaultAzureCredential(); const keyVaultUrl = process.env["KEY_VAULT_URL"]; if(!keyVaultUrl) throw new Error("KEY_VAULT_URL is empty"); const client = new CertificateClient(keyVaultUrl, credential); const uniqueString = new Date().getTime(); const certificateName = `cert${uniqueString}`; // Creating a self-signed certificate const createPoller = await client.beginCreateCertificate( certificateName, DefaultCertificatePolicy ); const pendingCertificate = createPoller.getResult(); console.log("Certificate: ", pendingCertificate); // To read a certificate with their policy: let certificateWithPolicy = await client.getCertificate(certificateName); // Note: It will always read the latest version of the certificate. console.log("Certificate with policy:", certificateWithPolicy); // To read a certificate from a specific version: const certificateFromVersion = await client.getCertificateVersion( certificateName, certificateWithPolicy.properties.version ); // Note: It will not retrieve the certificate's policy. console.log("Certificate from a specific version:", certificateFromVersion); const updatedCertificate = await client.updateCertificateProperties(certificateName, "", { tags: { customTag: "value" } }); console.log("Updated certificate:", updatedCertificate); // Updating the certificate's policy: await client.updateCertificatePolicy(certificateName, { issuerName: "Self", subject: "cn=MyOtherCert" }); certificateWithPolicy = await client.getCertificate(certificateName); console.log("updatedCertificate certificate's policy:", certificateWithPolicy.policy); // delete certificate const deletePoller = await client.beginDeleteCertificate(certificateName); const deletedCertificate = await deletePoller.pollUntilDone(); console.log("Recovery Id: ", deletedCertificate.recoveryId); console.log("Deleted Date: ", deletedCertificate.deletedOn); console.log("Scheduled Purge Date: ", deletedCertificate.scheduledPurgeDate); } main().catch((error) => { console.error("An error occurred:", error); process.exit(1); });
執行範例應用程式
執行應用程式:
node index.js
建立和取得方法傳回憑證的完整 JSON 物件:
{ "keyId": undefined, "secretId": undefined, "name": "YOUR-CERTIFICATE-NAME", "reuseKey": false, "keyCurveName": undefined, "exportable": true, "issuerName": 'Self', "certificateType": undefined, "certificateTransparency": undefined }, "properties": { "createdOn": 2021-11-29T20:17:45.000Z, "updatedOn": 2021-11-29T20:17:45.000Z, "expiresOn": 2022-11-29T20:17:45.000Z, "id": "https://YOUR-KEY-VAULT-NAME-ENDPOINT/certificates/YOUR-CERTIFICATE-NAME/YOUR-CERTIFICATE-VERSION", "enabled": false, "notBefore": 2021-11-29T20:07:45.000Z, "recoveryLevel": "Recoverable+Purgeable", "name": "YOUR-CERTIFICATE-NAME", "vaultUrl": "https://YOUR-KEY-VAULT-NAME-ENDPOINT", "version": "YOUR-CERTIFICATE-VERSION", "tags": undefined, "x509Thumbprint": undefined, "recoverableDays": 90 } }
建立新的文字檔,並將下列程式碼貼到 index.js 檔案中。
import { CertificateClient, DefaultCertificatePolicy, KeyVaultCertificate, DeletedCertificate, CertificatePolicy, KeyVaultCertificateWithPolicy, } from "@azure/keyvault-certificates"; import { DefaultAzureCredential } from "@azure/identity"; import "dotenv/config"; const credential = new DefaultAzureCredential(); // Get Key Vault name from environment variables // such as `https://${keyVaultName}.vault.azure.net` const keyVaultUrl = process.env.KEY_VAULT_URL; if (!keyVaultUrl) throw new Error("KEY_VAULT_URL is empty"); function printCertificate( certificate: KeyVaultCertificate | KeyVaultCertificateWithPolicy ): void { console.log("-- printCertificate ---------------------------"); // if policy is defined, it's a KeyVaultCertificateWithPolicy if ((certificate as KeyVaultCertificateWithPolicy).policy) { const { name, properties, policy } = certificate as KeyVaultCertificateWithPolicy; const { createdOn, updatedOn, expiresOn, vaultUrl, version, tags } = properties; console.log("Certificate: ", { name, createdOn, updatedOn, expiresOn, vaultUrl, version, }); console.log("Certificate Policy: ", policy); printObjectProperties(tags); return; } else { const { name, properties } = certificate; const { createdOn, updatedOn, expiresOn, vaultUrl, version, tags } = properties; console.log("Certificate: ", { name, createdOn, updatedOn, expiresOn, vaultUrl, version, }); printObjectProperties(tags); } } // Object properties are tags and CertificatePolicy function printObjectProperties(obj: Record<string, any>): void { if (!obj) return; console.log("-- printObjectProperties ---------------------------"); Object.entries(obj).forEach(([key, value]) => { if (key === "lifetimeActions") { console.log(`${key}: ${JSON.stringify(value)}`); } else { console.log(`${key}: ${value}`); } }); } function printDeletedCertificate(deletedCertificate: DeletedCertificate): void { const { recoveryId, deletedOn, scheduledPurgeDate } = deletedCertificate; console.log("Deleted Certificate: ", { recoveryId, deletedOn, scheduledPurgeDate, }); } async function main(): Promise<void> { // Create a new CertificateClient const client = new CertificateClient(keyVaultUrl, credential); // Create a unique certificate name const uniqueString = new Date().getTime().toString(); const certificateName = `cert${uniqueString}`; // Creating a self-signed certificate const createPoller = await client.beginCreateCertificate( certificateName, DefaultCertificatePolicy ); // Get the created certificate const pendingCertificate = await createPoller.getResult(); printCertificate(pendingCertificate); // Get certificate by name let certificateWithPolicy = await client.getCertificate(certificateName); printCertificate(pendingCertificate); // Get certificate by version const certificateFromVersion = await client.getCertificateVersion( certificateName, certificateWithPolicy.properties.version! ); printCertificate(certificateFromVersion); // Update properties of the certificate const updatedCertificate = await client.updateCertificateProperties( certificateName, certificateWithPolicy.properties.version!, { tags: { customTag: "my value", }, } ); printCertificate(updatedCertificate); // Updating the certificate's policy const certificatePolicy = await client.updateCertificatePolicy( certificateName, { issuerName: "Self", subject: "cn=MyOtherCert", } ); printObjectProperties(certificatePolicy); // Get certificate again to see the updated policy certificateWithPolicy = await client.getCertificate(certificateName); printCertificate(certificateWithPolicy); // Delete certificate const deletePoller = await client.beginDeleteCertificate(certificateName); const deletedCertificate = await deletePoller.pollUntilDone(); printDeletedCertificate(deletedCertificate); } main().catch((error) => { console.error("An error occurred:", error); process.exit(1); });
執行範例應用程式
組建 TypeScript 應用程式:
tsc
執行應用程式:
node index.js
建立和取得方法傳回憑證的完整 JSON 物件:
{ "keyId": undefined, "secretId": undefined, "name": "YOUR-CERTIFICATE-NAME", "reuseKey": false, "keyCurveName": undefined, "exportable": true, "issuerName": 'Self', "certificateType": undefined, "certificateTransparency": undefined }, "properties": { "createdOn": 2021-11-29T20:17:45.000Z, "updatedOn": 2021-11-29T20:17:45.000Z, "expiresOn": 2022-11-29T20:17:45.000Z, "id": "https://YOUR-KEY-VAULT-NAME-ENDPOINT/certificates/YOUR-CERTIFICATE-NAME/YOUR-CERTIFICATE-VERSION", "enabled": false, "notBefore": 2021-11-29T20:07:45.000Z, "recoveryLevel": "Recoverable+Purgeable", "name": "YOUR-CERTIFICATE-NAME", "vaultUrl": "https://YOUR-KEY-VAULT-NAME-ENDPOINT", "version": "YOUR-CERTIFICATE-VERSION", "tags": undefined, "x509Thumbprint": undefined, "recoverableDays": 90 } }
與應用程式組態整合
Azure SDK 提供協助程式方法 parseKeyVaultCertificateIdentifier,以剖析指定的 Key Vault 憑證識別碼,如果您使用參考 Key Vault 的應用程式組態,則這是必要項目。 應用程式組態儲存 Key Vault 憑證識別碼。 您需要 parseKeyVaultCertificateIdentifier 方法來剖析該識別碼,以取得憑證名稱。 取得憑證名稱之後,就可以使用本快速入門中的程式碼來取得目前的憑證。
下一步
在本快速入門中,您已建立金鑰保存庫、儲存憑證,並擷取該憑證。 若要深入了解 Key Vault 以及要如何將其與應用程式整合,請繼續閱讀下列文章。