Skip to content

Commit

Permalink
feat: always reference external SSM Parameters as Dynamic References …
Browse files Browse the repository at this point in the history
…(under feature flag)
  • Loading branch information
mrgrain committed Sep 26, 2022
1 parent 953d684 commit 3f75f28
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 7 deletions.
33 changes: 26 additions & 7 deletions packages/@aws-cdk/aws-ssm/lib/parameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import * as kms from '@aws-cdk/aws-kms';
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
import {
CfnDynamicReference, CfnDynamicReferenceService, CfnParameter,
ContextProvider, Fn, IResource, Resource, Stack, Token,
ContextProvider, FeatureFlags, Fn, IResource, Resource, Stack, Token,
Tokenization,
} from '@aws-cdk/core';
import * as cxapi from '@aws-cdk/cx-api';
import { Construct } from 'constructs';
import * as ssm from './ssm.generated';
import { arnForParameterName, AUTOGEN_MARKER } from './util';
Expand Down Expand Up @@ -473,9 +474,14 @@ export class StringParameter extends ParameterBase implements IStringParameter {

const type = attrs.type ?? attrs.valueType ?? ParameterValueType.STRING;

const stringValue = attrs.version
? new CfnDynamicReference(CfnDynamicReferenceService.SSM, `${attrs.parameterName}:${Tokenization.stringifyNumber(attrs.version)}`).toString()
: new CfnParameter(scope, `${id}.Parameter`, { type: `AWS::SSM::Parameter::Value<${type}>`, default: attrs.parameterName }).valueAsString;
let stringValue: string;
if (FeatureFlags.of(scope).isEnabled(cxapi.SSM_PARAMETER_IMPORT_AS_DYNAMIC_REFERENCE) ) {
stringValue = new CfnDynamicReference(CfnDynamicReferenceService.SSM, referencePatternFromAttributes(attrs)).toString();
} else {
stringValue = attrs.version
? new CfnDynamicReference(CfnDynamicReferenceService.SSM, referencePatternFromAttributes(attrs)).toString()
: new CfnParameter(scope, `${id}.Parameter`, { type: `AWS::SSM::Parameter::Value<${type}>`, default: attrs.parameterName }).valueAsString;
}

class Import extends ParameterBase {
public readonly parameterName = attrs.parameterName;
Expand Down Expand Up @@ -664,9 +670,14 @@ export class StringListParameter extends ParameterBase implements IStringListPar
const type = attrs.elementType ?? ParameterValueType.STRING;
const valueType = `List<${type}>`;

const stringValue = attrs.version
? new CfnDynamicReference(CfnDynamicReferenceService.SSM, `${attrs.parameterName}:${Tokenization.stringifyNumber(attrs.version)}`).toStringList()
: new CfnParameter(scope, `${id}.Parameter`, { type: `AWS::SSM::Parameter::Value<${valueType}>`, default: attrs.parameterName }).valueAsList;
let stringValue: string[];
if (FeatureFlags.of(scope).isEnabled(cxapi.SSM_PARAMETER_IMPORT_AS_DYNAMIC_REFERENCE) ) {
stringValue = new CfnDynamicReference(CfnDynamicReferenceService.SSM, referencePatternFromAttributes(attrs)).toStringList();
} else {
stringValue = attrs.version
? new CfnDynamicReference(CfnDynamicReferenceService.SSM, referencePatternFromAttributes(attrs)).toStringList()
: new CfnParameter(scope, `${id}.Parameter`, { type: `AWS::SSM::Parameter::Value<${valueType}>`, default: attrs.parameterName }).valueAsList;
}

class Import extends ParameterBase {
public readonly parameterName = attrs.parameterName;
Expand Down Expand Up @@ -771,3 +782,11 @@ function validateParameterName(parameterName: string) {
throw new Error(`name must only contain letters, numbers, and the following 4 symbols .-_/; got ${parameterName}`);
}
}

function referencePatternFromAttributes(attrs: StringParameterAttributes): string {
if (attrs.version) {
return `${attrs.parameterName}:${Tokenization.stringifyNumber(attrs.version)}`;
}

return attrs.parameterName;
}
24 changes: 24 additions & 0 deletions packages/@aws-cdk/cx-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,27 @@ becomes:
Principal:
AWS: "arn:aws:iam::123456789876:root"
```
* @aws-cdk/aws-ssm:importParameterAsDynamicReference
Enable this feature flag to change the default behavior for `aws-ssm.StringParameter.from*` methods to always use a dynamic reference.

Previously a dynamic reference was used for secure string parameters and when a parameter version was passed into `StringParameter.fromStringParameterAttributes.`. Otherwise a `CfnParameter` was created. This behavior was inconsistent and erroneously created a changeable CloudFormation Parameter for built-in SSM Parameters like Machine Image AMIs.

Users can still manually create SSM Parameters as template parameters:

```ts
declare ssmParameterName: string;
const ssmParameterValue = new CfnParameter(scope, id { type: `AWS::SSM::Parameter::Value<String>`, default: ssmParameterName }).valueAsString;
```

_cdk.json_

```json
{
"context": {
"@aws-cdk/aws-ssm:importParameterAsDynamicReference": true
}
}
```
10 changes: 10 additions & 0 deletions packages/@aws-cdk/cx-api/lib/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,15 @@ export const APIGATEWAY_DISABLE_CLOUDWATCH_ROLE = '@aws-cdk/aws-apigateway:disab
*/
export const ENABLE_PARTITION_LITERALS = '@aws-cdk/core:enablePartitionLiterals';

/**
* Enable this feature flag to change the default behavior for aws-smm.StringParameter.from* methods
* to always use a dynamic reference.
*
* Previously a dynamic reference was used for secure string parameters and when a parameter version was passed into
* StringParameter.fromStringParameterAttributes. Otherwise CfnParameter was created.
*/
export const SSM_PARAMETER_IMPORT_AS_DYNAMIC_REFERENCE = '@aws-cdk/aws-ssm:importParameterAsDynamicReference';

/**
* Flag values that should apply for new projects
*
Expand Down Expand Up @@ -387,6 +396,7 @@ export const FUTURE_FLAGS: { [key: string]: boolean } = {
[SNS_SUBSCRIPTIONS_SQS_DECRYPTION_POLICY]: true,
[APIGATEWAY_DISABLE_CLOUDWATCH_ROLE]: true,
[ENABLE_PARTITION_LITERALS]: true,
[SSM_PARAMETER_IMPORT_AS_DYNAMIC_REFERENCE]: true,
};

/**
Expand Down

0 comments on commit 3f75f28

Please sign in to comment.