Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a flag to ssm variables to resolve as string instead of object #1

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/providers/aws/guide/variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,26 @@ custom:
- false
```

If the variable value is valid JSON but you expect the plaintext form, then you can use the extended syntax `~decryptAsPlaintext`.

```
custom:
supersecret: ${ssm:/aws/reference/secretsmanager/secret_ID_in_Secrets_Manager~decryptAsPlaintext}
```

variables will be resolved like

```yml
service: new-service
provider: aws
functions:
hello:
name: hello
handler: handler.hello
custom:
supersecret: '{"num": 1,"str": "secret","arr": [true, false]}' # a plain text string
```

## Reference Variables in Other Files

You can reference variables in other YAML or JSON files. To reference variables in other YAML files use the `${file(./myFile.yml):someProperty}` syntax in your `serverless.yml` configuration file. To reference variables in other JSON files use the `${file(./myFile.json):someProperty}` syntax. It is important that the file you are referencing has the correct suffix, or file extension, for its file type (`.yml` for YAML or `.json` for JSON) in order for it to be interpreted correctly. Here's an example:
Expand Down
12 changes: 9 additions & 3 deletions lib/classes/Variables.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class Variables {
this.stringRefSyntax = RegExp(/(?:('|").*?\1)/g);
this.cfRefSyntax = RegExp(/^(?:\${)?cf(\.[a-zA-Z0-9-]+)?:/g);
this.s3RefSyntax = RegExp(/^(?:\${)?s3:(.+?)\/(.+)$/);
this.ssmRefSyntax = RegExp(/^(?:\${)?ssm:([a-zA-Z0-9_.\-/]+)[~]?(true|false|split)?/);
this.ssmRefSyntax = RegExp(/^(?:\${)?ssm:([a-zA-Z0-9_.\-/]+)[~]?(true|false|split|decryptAsPlaintext)?/);
}

loadVariableSyntax() {
Expand Down Expand Up @@ -761,8 +761,10 @@ class Variables {
getValueFromSsm(variableString) {
const groups = variableString.match(this.ssmRefSyntax);
const param = groups[1];
const decrypt = groups[2] === 'true';
const decrypt = groups[2] === 'true' || groups[2] === 'decryptAsPlaintext';
const split = groups[2] === 'split';
const decryptAsPlaintext = groups[2] === 'decryptAsPlaintext';

return this.serverless
.getProvider('aws')
.request(
Expand All @@ -778,8 +780,12 @@ class Variables {
const plainText = response.Parameter.Value;
const type = response.Parameter.Type;
// Only if Secrets Manager. Parameter Store does not support JSON.
// if decryptAsPlaintext skip json parsing
// We cannot parse StringList types, so don't try
if (type !== 'StringList' && param.startsWith('/aws/reference/secretsmanager')) {
if (type !== 'StringList'
&& param.startsWith('/aws/reference/secretsmanager')
&& ! decryptAsPlaintext
) {
try {
const json = JSON.parse(plainText);
return BbPromise.resolve(json);
Expand Down
18 changes: 18 additions & 0 deletions lib/classes/Variables.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2290,6 +2290,24 @@ module.exports = {
.then()
.finally(() => ssmStub.restore());
});
it('should get value as text if extended syntax matches ~decryptAsPlaintext', () => {
const secretParam = '/aws/reference/secretsmanager/foo-bar';
const jsonLikeText = '{"str":"abc","num":123}';

const awsResponse = {
Parameter: {
Value: jsonLikeText,
},
};
const ssmStub = sinon
.stub(awsProvider, 'request')
.callsFake(() => BbPromise.resolve(awsResponse));
return serverless.variables
.getValueFromSsm(`ssm:${secretParam}~decryptAsPlaintext`)
.should.become(jsonLikeText)
.then()
.finally(() => ssmStub.restore());
});
it('should get value as text if returned value is NOT json-like', () => {
const secretParam = '/aws/reference/secretsmanager/foo-bar';
const plainText = 'I am plain text';
Expand Down