Repository: serverless/serverless (JavaScript)
Date: 2019-12-24 17:16:07+00:00
Task type: Bug Fix

Issue:
API-G resource policies require manual removal
# Bug Report

## Description

Deleting an API-G resource policy from the stack configuration doesn't remove the previously defined policy from the endpoint.  

Similar or dependent issues:

- #4926

API-G resource policies require manual removal
# Bug Report

## Description

Deleting an API-G resource policy from the stack configuration doesn't remove the previously defined policy from the endpoint.  

Similar or dependent issues:

- #4926



Issue discussion:
Same issue here. Commenting or deleting the resourcePolicy definition does not remove it. As workaround - for my use case - I removed the conditions (IP whitelisting) 
From: 
```
 resourcePolicy:
    - Effect: Allow
      Principal: '*'
      Action: execute-api:Invoke
      Resource:
        - execute-api:/*
      Condition:
        IpAddress:
          aws:SourceIp:
            - 'x.x.x.x/x'
```
To: 

```
 resourcePolicy:
    - Effect: Allow
      Principal: '*'
      Action: execute-api:Invoke
      Resource:
        - execute-api:/*
```
@ferschubert  I used the same "work around".  I have a PR I'm going to submit that basically applies that policy when one isn't explicitly specified.
Same issue here. Commenting or deleting the resourcePolicy definition does not remove it. As workaround - for my use case - I removed the conditions (IP whitelisting) 
From: 
```
 resourcePolicy:
    - Effect: Allow
      Principal: '*'
      Action: execute-api:Invoke
      Resource:
        - execute-api:/*
      Condition:
        IpAddress:
          aws:SourceIp:
            - 'x.x.x.x/x'
```
To: 

```
 resourcePolicy:
    - Effect: Allow
      Principal: '*'
      Action: execute-api:Invoke
      Resource:
        - execute-api:/*
```
@ferschubert  I used the same "work around".  I have a PR I'm going to submit that basically applies that policy when one isn't explicitly specified.

Solution patch:
diff --git a/lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.js
index b420b28812f..fa0f3715bb4 100644
--- a/lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.js
+++ b/lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.js
@@ -3,6 +3,23 @@
 const _ = require('lodash');
 const BbPromise = require('bluebird');
 
+const defaultPolicy = {
+  Version: '2012-10-17',
+  Statement: [
+    {
+      Effect: 'Allow',
+      Principal: '*',
+      Action: 'execute-api:Invoke',
+      Resource: ['execute-api:/*/*/*'],
+      Condition: {
+        IpAddress: {
+          'aws:SourceIp': ['0.0.0.0/0', '::/0'],
+        },
+      },
+    },
+  ],
+};
+
 module.exports = {
   compileRestApi() {
     const apiGateway = this.serverless.service.provider.apiGateway || {};
@@ -63,6 +80,17 @@ module.exports = {
           Policy: policy,
         }
       );
+    } else {
+      // setting up a policy with no restrictions in cases where no policy is specified
+      // this ensures that a policy is always present
+      _.merge(
+        this.serverless.service.provider.compiledCloudFormationTemplate.Resources[
+          this.apiGatewayRestApiLogicalId
+        ].Properties,
+        {
+          Policy: defaultPolicy,
+        }
+      );
     }
 
     if (!_.isEmpty(apiGateway.apiKeySourceType)) {


Test patch:
diff --git a/lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.test.js
index 4c7ffa6df70..142ed7cc149 100644
--- a/lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.test.js
+++ b/lib/plugins/aws/package/compile/events/apiGateway/lib/restApi.test.js
@@ -49,6 +49,22 @@ describe('#compileRestApi()', () => {
           EndpointConfiguration: {
             Types: ['EDGE'],
           },
+          Policy: {
+            Statement: [
+              {
+                Action: 'execute-api:Invoke',
+                Condition: {
+                  IpAddress: {
+                    'aws:SourceIp': ['0.0.0.0/0', '::/0'],
+                  },
+                },
+                Effect: 'Allow',
+                Principal: '*',
+                Resource: ['execute-api:/*/*/*'],
+              },
+            ],
+            Version: '2012-10-17',
+          },
         },
       });
     }));
@@ -100,6 +116,40 @@ describe('#compileRestApi()', () => {
     });
   });
 
+  it('should provide open policy if no policy specified', () => {
+    const resources =
+      awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate.Resources;
+
+    return awsCompileApigEvents.compileRestApi().then(() => {
+      expect(resources.ApiGatewayRestApi).to.deep.equal({
+        Type: 'AWS::ApiGateway::RestApi',
+        Properties: {
+          Name: 'dev-new-service',
+          BinaryMediaTypes: undefined,
+          EndpointConfiguration: {
+            Types: ['EDGE'],
+          },
+          Policy: {
+            Version: '2012-10-17',
+            Statement: [
+              {
+                Effect: 'Allow',
+                Principal: '*',
+                Action: 'execute-api:Invoke',
+                Resource: ['execute-api:/*/*/*'],
+                Condition: {
+                  IpAddress: {
+                    'aws:SourceIp': ['0.0.0.0/0', '::/0'],
+                  },
+                },
+              },
+            ],
+          },
+        },
+      });
+    });
+  });
+
   it('should ignore REST API resource creation if there is predefined restApi config', () => {
     awsCompileApigEvents.serverless.service.provider.apiGateway = {
       restApiId: '6fyzt1pfpk',
@@ -128,6 +178,22 @@ describe('#compileRestApi()', () => {
             Types: ['EDGE'],
           },
           Name: 'dev-new-service',
+          Policy: {
+            Statement: [
+              {
+                Action: 'execute-api:Invoke',
+                Condition: {
+                  IpAddress: {
+                    'aws:SourceIp': ['0.0.0.0/0', '::/0'],
+                  },
+                },
+                Effect: 'Allow',
+                Principal: '*',
+                Resource: ['execute-api:/*/*/*'],
+              },
+            ],
+            Version: '2012-10-17',
+          },
         },
       });
     });