Невозможно получить данные cosmosDB с помощью функции Azure JavaScript и секрета Key Vault.

Я использую функции Azure (JavaScript/ узел) для запроса и получения данных из CosmosDB. Это прекрасно работает. Однако мне не удалось реализовать секреты хранилища ключей для хранения первичного ключа cosmosDB. Я получаю сообщение об ошибке:

      Executed 'Functions.getProjects' (Failed, Id=f319f320-af1c-4283-a8f4-43cc6becb3ca, 
Duration=1289ms)
[6/7/2021 4:37:44 AM] System.Private.CoreLib: Exception while executing function: 
Functions.getProjects. System.Private.CoreLib: Result: Failure
Exception: Error: Required Header authorization is missing. Ensure a valid Authorization token 
is passed.

Я изучил несколько руководств о том, что мне нужно сделать для запуска кода в Azure, а также о том, что мне нужно сделать для локального запуска кода в VS-коде. Для работы в Azure я создал свое хранилище ключей и добавил секрет. Я включил систему, назначенную управляемой идентичности для моей функции, чтобы она создавала субъекта-службы. Затем я создал политику доступа в хранилище ключей, которая позволяет моей функции / принципалу службы GET, LIST. При тестировании функции в Azure я получаю ту же ошибку, что и при локальном тестировании.

Мой код: config.js - конечная точка и ключ скрыты для безопасности

      const config = {
  endpoint: "https://<mysiteonazure>.documents.azure.com:443/",
  key: 
  "myreallylongkeyhiddenforsecurity",
  databaseId: "projectsDB",
  containerId: "projects",
  partitionKey: { kind: "Hash", paths: ["/category"] },
};
module.exports = config;

Мой код: index.js

      const config = require("../sharedCode/config");
const { CosmosClient } = require("@azure/cosmos");

const { DefaultAzureCredential } = require("@azure/identity");
const { SecretClient } = require("@azure/keyvault-secrets");

// this value is specified in local.settings.json file for local testing
const keyVaultName = process.env["KEY_VAULT_NAME"];

const keyVaultUri = `https://${keyVaultName}.vault.azure.net`;

// checks to see if local.settings.json has value first, indicates local
// second uses managed identity, indicating azure, since local.settings.js not uploaded
const credential = new DefaultAzureCredential();

const secretClient = new SecretClient(keyVaultUri, credential);

module.exports = async function (context, req) {
  
  const endpoint = config.endpoint;
  const key = await secretClient.getSecret("cosmosProjectKey");
  const keyx = key.value;

  const client = new CosmosClient({ endpoint, keyx });

  const database = client.database(config.databaseId);
  const container = database.container(config.containerId);

  const querySpec = {
    query: "SELECT * from c",
  };

  let myprojects = [];

  const { resources: items } = await container.items
    .query(querySpec)
    .fetchAll();

  items.forEach((item) => {
    myprojects.push(`${item.id} - ${item.project}`);
  });

  context.res = {
    // status: 200, /* Defaults to 200 */
    body: items,
  };
};

Как я уже упоминал, мой код работает, когда я жестко кодирую ключ в файле конфигурации (не лучшая кодировка JS). Я удалил все комментарии, которые показывают, что значение ключа возвращается из хранилища ключей. Я также не упомянул, что создал еще одного участника-службы, который, как мне кажется, используется, когда я пытаюсь получить доступ к хранилищу ключей при локальном запуске функции.

Любая помощь очень ценится.

1 ответ

Решение

Измените следующие строки кода:

      const key = await secretClient.getSecret("cosmosProjectKey");
const keyx = key.value;

к

      const secretKey = await secretClient.getSecret("cosmosProjectKey");
const key = secretKey.value;

И создайте свой CosmosClient, используя следующие

      const client = new CosmosClient({ endpoint, key });

Другой вариант - создать свой CosmosClient следующим образом:

      const client = new CosmosClient({ endpoint, key: keyx });
Другие вопросы по тегам