vault-sync
v2.0.4
Published
Generate configuration object from HashiCorp Vault by automatic authenticating with local token or kubernetes service account in pod environment.
Downloads
4,921
Readme
vault-sync
Generate configuration object synchronously from HashiCorp Vault by automatic authenticating with locally cached token or kubernetes service account in pod environment.
Features
- This module is built to pursue identical configuration way between local development and remote deployment in kubernetes.
- This module exports a single function to create an JavaScript Object (or any type).
- The function works in synchronous way by mimicking RPC call for asynchronous HTTP requests. It is a bad practice, but this is for the synchronous configuration loading at bootstrap.
- How it works:
- At first, It will try to use locally cached token (
~/.vault-token
). - If there is no cached token, it will try to auth to vault with kubernetes service account token (
/var/run/secrets/kubernetes.io/serviceaccount/token
). - If there is no kubernetes service account token, it will throw an error.
- If got error while reading secrets it will throw the original error.
- At first, It will try to use locally cached token (
- Requirements:
- vault server with kubernetes auth method enabled.
Usage
1. Install
NPM
$ npm i --save vault-sync
2. Examples
./sync-config.ts
import vault from "vault-sync";
module.exports = vault(async (get, list, { dbType }) => {
return {
app: (await get("secret/data/test")).data.hello,
keys: (await list("secret/metadata")).keys,
foo: {
db: (await get(`database/${dbType}/test`)),
foo: "other-property",
bar: [1,2,3],
},
};
}, {
// vault connection setting
uri: "https://server.vault.svc.cluster.local",
debug: false,
// alternative auth method for kubernetes pod
method: "kubernetes",
role: "default",
// inject some variable
sandbox: {
dbType: process.env.DB_TYPE || "mysql",
},
});
./sync-example.js
const config = require("./sync-config");
// Work with config
console.log(config);
./async-config-example.js
const vault = require("vault-sync").default;
// rather do asynchronously
vault.async(async get => { ... }, { ... })
.then(config => {
console.log(config);
})
./production-example1.js
const vault = require("vault-sync").default;
/*
* Read mandatory environment variables
*/
process.env.APP_K8S_CLUSTER = process.env.APP_K8S_CLUSTER || "dev"; // dev, dev-2, prod, prod-2. prod-asia-northeast-1a-2, ... GKE cluster name
process.env.APP_ENV = process.env.APP_ENV || "dev"; // dev, stage, prod, ... app provision envrionment
module.exports = vault(async get => {
const webhooks = await get("common/data/webhooks").then(res => res.data);
return {
webhooks,
APP_ENV: process.env.APP_ENV,
};
}, {
// vault connection setting
uri: "https://vault.internal.qmit.pro",
debug: false,
// alternative auth method for kubernetes pod
method: `k8s/${process.env.APP_K8S_CLUSTER}`,
role: "default",
});
./production-example2.js
const vault = require("vault-sync").default;
/*
* Read mandatory environment variables
*/
process.env.APP_K8S_CLUSTER = process.env.APP_K8S_CLUSTER || "dev"; // dev, dev-2, prod, prod-2. prod-asia-northeast-1a-2, ... GKE cluster name
process.env.APP_ENV = process.env.APP_ENV || "dev"; // dev, stage, prod, ... app provision envrionment
const { APP_ENV, APP_K8S_CLUSTER } = process.env;
/*
* Read common credentials and metadata
*/
const config = vault(async (get, list) => {
const [
stackdriverCredentials,
services,
serviceKeysWithCredentials,
] = await Promise.all([
get("common/data/gcp-stackdriver-service-account").then(res => res.data),
get("common/data/services").then(res => res.data),
list("common/metadata/services/credentials").then(res => res.keys),
]);
return {
stackdriverCredentials,
services,
serviceKeysWithCredentials,
serviceKeys: services.groups.reduce((names, g) => names.concat(g.items.map(i => i.key)), []),
};
}, {
// vault connection setting
uri: "https://vault.internal.qmit.pro",
debug: false,
// alternative auth method for kubernetes pod
method: `k8s/${APP_K8S_CLUSTER}`,
role: "default",
});
TypeScript Support
Supported from ES6: async/await poly-filled.
Development
1. Test
Currently it dose not provide mocking environment for Vault and Kubernetes. Configure your vault environment and use telepresence for k8s to test.
yarn test
2. Test and update coverage badge
yarn test:badge
3. Mocking K8S pod environment
sudo sh -c "mkdir -p /var/run/secrets/kubernetes.io/serviceaccount/ && kubectl get -n default secret $(kubectl get sa default -n default -o jsonpath='{.secrets[0].name}') -o json | jq '.data.token' -r | base64 -D > /var/run/secrets/kubernetes.io/serviceaccount/token"
(or just) yarn mock
4. Publish
yarn build
yarn publish