Skip to content

Commit 596fbfb

Browse files
authored
fix: Fail when Intrinsics are in SourceVPC list instead of IntrinsicsSourceVPC (#1999)
1 parent 90edf3e commit 596fbfb

File tree

6 files changed

+127
-24
lines changed

6 files changed

+127
-24
lines changed

samtranslator/swagger/swagger.py

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,8 @@ def add_resource_policy(self, resource_policy, path, api_id, stage):
892892
ip_range_blacklist = resource_policy.get("IpRangeBlacklist")
893893
source_vpc_whitelist = resource_policy.get("SourceVpcWhitelist")
894894
source_vpc_blacklist = resource_policy.get("SourceVpcBlacklist")
895+
896+
# Intrinsic's supported in these properties
895897
source_vpc_intrinsic_whitelist = resource_policy.get("IntrinsicVpcWhitelist")
896898
source_vpce_intrinsic_whitelist = resource_policy.get("IntrinsicVpceWhitelist")
897899
source_vpc_intrinsic_blacklist = resource_policy.get("IntrinsicVpcBlacklist")
@@ -913,31 +915,38 @@ def add_resource_policy(self, resource_policy, path, api_id, stage):
913915
resource_list = self._get_method_path_uri_list(path, api_id, stage)
914916
self._add_ip_resource_policy_for_method(ip_range_blacklist, "IpAddress", resource_list)
915917

916-
if (
917-
(source_vpc_blacklist is not None)
918-
or (source_vpc_intrinsic_blacklist is not None)
919-
or (source_vpce_intrinsic_blacklist is not None)
920-
):
921-
blacklist_dict = {
922-
"StringEndpointList": source_vpc_blacklist,
923-
"IntrinsicVpcList": source_vpc_intrinsic_blacklist,
924-
"IntrinsicVpceList": source_vpce_intrinsic_blacklist,
925-
}
926-
resource_list = self._get_method_path_uri_list(path, api_id, stage)
927-
self._add_vpc_resource_policy_for_method(blacklist_dict, "StringEquals", resource_list)
918+
if not SwaggerEditor._validate_list_property_is_resolved(source_vpc_blacklist):
919+
raise InvalidDocumentException(
920+
[
921+
InvalidTemplateException(
922+
"SourceVpcBlacklist must be a list of strings. Use IntrinsicVpcBlacklist instead for values that use Intrinsic Functions"
923+
)
924+
]
925+
)
928926

929-
if (
930-
(source_vpc_whitelist is not None)
931-
or (source_vpc_intrinsic_whitelist is not None)
932-
or (source_vpce_intrinsic_whitelist is not None)
933-
):
934-
whitelist_dict = {
935-
"StringEndpointList": source_vpc_whitelist,
936-
"IntrinsicVpcList": source_vpc_intrinsic_whitelist,
937-
"IntrinsicVpceList": source_vpce_intrinsic_whitelist,
938-
}
939-
resource_list = self._get_method_path_uri_list(path, api_id, stage)
940-
self._add_vpc_resource_policy_for_method(whitelist_dict, "StringNotEquals", resource_list)
927+
blacklist_dict = {
928+
"StringEndpointList": source_vpc_blacklist,
929+
"IntrinsicVpcList": source_vpc_intrinsic_blacklist,
930+
"IntrinsicVpceList": source_vpce_intrinsic_blacklist,
931+
}
932+
resource_list = self._get_method_path_uri_list(path, api_id, stage)
933+
self._add_vpc_resource_policy_for_method(blacklist_dict, "StringEquals", resource_list)
934+
935+
if not SwaggerEditor._validate_list_property_is_resolved(source_vpc_whitelist):
936+
raise InvalidDocumentException(
937+
[
938+
InvalidTemplateException(
939+
"SourceVpcWhitelist must be a list of strings. Use IntrinsicVpcWhitelist instead for values that use Intrinsic Functions"
940+
)
941+
]
942+
)
943+
944+
whitelist_dict = {
945+
"StringEndpointList": source_vpc_whitelist,
946+
"IntrinsicVpcList": source_vpc_intrinsic_whitelist,
947+
"IntrinsicVpceList": source_vpce_intrinsic_whitelist,
948+
}
949+
self._add_vpc_resource_policy_for_method(whitelist_dict, "StringNotEquals", resource_list)
941950

942951
self._doc[self._X_APIGW_POLICY] = self.resource_policy
943952

@@ -1268,3 +1277,17 @@ def safe_compare_regex_with_string(regex, data):
12681277
def get_path_without_trailing_slash(path):
12691278
# convert greedy paths to such as {greedy+}, {proxy+} to "*"
12701279
return re.sub(r"{([a-zA-Z0-9._-]+|[a-zA-Z0-9._-]+\+|proxy\+)}", "*", path)
1280+
1281+
@staticmethod
1282+
def _validate_list_property_is_resolved(property_list):
1283+
"""
1284+
Validate if the values of a Property List are all of type string
1285+
1286+
:param property_list: Value of a Property List
1287+
:return bool: True if the property_list is all of type string otherwise False
1288+
"""
1289+
1290+
if property_list is not None and not all(isinstance(x, string_types) for x in property_list):
1291+
return False
1292+
1293+
return True

tests/swagger/test_swagger.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,18 @@ def test_must_add_vpc_allow_string_only(self):
11811181

11821182
self.assertEqual(deep_sort_lists(expected), deep_sort_lists(self.editor.swagger[_X_POLICY]))
11831183

1184+
@parameterized.expand(
1185+
[
1186+
param("SourceVpcWhitelist"),
1187+
param("SourceVpcBlacklist"),
1188+
]
1189+
)
1190+
def test_must_fail_when_vpc_whitelist_is_non_string(self, resource_policy_key):
1191+
resource_policy = {resource_policy_key: [{"sub": "somevalue"}]}
1192+
1193+
with self.assertRaises(InvalidDocumentException):
1194+
self.editor.add_resource_policy(resource_policy, "/foo", "123", "prod")
1195+
11841196
def test_must_add_vpc_deny_string_only(self):
11851197

11861198
resourcePolicy = {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Globals:
2+
Api:
3+
Auth:
4+
ResourcePolicy:
5+
SourceVpcBlacklist: [{"Ref":"SomeParameter"}]
6+
7+
Parameters:
8+
SomeParameter:
9+
Type: String
10+
Default: param
11+
12+
Resources:
13+
MyFunction:
14+
Type: AWS::Serverless::Function
15+
Properties:
16+
InlineCode: |
17+
exports.handler = async (event) => {
18+
const response = {
19+
statusCode: 200,
20+
body: JSON.stringify('Hello from Lambda!'),
21+
};
22+
return response;
23+
};
24+
Handler: index.handler
25+
Runtime: nodejs12.x
26+
Events:
27+
Api:
28+
Type: Api
29+
Properties:
30+
Method: Put
31+
Path: /get
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Globals:
2+
Api:
3+
Auth:
4+
ResourcePolicy:
5+
SourceVpcWhitelist: [{"Ref":"SomeParameter"}]
6+
7+
Parameters:
8+
SomeParameter:
9+
Type: String
10+
Default: param
11+
12+
Resources:
13+
MyFunction:
14+
Type: AWS::Serverless::Function
15+
Properties:
16+
InlineCode: |
17+
exports.handler = async (event) => {
18+
const response = {
19+
statusCode: 200,
20+
body: JSON.stringify('Hello from Lambda!'),
21+
};
22+
return response;
23+
};
24+
Handler: index.handler
25+
Runtime: nodejs12.x
26+
Events:
27+
Api:
28+
Type: Api
29+
Properties:
30+
Method: Put
31+
Path: /get
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. SourceVpcBlacklist must be a list of strings. Use IntrinsicVpcBlacklist instead for values that use Intrinsic Functions"
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. SourceVpcWhitelist must be a list of strings. Use IntrinsicVpcWhitelist instead for values that use Intrinsic Functions"
3+
}

0 commit comments

Comments
 (0)