I am using Azure functions (JavaScript/node) to query and retrieve data from CosmosDB. That works fine. However, I haven't been successful at implementing key vault secrets to store the primary key for cosmosDB. I get the error:
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.
I have followed multiple tutorials on what I need to do to run the code in Azure as well as what I need to do to run the code locally in VS code. To run in Azure, I created my key vault and added the secret. I enabled system assigned managed identity on my function so that it creates a service principal. I then created an access policy in key vault that allows my function/service principal GET, LIST capabilities. I get the same error when testing the function in Azure as I do when I test locally.
My code: config.js - endpoint and key obscured for security
const config = {
endpoint: "https://<mysiteonazure>.documents.azure.com:443/",
key:
"myreallylongkeyhiddenforsecurity",
databaseId: "projectsDB",
containerId: "projects",
partitionKey: { kind: "Hash", paths: ["/category"] },
};
module.exports = config;
My code: 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,
};
};
As I mentioned, my code works when I hard-code the key in the config file (not the best JS coding). I've removed all the comments that show that the value of the key is returned from key vault. I also left out that I created another service principal, that I believe is used when I try to access the key vault when running the function locally.
Any help greatly appreciated.