从带有 MSI 的 linux 虚拟机中使用节点从 azure keyvault 获取秘密
Getting a secret from azure keyvault with node from a linux vm with MSI
我在 azure 上的 linux 虚拟机上使用来自节点应用程序 运行 的 azure-keyvault 包从 azure keyvault 获取秘密时遇到问题。
我正在使用以下代码:
import * as KeyVault from 'azure-keyvault';
import * as msRestAzure from 'ms-rest-azure'
function getKeyVaultCredentials(){
return msRestAzure.loginWithVmMSI();
}
function getKeyVaultSecret(credentials) {
let keyVaultClient = new KeyVault.KeyVaultClient(credentials,null);
return keyVaultClient.getSecret("my keyvault url here", 'my keyvault secret name here', "", null,null);
}
getKeyVaultCredentials().then(
getKeyVaultSecret
).then(function (secret){
//not getting here....
}).catch(function (err) {
//...error handling...
});
我在调用 getSecret 时收到 401 响应。
在 keyvault 和 MSI 上为机器设置了权限。
在我得到的错误中,似乎没有任何 header 身份验证或令牌,尽管我确实看到 header 看起来像响应中的身份验证 header。
我的实施过程中是否遗漏了什么?
编辑:
如果我使用
,我在这里分享的示例看起来会起作用
msRestAzure.loginWithVmMSI({resource: 'https://vault.azure.net' });
而不是不带参数调用它。
在您的 keyvault 中,确保您已在 Access policies
中添加具有正确秘密权限的服务主体(通过启用 MSI 自动创建)。然后尝试点击 Click to show advanced access policies
-> 选择 Enable access to Azure Virtual Machines for deployment
选项-> 保存。
这是一个代码示例,您可以检查检索秘密值的部分。
var http = require('http');
const KeyVault = require('azure-keyvault');
const msRestAzure = require('ms-rest-azure');
var server = http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
});
// The ms-rest-azure library allows us to login with MSI by providing the resource name. In this case the resource is Key Vault.
// For public regions the resource name is Key Vault
msRestAzure.loginWithAppServiceMSI({resource: 'https://vault.azure.net'}).then( (credentials) => {
const keyVaultClient = new KeyVault.KeyVaultClient(credentials);
var vaultUri = "https://" + "<YourVaultName>" + ".vault.azure.net/";
// We're setting the Secret value here and retrieving the secret value
keyVaultClient.setSecret(vaultUri, 'my-secret', 'test-secret-value', {})
.then( (kvSecretBundle, httpReq, httpResponse) => {
console.log("Secret id: '" + kvSecretBundle.id + "'.");
return keyVaultClient.getSecret(kvSecretBundle.id, {});
})
.then( (bundle) => {
console.log("Successfully retrieved 'test-secret'");
console.log(bundle);
})
.catch( (err) => {
console.log(err);
});
// Below code demonstrates how to retrieve a secret value
// keyVaultClient.getSecret(vaultUri, "AppSecret", "").then(function(response){
// console.log(response);
// })
});
详情请参考:Set and retrieve a secret from Azure Key Vault using a Node Web App.
您可以使用 read-azure-secrets,它将从 Azure Key Vault 中检索所有机密。
例如
let secretClient = require('read-azure-secrets');
async function loadKeyVaultValues() {
let applicationID = '';
let applicationSecret = '';
let vaultURL = 'https://<your-key-vault-name>.vault.azure.net/';
let secrets = await secretClient.getSecrets(applicationID, applicationSecret, vaultURL);
secrets.forEach(secret => {
console.log(secret);
});
}
loadKeyVaultValues();
这在新的 @azure/keyvault-secrets
包中得到了简化,其中 SecretClient
可以从 @azure/identity
包中获取 DefaultAzureCredential
,后者又足够智能,可以使用在您的 VM 中 运行 时的 MSI 详细信息以及在您的本地开发环境中时的开发人员凭据,如 VS Code 或 Azure CLI。您可以在 readme for @azure/identity
中了解更多相关信息
有了这个,你的代码将被简化为
const { SecretClient } = require("@azure/keyvault-secrets");
const { DefaultAzureCredential } = require("@azure/identity");
async function getValue(secretName, secretVersion) {
const credential = new DefaultAzureCredential();
const client = new SecretClient(KEY_VAULT_URI, credential);
const secret = await client.getSecret(secretName);
return secret.value;
}
要从现已弃用的旧 azure-keyvault
包中移动您的应用程序,您可以查看 migration guide to the new @azure/keyvault-secrets
我在 azure 上的 linux 虚拟机上使用来自节点应用程序 运行 的 azure-keyvault 包从 azure keyvault 获取秘密时遇到问题。
我正在使用以下代码:
import * as KeyVault from 'azure-keyvault';
import * as msRestAzure from 'ms-rest-azure'
function getKeyVaultCredentials(){
return msRestAzure.loginWithVmMSI();
}
function getKeyVaultSecret(credentials) {
let keyVaultClient = new KeyVault.KeyVaultClient(credentials,null);
return keyVaultClient.getSecret("my keyvault url here", 'my keyvault secret name here', "", null,null);
}
getKeyVaultCredentials().then(
getKeyVaultSecret
).then(function (secret){
//not getting here....
}).catch(function (err) {
//...error handling...
});
我在调用 getSecret 时收到 401 响应。 在 keyvault 和 MSI 上为机器设置了权限。 在我得到的错误中,似乎没有任何 header 身份验证或令牌,尽管我确实看到 header 看起来像响应中的身份验证 header。
我的实施过程中是否遗漏了什么?
编辑: 如果我使用
,我在这里分享的示例看起来会起作用msRestAzure.loginWithVmMSI({resource: 'https://vault.azure.net' });
而不是不带参数调用它。
在您的 keyvault 中,确保您已在 Access policies
中添加具有正确秘密权限的服务主体(通过启用 MSI 自动创建)。然后尝试点击 Click to show advanced access policies
-> 选择 Enable access to Azure Virtual Machines for deployment
选项-> 保存。
这是一个代码示例,您可以检查检索秘密值的部分。
var http = require('http');
const KeyVault = require('azure-keyvault');
const msRestAzure = require('ms-rest-azure');
var server = http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
});
// The ms-rest-azure library allows us to login with MSI by providing the resource name. In this case the resource is Key Vault.
// For public regions the resource name is Key Vault
msRestAzure.loginWithAppServiceMSI({resource: 'https://vault.azure.net'}).then( (credentials) => {
const keyVaultClient = new KeyVault.KeyVaultClient(credentials);
var vaultUri = "https://" + "<YourVaultName>" + ".vault.azure.net/";
// We're setting the Secret value here and retrieving the secret value
keyVaultClient.setSecret(vaultUri, 'my-secret', 'test-secret-value', {})
.then( (kvSecretBundle, httpReq, httpResponse) => {
console.log("Secret id: '" + kvSecretBundle.id + "'.");
return keyVaultClient.getSecret(kvSecretBundle.id, {});
})
.then( (bundle) => {
console.log("Successfully retrieved 'test-secret'");
console.log(bundle);
})
.catch( (err) => {
console.log(err);
});
// Below code demonstrates how to retrieve a secret value
// keyVaultClient.getSecret(vaultUri, "AppSecret", "").then(function(response){
// console.log(response);
// })
});
详情请参考:Set and retrieve a secret from Azure Key Vault using a Node Web App.
您可以使用 read-azure-secrets,它将从 Azure Key Vault 中检索所有机密。
例如
let secretClient = require('read-azure-secrets');
async function loadKeyVaultValues() {
let applicationID = '';
let applicationSecret = '';
let vaultURL = 'https://<your-key-vault-name>.vault.azure.net/';
let secrets = await secretClient.getSecrets(applicationID, applicationSecret, vaultURL);
secrets.forEach(secret => {
console.log(secret);
});
}
loadKeyVaultValues();
这在新的 @azure/keyvault-secrets
包中得到了简化,其中 SecretClient
可以从 @azure/identity
包中获取 DefaultAzureCredential
,后者又足够智能,可以使用在您的 VM 中 运行 时的 MSI 详细信息以及在您的本地开发环境中时的开发人员凭据,如 VS Code 或 Azure CLI。您可以在 readme for @azure/identity
有了这个,你的代码将被简化为
const { SecretClient } = require("@azure/keyvault-secrets");
const { DefaultAzureCredential } = require("@azure/identity");
async function getValue(secretName, secretVersion) {
const credential = new DefaultAzureCredential();
const client = new SecretClient(KEY_VAULT_URI, credential);
const secret = await client.getSecret(secretName);
return secret.value;
}
要从现已弃用的旧 azure-keyvault
包中移动您的应用程序,您可以查看 migration guide to the new @azure/keyvault-secrets