prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  E2506 prevents using SourceSecurityGroupId for non-vpc security groups
  https://github.com/aws-cloudformation/cfn-lint/blob/4a7af2bd53a9ad1ccaba3a509437c53102ade522/src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py#L33-L40
  
  I couldn't see any reason in the [cloudformation reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-rule-1.html#cfn-ec2-security-group-rule-sourcesecuritygroupid) that this wouldn't be valid, and I was able successfully create the following stack, where SecurityGroupB seems to be correctly restricted to traffic from SecurityGroupA. I _think_ that this rule is incorrect, unless I'm missing something
  
  ```yaml
  AWSTemplateFormatVersion: '2010-09-09'
  Resources:
    SecurityGroupA:
      Type: AWS::EC2::SecurityGroup
      Properties:
        GroupDescription: Group A
        SecurityGroupIngress:
          - FromPort: 80
            ToPort: 80
            IpProtocol: tcp
            CidrIp: 0.0.0.0/0
  
    SecurityGroupB:
      Type: AWS::EC2::SecurityGroup
      Properties:
        GroupDescription: Group B
        SecurityGroupIngress:
          - FromPort: 80
            ToPort: 80
            IpProtocol: tcp
            SourceSecurityGroupId:
              Fn::GetAtt:
                - SecurityGroupA
                - GroupId
  ```
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py`
  Content:
  ```
  1 """
  2 Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3 SPDX-License-Identifier: MIT-0
  4 """
  5 from cfnlint.rules import CloudFormationLintRule, RuleMatch
  6 
  7 
  8 class SecurityGroupIngress(CloudFormationLintRule):
  9     """Check if EC2 Security Group Ingress Properties"""
  10 
  11     id = "E2506"
  12     shortdesc = "Resource EC2 Security Group Ingress Properties"
  13     description = (
  14         "See if EC2 Security Group Ingress Properties are set correctly. "
  15         'Check that "SourceSecurityGroupId" or "SourceSecurityGroupName" are '
  16         " are exclusive and using the type of Ref or GetAtt "
  17     )
  18     source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-ingress.html"
  19     tags = ["resources", "ec2", "securitygroup"]
  20 
  21     def check_ingress_rule(self, vpc_id, properties, path):
  22         """Check ingress rule"""
  23 
  24         matches = []
  25         if vpc_id:
  26             # Check that SourceSecurityGroupName isn't specified
  27             if properties.get("SourceSecurityGroupName", None):
  28                 path_error = path[:] + ["SourceSecurityGroupName"]
  29                 message = (
  30                     "SourceSecurityGroupName shouldn't be specified for "
  31                     "Vpc Security Group at {0}"
  32                 )
  33                 matches.append(
  34                     RuleMatch(
  35                         path_error, message.format("/".join(map(str, path_error)))
  36                     )
  37                 )
  38 
  39         else:
  40             if properties.get("SourceSecurityGroupId", None):
  41                 path_error = path[:] + ["SourceSecurityGroupId"]
  42                 message = (
  43                     "SourceSecurityGroupId shouldn't be specified for "
  44                     "Non-Vpc Security Group at {0}"
  45                 )
  46                 matches.append(
  47                     RuleMatch(
  48                         path_error, message.format("/".join(map(str, path_error)))
  49                     )
  50                 )
  51 
  52         return matches
  53 
  54     def match(self, cfn):
  55         """Check EC2 Security Group Ingress Resource Parameters"""
  56 
  57         matches = []
  58 
  59         resources = cfn.get_resources(resource_type="AWS::EC2::SecurityGroup")
  60         for resource_name, resource_object in resources.items():
  61             properties = resource_object.get("Properties", {})
  62             if properties:
  63                 vpc_id = properties.get("VpcId", None)
  64                 ingress_rules = properties.get("SecurityGroupIngress")
  65                 if isinstance(ingress_rules, list):
  66                     for index, ingress_rule in enumerate(ingress_rules):
  67                         path = [
  68                             "Resources",
  69                             resource_name,
  70                             "Properties",
  71                             "SecurityGroupIngress",
  72                             index,
  73                         ]
  74                         matches.extend(
  75                             self.check_ingress_rule(
  76                                 vpc_id=vpc_id, properties=ingress_rule, path=path
  77                             )
  78                         )
  79 
  80         resources = None
  81         resources = cfn.get_resources(resource_type="AWS::EC2::SecurityGroupIngress")
  82         for resource_name, resource_object in resources.items():
  83             properties = resource_object.get("Properties", {})
  84             group_id = properties.get("GroupId", None)
  85             path = ["Resources", resource_name, "Properties"]
  86             if group_id:
  87                 vpc_id = "vpc-1234567"
  88             else:
  89                 vpc_id = None
  90 
  91             if properties:
  92                 path = ["Resources", resource_name, "Properties"]
  93                 matches.extend(
  94                     self.check_ingress_rule(
  95                         vpc_id=vpc_id, properties=properties, path=path
  96                     )
  97                 )
  98         return matches
  99
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py b/src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py
  --- a/src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py
  +++ b/src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py
  @@ -36,19 +36,6 @@
                       )
                   )
   
  -        else:
  -            if properties.get("SourceSecurityGroupId", None):
  -                path_error = path[:] + ["SourceSecurityGroupId"]
  -                message = (
  -                    "SourceSecurityGroupId shouldn't be specified for "
  -                    "Non-Vpc Security Group at {0}"
  -                )
  -                matches.append(
  -                    RuleMatch(
  -                        path_error, message.format("/".join(map(str, path_error)))
  -                    )
  -                )
  -
           return matches
   
       def match(self, cfn):
  
verification_info: {"golden_diff": "diff --git a/src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py b/src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py\n--- a/src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py\n+++ b/src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py\n@@ -36,19 +36,6 @@\n                     )\n                 )\n \n-        else:\n-            if properties.get(\"SourceSecurityGroupId\", None):\n-                path_error = path[:] + [\"SourceSecurityGroupId\"]\n-                message = (\n-                    \"SourceSecurityGroupId shouldn't be specified for \"\n-                    \"Non-Vpc Security Group at {0}\"\n-                )\n-                matches.append(\n-                    RuleMatch(\n-                        path_error, message.format(\"/\".join(map(str, path_error)))\n-                    )\n-                )\n-\n         return matches\n \n     def match(self, cfn):\n", "issue": "E2506 prevents using SourceSecurityGroupId for non-vpc security groups\nhttps://github.com/aws-cloudformation/cfn-lint/blob/4a7af2bd53a9ad1ccaba3a509437c53102ade522/src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py#L33-L40\r\n\r\nI couldn't see any reason in the [cloudformation reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-rule-1.html#cfn-ec2-security-group-rule-sourcesecuritygroupid) that this wouldn't be valid, and I was able successfully create the following stack, where SecurityGroupB seems to be correctly restricted to traffic from SecurityGroupA. I _think_ that this rule is incorrect, unless I'm missing something\r\n\r\n```yaml\r\nAWSTemplateFormatVersion: '2010-09-09'\r\nResources:\r\n  SecurityGroupA:\r\n    Type: AWS::EC2::SecurityGroup\r\n    Properties:\r\n      GroupDescription: Group A\r\n      SecurityGroupIngress:\r\n        - FromPort: 80\r\n          ToPort: 80\r\n          IpProtocol: tcp\r\n          CidrIp: 0.0.0.0/0\r\n\r\n  SecurityGroupB:\r\n    Type: AWS::EC2::SecurityGroup\r\n    Properties:\r\n      GroupDescription: Group B\r\n      SecurityGroupIngress:\r\n        - FromPort: 80\r\n          ToPort: 80\r\n          IpProtocol: tcp\r\n          SourceSecurityGroupId:\r\n            Fn::GetAtt:\r\n              - SecurityGroupA\r\n              - GroupId\r\n```\n", "before_files": [{"content": "\"\"\"\nCopyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\nfrom cfnlint.rules import CloudFormationLintRule, RuleMatch\n\n\nclass SecurityGroupIngress(CloudFormationLintRule):\n    \"\"\"Check if EC2 Security Group Ingress Properties\"\"\"\n\n    id = \"E2506\"\n    shortdesc = \"Resource EC2 Security Group Ingress Properties\"\n    description = (\n        \"See if EC2 Security Group Ingress Properties are set correctly. \"\n        'Check that \"SourceSecurityGroupId\" or \"SourceSecurityGroupName\" are '\n        \" are exclusive and using the type of Ref or GetAtt \"\n    )\n    source_url = \"https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-ingress.html\"\n    tags = [\"resources\", \"ec2\", \"securitygroup\"]\n\n    def check_ingress_rule(self, vpc_id, properties, path):\n        \"\"\"Check ingress rule\"\"\"\n\n        matches = []\n        if vpc_id:\n            # Check that SourceSecurityGroupName isn't specified\n            if properties.get(\"SourceSecurityGroupName\", None):\n                path_error = path[:] + [\"SourceSecurityGroupName\"]\n                message = (\n                    \"SourceSecurityGroupName shouldn't be specified for \"\n                    \"Vpc Security Group at {0}\"\n                )\n                matches.append(\n                    RuleMatch(\n                        path_error, message.format(\"/\".join(map(str, path_error)))\n                    )\n                )\n\n        else:\n            if properties.get(\"SourceSecurityGroupId\", None):\n                path_error = path[:] + [\"SourceSecurityGroupId\"]\n                message = (\n                    \"SourceSecurityGroupId shouldn't be specified for \"\n                    \"Non-Vpc Security Group at {0}\"\n                )\n                matches.append(\n                    RuleMatch(\n                        path_error, message.format(\"/\".join(map(str, path_error)))\n                    )\n                )\n\n        return matches\n\n    def match(self, cfn):\n        \"\"\"Check EC2 Security Group Ingress Resource Parameters\"\"\"\n\n        matches = []\n\n        resources = cfn.get_resources(resource_type=\"AWS::EC2::SecurityGroup\")\n        for resource_name, resource_object in resources.items():\n            properties = resource_object.get(\"Properties\", {})\n            if properties:\n                vpc_id = properties.get(\"VpcId\", None)\n                ingress_rules = properties.get(\"SecurityGroupIngress\")\n                if isinstance(ingress_rules, list):\n                    for index, ingress_rule in enumerate(ingress_rules):\n                        path = [\n                            \"Resources\",\n                            resource_name,\n                            \"Properties\",\n                            \"SecurityGroupIngress\",\n                            index,\n                        ]\n                        matches.extend(\n                            self.check_ingress_rule(\n                                vpc_id=vpc_id, properties=ingress_rule, path=path\n                            )\n                        )\n\n        resources = None\n        resources = cfn.get_resources(resource_type=\"AWS::EC2::SecurityGroupIngress\")\n        for resource_name, resource_object in resources.items():\n            properties = resource_object.get(\"Properties\", {})\n            group_id = properties.get(\"GroupId\", None)\n            path = [\"Resources\", resource_name, \"Properties\"]\n            if group_id:\n                vpc_id = \"vpc-1234567\"\n            else:\n                vpc_id = None\n\n            if properties:\n                path = [\"Resources\", resource_name, \"Properties\"]\n                matches.extend(\n                    self.check_ingress_rule(\n                        vpc_id=vpc_id, properties=properties, path=path\n                    )\n                )\n        return matches\n", "path": "src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py"}], "after_files": [{"content": "\"\"\"\nCopyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\nfrom cfnlint.rules import CloudFormationLintRule, RuleMatch\n\n\nclass SecurityGroupIngress(CloudFormationLintRule):\n    \"\"\"Check if EC2 Security Group Ingress Properties\"\"\"\n\n    id = \"E2506\"\n    shortdesc = \"Resource EC2 Security Group Ingress Properties\"\n    description = (\n        \"See if EC2 Security Group Ingress Properties are set correctly. \"\n        'Check that \"SourceSecurityGroupId\" or \"SourceSecurityGroupName\" are '\n        \" are exclusive and using the type of Ref or GetAtt \"\n    )\n    source_url = \"https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-ingress.html\"\n    tags = [\"resources\", \"ec2\", \"securitygroup\"]\n\n    def check_ingress_rule(self, vpc_id, properties, path):\n        \"\"\"Check ingress rule\"\"\"\n\n        matches = []\n        if vpc_id:\n            # Check that SourceSecurityGroupName isn't specified\n            if properties.get(\"SourceSecurityGroupName\", None):\n                path_error = path[:] + [\"SourceSecurityGroupName\"]\n                message = (\n                    \"SourceSecurityGroupName shouldn't be specified for \"\n                    \"Vpc Security Group at {0}\"\n                )\n                matches.append(\n                    RuleMatch(\n                        path_error, message.format(\"/\".join(map(str, path_error)))\n                    )\n                )\n\n        return matches\n\n    def match(self, cfn):\n        \"\"\"Check EC2 Security Group Ingress Resource Parameters\"\"\"\n\n        matches = []\n\n        resources = cfn.get_resources(resource_type=\"AWS::EC2::SecurityGroup\")\n        for resource_name, resource_object in resources.items():\n            properties = resource_object.get(\"Properties\", {})\n            if properties:\n                vpc_id = properties.get(\"VpcId\", None)\n                ingress_rules = properties.get(\"SecurityGroupIngress\")\n                if isinstance(ingress_rules, list):\n                    for index, ingress_rule in enumerate(ingress_rules):\n                        path = [\n                            \"Resources\",\n                            resource_name,\n                            \"Properties\",\n                            \"SecurityGroupIngress\",\n                            index,\n                        ]\n                        matches.extend(\n                            self.check_ingress_rule(\n                                vpc_id=vpc_id, properties=ingress_rule, path=path\n                            )\n                        )\n\n        resources = None\n        resources = cfn.get_resources(resource_type=\"AWS::EC2::SecurityGroupIngress\")\n        for resource_name, resource_object in resources.items():\n            properties = resource_object.get(\"Properties\", {})\n            group_id = properties.get(\"GroupId\", None)\n            path = [\"Resources\", resource_name, \"Properties\"]\n            if group_id:\n                vpc_id = \"vpc-1234567\"\n            else:\n                vpc_id = None\n\n            if properties:\n                path = [\"Resources\", resource_name, \"Properties\"]\n                matches.extend(\n                    self.check_ingress_rule(\n                        vpc_id=vpc_id, properties=properties, path=path\n                    )\n                )\n        return matches\n", "path": "src/cfnlint/rules/resources/ectwo/SecurityGroupIngress.py"}]}