{"id":22006503,"url":"https://github.com/anoff/azure-keyvault-secretstore","last_synced_at":"2026-05-07T07:32:00.253Z","repository":{"id":31538348,"uuid":"128218130","full_name":"anoff/azure-keyvault-secretstore","owner":"anoff","description":"Easily use Azure KeyVault to manage secrets in Function Apps","archived":false,"fork":false,"pushed_at":"2022-02-12T06:03:31.000Z","size":2186,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-28T13:48:05.516Z","etag":null,"topics":["azure","azure-functions","azure-keyvault","keyvault","msi"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anoff.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-05T14:29:00.000Z","updated_at":"2022-06-28T17:05:22.000Z","dependencies_parsed_at":"2022-08-03T01:31:18.932Z","dependency_job_id":null,"html_url":"https://github.com/anoff/azure-keyvault-secretstore","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anoff%2Fazure-keyvault-secretstore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anoff%2Fazure-keyvault-secretstore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anoff%2Fazure-keyvault-secretstore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anoff%2Fazure-keyvault-secretstore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anoff","download_url":"https://codeload.github.com/anoff/azure-keyvault-secretstore/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245066523,"owners_count":20555404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","azure-functions","azure-keyvault","keyvault","msi"],"created_at":"2024-11-30T01:12:35.789Z","updated_at":"2026-05-07T07:31:55.229Z","avatar_url":"https://github.com/anoff.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# azure-keyvault-secretstore\n\n[![npm version](https://img.shields.io/npm/v/azure-keyvault-secretstore.svg)](https://www.npmjs.com/package/azure-keyvault-secretstore)\n[![Build Status](https://travis-ci.org/anoff/azure-keyvault-secretstore.svg?branch=master)](https://travis-ci.org/anoff/azure-keyvault-secretstore)\n[![Coverage Status](https://coveralls.io/repos/github/anoff/azure-keyvault-secretstore/badge.svg?branch=master)](https://coveralls.io/github/anoff/azure-keyvault-secretstore?branch=master)\n[![Greenkeeper badge](https://badges.greenkeeper.io/anoff/azure-keyvault-secretstore.svg)](https://greenkeeper.io/)\n[![Known Vulnerabilities](https://snyk.io/test/npm/azure-keyvault-secretstore/badge.svg)](https://snyk.io/test/npm/azure-keyvault-secretstore)\n[![Outdated dependencies](https://david-dm.org/anoff/azure-keyvault-secretstore.svg)](https://david-dm.org/anoff/azure-keyvault-secretstore)\n\n\u003e Storing secrets in KeyVault 🔐 and using them in Azure Function ⚡️ without writing boilerplate each time\n\n\u003c!-- TOC depthFrom:2 depthTo:4 --\u003e\n\n- [Install](#install)\n- [Usage](#usage)\n- [API](#api)\n  - [SecretStore](#secretstore)\n    - [SecretStore.secrets](#secretstoresecrets)\n    - [SecretStore.isUpdating](#secretstoreisupdating)\n    - [new SecretStore(keyVaultUrl, createKeyVaultClientFn)](#new-secretstorekeyvaulturl-createkeyvaultclientfn)\n    - [secretStore.add(secretName)](#secretstoreaddsecretname)\n    - [secretStore.age()](#secretstoreage)\n    - [secretStore.refresh()](#secretstorerefresh)\n    - [secretStore.get(secretName)](#secretstoregetsecretname)\n  - [getKeyVaultClient(options)](#getkeyvaultclientoptions)\n    - [options.clientId](#optionsclientid)\n    - [options.clientSecret](#optionsclientsecret)\n    - [options.tenantId](#optionstenantid)\n    - [options.msiEndpoint](#optionsmsiendpoint)\n  - [createKeyVaultClient()](#createkeyvaultclient)\n- [License](#license)\n\n\u003c!-- /TOC --\u003e\n\n## Install\n\nFirst get the module installed in your Function App by adding it to your `package.json`\n\n```sh\nnpm install azure-keyvault-secretstore\n```\n\n## Usage\n\nQuick example how to use this in a Function App with MSI enabled:\n\n```javascript\nconst { SecretStore, createKeyVaultClient } = require('azure-keyvault-secretstore')\n\nconst secretStore = new SecretStore('https://customvault123.vault.azure.net', createKeyVaultClient)\nsecretStore.add('secret-one').add('another-secret').add('same-name-as-in-keyvault')\nsecretStore.refresh() // initial refresh\n.then(/* ... bootstrap databases etc using the secrets using secretStore.get('secret-one').value */)\nmodule.exports = (context, req) =\u003e {\n  if (secretStore.age() \u003e 60*60) secretStore.refresh() // update secrets (async) once per hour - depending on function call frequency\n  console.log(`secret-one has a value of \"${secretStore.get('secret-one').value}\" and was last updated ${Date.now() - secretStore.get('secret-one').updated} seconds ago`)\n}\n```\n\n## API\n\nThe module returns an object containing multiple functions. The functions are specified below.\n\nAll methods are _promise-friendly_\n\n### SecretStore\n\n#### SecretStore.secrets\n\nType: `Array`\n\nExposes the internal array of all secrets.\n\n#### SecretStore.isUpdating\n\nType: `Boolean`\n\nIs true if there is a `refresh()` in progress.\n\n#### new SecretStore(keyVaultUrl, createKeyVaultClientFn)\n\nCreate a new SecretStore instance. Specify the URL endpoint of the KeyVault and a function that will (eventually) return a valid **azure-keyvault** client. See below for ways to get a client.\n\n##### keyVaultUrl\n\nType: `string`\n\nURL endpoint of an Azure KeyVault e.g. https://myvault.vault.azure.net\n\n##### createKeyVaultClientFn\n\nType: `function`\n\nA function that will either return a valid client or a Promise that resolves to one.\n\n#### secretStore.add(secretName)\n\nAdd a secret to the store that should be fetched from the KeyVault. Returns the instance itself so the method can be chained.\n\n##### secretName\n\nType: `string`\n\nSame name that the secret has in the vault.\n\n#### secretStore.age()\n\nReturns the number of seconds since the store has been refreshed.\n\n#### secretStore.refresh()\n\nFetch the current values for all secrets added to the store from KeyVault. Returns a Promise resolving to the updated `SecretStore` instance.\n\nThis method will `Promise.reject` if any of the added secrets can not be fetched from KeyVault. The resulting error message is a transparent message from the **azure-keyvault** library:\n\n```javascript\n{\n  \"statusCode\": 404,\n  \"request\": {...},\n  \"response\": {...},\n  \"code\": \"SecretNotFound\",\n  \"body\": {\n    \"error\": {\n      \"code\": \"SecretNotFound\",\n      \"message\": \"Secret not found: another-secret\"\n    }\n  }\n}\n```\n\n#### secretStore.get(secretName)\n\nFetch the contents of a specific secret.\n\n##### secretName\n\nType: `string`\n\nSame name as previously used during `.add()`\n\n##### return\nWill return an object containing:\n\n```javascript\n{\n  name: 'secretName',\n  value: 'supersecret',\n  updated: '2010-10-20T20:10:00.123Z'\n}\n```\n\nif `refresh()` has not been called the secrets will default to\n\n```javascript\n{\n  name: 'secretName',\n  value: null,\n  updated: '1970-01-01T00:00:00.000Z'\n}\n```\n\n### getKeyVaultClient(options)\n\nGet a valid KeyVaultClient to be used in `SecretStore` constructor. Supply authentication options via _options_ argument. Either need a valid `msiEndpoint` in case MSI is activated or Service Principal credentials.\nReturns a Promise resolving to a client.\n\n#### options.clientId\n\nType: `string`\n\nService Principal ID that has access to the KeyVault.\n\n#### options.clientSecret\n\nType: `string`\n\nService Principal Secret that has access to the KeyVault.\n\n#### options.tenantId\n\nType: `string`\n\nAzure AD tenant where KeyVault and SP are hosted.\n\n#### options.msiEndpoint\n\nType: `string`\n\nThe Managed Service Identity endpoint for your function. Usually available via `process.env.MSI_ENDPOINT` after activating MSI.\n\n### createKeyVaultClient()\n\nA bootstrapped version of `getKeyVaultClient()` that reads some default environment variables and uses those to create a valid client. This works off the shelf if MSI is activated, otherwise Service Principal credentials have to be exposed to the process.\n\n```javascript\nprocess.env['CLIENT_ID'] // -\u003e options.clientId\nprocess.env['CLIENT_SECRET'] // -\u003e options.clientSecret\nprocess.env['TENANT_ID'] // -\u003e options.tenantId\nprocess.env['MSI_ENDPOINT'] // -\u003e options.msiEndpoint\n```\n\n## License\n\n[MIT](./LICENSE) by [Andreas Offenhaeuser](https://anoff.io)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanoff%2Fazure-keyvault-secretstore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanoff%2Fazure-keyvault-secretstore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanoff%2Fazure-keyvault-secretstore/lists"}