npm install aws-ssmHelps to provide a simple interaction with AWS's
SSM Parameter Store.
First install:
``sh`npm
npm install aws-ssmyarn
yarn add aws-ssm
Then you can use in your Typescript/Javascript file like so:
`typescript
import SSM from "aws-ssm";
const ssm = new SSM({
// Config
});
function doSomething(name: string) {
const param = await ssm.get(name);
// ...
}
`
The following basic functions are available from aws-ssm:
`typescript
// get a value from SSM
function get(name: string, options?: ISsmGetOptions);
// add a value to SSM; use { overwrite: true } in options if you updating
function put(name: string, value: SsmType, options?: ISsmSetOptions);
// list all or a subset of SSM Parameters
function list(options);
// the same as list but values are decrypted
function values(path, options);
// remove a SSM module
function remove(name, options);
// get a hash of SSM values (decrypted) by module name
function modules(moduleNames[], options)
/**
* very similar to list but uses a differnt API endpoint which
* loses the ability to bring back _values_ but adds the user
* who last updated the parameter.
*/
function describeParameters();
`
With SSM you're able to use any naming you choose for your variables and that includes
full "paths" (aka, strings with the "/" character deliminiting the name). With aws-ssm
we have established a naming convention which follows the following structure:
> / [ stage ] / [ version ] / [ system ] / [ NAME ]
So, for example, if you were using the Firebase Admin SDK you'd likely want to set the
_production_ service account as:
`typescript`
const ssm = new SSM(/* config /);
await ssm.put("/prod/1/firebase/SERVICE_ACCOUNT", "...");
Because of convention, we are afforded a lot of convenience assuming we follow some basic
environment variable conventions:
`typescript`
const ssm = new SSM(/* config /);
const serviceAccount = await ssm.get("firebase/SERVICE_ACCOUNT");
The above will resolve the _stage_ for you so long as the AWS_STAGE environment variableNODE_ENV
is set (or as a fallback the variable) and the version will be set to "1"AWS_VERSION
unless the is set.
This library is intended to work both as an aid to CLI tools as well as programatically
embedded into your serverless functions (or other code I guess). Because of this there are
two main modalities for configuration.
When you're using a CLI you'll want to simply provide a "profile name" which can be looked
up in the user's AWS credentials file ( ~/.aws/credentials ). So assuming you have a
profile in your credentials file named "myProject" you could use the following to
configure aws-ssm:
`typescript`
const ssm = new SSM({ profile: "myProject" });
When your using this library with serverless functions you will need to ensure they have
permission to execute SSM actions. Assuming you are using the
Serverless Framework, you would provide permissions something
like the following:
`typescriptarn:aws:ssm:${REGION}:${ACCOUNT}:parameter*
const ssmPermissions: IServerlessIAMRole = {
Effect: "Allow",
Action: ["ssm:GetParameter", "ssm:GetParametersByPath"],
Resource: []`
};
> Note: we're suckers for TS and typing but you'll probably need to convert the above
> to YAML for your purposes; unless of course you're using the
> typescript-microservice
> yeoman template.
You'll notice that we allowed access to all SSM paths for the given region and account but
actually probably a smarter strategy would be to limit access to the _stage_ you're in:
> Resource: [ 'arn:aws:ssm:${REGION}:${ACCOUNT}:parameter-${STAGE}*' ]
Final note, if it wasn't clear. When you give permissions at deploy time, your serverless
code executed at run time needs zero config because it by default has permissions:
`typescript`
const ssm = new SSM();
If you want you can also programatically add in the AWS Credentials at run time:
`typescript`
const ssm = new SSM({
CredentialsOptions: {
accessKey: "abc",
secretAccessKey: "123"
}
});
You can also add the following config items to your configuration (regardless of which
strategy from above you use):
- cli - by default this logger will not output anything to stdout but if you turndefaultType
this on with a "TRUE" then it will output useful CLI output
- - by default variables will be presumed to be of type "SecureString" but
you change this to "String" if you prefer that as a default type
Since we build this library in large part to be used within AWS serverless architectures,
we wanted to conclude with what we see as a good example of usage of aws-ssm in a AWS
Lambda function. In this example we'll assume that the particular module depends on
getting secrets from "firebase" and "logzio". In this case we might write the handler
function like this:
`typescript
let _secrets: ISsmExportsOutput;
const getSecrets = async () => {
if(!_secrets) {
const ssm = new SSM();
_secrets = await ssm.modules(["firebase", "logzio"]);
}
return _secrets;
};
const async handler(event, context, callback) {
const secrets = await getSecrets();
// ...
const db = await DB.connect( secrets.firebase.serviceAccount );
}
`
In the above example we provide a compact way of specifying the modules we want secrets
on. Assuming that the environment variables are set -- which you should always do anyway
-- then aws-ssm` will have no issues resolving all secrets. At the same time, there is a
time cost in using SSM so we have wrapped the functionality in a way that ensures that if
the AWS Lambda function is _reused_ (aka, a warm start) then the SSM calls will not be
made after the first time.
Copyright (c) 2019 Inocan Group
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.