Skip to content

Commit

Permalink
Merge pull request #7 from Asymmetrik/feature/add-ttl-for-cache
Browse files Browse the repository at this point in the history
Feature/add ttl for cache
  • Loading branch information
jyoung-asymmetrik committed Dec 4, 2017
2 parents 0c462df + dca5281 commit 0457ff4
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 8 deletions.
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ module.exports = (options) => {
region: module.exports.getSecretRegion(),
table: module.exports.getSecretTable(),
kmsKey: module.exports.getSecretKMSAlias(),
kmsRegion: module.exports.getSecretKMSRegion()
kmsRegion: module.exports.getSecretKMSRegion(),
cacheBuster: module.exports.getSecretCacheBusterKey()
});

return {
Expand All @@ -37,6 +38,7 @@ module.exports.getSecretRegion = env.getSecretRegion;
module.exports.getSecretPrefix = env.getSecretPrefix;
module.exports.getSecretKMSAlias = env.getSecretKMSAlias;
module.exports.getSecretKMSRegion = env.getSecretKMSRegion;
module.exports.getSecretCacheBusterKey = env.getSecretCacheBusterKey;

module.exports.generateSecretKey = require('./src/lib/secretGen');

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@asymmetrik/yadda-secret",
"description": "Client secret library",
"version": "0.0.8",
"version": "0.0.9",
"main": "index.js",
"author": "contributors",
"contributors": [
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ will need to be defined in the environment in order for this tool to work.
- `__YADDA__DEPLOYMENT_SECRET_PREFIX__`: The secret key prefix (*AppName/Region/Environment*)
- `__YADDA__DEPLOYMENT_SECRET_KMSALIAS__`: The KMS CMK alias to encrypt and decrypt
- `__YADDA__DEPLOYMENT_SECRET_REGION__`: The region the KMS key resides in (optional)
- `__YADDA__DEPLOYMENT_SECRET_CACHE_BUSTER_KEY__`: The key for the cache buster secret (optional)

Developers using this tool will not need access to the CMK but the resulting deployed container will need
access.
Expand Down
3 changes: 2 additions & 1 deletion src/lib/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ module.exports.getSecretTable = function(){ return process.env.__YADDA__DEPLOYME
module.exports.getSecretRegion = function(){ return process.env.__YADDA__DEPLOYMENT_SECRET_TABLE_REGION__ || null };
module.exports.getSecretPrefix = function(){ return process.env.__YADDA__DEPLOYMENT_SECRET_PREFIX__ || null };
module.exports.getSecretKMSAlias = function(){ return process.env.__YADDA__DEPLOYMENT_SECRET_KMSALIAS__ || null };
module.exports.getSecretKMSRegion = function(){ return process.env.__YADDA__DEPLOYMENT_SECRET_REGION__ || process.env.__YADDA__DEPLOYMENT_SECRET_TABLE_REGION__ || null };
module.exports.getSecretKMSRegion = function(){ return process.env.__YADDA__DEPLOYMENT_SECRET_REGION__ || process.env.__YADDA__DEPLOYMENT_SECRET_TABLE_REGION__ || null };
module.exports.getSecretCacheBusterKey = function(){ return process.env.__YADDA__DEPLOYMENT_SECRET_CACHE_BUSTER_KEY__ || null };
25 changes: 22 additions & 3 deletions src/lib/secretstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ class SecretStore {
if(!options.awsOpts.region)
throw new Error('AWS Region must be defined');

if(options.cacheBuster) {
// check the cache buster key every minute
const cacheBusterKey = options.cacheBuster;
setInterval(() => {
this.getSecret({name: cacheBusterKey}).then(secret => this.cacheRefreshTime = Number(secret));
}, 60000);
delete options.cacheBuster;
}
this.options = options;
this.store = new Credstash(options);
this.cache = {};
Expand All @@ -30,16 +38,27 @@ class SecretStore {
return new Promise((resolve, reject) => {
const key = secretGen(name);

if(key in this.cache)
return void resolve(this.cache[key]);
if(key in this.cache) {
// doing a less than comparison for a time to a null/undefined value will be false
if(this.cache[key].timestamp < this.cacheRefreshTime)
delete this.cache[key];
else
return void resolve(this.cache[key].value);
}

//Can't return this as it's not interpreted as a promise...
this.store.getSecret({
name: key,
version,
context
})
.then(secret => resolve(this.cache[key] = secret))
.then((secret) => {
this.cache[key] = {
timestamp: Date.now(),
value: secret
};
resolve(secret);
})
.catch(err => reject(err));
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ class Wrapper {
if(this.store)
return this.store;

const { region, table, kmsKey, kmsRegion } = this.options;
const { region, table, kmsKey, kmsRegion, cacheBuster } = this.options;
if(region && table)
this.store = new SecretStore({ table, awsOpts: { region }, kmsOpts: { region: kmsRegion }, kmsKey });
this.store = new SecretStore({ table, awsOpts: { region }, kmsOpts: { region: kmsRegion }, kmsKey, cacheBuster });
else {
console.warn('region and table are not defined!');
}
Expand Down

0 comments on commit 0457ff4

Please sign in to comment.