У меня возникают проблемы с получением секрета из хранилища ключей Azure с помощью пакета azure-keyvault из приложения узла, работающего на виртуальной машине Linux в Azure.
Я использую следующий код:
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...
});
Я получаю ответ 401 при вызове getSecret. В хранилище ключей и MSI установлены разрешения для машины. В ошибке, которую я получаю, похоже, нет заголовка аутентификации или токена, хотя я вижу заголовок, который выглядит как заголовок аутентификации в ответе.
Есть ли что-то, что мне не хватает в моей реализации?
Обновлено: Похоже, что пример, которым я поделился здесь, сработал бы, если бы я использовал
msRestAzure.loginWithVmMSI({resource: 'https://vault.azure.net' });
вместо того, чтобы вызывать его без параметров.
@ Rthomas529 Rthomas529 Я пытаюсь использовать пакет azure-keyvault... поэтому часть информации скрыта от меня. Вы предлагаете просто использовать обычный API с простыми HTTP-запросами?
В хранилище ключей убедитесь, что вы добавили субъект-службу (созданную автоматически при включении MSI) в Access policies
с правильным секретным разрешением. Затем попробуйте нажать 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.info("Secret id: '" + kvSecretBundle.id + "'.");
return keyVaultClient.getSecret(kvSecretBundle.id, {});
})
.then( (bundle) => {
console.info("Successfully retrieved 'test-secret'");
console.info(bundle);
})
.catch( (err) => {
console.info(err);
});
// Below code demonstrates how to retrieve a secret value
// keyVaultClient.getSecret(vaultUri, "AppSecret", "").then(function(response){
// console.info(response);
// })
});
Для получения более подробной информации вы можете обратиться к: Установка и получение секрета из Azure Key Vault с помощью веб-приложения Node..
Я заметил, что вы используете loginWithAppServiceMSI в своем примере, но у меня нет AppService, у меня есть обычная виртуальная машина, разве я не должен использовать loginWithVmMSI?
@Mithir Да, я думаю, в вашем случае вам следует использовать loginWithVmMSI. Кстати, вы сначала проверили свои разрешения?
Я только что реализовал получение секрета с помощью простых http-запросов, и это сработало. Сначала я получаю токен, а затем получаю секрет с заголовком авторизации, в котором есть данные о токене, поэтому разрешения в порядке. Я все еще предпочитаю использовать пакет, но я не уверен, чего не хватает...
@Mithir Не могли бы вы последовать образцу, чтобы попробовать? Независимо от того, используете ли вы msi службы приложений или vm, логика должна быть одинаковой.
Хорошо, большое спасибо... кажется, я пропустил ресурсную часть в своем примере... Большое спасибо!
Вы можете использовать чтение лазурных секретов, который извлечет все секреты из хранилища ключей Azure.
Например
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.info(secret);
});
}
loadKeyVaultValues();
Теперь это было упрощено в новом пакете @azure/keyvault-secrets
, где SecretClient
может взять DefaultAzureCredential
из пакета @azure/identity
, который, в свою очередь, достаточно умен, чтобы использовать данные MSI при запуске на вашей виртуальной машине, а также учетные данные разработчика, такие как VS Code или Azure CLI, когда в вашей локальной среде разработки. Вы можете узнать больше об этом в ридми для @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
, который в настоящее время устарел, вы можете увидеть руководство по переходу на новый @azure/keyvault-secrets
Я запутался. Где вы запрашиваете токен? Вы должны увидеть свой токен в заголовке ответа от вашего https-запроса. Также вам нужно использовать обратные вызовы.