Best Practices for Storing a Secret Key that Changes Every X Months?

I use an API that requires me to change the API secret key every X months. They give me an API endpoint I can call so this can be done programatically. I’m trying to figure out where to store the updated key. I don’t think I can programmatically update the settings.json file. I don’t see any articles advising me to put it in my database.

What are best practices for storing a dynamically changing key like this?

We have created a separate git repository exclusively for system configuration data of our various deployment environments (dev, stage, prod).

Each file is actually a mongodb shell script to update a single particular configuration document for the designated environment, neatly organized in separate (parallel) directories.

Note:

  • the repository does not contain any source file of our app or any other file related to development
  • it can only be accessed by select members of our team with different credentials.

We also have a script to execute all mongodb shell scripts for a specific environment.

At the end all configuration documents are upserted in mongodb, easy to be fetched (and, if deemed necessary, cached) on the Meteor server instances. This approach comes with a number of benefits:

  • access limited to individuals with higher privileges
  • changes to data are tracked in git (who / when / what)
  • no redeployment of the app is needed if configuration data gets updated
  • in case the config data is cached on the server(s), cache invalidation is still easy via redis pub/sub based notification

Final remark, not strictly related to the original question: although we didn’t implement this last bit, this approach also allows for a dynamic changing of Meteor.settings.public (i.e. client settings). As noted in the Meteor documentation about settings:

Changes to Meteor.settings.public at runtime will be picked up by new client connections.

I.e. the only limitation is that Meteor.settings.public of currently running clients would not be updated.

1 Like

How about something like this:

  • Install an npm RSA package e.g. node-rsa.
  • Create a database table called settings with fields xxx_api_key and rsa_public_key
  • Generate a .pem file – store the public key in the db table settings-> rsa_public_key and store the private key in settings.json
  • Encrypt the api secret key with rsa and store it in the db table settings-> xxx_api_key
  • When needed for the api, load xxx_api_key from the db, and rsa-decrypt it using the private key from settings.json

Would something like that potentially be effective?

2 Likes

Do you host on Galaxy or on other platforms?

That would certainly work and would make things safe®. Storing the public key along with the encrypted data is not even necessary in this instance, you could keep it in settings.json along with the private key.

Depending on the expected frequency of access, it would probably make sense to cache it after decryption.

OTOH when it comes to highly sensitive secret data, such as e.g. bank account credentials, I would keep them in settings.json – they aren’t prone to change anyway.

1 Like

Yes, I am hosting on Galaxy.

@peterfkruger Thanks very much for this feedback.

I hadn’t previously heard of caching data on the server. Is there a best practices way to cache non-Mongo data server-side?

1 Like

I don’t know about best practices in this respect. We use js-cache both on the client and on the server, and it works flawlessly.

We use it to cache data from MongoDB that we know will either not become stale anytime soon, or even if it does, it’s not a real problem. In another instance the cache will be used to store the IP-based geolocation as resolved by an external system.

In some cases, some mechanism needs to be provided for a cache invalidation from outside: as I hinted earlier, redis pub/sub is an easy way to deal with this. The advantage of this is that even if your app runs in several instances, the cache invalidation takes place everywhere.

1 Like