Repository: aws-cloudformation/cfn-lint

Issue:
ECS Task definition container log driver enum does not include "sumologic"
Our team uses the somologic log driver in container definitions. It appears that when validation was added sub properties, "sumologic" was not included in the enum used to validate LogDriver types. This change seems to have been introduced in issue #3763. 

Here's an example of where we are using the sumologic log driver. 

```yaml
TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      TaskRoleArn: !Ref TaskRole
      ExecutionRoleArn: !GetAtt ExecutionRole.Arn
      ContainerDefinitions:
        - Name: nginx
          Essential: true
          Image: !Sub  <accountId>.dkr.ecr.${AWS::Region}.amazonaws.com/<imageName>:latest
          Memory: 16
          PortMappings:
            - ContainerPort: 443
          Links:
            - app
          LogConfiguration:
            LogDriver: sumologic
            Options:
              sumo-url: !GetAtt SumoUrl.Value
              sumo-source-category: !Sub ${Environment}/${ProjectName}/access
```

When we execute cfn-lint the following error is returned.

```
E3030 'sumologic' is not one of ['awsfirelens', 'awslogs', 'fluentd', 'gelf', 'journald', 'json-file', 'splunk', 'syslog']
ci/service.template:234:13
```

Is resolving this just a matter of extending the enum to include "sumologic" log driver? If so, I can contribute this and submit a PR.


Discussion:
Looking into this.  When I look at the [API docs](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LogConfiguration.html) or [CFN docs](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LogConfiguration.html) they don't list sumologic. Trying to find a more complete list then or what I'm missing.
[This](https://github.com/aws/amazon-ecs-agent/blob/0f876b5372c9ecb15228f607f11d2c4be629d364/agent/dockerclient/logging_drivers.go#L18-L30) looks like its the complete list and we are taking this value from [boto](https://github.com/boto/botocore/blob/3ff30ef929da20bc83a1f21d1bd3ab6e408648fe/botocore/data/ecs/2014-11-13/service-2.json#L3554-L3566). 
Are you using External or EC2 launch types or compatibilities?
I'm not sure what you mean by launch type but we deploy to ECS on ec2. 
Yea, slight typo there.  Either way the LogDriver when using EC2 and EXTERNAL should work. I have updated our definition and logic to remove this error for you.



Patch:
diff --git a/scripts/boto/update_schemas_from_boto.py b/scripts/boto/update_schemas_from_boto.py
index 829cd3f629..4cfea803bd 100755
--- a/scripts/boto/update_schemas_from_boto.py
+++ b/scripts/boto/update_schemas_from_boto.py
@@ -29,7 +29,8 @@
 ]
 
 exceptions = {
-    "ses": ["/definitions/EventDestination/properties/MatchingEventTypes/items"]
+    "ses": ["/definitions/EventDestination/properties/MatchingEventTypes/items"],
+    "ecs": ["/definitions/LogConfiguration/properties/LogDriver"],
 }
 
 
diff --git a/src/cfnlint/data/schemas/extensions/aws_ecs_taskdefinition/fargate_properties.json b/src/cfnlint/data/schemas/extensions/aws_ecs_taskdefinition/fargate_properties.json
index f0326beeb0..94885935c2 100644
--- a/src/cfnlint/data/schemas/extensions/aws_ecs_taskdefinition/fargate_properties.json
+++ b/src/cfnlint/data/schemas/extensions/aws_ecs_taskdefinition/fargate_properties.json
@@ -16,54 +16,119 @@
   ]
  },
  "then": {
-  "if": {
-   "properties": {
-    "Cpu": {
-     "type": [
-      "string",
-      "integer"
+  "allOf": [
+   {
+    "if": {
+     "properties": {
+      "NetworkMode": {
+       "type": "string"
+      }
+     },
+     "required": [
+      "NetworkMode"
+     ]
+    },
+    "required": [
+     "NetworkMode"
+    ],
+    "then": {
+     "properties": {
+      "NetworkMode": {
+       "enum": [
+        "awsvpc"
+       ],
+       "type": "string"
+      }
+     },
+     "required": [
+      "NetworkMode"
      ]
     }
    },
-   "required": [
-    "Cpu"
-   ]
-  },
-  "not": {
-   "required": [
-    "PlacementConstraints"
-   ]
-  },
-  "required": [
-   "Cpu",
-   "Memory"
-  ],
-  "then": {
-   "properties": {
-    "Cpu": {
-     "else": {
-      "pattern": "^(\\.25|\\.5|1|2|4|8|16)\\s*(?i)vCpu$"
-     },
-     "if": {
-      "pattern": "^\\d+$",
-      "type": [
-       "integer",
-       "string"
-      ]
+   {
+    "properties": {
+     "ContainerDefinitions": {
+      "items": {
+       "properties": {
+        "LogConfiguration": {
+         "if": {
+          "properties": {
+           "LogDriver": {
+            "type": "string"
+           }
+          },
+          "required": [
+           "LogDriver"
+          ]
+         },
+         "then": {
+          "properties": {
+           "LogDriver": {
+            "enum": [
+             "awslogs",
+             "splunk",
+             "awsfirelens"
+            ]
+           }
+          }
+         }
+        }
+       }
+      }
+     }
+    }
+   },
+   {
+    "if": {
+     "properties": {
+      "Cpu": {
+       "type": [
+        "string",
+        "integer"
+       ]
+      }
      },
-     "then": {
-      "enum": [
-       "256",
-       "512",
-       "1024",
-       "2048",
-       "4096",
-       "8192",
-       "16384"
-      ]
+     "required": [
+      "Cpu"
+     ]
+    },
+    "not": {
+     "required": [
+      "PlacementConstraints"
+     ]
+    },
+    "required": [
+     "Cpu",
+     "Memory"
+    ],
+    "then": {
+     "properties": {
+      "Cpu": {
+       "else": {
+        "pattern": "^(\\.25|\\.5|1|2|4|8|16)\\s*(?i)vCpu$"
+       },
+       "if": {
+        "pattern": "^\\d+$",
+        "type": [
+         "integer",
+         "string"
+        ]
+       },
+       "then": {
+        "enum": [
+         "256",
+         "512",
+         "1024",
+         "2048",
+         "4096",
+         "8192",
+         "16384"
+        ]
+       }
+      }
      }
     }
    }
-  }
+  ]
  }
 }
diff --git a/src/cfnlint/data/schemas/patches/extensions/all/aws_ecs_service/boto.json b/src/cfnlint/data/schemas/patches/extensions/all/aws_ecs_service/boto.json
index e6ad41c272..fd1d715eeb 100644
--- a/src/cfnlint/data/schemas/patches/extensions/all/aws_ecs_service/boto.json
+++ b/src/cfnlint/data/schemas/patches/extensions/all/aws_ecs_service/boto.json
@@ -9,20 +9,6 @@
   "path": "/definitions/Tag/properties/Value/pattern",
   "value": "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$"
  },
- {
-  "op": "add",
-  "path": "/definitions/LogConfiguration/properties/LogDriver/enum",
-  "value": [
-   "awsfirelens",
-   "awslogs",
-   "fluentd",
-   "gelf",
-   "journald",
-   "json-file",
-   "splunk",
-   "syslog"
-  ]
- },
  {
   "op": "add",
   "path": "/definitions/EBSTagSpecification/properties/ResourceType/enum",
diff --git a/src/cfnlint/data/schemas/patches/extensions/all/aws_ecs_taskdefinition/boto.json b/src/cfnlint/data/schemas/patches/extensions/all/aws_ecs_taskdefinition/boto.json
index fb8d335eb8..f0973d86f5 100644
--- a/src/cfnlint/data/schemas/patches/extensions/all/aws_ecs_taskdefinition/boto.json
+++ b/src/cfnlint/data/schemas/patches/extensions/all/aws_ecs_taskdefinition/boto.json
@@ -71,20 +71,6 @@
    "stack"
   ]
  },
- {
-  "op": "add",
-  "path": "/definitions/LogConfiguration/properties/LogDriver/enum",
-  "value": [
-   "awsfirelens",
-   "awslogs",
-   "fluentd",
-   "gelf",
-   "journald",
-   "json-file",
-   "splunk",
-   "syslog"
-  ]
- },
  {
   "op": "add",
   "path": "/definitions/ResourceRequirement/properties/Type/enum",
diff --git a/src/cfnlint/data/schemas/providers/eu_central_1/aws-ecs-service.json b/src/cfnlint/data/schemas/providers/eu_central_1/aws-ecs-service.json
index 39c164ea67..7065156406 100644
--- a/src/cfnlint/data/schemas/providers/eu_central_1/aws-ecs-service.json
+++ b/src/cfnlint/data/schemas/providers/eu_central_1/aws-ecs-service.json
@@ -174,16 +174,6 @@
    "additionalProperties": false,
    "properties": {
     "LogDriver": {
-     "enum": [
-      "awsfirelens",
-      "awslogs",
-      "fluentd",
-      "gelf",
-      "journald",
-      "json-file",
-      "splunk",
-      "syslog"
-     ],
      "type": "string"
     },
     "Options": {
diff --git a/src/cfnlint/data/schemas/providers/us_east_1/aws-ecs-taskdefinition.json b/src/cfnlint/data/schemas/providers/us_east_1/aws-ecs-taskdefinition.json
index 8b9f473363..2db10e86bc 100644
--- a/src/cfnlint/data/schemas/providers/us_east_1/aws-ecs-taskdefinition.json
+++ b/src/cfnlint/data/schemas/providers/us_east_1/aws-ecs-taskdefinition.json
@@ -581,16 +581,6 @@
    "additionalProperties": false,
    "properties": {
     "LogDriver": {
-     "enum": [
-      "awsfirelens",
-      "awslogs",
-      "fluentd",
-      "gelf",
-      "journald",
-      "json-file",
-      "splunk",
-      "syslog"
-     ],
      "type": "string"
     },
     "Options": {
diff --git a/src/cfnlint/data/schemas/providers/us_west_2/aws-ecs-service.json b/src/cfnlint/data/schemas/providers/us_west_2/aws-ecs-service.json
index 39c164ea67..7065156406 100644
--- a/src/cfnlint/data/schemas/providers/us_west_2/aws-ecs-service.json
+++ b/src/cfnlint/data/schemas/providers/us_west_2/aws-ecs-service.json
@@ -174,16 +174,6 @@
    "additionalProperties": false,
    "properties": {
     "LogDriver": {
-     "enum": [
-      "awsfirelens",
-      "awslogs",
-      "fluentd",
-      "gelf",
-      "journald",
-      "json-file",
-      "splunk",
-      "syslog"
-     ],
      "type": "string"
     },
     "Options": {


Test patch:
diff --git a/test/unit/rules/resources/ecs/test_ecs_task_fargate_properties.py b/test/unit/rules/resources/ecs/test_ecs_task_fargate_properties.py
index b2935bd6b2..8d557e623c 100644
--- a/test/unit/rules/resources/ecs/test_ecs_task_fargate_properties.py
+++ b/test/unit/rules/resources/ecs/test_ecs_task_fargate_properties.py
@@ -22,6 +22,7 @@ def rule():
     [
         (
             {
+                "NetworkMode": "awsvpc",
                 "RequiresCompatibilities": ["FARGATE"],
                 "Cpu": 256,
                 "Memory": "512",
@@ -30,6 +31,7 @@ def rule():
         ),
         (
             {
+                "NetworkMode": "awsvpc",
                 "RequiresCompatibilities": ["FARGATE"],
                 "Cpu": ".25     vCpU",
                 "Memory": "512",
@@ -38,6 +40,7 @@ def rule():
         ),
         (
             {
+                "NetworkMode": "awsvpc",
                 "RequiresCompatibilities": ["FARGATE"],
                 "Cpu": 16384,
             },
@@ -47,12 +50,13 @@ def rule():
                     rule=TaskFargateProperties(),
                     path=deque([]),
                     validator="required",
-                    schema_path=deque(["then", "required"]),
+                    schema_path=deque(["then", "allOf", 2, "required"]),
                 )
             ],
         ),
         (
             {
+                "NetworkMode": "awsvpc",
                 "RequiresCompatibilities": ["FARGATE"],
                 "Memory": "512",
             },
@@ -62,12 +66,13 @@ def rule():
                     rule=TaskFargateProperties(),
                     path=deque([]),
                     validator="required",
-                    schema_path=deque(["then", "required"]),
+                    schema_path=deque(["then", "allOf", 2, "required"]),
                 )
             ],
         ),
         (
             {
+                "NetworkMode": "awsvpc",
                 "RequiresCompatibilities": ["FARGATE"],
                 "Memory": "512",
                 "Cpu": 256,
@@ -79,12 +84,13 @@ def rule():
                     rule=TaskFargateProperties(),
                     path=deque(["PlacementConstraints"]),
                     validator="not",
-                    schema_path=deque(["then", "not"]),
+                    schema_path=deque(["then", "allOf", 2, "not"]),
                 )
             ],
         ),
         (
             {
+                "NetworkMode": "awsvpc",
                 "RequiresCompatibilities": ["FARGATE"],
                 "Cpu": {"Ref": "MyParameter"},
                 "Memory": "512",
@@ -93,6 +99,7 @@ def rule():
         ),
         (
             {
+                "NetworkMode": "awsvpc",
                 "RequiresCompatibilities": ["FARGATE"],
                 "Cpu": 128,
                 "Memory": "512",
@@ -107,7 +114,128 @@ def rule():
                     path=deque(["Cpu"]),
                     validator="enum",
                     schema_path=deque(
-                        ["then", "then", "properties", "Cpu", "then", "enum"]
+                        [
+                            "then",
+                            "allOf",
+                            2,
+                            "then",
+                            "properties",
+                            "Cpu",
+                            "then",
+                            "enum",
+                        ]
+                    ),
+                )
+            ],
+        ),
+        (
+            {
+                "RequiresCompatibilities": ["FARGATE"],
+                "Cpu": 256,
+                "Memory": "512",
+                "NetworkMode": {"Ref": "MyParameter"},
+            },
+            [],
+        ),
+        (
+            {
+                "RequiresCompatibilities": ["FARGATE"],
+                "Cpu": 256,
+                "Memory": "512",
+            },
+            [
+                ValidationError(
+                    ("'NetworkMode' is a required property"),
+                    rule=TaskFargateProperties(),
+                    path=deque([]),
+                    validator="required",
+                    schema_path=deque(["then", "allOf", 0, "required"]),
+                )
+            ],
+        ),
+        (
+            {
+                "RequiresCompatibilities": ["FARGATE"],
+                "Cpu": 256,
+                "Memory": "512",
+                "NetworkMode": "awsvpc",
+                "ContainerDefinitions": [
+                    {
+                        "LogConfiguration": {
+                            "LogDriver": "awslogs",
+                            "Options": {
+                                "awslogs-group": "log-group",
+                                "awslogs-region": "us-east-1",
+                                "awslogs-stream-prefix": "ecs",
+                            },
+                        }
+                    }
+                ],
+            },
+            [],
+        ),
+        (
+            {
+                "RequiresCompatibilities": ["FARGATE"],
+                "Cpu": 256,
+                "Memory": "512",
+                "NetworkMode": "awsvpc",
+                "ContainerDefinitions": [
+                    {
+                        "LogConfiguration": {
+                            "LogDriver": {"Ref": "MyParameter"},
+                            "Options": {
+                                "awslogs-group": "log-group",
+                                "awslogs-region": "us-east-1",
+                                "awslogs-stream-prefix": "ecs",
+                            },
+                        }
+                    }
+                ],
+            },
+            [],
+        ),
+        (
+            {
+                "RequiresCompatibilities": ["FARGATE"],
+                "Cpu": 256,
+                "Memory": "512",
+                "NetworkMode": "awsvpc",
+                "ContainerDefinitions": [
+                    {
+                        "LogConfiguration": {
+                            "LogDriver": "sumologic",
+                            "Options": {
+                                "sumo-url": "aurl",
+                                "sumo-source-category": "access",
+                            },
+                        }
+                    }
+                ],
+            },
+            [
+                ValidationError(
+                    ("'sumologic' is not one of ['awslogs', 'splunk', 'awsfirelens']"),
+                    rule=TaskFargateProperties(),
+                    path=deque(
+                        ["ContainerDefinitions", 0, "LogConfiguration", "LogDriver"]
+                    ),
+                    validator="enum",
+                    schema_path=deque(
+                        [
+                            "then",
+                            "allOf",
+                            1,
+                            "properties",
+                            "ContainerDefinitions",
+                            "items",
+                            "properties",
+                            "LogConfiguration",
+                            "then",
+                            "properties",
+                            "LogDriver",
+                            "enum",
+                        ]
                     ),
                 )
             ],