enhancement(SSM): Add DataType attribute to SSM Parameters (#4232)

This commit is contained in:
Julian 2021-08-29 13:28:51 -03:00 committed by GitHub
parent dc49232734
commit 58da62cc71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 18 deletions

View File

@ -55,6 +55,7 @@ class Parameter(BaseModel):
keyid,
last_modified_date,
version,
data_type,
tags=None,
):
self.name = name
@ -64,6 +65,7 @@ class Parameter(BaseModel):
self.keyid = keyid
self.last_modified_date = last_modified_date
self.version = version
self.data_type = data_type
self.tags = tags or []
self.labels = []
@ -93,6 +95,7 @@ class Parameter(BaseModel):
"Value": self.decrypt(self.value) if decrypt else self.value,
"Version": self.version,
"LastModifiedDate": round(self.last_modified_date, 3),
"DataType": self.data_type,
}
if region:
@ -618,6 +621,14 @@ def _document_filter_match(filters, ssm_doc):
return True
def _valid_parameter_data_type(data_type):
"""
Parameter DataType field allows only `text` and `aws:ec2:image` values
"""
return data_type in ("text", "aws:ec2:image")
class SimpleSystemManagerBackend(BaseBackend):
def __init__(self, region_name=None):
super(SimpleSystemManagerBackend, self).__init__()
@ -1480,7 +1491,16 @@ class SimpleSystemManagerBackend(BaseBackend):
)
def put_parameter(
self, name, description, value, type, allowed_pattern, keyid, overwrite, tags,
self,
name,
description,
value,
type,
allowed_pattern,
keyid,
overwrite,
tags,
data_type,
):
if not value:
raise ValidationException(
@ -1504,6 +1524,15 @@ class SimpleSystemManagerBackend(BaseBackend):
"formed as a mix of letters, numbers and the following 3 symbols .-_"
)
raise ValidationException(invalid_prefix_error)
if not _valid_parameter_data_type(data_type):
# The check of the existence of an AMI ID in the account for a parameter of DataType `aws:ec2:image`
# is not supported. The parameter will be created.
# https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-ec2-aliases.html
raise ValidationException(
f"The following data type is not supported: {data_type} (Data type names are all lowercase.)"
)
previous_parameter_versions = self._parameters[name]
if len(previous_parameter_versions) == 0:
previous_parameter = None
@ -1522,15 +1551,16 @@ class SimpleSystemManagerBackend(BaseBackend):
last_modified_date = time.time()
self._parameters[name].append(
Parameter(
name,
value,
type,
description,
allowed_pattern,
keyid,
last_modified_date,
version,
tags or [],
name=name,
value=value,
type=type,
description=description,
allowed_pattern=allowed_pattern,
keyid=keyid,
last_modified_date=last_modified_date,
version=version,
tags=tags or [],
data_type=data_type,
)
)

View File

@ -277,9 +277,18 @@ class SimpleSystemManagerResponse(BaseResponse):
keyid = self._get_param("KeyId")
overwrite = self._get_param("Overwrite", False)
tags = self._get_param("Tags", [])
data_type = self._get_param("DataType", "text")
result = self.ssm_backend.put_parameter(
name, description, value, type_, allowed_pattern, keyid, overwrite, tags
name,
description,
value,
type_,
allowed_pattern,
keyid,
overwrite,
tags,
data_type,
)
if result is None:

View File

@ -232,9 +232,8 @@ def test_get_parameters_by_path():
@mock_ssm
def test_put_parameter(name):
client = boto3.client("ssm", region_name="us-east-1")
response = client.put_parameter(
Name=name, Description="A test parameter", Value="value", Type="String"
Name=name, Description="A test parameter", Value="value", Type="String",
)
response["Version"].should.equal(1)
@ -246,6 +245,7 @@ def test_put_parameter(name):
response["Parameters"][0]["Value"].should.equal("value")
response["Parameters"][0]["Type"].should.equal("String")
response["Parameters"][0]["Version"].should.equal(1)
response["Parameters"][0]["DataType"].should.equal("text")
response["Parameters"][0]["LastModifiedDate"].should.be.a(datetime.datetime)
response["Parameters"][0]["ARN"].should.equal(
"arn:aws:ssm:us-east-1:{}:parameter/{}".format(ACCOUNT_ID, name)
@ -271,15 +271,21 @@ def test_put_parameter(name):
response["Parameters"][0]["Value"].should.equal("value")
response["Parameters"][0]["Type"].should.equal("String")
response["Parameters"][0]["Version"].should.equal(1)
response["Parameters"][0]["DataType"].should.equal("text")
response["Parameters"][0]["LastModifiedDate"].should.equal(
initial_modification_date
)
response["Parameters"][0]["ARN"].should.equal(
"arn:aws:ssm:us-east-1:{}:parameter/{}".format(ACCOUNT_ID, name)
)
new_data_type = "aws:ec2:image"
response = client.put_parameter(
Name=name, Description="desc 3", Value="value 3", Type="String", Overwrite=True,
Name=name,
Description="desc 3",
Value="value 3",
Type="String",
Overwrite=True,
DataType=new_data_type,
)
response["Version"].should.equal(2)
@ -292,6 +298,8 @@ def test_put_parameter(name):
response["Parameters"][0]["Value"].should.equal("value 3")
response["Parameters"][0]["Type"].should.equal("String")
response["Parameters"][0]["Version"].should.equal(2)
response["Parameters"][0]["DataType"].should_not.equal("text")
response["Parameters"][0]["DataType"].should.equal(new_data_type)
response["Parameters"][0]["LastModifiedDate"].should_not.equal(
initial_modification_date
)
@ -394,12 +402,30 @@ def test_put_parameter_china():
response["Version"].should.equal(1)
@mock_ssm
@pytest.mark.parametrize("bad_data_type", ["not_text", "not_ec2", "something weird"])
def test_put_parameter_invalid_data_type(bad_data_type):
client = boto3.client("ssm", region_name="us-east-1")
with pytest.raises(ClientError) as e:
client.put_parameter(
Name="test_name", Value="some_value", Type="String", DataType=bad_data_type
)
ex = e.value
ex.operation_name.should.equal("PutParameter")
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.response["Error"]["Code"].should.contain("ValidationException")
ex.response["Error"]["Message"].should.equal(
f"The following data type is not supported: {bad_data_type}"
" (Data type names are all lowercase.)"
)
@mock_ssm
def test_get_parameter():
client = boto3.client("ssm", region_name="us-east-1")
client.put_parameter(
Name="test", Description="A test parameter", Value="value", Type="String"
Name="test", Description="A test parameter", Value="value", Type="String",
)
response = client.get_parameter(Name="test", WithDecryption=False)
@ -407,6 +433,7 @@ def test_get_parameter():
response["Parameter"]["Name"].should.equal("test")
response["Parameter"]["Value"].should.equal("value")
response["Parameter"]["Type"].should.equal("String")
response["Parameter"]["DataType"].should.equal("text")
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
response["Parameter"]["ARN"].should.equal(
"arn:aws:ssm:us-east-1:{}:parameter/test".format(ACCOUNT_ID)
@ -418,10 +445,10 @@ def test_get_parameter_with_version_and_labels():
client = boto3.client("ssm", region_name="us-east-1")
client.put_parameter(
Name="test-1", Description="A test parameter", Value="value", Type="String"
Name="test-1", Description="A test parameter", Value="value", Type="String",
)
client.put_parameter(
Name="test-2", Description="A test parameter", Value="value", Type="String"
Name="test-2", Description="A test parameter", Value="value", Type="String",
)
client.label_parameter_version(
@ -433,6 +460,7 @@ def test_get_parameter_with_version_and_labels():
response["Parameter"]["Name"].should.equal("test-1")
response["Parameter"]["Value"].should.equal("value")
response["Parameter"]["Type"].should.equal("String")
response["Parameter"]["DataType"].should.equal("text")
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
response["Parameter"]["ARN"].should.equal(
"arn:aws:ssm:us-east-1:{}:parameter/test-1".format(ACCOUNT_ID)
@ -442,6 +470,7 @@ def test_get_parameter_with_version_and_labels():
response["Parameter"]["Name"].should.equal("test-2")
response["Parameter"]["Value"].should.equal("value")
response["Parameter"]["Type"].should.equal("String")
response["Parameter"]["DataType"].should.equal("text")
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
response["Parameter"]["ARN"].should.equal(
"arn:aws:ssm:us-east-1:{}:parameter/test-2".format(ACCOUNT_ID)
@ -451,6 +480,7 @@ def test_get_parameter_with_version_and_labels():
response["Parameter"]["Name"].should.equal("test-2")
response["Parameter"]["Value"].should.equal("value")
response["Parameter"]["Type"].should.equal("String")
response["Parameter"]["DataType"].should.equal("text")
response["Parameter"]["LastModifiedDate"].should.be.a(datetime.datetime)
response["Parameter"]["ARN"].should.equal(
"arn:aws:ssm:us-east-1:{}:parameter/test-2".format(ACCOUNT_ID)
@ -532,6 +562,7 @@ def test_describe_parameters():
parameters.should.have.length_of(1)
parameters[0]["Name"].should.equal("test")
parameters[0]["Type"].should.equal("String")
parameters[0]["DataType"].should.equal("text")
parameters[0]["AllowedPattern"].should.equal(r".*")