Repository: aws-cloudformation/cfn-lint (Python)

Issue:
AWS::Serverless transform creating resources that fail W3011 (DeletionPolicy/UpdateReplacePolicy rule)
*cfn-lint version: (`cfn-lint --version`)*
0.26.01

*Description of issue.*
The latest version of cfn-lint creates a warning in case of missing Deletion and UpdateReplace policy. This complain appears even though both properties are set for an S3 bucket which is the only resource in our stack wich requires these properties according to https://github.com/aws-cloudformation/cfn-python-lint/pull/1232. This warning did not appear prior to version 0.26.1. What is the difference beween I3011 and W3011?

```
Resources:
  xxxBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Delete
    UpdateReplacePolicy: Delete
    Properties:...
```


Discussion:
> What is the difference beween I3011 and W3011?

[`W3011`](https://github.com/aws-cloudformation/cfn-python-lint/blob/master/src/cfnlint/rules/resources/BothUpdateReplacePolicyDeletionPolicyNeeded.py) warns about any resource that is protected from deletion through either an [`UpdateReplacePolicy`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatereplacepolicy.html) or a [`DeletionPolicy`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) but not protected by both

[`I3011`](https://github.com/aws-cloudformation/cfn-python-lint/blob/master/src/cfnlint/rules/resources/UpdateReplacePolicyDeletionPolicyOnStatefulResourceTypes.py) informs about any resource missing [`UpdateReplacePolicy`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatereplacepolicy.html) / [`DeletionPolicy`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) that could potentially result in data loss based on its resource type:

https://github.com/aws-cloudformation/cfn-lint/blob/c3d16457059e03eaaf752f403d1983c1c7be3d0a/src/cfnlint/rules/resources/UpdateReplacePolicyDeletionPolicyOnStatefulResourceTypes.py#L22-L39

---

@TLaue are you comfortable sharing the template that is generating the warning? I wasn't able to produce output with either of these templates:

```yaml
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Delete
    UpdateReplacePolicy: Delete
```

```yaml
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Delete
    UpdateReplacePolicy: Delete
    Properties:
      BucketName: bucket
```

---

@TLaue @kddejong some of the confusion might be coming from the 3011 messages lacking the resource logical ID that other rules provide. I can add that. In the meantime, rules give the line number of the violation and the [Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=kddejong.vscode-cfn-lint) should show them in context 
May I send the template via email to you? Can you provide an email address?
It is on the way.
@TLaue I believe the [`AWS::Serverless`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/transform-aws-serverless.html) transform is creating [`AWS::Lambda::Version`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-version.html) resources with `DeletionPolicy: Retain` but no [`UpdateReplacePolicy`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatereplacepolicy.html). Will reach out to them about that
> AWS::Lambda::Version

In my template, I've got `Transform: AWS::Serverless-2016-10-31` and `AutoPublishAlias: live` property in my `AWS::Serverless::Function`, and it fails to pass the updated `W3011`. I believe it's the `AWS::Lambda::Version` causing the problem, as if I comment out `AutoPublishAlias: live`, `W3011` passes.
#1266 should make what's happening clearer

@keetonian @praneetap any thoughts on which [`UpdateReplacePolicy`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatereplacepolicy.html) to set on those resources?

https://github.com/awslabs/serverless-application-model/blob/a9388b64147e12426ba585482ee96f81db2dd25a/samtranslator/model/sam_resources.py#L415
https://github.com/awslabs/serverless-application-model/blob/a9388b64147e12426ba585482ee96f81db2dd25a/samtranslator/model/sam_resources.py#L794
A workaround: 
```bash
cfn-lint --ignore-checks W3011 -t template.yml
```
The error is because SAM creates resources of type `AWS::Lambda::Version` for each lambda function. 
This Version resource has a default property `"DeletionPolicy": "Retain"` , but they don't have `UpdateReplacePolicy` property.
To see the full resources after transformation run cfn-lint with `--info`.

@PatMyron any news on this?
Any update on this ?
[The explicit UpdateReplacePolicy changes](https://github.com/awslabs/serverless-application-model/pull/1481) have been merged into AWS::Serverless transform's develop branch, but [still haven't made it into a release yet](https://github.com/awslabs/serverless-application-model/releases). Will update once those changes have been released
[Taking longer than expected](https://github.com/awslabs/serverless-application-model/pull/1481#issuecomment-618516935) for [`AWS::Serverless` transform](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/transform-aws-serverless.html) [`UpdateReplacePolicy`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatereplacepolicy.html) support so [I've exempted those two `AWS::Lambda` resource types ](https://github.com/aws-cloudformation/cfn-python-lint/pull/1529) from evaluation in [`W3011`](https://github.com/aws-cloudformation/cfn-python-lint/blob/master/src/cfnlint/rules/resources/BothUpdateReplacePolicyDeletionPolicyNeeded.py), so it should be enforceable as of [`0.31.1`](https://github.com/aws-cloudformation/cfn-python-lint/pull/1530), which is available through [`pip3 install cfn-lint --upgrade`](https://pypi.org/project/cfn-lint/0.31.1/)

Sorry for delays and thanks for waiting
I'm still getting this with the below template:

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Resources:

  Bucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    UpdateReplacePolicy: Retain

  Function:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs12.x
      Events:
        ObjectCreated:
          Type: S3
          Properties:
            Bucket: !Ref Bucket
            Events: s3:ObjectCreated:*
```

```
[cfn-lint] W3011: Both UpdateReplacePolicy and DeletionPolicy are needed to protect Resources/Bucket from deletion
```

EDIT: Looking at the transformed template, it seems there's still the same issue with SAM – it removes the `UpdateReplacePolicy`:
```yaml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  Bucket:
    DeletionPolicy: Retain
    DependsOn:
    - FunctionObjectCreatedPermission
    Properties:
      NotificationConfiguration:
        LambdaConfigurations:
        - Event: s3:ObjectCreated:*
          Function:
            Fn::GetAtt:
            - Function
            - Arn
    Type: AWS::S3::Bucket
# ...
```

Commented on the SAM repo over at: https://github.com/aws/serverless-application-model/issues/450#issuecomment-695323146



Patch:
diff --git a/src/cfnlint/rules/resources/BothUpdateReplacePolicyDeletionPolicyNeeded.py b/src/cfnlint/rules/resources/BothUpdateReplacePolicyDeletionPolicyNeeded.py
index 04ddf88302..c110133e6d 100644
--- a/src/cfnlint/rules/resources/BothUpdateReplacePolicyDeletionPolicyNeeded.py
+++ b/src/cfnlint/rules/resources/BothUpdateReplacePolicyDeletionPolicyNeeded.py
@@ -19,10 +19,11 @@ def match(self, cfn):
         matches = []
 
         for r_name, r_values in cfn.get_resources().items():
-            # pylint: disable=too-many-boolean-expressions
-            if r_values.get('DeletionPolicy') and r_values.get('DeletionPolicy') != 'Delete' and not r_values.get('UpdateReplacePolicy') or not r_values.get('DeletionPolicy') and r_values.get('UpdateReplacePolicy') and r_values.get('UpdateReplacePolicy') != 'Delete':
-                path = ['Resources', r_name]
-                message = 'Both UpdateReplacePolicy and DeletionPolicy are needed to protect %s from deletion' % '/'.join(path)
-                matches.append(RuleMatch(path, message))
+            if r_values.get('Type') not in ['AWS::Lambda::Version', 'AWS::Lambda::LayerVersion']:
+                # pylint: disable=too-many-boolean-expressions
+                if r_values.get('DeletionPolicy') and r_values.get('DeletionPolicy') != 'Delete' and not r_values.get('UpdateReplacePolicy') or not r_values.get('DeletionPolicy') and r_values.get('UpdateReplacePolicy') and r_values.get('UpdateReplacePolicy') != 'Delete':
+                    path = ['Resources', r_name]
+                    message = 'Both UpdateReplacePolicy and DeletionPolicy are needed to protect %s from deletion' % '/'.join(path)
+                    matches.append(RuleMatch(path, message))
 
         return matches


Test patch:
diff --git a/test/integration/test_good_templates.py b/test/integration/test_good_templates.py
index dd1b79d82b..7f9e2802a0 100644
--- a/test/integration/test_good_templates.py
+++ b/test/integration/test_good_templates.py
@@ -22,34 +22,8 @@ class TestQuickStartTemplates(BaseCliTestCase):
         },
         {
             'filename': 'test/fixtures/templates/good/transform.yaml',
-            'results': [
-                {
-                    "Filename": "test/fixtures/templates/good/transform.yaml",
-                    "Level": "Warning",
-                    "Location": {
-                        "End": {
-                            "ColumnNumber": 10,
-                            "LineNumber": 4
-                        },
-                        "Path": [
-                            "Resources",
-                            "ExampleLayer29b0582575"
-                        ],
-                        "Start": {
-                            "ColumnNumber": 1,
-                            "LineNumber": 4
-                        }
-                    },
-                    "Message": "Both UpdateReplacePolicy and DeletionPolicy are needed to protect Resources/ExampleLayer29b0582575 from deletion",
-                    "Rule": {
-                        "Description": "Both UpdateReplacePolicy and DeletionPolicy are needed to protect resources from deletion",
-                        "Id": "W3011",
-                        "ShortDescription": "Check resources with UpdateReplacePolicy/DeletionPolicy have both",
-                        "Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html"
-                    }
-                }
-            ],
-            'exit_code': 4,
+            'results': [],
+            'exit_code': 0,
         },
         {
             'filename': 'test/fixtures/templates/bad/transform_serverless_template.yaml',
@@ -135,94 +109,17 @@ class TestQuickStartTemplates(BaseCliTestCase):
         },
         {
             'filename': 'test/fixtures/templates/good/transform_serverless_api.yaml',
-            'results': [
-                {
-                    "Filename": "test/fixtures/templates/good/transform_serverless_api.yaml",
-                    "Level": "Warning",
-                    "Location": {
-                        "End": {
-                            "ColumnNumber": 10,
-                            "LineNumber": 4
-                        },
-                        "Path": [
-                            "Resources",
-                            "myFunctionVersionee13cf2679"
-                        ],
-                        "Start": {
-                            "ColumnNumber": 1,
-                            "LineNumber": 4
-                        }
-                    },
-                    "Message": "Both UpdateReplacePolicy and DeletionPolicy are needed to protect Resources/myFunctionVersionee13cf2679 from deletion",
-                    "Rule": {
-                        "Description": "Both UpdateReplacePolicy and DeletionPolicy are needed to protect resources from deletion",
-                        "Id": "W3011",
-                        "ShortDescription": "Check resources with UpdateReplacePolicy/DeletionPolicy have both",
-                        "Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html"
-                    }
-                }
-            ],
-            'exit_code': 4,
+            'results': [],
+            'exit_code': 0,
         },
         {
             'filename': 'test/fixtures/templates/good/transform_serverless_function.yaml',
-            'results': [
-                {
-                    "Filename": "test/fixtures/templates/good/transform_serverless_function.yaml",
-                    "Level": "Warning",
-                    "Location": {
-                        "End": {
-                            "ColumnNumber": 10,
-                            "LineNumber": 4
-                        },
-                        "Path": [
-                            "Resources",
-                            "myFunctionVersionee13cf2679"
-                        ],
-                        "Start": {
-                            "ColumnNumber": 1,
-                            "LineNumber": 4
-                        }
-                    },
-                    "Message": "Both UpdateReplacePolicy and DeletionPolicy are needed to protect Resources/myFunctionVersionee13cf2679 from deletion",
-                    "Rule": {
-                        "Description": "Both UpdateReplacePolicy and DeletionPolicy are needed to protect resources from deletion",
-                        "Id": "W3011",
-                        "ShortDescription": "Check resources with UpdateReplacePolicy/DeletionPolicy have both",
-                        "Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html"
-                    }
-                }
-            ],
-            'exit_code': 4,
+            'results': [],
+            'exit_code': 0,
         },
         {
             'filename': 'test/fixtures/templates/good/transform_serverless_globals.yaml',
             'results': [
-                {
-                    "Filename": "test/fixtures/templates/good/transform_serverless_globals.yaml",
-                    "Level": "Warning",
-                    "Location": {
-                        "End": {
-                            "ColumnNumber": 10,
-                            "LineNumber": 9
-                        },
-                        "Path": [
-                            "Resources",
-                            "myFunctionVersionee13cf2679"
-                        ],
-                        "Start": {
-                            "ColumnNumber": 1,
-                            "LineNumber": 9
-                        }
-                    },
-                    "Message": "Both UpdateReplacePolicy and DeletionPolicy are needed to protect Resources/myFunctionVersionee13cf2679 from deletion",
-                    "Rule": {
-                        "Description": "Both UpdateReplacePolicy and DeletionPolicy are needed to protect resources from deletion",
-                        "Id": "W3011",
-                        "ShortDescription": "Check resources with UpdateReplacePolicy/DeletionPolicy have both",
-                        "Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html"
-                    }
-                },
                 {
                     "Filename": "test/fixtures/templates/good/transform_serverless_globals.yaml",
                     "Level": "Error",
@@ -251,38 +148,12 @@ class TestQuickStartTemplates(BaseCliTestCase):
                     }
                 }
             ],
-            'exit_code': 6,
+            'exit_code': 2,
         },
         {
             'filename': 'test/fixtures/templates/good/transform/list_transform.yaml',
-            'results': [
-                {
-                    "Filename": "test/fixtures/templates/good/transform/list_transform.yaml",
-                    "Level": "Warning",
-                    "Location": {
-                        "End": {
-                            "ColumnNumber": 10,
-                            "LineNumber": 14
-                        },
-                        "Path": [
-                            "Resources",
-                            "SkillFunctionVersion55ff35af87"
-                        ],
-                        "Start": {
-                            "ColumnNumber": 1,
-                            "LineNumber": 14
-                        }
-                    },
-                    "Message": "Both UpdateReplacePolicy and DeletionPolicy are needed to protect Resources/SkillFunctionVersion55ff35af87 from deletion",
-                    "Rule": {
-                        "Description": "Both UpdateReplacePolicy and DeletionPolicy are needed to protect resources from deletion",
-                        "Id": "W3011",
-                        "ShortDescription": "Check resources with UpdateReplacePolicy/DeletionPolicy have both",
-                        "Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html"
-                    }
-                }
-            ],
-            'exit_code': 4,
+            'results': [],
+            'exit_code': 0,
         },
         {
             'filename': 'test/fixtures/templates/good/transform/list_transform_many.yaml',