Using Vault's IAM Auth in NodeJS, part 2
• Mark Eschbach
Okay, so I’ve got the basics setup. This particular application predates the current platform, although it was half migrated to actually run. So it’s time to begin refactoring the application so we can properly configure it. Our usage of Sentry activates on load of a module intended to configure it. This worked well during the previous incarnation, however given I’m extracting credentails and injecting them this paradigm no longer works. We also have different environments which may not need this particular unit configured. I think the first step for me will be extacting the code running during module initialization into a function.
In the prior design we used
module.exports to return a refernece to the object initialized and configured in the module. I’m not realizing this provides a bit of a problem since I can’t stub it to throw an exception to catch places I miss in the dev cycle. Unforunate. Let’s see if I can void this again. I really want to say I’m jumping the gun here, however this module is sucked in fairly early so it doesn’t leave much wiggle room for configuration. It’s hooked through the main module, so I’ll have to pull it from there and place it in the command line driver.
Okay, turns out the application was less mature than I remember when I began migrating. Probably why I opted for just getting it running months ago. Meh. Okay, so after some refactoring I’ve got the primary debug entry point looking similar to the entry point for the production driver. I would love to unify the driver and reuse the code. Really the only difference is verifying how we have credentials. In Docker it’s just expected to be there, while under the debug driver it’s verified. I wrote a short script to checkout this SO post’s method of checking however I didn’t have any luck locally. The value yielded below is
let AWS =require('aws-sdk') let s3 = new AWS.S3() s3.config.credentials
I’m think I’m going to cheat here and use the same method Vault does: getCallerIdentity. Let’s see how this works. Worked like a charm once I remember you have to se the environment variable
true to ensure the
AWS_PROFILE is properly loaded. Note that setting the environment within the application doesn’t resolve the profile correctly and a brief search yielded nothing to report back about.
let AWS = require('aws-sdk') let sts = new AWS.STS() let ident_promise = sts.getCallerIdentity().promise()
Cool, with that check out of the way I can unify the two. Easily enough done. Now I can verify the code.
In a production scenario I expect the IAM profile fo the application to be implicit which allows for authentication with Vault. However this isn’t the case for a developer working locally, so in the process bootstrap I’ve had to the make the code diverge. It’s also reasonable as the application will also need to communicate with a different Vault instance. So I use environment variables to pass them in when in developer mode. I’m sure there are better soultions, however bootstrapping is always a bit interesting.
Now I must settle on a loggin library for our NodeJS systems. I’ve been on the fence for a while between Winston and Bunyan. Both seem well supported by the community and widely used. My requirements are fairly straight forward as I must be able to communicate via Syslog over TLS when deployed in production like environments and must produce huamn readable output otherwise. Having so much Java in my background I’m become accustom to hierarchical loggers to provide context and details. Looking through StrongLoop’s review of the two systems, the Child Loggers are really intriguing. The standard syslog library for Bunyan has a PR for adding TLS. Shouldn’t take to much effort to fork it. Oh hey! I’ve already done that! Hmm, while installing Bunyan, it also installed a dtrace library. I feel a bit uncomfortable like.
Getting Bunyan up and running for the root logger is exciting and easy. Definitely need to pipe the output through the
bunyan command to make it usable by any means locally. I need to return later to finish out the setup. I hope I can attach additional streams after construction of the initial logger.