From 7b47b8703e5fa21f3c1ace67da5f40e309d2c484 Mon Sep 17 00:00:00 2001 From: Praneeta Prakash Date: Tue, 4 Feb 2020 08:56:10 -0800 Subject: [PATCH] fix: bug fixes in api resource policies (#1395) --- .../api_resource_policy/template.yaml | 37 ++- samtranslator/model/api/api_generator.py | 2 + samtranslator/model/eventsources/push.py | 6 +- samtranslator/model/sam_resources.py | 12 +- samtranslator/swagger/swagger.py | 49 ++-- tests/swagger/test_swagger.py | 44 +++- ...h_if_conditional_with_resource_policy.yaml | 54 +++++ .../api_with_resource_policy_global.yaml | 40 ++- .../input/api_with_source_vpc_whitelist.yaml | 10 +- ...i_with_basic_custom_domain_intrinsics.json | 6 +- ...h_if_conditional_with_resource_policy.json | 219 +++++++++++++++++ .../output/api_with_resource_policy.json | 60 +++-- .../api_with_resource_policy_global.json | 163 ++++++++----- .../output/api_with_source_vpc_blacklist.json | 46 ++-- .../output/api_with_source_vpc_whitelist.json | 146 +++++------ ...h_if_conditional_with_resource_policy.json | 227 ++++++++++++++++++ .../aws-cn/api_with_resource_policy.json | 60 +++-- .../api_with_resource_policy_global.json | 173 +++++++------ .../aws-cn/api_with_source_vpc_blacklist.json | 46 ++-- .../aws-cn/api_with_source_vpc_whitelist.json | 160 +++++------- ...h_if_conditional_with_resource_policy.json | 227 ++++++++++++++++++ .../aws-us-gov/api_with_resource_policy.json | 60 +++-- .../api_with_resource_policy_global.json | 173 +++++++------ .../api_with_source_vpc_blacklist.json | 32 +-- .../api_with_source_vpc_whitelist.json | 160 +++++------- tests/translator/test_translator.py | 1 + versions/2016-10-31.md | 15 +- 27 files changed, 1527 insertions(+), 701 deletions(-) create mode 100644 tests/translator/input/api_with_if_conditional_with_resource_policy.yaml create mode 100644 tests/translator/output/api_with_if_conditional_with_resource_policy.json create mode 100644 tests/translator/output/aws-cn/api_with_if_conditional_with_resource_policy.json create mode 100644 tests/translator/output/aws-us-gov/api_with_if_conditional_with_resource_policy.json diff --git a/examples/2016-10-31/api_resource_policy/template.yaml b/examples/2016-10-31/api_resource_policy/template.yaml index d6f4604ed..808603414 100644 --- a/examples/2016-10-31/api_resource_policy/template.yaml +++ b/examples/2016-10-31/api_resource_policy/template.yaml @@ -1,22 +1,33 @@ AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 +Conditions: + C1: + Fn::Equals: + - true + - true Globals: Api: Auth: ResourcePolicy: - CustomStatements: [{ - "Effect": "Allow", - "Principal": "*", - "Action": "execute-api:Invoke", - "Resource": "execute-api:/Prod/PUT/get", - "Condition": { - "IpAddress": { - "aws:SourceIp": "1.2.3.4" - } - } - }] - # OR you can use the following, they both do the same thing - IpRangeBlacklist: ['1.2.3.4'] + CustomStatements: + Fn::If: + - C1 + - Principal: '*' + Action: execute-api:Invoke + Resource: + - execute-api:/Prod/PUT/get + Condition: + IpAddress: + aws:SourceIp: 1.2.3.4 + - Principal: '*' + Action: execute-api:Invoke + Resource: + - execute-api:/Prod/PUT/get + Condition: + IpAddress: + aws:SourceIp: 5.6.7.8 + # OR you can use the following + # IpRangeBlacklist: ['1.2.3.4'] Resources: MyFunction: Type: AWS::Serverless::Function diff --git a/samtranslator/model/api/api_generator.py b/samtranslator/model/api/api_generator.py index fcaf689e4..fe6d139b6 100644 --- a/samtranslator/model/api/api_generator.py +++ b/samtranslator/model/api/api_generator.py @@ -535,6 +535,8 @@ def _add_auth(self): swagger_editor.add_resource_policy( auth_properties.ResourcePolicy, path, self.logical_id, self.stage_name ) + if auth_properties.ResourcePolicy.get("CustomStatements"): + swagger_editor.add_custom_statements(auth_properties.ResourcePolicy.get("CustomStatements")) self.definition_body = self._openapi_postprocess(swagger_editor.swagger) diff --git a/samtranslator/model/eventsources/push.py b/samtranslator/model/eventsources/push.py index 42eab76d5..0c841f223 100644 --- a/samtranslator/model/eventsources/push.py +++ b/samtranslator/model/eventsources/push.py @@ -545,6 +545,7 @@ def to_cloudformation(self, **kwargs): resources = [] function = kwargs.get("function") + intrinsics_resolver = kwargs.get("intrinsics_resolver") if not function: raise TypeError("Missing required keyword argument: function") @@ -557,7 +558,7 @@ def to_cloudformation(self, **kwargs): explicit_api = kwargs["explicit_api"] if explicit_api.get("__MANAGE_SWAGGER"): - self._add_swagger_integration(explicit_api, function) + self._add_swagger_integration(explicit_api, function, intrinsics_resolver) return resources @@ -600,7 +601,7 @@ def _get_permission(self, resources_to_link, stage, suffix): return self._construct_permission(resources_to_link["function"], source_arn=source_arn, suffix=suffix) - def _add_swagger_integration(self, api, function): + def _add_swagger_integration(self, api, function, intrinsics_resolver): """Adds the path and method for this Api event source to the Swagger body for the provided RestApi. :param model.apigateway.ApiGatewayRestApi rest_api: the RestApi to which the path and method should be added. @@ -639,6 +640,7 @@ def _add_swagger_integration(self, api, function): if self.Auth: method_authorizer = self.Auth.get("Authorizer") api_auth = api.get("Auth") + api_auth = intrinsics_resolver.resolve_parameter_refs(api_auth) if method_authorizer: api_authorizers = api_auth and api_auth.get("Authorizers") diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index 910aa6618..3d1af1af8 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -168,7 +168,11 @@ def to_cloudformation(self, **kwargs): try: resources += self._generate_event_resources( - lambda_function, execution_role, kwargs["event_resources"], lambda_alias=lambda_alias + lambda_function, + execution_role, + kwargs["event_resources"], + intrinsics_resolver, + lambda_alias=lambda_alias, ) except InvalidEventException as e: raise InvalidResourceException(self.logical_id, e.message) @@ -563,7 +567,9 @@ def order_events(event): return logical_id return event_dict.get("Properties", {}).get("Path", logical_id) - def _generate_event_resources(self, lambda_function, execution_role, event_resources, lambda_alias=None): + def _generate_event_resources( + self, lambda_function, execution_role, event_resources, intrinsics_resolver, lambda_alias=None + ): """Generates and returns the resources associated with this function's events. :param model.lambda_.LambdaFunction lambda_function: generated Lambda function @@ -591,6 +597,7 @@ def _generate_event_resources(self, lambda_function, execution_role, event_resou # When Alias is provided, connect all event sources to the alias and *not* the function "function": lambda_alias or lambda_function, "role": execution_role, + "intrinsics_resolver": intrinsics_resolver, } for name, resource in event_resources[logical_id].items(): @@ -773,7 +780,6 @@ def to_cloudformation(self, **kwargs): self.BinaryMediaTypes = intrinsics_resolver.resolve_parameter_refs(self.BinaryMediaTypes) self.Domain = intrinsics_resolver.resolve_parameter_refs(self.Domain) self.Auth = intrinsics_resolver.resolve_parameter_refs(self.Auth) - redeploy_restapi_parameters = kwargs.get("redeploy_restapi_parameters") api_generator = ApiGenerator( diff --git a/samtranslator/swagger/swagger.py b/samtranslator/swagger/swagger.py index 9c8d0575e..abd15b92c 100644 --- a/samtranslator/swagger/swagger.py +++ b/samtranslator/swagger/swagger.py @@ -3,8 +3,8 @@ import re from six import string_types -from samtranslator.model.intrinsics import ref -from samtranslator.model.intrinsics import make_conditional, fnSub +from samtranslator.model.intrinsics import ref, is_intrinsic_no_value +from samtranslator.model.intrinsics import make_conditional, fnSub, is_intrinsic_if from samtranslator.model.exceptions import InvalidDocumentException, InvalidTemplateException @@ -804,7 +804,6 @@ def add_resource_policy(self, resource_policy, path, api_id, stage): ip_range_blacklist = resource_policy.get("IpRangeBlacklist") source_vpc_whitelist = resource_policy.get("SourceVpcWhitelist") source_vpc_blacklist = resource_policy.get("SourceVpcBlacklist") - custom_statements = resource_policy.get("CustomStatements") if aws_account_whitelist is not None: resource_list = self._get_method_path_uri_list(path, api_id, stage) @@ -824,16 +823,16 @@ def add_resource_policy(self, resource_policy, path, api_id, stage): if source_vpc_whitelist is not None: resource_list = self._get_method_path_uri_list(path, api_id, stage) - for endpoint in source_vpc_whitelist: - self._add_vpc_resource_policy_for_method(endpoint, "StringNotEquals", resource_list) + self._add_vpc_resource_policy_for_method(source_vpc_whitelist, "StringNotEquals", resource_list) if source_vpc_blacklist is not None: resource_list = self._get_method_path_uri_list(path, api_id, stage) - for endpoint in source_vpc_blacklist: - self._add_vpc_resource_policy_for_method(endpoint, "StringEquals", resource_list) + self._add_vpc_resource_policy_for_method(source_vpc_blacklist, "StringEquals", resource_list) - if custom_statements is not None: - self._add_custom_statement(custom_statements) + self._doc[self._X_APIGW_POLICY] = self.resource_policy + + def add_custom_statements(self, custom_statements): + self._add_custom_statement(custom_statements) self._doc[self._X_APIGW_POLICY] = self.resource_policy @@ -932,24 +931,33 @@ def _add_ip_resource_policy_for_method(self, ip_list, conditional, resource_list statement.extend([deny_statement]) self.resource_policy["Statement"] = statement - def _add_vpc_resource_policy_for_method(self, vpc, conditional, resource_list): + def _add_vpc_resource_policy_for_method(self, endpoint_list, conditional, resource_list): """ This method generates a policy statement to grant/deny specific VPC/VPCE access to the API method and appends it to the swagger under `x-amazon-apigateway-policy` :raises ValueError: If the conditional passed in does not match the allowed values. """ - if not vpc: + if not endpoint_list: return if conditional not in ["StringNotEquals", "StringEquals"]: raise ValueError("Conditional must be one of {}".format(["StringNotEquals", "StringEquals"])) vpce_regex = r"^vpce-" - if not re.match(vpce_regex, vpc): - endpoint = "aws:SourceVpc" - else: - endpoint = "aws:SourceVpce" - + vpc_regex = r"^vpc-" + vpc_list = [] + vpce_list = [] + for endpoint in endpoint_list: + if re.match(vpce_regex, endpoint): + vpce_list.append(endpoint) + if re.match(vpc_regex, endpoint): + vpc_list.append(endpoint) + + condition = {} + if vpc_list: + condition["aws:SourceVpc"] = vpc_list + if vpce_list: + condition["aws:SourceVpce"] = vpce_list self.resource_policy["Version"] = "2012-10-17" allow_statement = {} allow_statement["Effect"] = "Allow" @@ -962,7 +970,7 @@ def _add_vpc_resource_policy_for_method(self, vpc, conditional, resource_list): deny_statement["Action"] = "execute-api:Invoke" deny_statement["Resource"] = resource_list deny_statement["Principal"] = "*" - deny_statement["Condition"] = {conditional: {endpoint: vpc}} + deny_statement["Condition"] = {conditional: condition} if self.resource_policy.get("Statement") is None: self.resource_policy["Statement"] = [allow_statement, deny_statement] @@ -980,16 +988,17 @@ def _add_custom_statement(self, custom_statements): if custom_statements is None: return - if not isinstance(custom_statements, list): - custom_statements = [custom_statements] - self.resource_policy["Version"] = "2012-10-17" if self.resource_policy.get("Statement") is None: self.resource_policy["Statement"] = custom_statements else: + if not isinstance(custom_statements, list): + custom_statements = [custom_statements] + statement = self.resource_policy["Statement"] if not isinstance(statement, list): statement = [statement] + for s in custom_statements: if s not in statement: statement.append(s) diff --git a/tests/swagger/test_swagger.py b/tests/swagger/test_swagger.py index c4b409d62..bb21d08b5 100644 --- a/tests/swagger/test_swagger.py +++ b/tests/swagger/test_swagger.py @@ -995,7 +995,7 @@ def test_must_add_custom_statements(self): ] } - self.editor.add_resource_policy(resourcePolicy, "/foo", "123", "prod") + self.editor.add_custom_statements(resourcePolicy.get("CustomStatements")) expected = { "Version": "2012-10-17", @@ -1007,6 +1007,33 @@ def test_must_add_custom_statements(self): self.assertEqual(deep_sort_lists(expected), deep_sort_lists(self.editor.swagger[_X_POLICY])) + def test_must_add_fn_if_custom_statements(self): + + resourcePolicy = { + "CustomStatements": { + "Fn::If": [ + "condition", + {"Action": "execute-api:Invoke", "Resource": ["execute-api:/*/*/*"]}, + {"Action": "execute-api:blah", "Resource": ["execute-api:/*/*/*"]}, + ], + } + } + + self.editor.add_custom_statements(resourcePolicy.get("CustomStatements")) + + expected = { + "Version": "2012-10-17", + "Statement": { + "Fn::If": [ + "condition", + {"Action": "execute-api:Invoke", "Resource": ["execute-api:/*/*/*"]}, + {"Action": "execute-api:blah", "Resource": ["execute-api:/*/*/*"]}, + ] + }, + } + + self.assertEqual(deep_sort_lists(expected), deep_sort_lists(self.editor.swagger[_X_POLICY])) + def test_must_add_iam_allow(self): ## fails resourcePolicy = {"AwsAccountWhitelist": ["123456"]} @@ -1140,17 +1167,7 @@ def test_must_add_vpc_allow(self): {"Fn::Sub": ["execute-api:/${__Stage__}/GET/foo", {"__Stage__": "prod"}]}, ], "Effect": "Deny", - "Condition": {"StringNotEquals": {"aws:SourceVpc": "vpc-123"}}, - "Principal": "*", - }, - { - "Action": "execute-api:Invoke", - "Resource": [ - {"Fn::Sub": ["execute-api:/${__Stage__}/PUT/foo", {"__Stage__": "prod"}]}, - {"Fn::Sub": ["execute-api:/${__Stage__}/GET/foo", {"__Stage__": "prod"}]}, - ], - "Effect": "Deny", - "Condition": {"StringNotEquals": {"aws:SourceVpce": "vpce-345"}}, + "Condition": {"StringNotEquals": {"aws:SourceVpc": ["vpc-123"], "aws:SourceVpce": ["vpce-345"]}}, "Principal": "*", }, ], @@ -1183,7 +1200,7 @@ def test_must_add_vpc_deny(self): {"Fn::Sub": ["execute-api:/${__Stage__}/GET/foo", {"__Stage__": "prod"}]}, ], "Effect": "Deny", - "Condition": {"StringEquals": {"aws:SourceVpc": "vpc-123"}}, + "Condition": {"StringEquals": {"aws:SourceVpc": ["vpc-123"]}}, "Principal": "*", }, ], @@ -1201,6 +1218,7 @@ def test_must_add_iam_allow_and_custom(self): } self.editor.add_resource_policy(resourcePolicy, "/foo", "123", "prod") + self.editor.add_custom_statements(resourcePolicy.get("CustomStatements")) expected = { "Version": "2012-10-17", diff --git a/tests/translator/input/api_with_if_conditional_with_resource_policy.yaml b/tests/translator/input/api_with_if_conditional_with_resource_policy.yaml new file mode 100644 index 000000000..3ffecb9b7 --- /dev/null +++ b/tests/translator/input/api_with_if_conditional_with_resource_policy.yaml @@ -0,0 +1,54 @@ +Conditions: + C1: + Fn::Equals: + - true + - true +Resources: + ExplicitApi: + Type: AWS::Serverless::Api + Properties: + StageName: Prod + Auth: + ResourcePolicy: + CustomStatements: + Fn::If: [ + C1, + { + Action: 'execute-api:Invoke', + Resource: ['execute-api:/*/*/*'] + }, + { + Ref: 'AWS::NoValue' + }, + ] + + ExplicitApiFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/member_portal.zip + Handler: index.gethtml + Runtime: nodejs12.x + Events: + GetHtml: + Type: Api + Properties: + RestApiId: + Ref: ExplicitApi + Path: /one + Method: get + PostHtml: + Type: Api + Properties: + RestApiId: + Ref: ExplicitApi + Path: /two + Method: post + PutHtml: + Type: Api + Properties: + RestApiId: + Ref: ExplicitApi + Path: /three + Method: put + + \ No newline at end of file diff --git a/tests/translator/input/api_with_resource_policy_global.yaml b/tests/translator/input/api_with_resource_policy_global.yaml index e4c344c82..3bb00a4ef 100644 --- a/tests/translator/input/api_with_resource_policy_global.yaml +++ b/tests/translator/input/api_with_resource_policy_global.yaml @@ -2,20 +2,24 @@ Parameters: StageName: Type: String Default: MyOwnStage +Conditions: + C1: + Fn::Equals: + - true + - true Globals: Api: Auth: ResourcePolicy: - CustomStatements: [{ - Action: 'execute-api:Invoke', - Resource: ['execute-api:/*/*/*'] - }, - { - Action: 'execute-api:blah', - Resource: ['execute-api:/*/*/*'] - } - ] - IpRangeWhitelist: [ '1.2.3.4' ] + CustomStatements: + Fn::If: + - C1 + - Action: execute-api:Invoke + Resource: + - execute-api:/*/*/* + - Action: execute-api:Blah + Resource: + - execute-api:/*/*/* Resources: ExplicitApiFunction: Type: AWS::Serverless::Function @@ -56,4 +60,18 @@ Resources: Effect: Allow Principal: Service: 'lambda.amazonaws.com' - + AnotherApi: + Type: AWS::Serverless::Api + Properties: + StageName: !Ref StageName + Auth: + ResourcePolicy: + CustomStatements: + Fn::If: + - C1 + - Action: execute-api:Invoke + Resource: + - execute-api:/*/*/* + - Action: execute-api:Another + Resource: + - execute-api:/*/*/* diff --git a/tests/translator/input/api_with_source_vpc_whitelist.yaml b/tests/translator/input/api_with_source_vpc_whitelist.yaml index f893462b1..1cacf3941 100644 --- a/tests/translator/input/api_with_source_vpc_whitelist.yaml +++ b/tests/translator/input/api_with_source_vpc_whitelist.yaml @@ -1,9 +1,15 @@ +Parameters: + Vpc1: + Type: String + Default: vpc-1234 + Globals: Api: Auth: ResourcePolicy: - SourceVpcWhitelist: ['vpc-1234'] - SourceVpcBlacklist: ['vpce-5678'] + SourceVpcWhitelist: + - !Ref Vpc1 + - vpc-5678 Resources: MyFunction: diff --git a/tests/translator/output/api_with_basic_custom_domain_intrinsics.json b/tests/translator/output/api_with_basic_custom_domain_intrinsics.json index a4988cc51..d763bf30f 100644 --- a/tests/translator/output/api_with_basic_custom_domain_intrinsics.json +++ b/tests/translator/output/api_with_basic_custom_domain_intrinsics.json @@ -31,7 +31,7 @@ "Arn" ] }, - "Runtime": "nodejs12.x", + "Runtime": "nodejs12.x", "Tags": [ { "Value": "SAM", @@ -44,7 +44,7 @@ "MyFunctionImplicitGetPermissionProd": { "Type": "AWS::Lambda::Permission", "Properties": { - "Action": "lambda:InvokeFunction", + "Action": "lambda:InvokeFunction", "Principal": "apigateway.amazonaws.com", "FunctionName": { "Ref": "MyFunction" @@ -297,7 +297,7 @@ "MyFunctionApiPermissionProd": { "Type": "AWS::Lambda::Permission", "Properties": { - "Action": "lambda:InvokeFunction", + "Action": "lambda:InvokeFunction", "Principal": "apigateway.amazonaws.com", "FunctionName": { "Ref": "MyFunction" diff --git a/tests/translator/output/api_with_if_conditional_with_resource_policy.json b/tests/translator/output/api_with_if_conditional_with_resource_policy.json new file mode 100644 index 000000000..74572a17f --- /dev/null +++ b/tests/translator/output/api_with_if_conditional_with_resource_policy.json @@ -0,0 +1,219 @@ +{ + "Conditions": { + "C1": { + "Fn::Equals": [ + true, + true + ] + } + }, + "Resources": { + "ExplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ExplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ExplicitApiFunctionPutHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ExplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/PUT/three", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + }, + "ExplicitApiDeploymenta1d4cfbf94": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: a1d4cfbf94fc1b83780825310ec70e2a1c5e42b4", + "StageName": "Stage" + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/one": { + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + }, + "/three": { + "put": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + }, + "/two": { + "post": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "swagger": "2.0", + "x-amazon-apigateway-policy": { + "Version": "2012-10-17", + "Statement": { + "Fn::If": [ + "C1", + { + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" + ] + }, + { + "Ref": "AWS::NoValue" + } + ] + } + } + } + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeploymenta1d4cfbf94" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "ExplicitApiFunctionPostHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ExplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/POST/two", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + }, + "ExplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ExplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ExplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/one", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/api_with_resource_policy.json b/tests/translator/output/api_with_resource_policy.json index 05de51130..4fd6e00f6 100644 --- a/tests/translator/output/api_with_resource_policy.json +++ b/tests/translator/output/api_with_resource_policy.json @@ -14,7 +14,7 @@ "Arn" ] }, - "Runtime": "nodejs12.x", + "Runtime": "nodejs12.x", "Tags": [ { "Value": "SAM", @@ -23,16 +23,6 @@ ] } }, - "ExplicitApiDeploymentd2036decb3": { - "Type": "AWS::ApiGateway::Deployment", - "Properties": { - "RestApiId": { - "Ref": "ExplicitApi" - }, - "Description": "RestApi deployment id: d2036decb36ce147b7738a97c419737ea7e02555", - "StageName": "Stage" - } - }, "ExplicitApiFunctionPutHtmlPermissionProd": { "Type": "AWS::Lambda::Permission", "Properties": { @@ -105,14 +95,12 @@ "swagger": "2.0", "x-amazon-apigateway-policy": { "Version": "2012-10-17", - "Statement": [ - { - "Action": "execute-api:Invoke", - "Resource": [ - "execute-api:/*/*/*" - ] - } - ] + "Statement": { + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" + ] + } } } } @@ -121,7 +109,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "ExplicitApiDeploymentd2036decb3" + "Ref": "ExplicitApiDeployment215ee6137d" }, "RestApiId": { "Ref": "ExplicitApi" @@ -153,15 +141,6 @@ "ExplicitApiFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -177,7 +156,26 @@ } } ] - } + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ExplicitApiDeployment215ee6137d": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 215ee6137d74bceebd1cd5a2b8fb2d8f8604e708", + "StageName": "Stage" } }, "ExplicitApiFunctionGetHtmlPermissionProd": { @@ -202,4 +200,4 @@ } } } -} +} \ No newline at end of file diff --git a/tests/translator/output/api_with_resource_policy_global.json b/tests/translator/output/api_with_resource_policy_global.json index b0e0ada34..f226bb7a5 100644 --- a/tests/translator/output/api_with_resource_policy_global.json +++ b/tests/translator/output/api_with_resource_policy_global.json @@ -1,4 +1,12 @@ { + "Conditions": { + "C1": { + "Fn::Equals": [ + true, + true + ] + } + }, "Parameters": { "StageName": { "Default": "MyOwnStage", @@ -6,16 +14,65 @@ } }, "Resources": { - "ExplicitApiDeploymente173c8c5c6": { + "AnotherApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": {}, + "swagger": "2.0", + "x-amazon-apigateway-policy": { + "Version": "2012-10-17", + "Statement": { + "Fn::If": [ + "C1", + { + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" + ] + }, + { + "Action": "execute-api:Another", + "Resource": [ + "execute-api:/*/*/*" + ] + } + ] + } + } + } + } + }, + "ExplicitApiDeploymenta5a5c4e3ff": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { "Ref": "ExplicitApi" }, - "Description": "RestApi deployment id: e173c8c5c6055492b897fc85a73484cfdba2742f", + "Description": "RestApi deployment id: a5a5c4e3ff6901cf27436628359ed20300d34aa4", "StageName": "Stage" } }, + "ExplicitApiStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeploymenta5a5c4e3ff" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": { + "Ref": "StageName" + } + } + }, "ExplicitApiFunctionGetHtmlPermissionStage": { "Type": "AWS::Lambda::Permission", "Properties": { @@ -37,18 +94,14 @@ } } }, - "ExplicitApiStage": { - "Type": "AWS::ApiGateway::Stage", + "AnotherApiDeploymentfdf1387e0a": { + "Type": "AWS::ApiGateway::Deployment", "Properties": { - "DeploymentId": { - "Ref": "ExplicitApiDeploymente173c8c5c6" - }, "RestApiId": { - "Ref": "ExplicitApi" + "Ref": "AnotherApi" }, - "StageName": { - "Ref": "StageName" - } + "Description": "RestApi deployment id: fdf1387e0a89fa15996401a79284cdaaf2c43844", + "StageName": "Stage" } }, "ExplicitApiFunction": { @@ -65,7 +118,7 @@ "Arn" ] }, - "Runtime": "nodejs12.x", + "Runtime": "nodejs12.x", "Tags": [ { "Value": "SAM", @@ -77,15 +130,6 @@ "ExplicitApiFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -101,6 +145,29 @@ } } ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "AnotherApiStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "AnotherApiDeploymentfdf1387e0a" + }, + "RestApiId": { + "Ref": "AnotherApi" + }, + "StageName": { + "Ref": "StageName" } } }, @@ -140,56 +207,20 @@ } }, { - "Action": "execute-api:Invoke", - "Resource": [ + "Fn::If": [ + "C1", { - "Fn::Sub": [ - "execute-api:/${__Stage__}/GET/", - { - "__Stage__": { - "Ref": "StageName" - } - } + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" ] - } - ], - "Effect": "Allow", - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ + }, { - "Fn::Sub": [ - "execute-api:/${__Stage__}/GET/", - { - "__Stage__": { - "Ref": "StageName" - } - } + "Action": "execute-api:Blah", + "Resource": [ + "execute-api:/*/*/*" ] } - ], - "Effect": "Deny", - "Condition": { - "NotIpAddress": { - "aws:SourceIp": [ - "1.2.3.4" - ] - } - }, - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ - "execute-api:/*/*/*" - ] - }, - { - "Action": "execute-api:blah", - "Resource": [ - "execute-api:/*/*/*" ] } ] diff --git a/tests/translator/output/api_with_source_vpc_blacklist.json b/tests/translator/output/api_with_source_vpc_blacklist.json index ccfeeef6e..3923d1d60 100644 --- a/tests/translator/output/api_with_source_vpc_blacklist.json +++ b/tests/translator/output/api_with_source_vpc_blacklist.json @@ -22,40 +22,31 @@ ] } }, - "ServerlessRestApiProdStage": { - "Type": "AWS::ApiGateway::Stage", + "ServerlessRestApiDeployment0e25d06cd3": { + "Type": "AWS::ApiGateway::Deployment", "Properties": { - "DeploymentId": { - "Ref": "ServerlessRestApiDeployment68fcd6e127" - }, "RestApiId": { "Ref": "ServerlessRestApi" }, - "StageName": "Prod" + "Description": "RestApi deployment id: 0e25d06cd3bcb2adf9b3cd988ce86aa2d9370cb3", + "StageName": "Stage" } }, - "ServerlessRestApiDeployment68fcd6e127": { - "Type": "AWS::ApiGateway::Deployment", + "ServerlessRestApiProdStage": { + "Type": "AWS::ApiGateway::Stage", "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeployment0e25d06cd3" + }, "RestApiId": { "Ref": "ServerlessRestApi" }, - "Description": "RestApi deployment id: 68fcd6e127ad767b7bafd3b7a4552a56cb5ea19d", - "StageName": "Stage" + "StageName": "Prod" } }, "MyFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -71,7 +62,16 @@ } } ] - } + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] } }, "ServerlessRestApi": { @@ -132,7 +132,9 @@ "Effect": "Deny", "Condition": { "StringEquals": { - "aws:SourceVpce": "vpce-3456" + "aws:SourceVpce": [ + "vpce-3456" + ] } }, "Principal": "*" @@ -164,4 +166,4 @@ } } } -} +} \ No newline at end of file diff --git a/tests/translator/output/api_with_source_vpc_whitelist.json b/tests/translator/output/api_with_source_vpc_whitelist.json index 5af004672..715b18831 100644 --- a/tests/translator/output/api_with_source_vpc_whitelist.json +++ b/tests/translator/output/api_with_source_vpc_whitelist.json @@ -1,4 +1,10 @@ { + "Parameters": { + "Vpc1": { + "Default": "vpc-1234", + "Type": "String" + } + }, "Resources": { "MyFunction": { "Type": "AWS::Lambda::Function", @@ -55,14 +61,16 @@ "StageName": "Prod" } }, - "ServerlessRestApiDeploymente137534328": { - "Type": "AWS::ApiGateway::Deployment", + "ServerlessRestApiProdStage": { + "Type": "AWS::ApiGateway::Stage", "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeployment276f3672ac" + }, "RestApiId": { "Ref": "ServerlessRestApi" }, - "Description": "RestApi deployment id: e1375343284100b701b94f5b3d70cde0563eca05", - "StageName": "Stage" + "StageName": "Prod" } }, "MyApiDeployment5332c373d4": { @@ -75,45 +83,40 @@ "StageName": "Stage" } }, - "ServerlessRestApiProdStage": { - "Type": "AWS::ApiGateway::Stage", + "ServerlessRestApiDeployment276f3672ac": { + "Type": "AWS::ApiGateway::Deployment", "Properties": { - "DeploymentId": { - "Ref": "ServerlessRestApiDeploymente137534328" - }, "RestApiId": { "Ref": "ServerlessRestApi" }, - "StageName": "Prod" + "Description": "RestApi deployment id: 276f3672acc0db05468d66e75218112e92b84253", + "StageName": "Stage" } }, - "MyApi": { - "Type": "AWS::ApiGateway::RestApi", + "MyFunctionApiPermissionProd": { + "Type": "AWS::Lambda::Permission", "Properties": { - "Body": { - "info": { - "version": "1.0", - "title": { - "Ref": "AWS::StackName" + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "MyFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/PUT/get", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } } - }, - "paths": {}, - "swagger": "2.0" + ] } } }, "MyFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -129,7 +132,16 @@ } } ] - } + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] } }, "ServerlessRestApi": { @@ -202,28 +214,11 @@ "Effect": "Deny", "Condition": { "StringNotEquals": { - "aws:SourceVpc": "vpc-1234" - } - }, - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ - { - "Fn::Sub": [ - "execute-api:/${__Stage__}/PUT/get", - { - "__Stage__": "Prod" - } + "aws:SourceVpc": [ + "vpc-1234", + "vpc-5678" ] } - ], - "Effect": "Deny", - "Condition": { - "StringEquals": { - "aws:SourceVpce": "vpce-5678" - } }, "Principal": "*" }, @@ -257,28 +252,11 @@ "Effect": "Deny", "Condition": { "StringNotEquals": { - "aws:SourceVpc": "vpc-1234" - } - }, - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ - { - "Fn::Sub": [ - "execute-api:/${__Stage__}/POST/fetch", - { - "__Stage__": "Prod" - } + "aws:SourceVpc": [ + "vpc-1234", + "vpc-5678" ] } - ], - "Effect": "Deny", - "Condition": { - "StringEquals": { - "aws:SourceVpce": "vpce-5678" - } }, "Principal": "*" } @@ -287,26 +265,20 @@ } } }, - "MyFunctionApiPermissionProd": { - "Type": "AWS::Lambda::Permission", + "MyApi": { + "Type": "AWS::ApiGateway::RestApi", "Properties": { - "Action": "lambda:InvokeFunction", - "Principal": "apigateway.amazonaws.com", - "FunctionName": { - "Ref": "MyFunction" - }, - "SourceArn": { - "Fn::Sub": [ - "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/PUT/get", - { - "__Stage__": "*", - "__ApiId__": { - "Ref": "ServerlessRestApi" - } + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" } - ] + }, + "paths": {}, + "swagger": "2.0" } } } } -} +} \ No newline at end of file diff --git a/tests/translator/output/aws-cn/api_with_if_conditional_with_resource_policy.json b/tests/translator/output/aws-cn/api_with_if_conditional_with_resource_policy.json new file mode 100644 index 000000000..a5ab0daf8 --- /dev/null +++ b/tests/translator/output/aws-cn/api_with_if_conditional_with_resource_policy.json @@ -0,0 +1,227 @@ +{ + "Conditions": { + "C1": { + "Fn::Equals": [ + true, + true + ] + } + }, + "Resources": { + "ExplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ExplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ExplicitApiFunctionPutHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ExplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/PUT/three", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + }, + "ExplicitApiDeployment1864127303": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 1864127303922f015249dddc233722580882c9ad", + "StageName": "Stage" + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/one": { + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + }, + "/three": { + "put": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + }, + "/two": { + "post": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "swagger": "2.0", + "x-amazon-apigateway-policy": { + "Version": "2012-10-17", + "Statement": { + "Fn::If": [ + "C1", + { + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" + ] + }, + { + "Ref": "AWS::NoValue" + } + ] + } + } + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment1864127303" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "ExplicitApiFunctionPostHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ExplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/POST/two", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + }, + "ExplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ExplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ExplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/one", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-cn/api_with_resource_policy.json b/tests/translator/output/aws-cn/api_with_resource_policy.json index 89ce41957..b7299850f 100644 --- a/tests/translator/output/aws-cn/api_with_resource_policy.json +++ b/tests/translator/output/aws-cn/api_with_resource_policy.json @@ -14,7 +14,7 @@ "Arn" ] }, - "Runtime": "nodejs12.x", + "Runtime": "nodejs12.x", "Tags": [ { "Value": "SAM", @@ -44,16 +44,6 @@ } } }, - "ExplicitApiDeployment09f793ab58": { - "Type": "AWS::ApiGateway::Deployment", - "Properties": { - "RestApiId": { - "Ref": "ExplicitApi" - }, - "Description": "RestApi deployment id: 09f793ab583fe684660829cf209f0e28340df577", - "StageName": "Stage" - } - }, "ExplicitApi": { "Type": "AWS::ApiGateway::RestApi", "Properties": { @@ -105,14 +95,12 @@ "swagger": "2.0", "x-amazon-apigateway-policy": { "Version": "2012-10-17", - "Statement": [ - { - "Action": "execute-api:Invoke", - "Resource": [ - "execute-api:/*/*/*" - ] - } - ] + "Statement": { + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" + ] + } } }, "EndpointConfiguration": { @@ -129,7 +117,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "ExplicitApiDeployment09f793ab58" + "Ref": "ExplicitApiDeployment39d7eca1e3" }, "RestApiId": { "Ref": "ExplicitApi" @@ -161,15 +149,6 @@ "ExplicitApiFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -185,7 +164,16 @@ } } ] - } + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] } }, "ExplicitApiFunctionGetHtmlPermissionProd": { @@ -208,6 +196,16 @@ ] } } + }, + "ExplicitApiDeployment39d7eca1e3": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 39d7eca1e3352a144ce8a9f729862b19b28a8734", + "StageName": "Stage" + } } } -} +} \ No newline at end of file diff --git a/tests/translator/output/aws-cn/api_with_resource_policy_global.json b/tests/translator/output/aws-cn/api_with_resource_policy_global.json index 66069a7d8..0d7c8c732 100644 --- a/tests/translator/output/aws-cn/api_with_resource_policy_global.json +++ b/tests/translator/output/aws-cn/api_with_resource_policy_global.json @@ -1,4 +1,12 @@ { + "Conditions": { + "C1": { + "Fn::Equals": [ + true, + true + ] + } + }, "Parameters": { "StageName": { "Default": "MyOwnStage", @@ -6,16 +14,73 @@ } }, "Resources": { - "ExplicitApiDeploymente173c8c5c6": { + "AnotherApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": {}, + "swagger": "2.0", + "x-amazon-apigateway-policy": { + "Version": "2012-10-17", + "Statement": { + "Fn::If": [ + "C1", + { + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" + ] + }, + { + "Action": "execute-api:Another", + "Resource": [ + "execute-api:/*/*/*" + ] + } + ] + } + } + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ExplicitApiDeploymenta5a5c4e3ff": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { "Ref": "ExplicitApi" }, - "Description": "RestApi deployment id: e173c8c5c6055492b897fc85a73484cfdba2742f", + "Description": "RestApi deployment id: a5a5c4e3ff6901cf27436628359ed20300d34aa4", "StageName": "Stage" } }, + "ExplicitApiStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeploymenta5a5c4e3ff" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": { + "Ref": "StageName" + } + } + }, "ExplicitApiFunctionGetHtmlPermissionStage": { "Type": "AWS::Lambda::Permission", "Properties": { @@ -37,18 +102,14 @@ } } }, - "ExplicitApiStage": { - "Type": "AWS::ApiGateway::Stage", + "AnotherApiDeploymentfdf1387e0a": { + "Type": "AWS::ApiGateway::Deployment", "Properties": { - "DeploymentId": { - "Ref": "ExplicitApiDeploymente173c8c5c6" - }, "RestApiId": { - "Ref": "ExplicitApi" + "Ref": "AnotherApi" }, - "StageName": { - "Ref": "StageName" - } + "Description": "RestApi deployment id: fdf1387e0a89fa15996401a79284cdaaf2c43844", + "StageName": "Stage" } }, "ExplicitApiFunction": { @@ -65,7 +126,7 @@ "Arn" ] }, - "Runtime": "nodejs12.x", + "Runtime": "nodejs12.x", "Tags": [ { "Value": "SAM", @@ -77,15 +138,6 @@ "ExplicitApiFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -101,6 +153,29 @@ } } ] + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "AnotherApiStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "AnotherApiDeploymentfdf1387e0a" + }, + "RestApiId": { + "Ref": "AnotherApi" + }, + "StageName": { + "Ref": "StageName" } } }, @@ -140,56 +215,20 @@ } }, { - "Action": "execute-api:Invoke", - "Resource": [ + "Fn::If": [ + "C1", { - "Fn::Sub": [ - "execute-api:/${__Stage__}/GET/", - { - "__Stage__": { - "Ref": "StageName" - } - } + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" ] - } - ], - "Effect": "Allow", - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ + }, { - "Fn::Sub": [ - "execute-api:/${__Stage__}/GET/", - { - "__Stage__": { - "Ref": "StageName" - } - } + "Action": "execute-api:Blah", + "Resource": [ + "execute-api:/*/*/*" ] } - ], - "Effect": "Deny", - "Condition": { - "NotIpAddress": { - "aws:SourceIp": [ - "1.2.3.4" - ] - } - }, - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ - "execute-api:/*/*/*" - ] - }, - { - "Action": "execute-api:blah", - "Resource": [ - "execute-api:/*/*/*" ] } ] @@ -206,4 +245,4 @@ } } } -} +} \ No newline at end of file diff --git a/tests/translator/output/aws-cn/api_with_source_vpc_blacklist.json b/tests/translator/output/aws-cn/api_with_source_vpc_blacklist.json index 0da2e8663..6dfbef3fa 100644 --- a/tests/translator/output/aws-cn/api_with_source_vpc_blacklist.json +++ b/tests/translator/output/aws-cn/api_with_source_vpc_blacklist.json @@ -22,11 +22,21 @@ ] } }, + "ServerlessRestApiDeploymentb8219b2586": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: b8219b2586b8c860b699470c380956bb09244f77", + "StageName": "Stage" + } + }, "ServerlessRestApiProdStage": { "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "ServerlessRestApiDeployment9042dce526" + "Ref": "ServerlessRestApiDeploymentb8219b2586" }, "RestApiId": { "Ref": "ServerlessRestApi" @@ -37,15 +47,6 @@ "MyFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -61,17 +62,16 @@ } } ] - } - } - }, - "ServerlessRestApiDeployment9042dce526": { - "Type": "AWS::ApiGateway::Deployment", - "Properties": { - "RestApiId": { - "Ref": "ServerlessRestApi" }, - "Description": "RestApi deployment id: 9042dce526aaebf4138c89cce3779fd4ec217cf5", - "StageName": "Stage" + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] } }, "ServerlessRestApi": { @@ -132,7 +132,9 @@ "Effect": "Deny", "Condition": { "StringEquals": { - "aws:SourceVpce": "vpce-3456" + "aws:SourceVpce": [ + "vpce-3456" + ] } }, "Principal": "*" @@ -172,4 +174,4 @@ } } } -} +} \ No newline at end of file diff --git a/tests/translator/output/aws-cn/api_with_source_vpc_whitelist.json b/tests/translator/output/aws-cn/api_with_source_vpc_whitelist.json index 1a7632b3f..0d238d2a2 100644 --- a/tests/translator/output/aws-cn/api_with_source_vpc_whitelist.json +++ b/tests/translator/output/aws-cn/api_with_source_vpc_whitelist.json @@ -1,4 +1,10 @@ { + "Parameters": { + "Vpc1": { + "Default": "vpc-1234", + "Type": "String" + } + }, "Resources": { "MyFunction": { "Type": "AWS::Lambda::Function", @@ -55,6 +61,16 @@ "StageName": "Prod" } }, + "ServerlessRestApiDeploymentf39840708b": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: f39840708b20c848b8e57aa8a8b97de327b40de6", + "StageName": "Stage" + } + }, "MyApiDeployment5332c373d4": { "Type": "AWS::ApiGateway::Deployment", "Properties": { @@ -69,7 +85,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "ServerlessRestApiDeployment4076852abe" + "Ref": "ServerlessRestApiDeploymentf39840708b" }, "RestApiId": { "Ref": "ServerlessRestApi" @@ -77,41 +93,30 @@ "StageName": "Prod" } }, - "MyApi": { - "Type": "AWS::ApiGateway::RestApi", + "MyFunctionApiPermissionProd": { + "Type": "AWS::Lambda::Permission", "Properties": { - "Body": { - "info": { - "version": "1.0", - "title": { - "Ref": "AWS::StackName" - } - }, - "paths": {}, - "swagger": "2.0" + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "MyFunction" }, - "EndpointConfiguration": { - "Types": [ - "REGIONAL" + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/PUT/get", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } ] - }, - "Parameters": { - "endpointConfigurationTypes": "REGIONAL" } } }, "MyFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -127,7 +132,16 @@ } } ] - } + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] } }, "ServerlessRestApi": { @@ -200,28 +214,11 @@ "Effect": "Deny", "Condition": { "StringNotEquals": { - "aws:SourceVpc": "vpc-1234" - } - }, - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ - { - "Fn::Sub": [ - "execute-api:/${__Stage__}/PUT/get", - { - "__Stage__": "Prod" - } + "aws:SourceVpc": [ + "vpc-1234", + "vpc-5678" ] } - ], - "Effect": "Deny", - "Condition": { - "StringEquals": { - "aws:SourceVpce": "vpce-5678" - } }, "Principal": "*" }, @@ -255,28 +252,11 @@ "Effect": "Deny", "Condition": { "StringNotEquals": { - "aws:SourceVpc": "vpc-1234" - } - }, - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ - { - "Fn::Sub": [ - "execute-api:/${__Stage__}/POST/fetch", - { - "__Stage__": "Prod" - } + "aws:SourceVpc": [ + "vpc-1234", + "vpc-5678" ] } - ], - "Effect": "Deny", - "Condition": { - "StringEquals": { - "aws:SourceVpce": "vpce-5678" - } }, "Principal": "*" } @@ -293,36 +273,28 @@ } } }, - "ServerlessRestApiDeployment4076852abe": { - "Type": "AWS::ApiGateway::Deployment", - "Properties": { - "RestApiId": { - "Ref": "ServerlessRestApi" - }, - "Description": "RestApi deployment id: 4076852abe795c70d8c28e5881f135018039f144", - "StageName": "Stage" - } - }, - "MyFunctionApiPermissionProd": { - "Type": "AWS::Lambda::Permission", + "MyApi": { + "Type": "AWS::ApiGateway::RestApi", "Properties": { - "Action": "lambda:InvokeFunction", - "Principal": "apigateway.amazonaws.com", - "FunctionName": { - "Ref": "MyFunction" - }, - "SourceArn": { - "Fn::Sub": [ - "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/PUT/get", - { - "__Stage__": "*", - "__ApiId__": { - "Ref": "ServerlessRestApi" - } + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" } + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" } } } } -} +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/api_with_if_conditional_with_resource_policy.json b/tests/translator/output/aws-us-gov/api_with_if_conditional_with_resource_policy.json new file mode 100644 index 000000000..b0bd1013b --- /dev/null +++ b/tests/translator/output/aws-us-gov/api_with_if_conditional_with_resource_policy.json @@ -0,0 +1,227 @@ +{ + "Conditions": { + "C1": { + "Fn::Equals": [ + true, + true + ] + } + }, + "Resources": { + "ExplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ExplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ExplicitApiFunctionPutHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ExplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/PUT/three", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + }, + "ExplicitApiDeploymente252ad8b51": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: e252ad8b5121d1fcb94bf7ef489dbbd46a3dd461", + "StageName": "Stage" + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/one": { + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + }, + "/three": { + "put": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + }, + "/two": { + "post": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "swagger": "2.0", + "x-amazon-apigateway-policy": { + "Version": "2012-10-17", + "Statement": { + "Fn::If": [ + "C1", + { + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" + ] + }, + { + "Ref": "AWS::NoValue" + } + ] + } + } + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeploymente252ad8b51" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "ExplicitApiFunctionPostHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ExplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/POST/two", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + }, + "ExplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ExplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ExplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/one", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/api_with_resource_policy.json b/tests/translator/output/aws-us-gov/api_with_resource_policy.json index d2f31f0e1..086f0655d 100644 --- a/tests/translator/output/aws-us-gov/api_with_resource_policy.json +++ b/tests/translator/output/aws-us-gov/api_with_resource_policy.json @@ -14,7 +14,7 @@ "Arn" ] }, - "Runtime": "nodejs12.x", + "Runtime": "nodejs12.x", "Tags": [ { "Value": "SAM", @@ -44,16 +44,6 @@ } } }, - "ExplicitApiDeployment07fc5ee8d3": { - "Type": "AWS::ApiGateway::Deployment", - "Properties": { - "RestApiId": { - "Ref": "ExplicitApi" - }, - "Description": "RestApi deployment id: 07fc5ee8d3073a50b2164fe22c3e49e5abb343ec", - "StageName": "Stage" - } - }, "ExplicitApi": { "Type": "AWS::ApiGateway::RestApi", "Properties": { @@ -105,14 +95,12 @@ "swagger": "2.0", "x-amazon-apigateway-policy": { "Version": "2012-10-17", - "Statement": [ - { - "Action": "execute-api:Invoke", - "Resource": [ - "execute-api:/*/*/*" - ] - } - ] + "Statement": { + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" + ] + } } }, "EndpointConfiguration": { @@ -129,7 +117,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "ExplicitApiDeployment07fc5ee8d3" + "Ref": "ExplicitApiDeploymentb5a112ecdf" }, "RestApiId": { "Ref": "ExplicitApi" @@ -161,15 +149,6 @@ "ExplicitApiFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -185,7 +164,26 @@ } } ] - } + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ExplicitApiDeploymentb5a112ecdf": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: b5a112ecdfe9f71fbad3f114ad9aeddc73ce44e5", + "StageName": "Stage" } }, "ExplicitApiFunctionGetHtmlPermissionProd": { @@ -210,4 +208,4 @@ } } } -} +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/api_with_resource_policy_global.json b/tests/translator/output/aws-us-gov/api_with_resource_policy_global.json index 13cb4d6fb..b690b0271 100644 --- a/tests/translator/output/aws-us-gov/api_with_resource_policy_global.json +++ b/tests/translator/output/aws-us-gov/api_with_resource_policy_global.json @@ -1,4 +1,12 @@ { + "Conditions": { + "C1": { + "Fn::Equals": [ + true, + true + ] + } + }, "Parameters": { "StageName": { "Default": "MyOwnStage", @@ -6,16 +14,73 @@ } }, "Resources": { - "ExplicitApiDeploymente173c8c5c6": { + "AnotherApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": {}, + "swagger": "2.0", + "x-amazon-apigateway-policy": { + "Version": "2012-10-17", + "Statement": { + "Fn::If": [ + "C1", + { + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" + ] + }, + { + "Action": "execute-api:Another", + "Resource": [ + "execute-api:/*/*/*" + ] + } + ] + } + } + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ExplicitApiDeploymenta5a5c4e3ff": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { "Ref": "ExplicitApi" }, - "Description": "RestApi deployment id: e173c8c5c6055492b897fc85a73484cfdba2742f", + "Description": "RestApi deployment id: a5a5c4e3ff6901cf27436628359ed20300d34aa4", "StageName": "Stage" } }, + "ExplicitApiStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeploymenta5a5c4e3ff" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": { + "Ref": "StageName" + } + } + }, "ExplicitApiFunctionGetHtmlPermissionStage": { "Type": "AWS::Lambda::Permission", "Properties": { @@ -37,18 +102,14 @@ } } }, - "ExplicitApiStage": { - "Type": "AWS::ApiGateway::Stage", + "AnotherApiDeploymentfdf1387e0a": { + "Type": "AWS::ApiGateway::Deployment", "Properties": { - "DeploymentId": { - "Ref": "ExplicitApiDeploymente173c8c5c6" - }, "RestApiId": { - "Ref": "ExplicitApi" + "Ref": "AnotherApi" }, - "StageName": { - "Ref": "StageName" - } + "Description": "RestApi deployment id: fdf1387e0a89fa15996401a79284cdaaf2c43844", + "StageName": "Stage" } }, "ExplicitApiFunction": { @@ -65,7 +126,7 @@ "Arn" ] }, - "Runtime": "nodejs12.x", + "Runtime": "nodejs12.x", "Tags": [ { "Value": "SAM", @@ -77,15 +138,6 @@ "ExplicitApiFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -101,6 +153,29 @@ } } ] + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "AnotherApiStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "AnotherApiDeploymentfdf1387e0a" + }, + "RestApiId": { + "Ref": "AnotherApi" + }, + "StageName": { + "Ref": "StageName" } } }, @@ -140,56 +215,20 @@ } }, { - "Action": "execute-api:Invoke", - "Resource": [ + "Fn::If": [ + "C1", { - "Fn::Sub": [ - "execute-api:/${__Stage__}/GET/", - { - "__Stage__": { - "Ref": "StageName" - } - } + "Action": "execute-api:Invoke", + "Resource": [ + "execute-api:/*/*/*" ] - } - ], - "Effect": "Allow", - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ + }, { - "Fn::Sub": [ - "execute-api:/${__Stage__}/GET/", - { - "__Stage__": { - "Ref": "StageName" - } - } + "Action": "execute-api:Blah", + "Resource": [ + "execute-api:/*/*/*" ] } - ], - "Effect": "Deny", - "Condition": { - "NotIpAddress": { - "aws:SourceIp": [ - "1.2.3.4" - ] - } - }, - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ - "execute-api:/*/*/*" - ] - }, - { - "Action": "execute-api:blah", - "Resource": [ - "execute-api:/*/*/*" ] } ] @@ -206,4 +245,4 @@ } } } -} +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/api_with_source_vpc_blacklist.json b/tests/translator/output/aws-us-gov/api_with_source_vpc_blacklist.json index 66caac7b4..349d33670 100644 --- a/tests/translator/output/aws-us-gov/api_with_source_vpc_blacklist.json +++ b/tests/translator/output/aws-us-gov/api_with_source_vpc_blacklist.json @@ -22,13 +22,13 @@ ] } }, - "ServerlessRestApiDeployment023bd5bca7": { + "ServerlessRestApiDeployment8123e1b4d0": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { "Ref": "ServerlessRestApi" }, - "Description": "RestApi deployment id: 023bd5bca761c7eb2832fb8a1a5dfa344af40f78", + "Description": "RestApi deployment id: 8123e1b4d0dbc08e51be7b4c910cacad26d29673", "StageName": "Stage" } }, @@ -36,7 +36,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "ServerlessRestApiDeployment023bd5bca7" + "Ref": "ServerlessRestApiDeployment8123e1b4d0" }, "RestApiId": { "Ref": "ServerlessRestApi" @@ -47,15 +47,6 @@ "MyFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -71,7 +62,16 @@ } } ] - } + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] } }, "ServerlessRestApi": { @@ -132,7 +132,9 @@ "Effect": "Deny", "Condition": { "StringEquals": { - "aws:SourceVpce": "vpce-3456" + "aws:SourceVpce": [ + "vpce-3456" + ] } }, "Principal": "*" @@ -172,4 +174,4 @@ } } } -} +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/api_with_source_vpc_whitelist.json b/tests/translator/output/aws-us-gov/api_with_source_vpc_whitelist.json index 587cb96f4..f6b28aa07 100644 --- a/tests/translator/output/aws-us-gov/api_with_source_vpc_whitelist.json +++ b/tests/translator/output/aws-us-gov/api_with_source_vpc_whitelist.json @@ -1,4 +1,10 @@ { + "Parameters": { + "Vpc1": { + "Default": "vpc-1234", + "Type": "String" + } + }, "Resources": { "MyFunction": { "Type": "AWS::Lambda::Function", @@ -43,16 +49,6 @@ } } }, - "ServerlessRestApiDeployment48156fe851": { - "Type": "AWS::ApiGateway::Deployment", - "Properties": { - "RestApiId": { - "Ref": "ServerlessRestApi" - }, - "Description": "RestApi deployment id: 48156fe85100710f74059d13d889812a9defa259", - "StageName": "Stage" - } - }, "MyApiProdStage": { "Type": "AWS::ApiGateway::Stage", "Properties": { @@ -75,11 +71,21 @@ "StageName": "Stage" } }, + "ServerlessRestApiDeploymente6268e43cf": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: e6268e43cf1f64034297b37a261d5d5a0cc7375b", + "StageName": "Stage" + } + }, "ServerlessRestApiProdStage": { "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "ServerlessRestApiDeployment48156fe851" + "Ref": "ServerlessRestApiDeploymente6268e43cf" }, "RestApiId": { "Ref": "ServerlessRestApi" @@ -87,41 +93,30 @@ "StageName": "Prod" } }, - "MyApi": { - "Type": "AWS::ApiGateway::RestApi", + "MyFunctionApiPermissionProd": { + "Type": "AWS::Lambda::Permission", "Properties": { - "Body": { - "info": { - "version": "1.0", - "title": { - "Ref": "AWS::StackName" - } - }, - "paths": {}, - "swagger": "2.0" + "Action": "lambda:InvokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "MyFunction" }, - "EndpointConfiguration": { - "Types": [ - "REGIONAL" + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/PUT/get", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } ] - }, - "Parameters": { - "endpointConfigurationTypes": "REGIONAL" } } }, "MyFunctionRole": { "Type": "AWS::IAM::Role", "Properties": { - "ManagedPolicyArns": [ - "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ], - "Tags": [ - { - "Value": "SAM", - "Key": "lambda:createdBy" - } - ], "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -137,7 +132,16 @@ } } ] - } + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] } }, "ServerlessRestApi": { @@ -210,28 +214,11 @@ "Effect": "Deny", "Condition": { "StringNotEquals": { - "aws:SourceVpc": "vpc-1234" - } - }, - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ - { - "Fn::Sub": [ - "execute-api:/${__Stage__}/PUT/get", - { - "__Stage__": "Prod" - } + "aws:SourceVpc": [ + "vpc-1234", + "vpc-5678" ] } - ], - "Effect": "Deny", - "Condition": { - "StringEquals": { - "aws:SourceVpce": "vpce-5678" - } }, "Principal": "*" }, @@ -265,28 +252,11 @@ "Effect": "Deny", "Condition": { "StringNotEquals": { - "aws:SourceVpc": "vpc-1234" - } - }, - "Principal": "*" - }, - { - "Action": "execute-api:Invoke", - "Resource": [ - { - "Fn::Sub": [ - "execute-api:/${__Stage__}/POST/fetch", - { - "__Stage__": "Prod" - } + "aws:SourceVpc": [ + "vpc-1234", + "vpc-5678" ] } - ], - "Effect": "Deny", - "Condition": { - "StringEquals": { - "aws:SourceVpce": "vpce-5678" - } }, "Principal": "*" } @@ -303,26 +273,28 @@ } } }, - "MyFunctionApiPermissionProd": { - "Type": "AWS::Lambda::Permission", + "MyApi": { + "Type": "AWS::ApiGateway::RestApi", "Properties": { - "Action": "lambda:InvokeFunction", - "Principal": "apigateway.amazonaws.com", - "FunctionName": { - "Ref": "MyFunction" - }, - "SourceArn": { - "Fn::Sub": [ - "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/PUT/get", - { - "__Stage__": "*", - "__ApiId__": { - "Ref": "ServerlessRestApi" - } + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" } + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" } } } } -} +} \ No newline at end of file diff --git a/tests/translator/test_translator.py b/tests/translator/test_translator.py index 6dc2d86e3..7a271f507 100644 --- a/tests/translator/test_translator.py +++ b/tests/translator/test_translator.py @@ -408,6 +408,7 @@ def test_transform_success_openapi3(self, testcase, partition_with_region): "api_with_resource_policy", "api_with_resource_policy_global", "api_with_resource_policy_global_implicit", + "api_with_if_conditional_with_resource_policy", ], [ ("aws", "ap-southeast-1"), diff --git a/versions/2016-10-31.md b/versions/2016-10-31.md index 88f36cd0d..4aaaa7d1a 100644 --- a/versions/2016-10-31.md +++ b/versions/2016-10-31.md @@ -1111,20 +1111,21 @@ Auth: **ResourcePolicy:** Configure Resource Policy for all methods and paths on an API. This setting can also be defined on individual `AWS::Serverless::Function` using the [Function Auth Object](#function-auth-object). This is required for APIs with `EndpointConfiguration: PRIVATE`. + ```yaml Auth: ResourcePolicy: - CustomStatements: + CustomStatements: # Supports Ref and Fn::If conditions, does not work with AWS::NoValue in policy statements - Effect: Allow Principal: * Action: execute-api:Invoke ... - AwsAccountWhitelist: [] - AwsAccountBlacklist: [] - IpRangeWhitelist: [] - IpRangeBlacklist: [] - SourceVpcWhitelist: [] - SourceVpcBlacklist: [] + AwsAccountWhitelist: [] # Supports Ref + AwsAccountBlacklist: [] # Supports Ref + IpRangeWhitelist: [] # Supports Ref + IpRangeBlacklist: [] # Supports Ref + SourceVpcWhitelist: [] # Supports Ref + SourceVpcBlacklist: [] # Supports Ref ```