SSM parameters in cloudformation (AWS::SSM::Parameter::) are not recognized and resolved (#3929)

* Add ssm parsing support for cloudformation stacks

* Start adding unit tests for ssm parameter parsing

* Add tests for code update

* Add tests to parse ssm parameters code

* Fix black lint errors

* Fix bug.

* Need to specify region_name

* region needs to be same

* Use ssm_backends[region] instead of ssm_backend

* StringList -> string

* Linting

* check if servermode tests are on

* Typo

Co-authored-by: Bert Blommers <bblommers@users.noreply.github.com>
This commit is contained in:
Sahil Shah 2021-05-19 03:30:25 -04:00 committed by GitHub
parent 4ad6c3932e
commit 24fa8f25a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 0 deletions

View File

@ -41,6 +41,7 @@ from moto.sagemaker import models as sagemaker_models # noqa
from moto.sns import models as sns_models # noqa
from moto.sqs import models as sqs_models # noqa
from moto.stepfunctions import models as stepfunctions_models # noqa
from moto.ssm import models as ssm_models, ssm_backends # noqa
# End ugly list of imports
@ -516,6 +517,23 @@ class ResourceMap(collections_abc.Mapping):
parameter_slot = parameter_slots[key]
value_type = parameter_slot.get("Type", "String")
def _parse_ssm_parameter(value, value_type):
# The Value in SSM parameters is the SSM parameter path
# we need to use ssm_backend to retreive the
# actual value from parameter store
parameter = ssm_backends[self._region_name].get_parameter(
value, False
)
actual_value = parameter.value
if value_type.find("List") > 0:
return actual_value.split(",")
return actual_value
if value_type.startswith("AWS::SSM::Parameter::"):
value = _parse_ssm_parameter(value, value_type)
if value_type == "CommaDelimitedList" or value_type.startswith("List"):
value = value.split(",")

View File

@ -1,4 +1,5 @@
from __future__ import unicode_literals
import boto3
import json
import yaml
@ -12,6 +13,7 @@ from moto.cloudformation.parsing import (
parse_condition,
Export,
)
from moto import mock_ssm, settings
from moto.sqs.models import Queue
from moto.s3.models import FakeBucket
from moto.cloudformation.utils import yaml_tag_constructor
@ -73,6 +75,13 @@ parameters = {
}
}
ssm_parameter = {
"Parameters": {
"SingleParamCfn": {"Type": "AWS::SSM::Parameter::Value<String>"},
"ListParamCfn": {"Type": "AWS::SSM::Parameter::Value<List<String>>"},
}
}
split_select_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
@ -143,6 +152,9 @@ get_availability_zones_template = dict(
)
parameters_template = dict(list(dummy_template.items()) + list(parameters.items()))
ssm_parameter_template = dict(
list(dummy_template.items()) + list(ssm_parameter.items())
)
dummy_template_json = json.dumps(dummy_template)
name_type_template_json = json.dumps(name_type_template)
@ -151,6 +163,7 @@ bad_output_template_json = json.dumps(bad_outputs_template)
get_attribute_outputs_template_json = json.dumps(get_attribute_outputs_template)
get_availability_zones_template_json = json.dumps(get_availability_zones_template)
parameters_template_json = json.dumps(parameters_template)
ssm_parameter_template_json = json.dumps(ssm_parameter_template)
split_select_template_json = json.dumps(split_select_template)
sub_template_json = json.dumps(sub_template)
export_value_template_json = json.dumps(export_value_template)
@ -498,3 +511,29 @@ def test_short_form_func_in_yaml_teamplate():
]
for k, v in key_and_expects:
template_dict.should.have.key(k).which.should.be.equal(v)
@mock_ssm
def test_ssm_parameter_parsing():
client = boto3.client("ssm", region_name="us-west-1")
client.put_parameter(Name="/path/to/single/param", Value="string", Type="String")
client.put_parameter(
Name="/path/to/list/param", Value="comma,separated,string", Type="StringList"
)
if not settings.TEST_SERVER_MODE:
stack = FakeStack(
stack_id="test_id",
name="test_stack",
template=ssm_parameter_template_json,
parameters={
"SingleParamCfn": "/path/to/single/param",
"ListParamCfn": "/path/to/list/param",
},
region_name="us-west-1",
)
stack.resource_map.resolved_parameters["SingleParamCfn"].should.equal("string")
stack.resource_map.resolved_parameters["ListParamCfn"].should.equal(
["comma", "separated", "string"]
)