Repository: serverless/serverless (JavaScript)
Date: 2019-10-13 18:15:52+00:00
Task type: Bug Fix

Issue:
Using 2 or more "CloudWatchLog event handlers" for the same lambda fails to create correct permissions
<!--
1. If you have a question and not a bug report please ask first at http://forum.serverless.com
2. Please check if an issue already exists. This bug may have already been documented
3. Check out and follow our Guidelines: https://github.com/serverless/serverless/blob/master/CONTRIBUTING.md
4. Fill out the whole template so we have a good overview on the issue
5. Do not remove any section of the template. If something is not applicable leave it empty but leave it in the Issue
6. Please follow the template, otherwise we'll have to ask you to update it
-->

# This is a Bug Report

## Description

```
functions:
  dummy-logger:
    handler: handler.logger
    events:
      - cloudwatchLog:
          logGroup: '/aws/lambda/yada-${self:provider.stage}-dummy'
          filter: 'REPORT'
      - cloudwatchLog:
          logGroup: '/aws/lambda/yada-${self:provider.stage}-dummy2'
          filter: 'REPORT'
```

* 2 AWS::Logs::SubscriptionFilter objects are created (using index see issue #6263)
* Only one AWS::Lambda::Permission is created (likely from index 1/blank)
* Permission Object only refers to logGroup from first SubscriptionFilter handler
* Template fails with:
`Could not execute the lambda function. Make sure you have given CloudWatch Logs permission to execute your function. (Service: AWSLogs; Status Code: 400; Error Code: InvalidParameterException; Request ID: 0b096e01-87d2-11e9-b52a-59a1410a5e04)`

Similar or dependent issues:
* #5833
* #6263

## Additional Data

* serverless@1.44.1
* Ubuntu and MacOs(Darwin)
* 'Could not execute the lambda function. Make sure you have given CloudWatch Logs permission to execute your function. (Service: AWSLogs; Status Code: 400; Error Code: InvalidParameterException; Request ID: 0b096e01-87d2-11e9-b52a-59a1410a5e04)'
* As reported on 6/5 [forum.serverless.com](https://forum.serverless.com/t/aws-provider-fails-if-2-or-more-cloudwatchlog-events-listed/8483) 



Issue discussion:
As a workaround I found serverless@1.35.1 to be the latest version which does not suffer from this bug.

Solution patch:
diff --git a/docs/providers/aws/events/cloudwatch-log.md b/docs/providers/aws/events/cloudwatch-log.md
index d5021973b7d..e6e385cc599 100644
--- a/docs/providers/aws/events/cloudwatch-log.md
+++ b/docs/providers/aws/events/cloudwatch-log.md
@@ -26,6 +26,8 @@ functions:
       - cloudwatchLog: '/aws/lambda/hello'
 ```
 
+**WARNING**: If you specify several CloudWatch Log events for one AWS Lambda function you'll only see the first subscription in the AWS Lambda Web console. This is a known AWS problem but it's only graphical, you should be able to view your CloudWatch Log Group subscriptions in the CloudWatch Web console.
+
 ## Specifying a filter
 
 Here's an example how you can specify a filter rule.
diff --git a/lib/plugins/aws/package/compile/events/cloudWatchLog/index.js b/lib/plugins/aws/package/compile/events/cloudWatchLog/index.js
index 58024492c8b..d5ca4210bcf 100644
--- a/lib/plugins/aws/package/compile/events/cloudWatchLog/index.js
+++ b/lib/plugins/aws/package/compile/events/cloudWatchLog/index.js
@@ -151,7 +151,7 @@ class AwsCompileCloudWatchLogEvents {
 
   longestCommonSuffix(logGroupNames) {
     const first = logGroupNames[0];
-    const longestCommon = logGroupNames.reduce((last, current) => {
+    let longestCommon = logGroupNames.reduce((last, current) => {
       for (let i = 0; i < last.length; i++) {
         if (last[i] !== current[i]) {
           return last.substring(0, i);
@@ -159,7 +159,12 @@ class AwsCompileCloudWatchLogEvents {
       }
       return last;
     }, first);
-    return longestCommon + (longestCommon === first ? '' : '*');
+
+    if (logGroupNames.length > 1 && !longestCommon.endsWith('*')) {
+      longestCommon += '*';
+    }
+
+    return longestCommon;
   }
 }
 


Test patch:
diff --git a/lib/plugins/aws/package/compile/events/cloudWatchLog/index.test.js b/lib/plugins/aws/package/compile/events/cloudWatchLog/index.test.js
index 9161f09dcc1..7803c51814b 100644
--- a/lib/plugins/aws/package/compile/events/cloudWatchLog/index.test.js
+++ b/lib/plugins/aws/package/compile/events/cloudWatchLog/index.test.js
@@ -311,6 +311,15 @@ describe('AwsCompileCloudWatchLogEvents', () => {
       expect(
         awsCompileCloudWatchLogEvents.longestCommonSuffix(['/aws/lambda/*', '/aws/lambda/hello'])
       ).to.equal('/aws/lambda/*');
+      expect(
+        awsCompileCloudWatchLogEvents.longestCommonSuffix(['/aws/lambda', '/aws/lambda/hello'])
+      ).to.equal('/aws/lambda*');
+      expect(
+        awsCompileCloudWatchLogEvents.longestCommonSuffix([
+          '/aws/lambda/yada-dev-dummy',
+          '/aws/lambda/yada-dev-dummy2',
+        ])
+      ).to.equal('/aws/lambda/yada-dev-dummy*');
     });
 
     it('should throw an error if "logGroup" is duplicated in one CloudFormation stack', () => {