Repository: cloud-custodian/cloud-custodian

Issue:
azure - event subscription - can only handle 5 events
Only allowed to specify 5 filters on an Azure Event Grid Subscription. Bug found in the Functions hosting, but this is applicable to Container Hosting where all of the registered event-based policies register with the same event grid subscription.

Message recieved when executing the following policy:
```
2019-08-23 18:45:14,059: custodian.azure.AzureFunctionMode:ERROR Event Subscription creation failed with error: Azure Error: InvalidRequest
Message: The maximum number of values allowed on an advanced filter is 5.
```

Policy for reproducing the error:
```
policies:
  - name: azure-auto-tag-creator-date
    mode:
      type: azure-event-grid
      events:
        - AppServicePlanWrite
        - CognitiveServiceWrite
        - CosmosDbWrite
        - DataFactoryWrite
        - DataLakeWrite
        - DiskWrite
        - KeyVaultWrite
        - ResourceGroupWrite
        - StorageWrite
        - VmWrite
    resource: azure.armresource
    description: |
      Tag all new VMs and StorageAccounts with the tags 'CreatorEmail' and 'CreatedDate'
      Note- 'resource-type' filter is not required because policy is not triggered by other resources.
    actions:
      - type: auto-tag-user
        tag: CreatorEmail
      - type: auto-tag-date
        tag: CreatedDate
        format: "%m-%d-%Y"
```
@stefangordon 


Discussion:
For Azure Functions hosting we can update the JSON schema and documentation to catch this at validation.   For container host we'll need to test removing the advanced filter entirely as we do secondary filtering anyway.
We should be able to expand this limit to 25 event types. (5 filters, up to 5 values each)

https://docs.microsoft.com/en-us/azure/event-grid/event-filtering#limitations
TODO: fix schema so users can only pass 5
TODO: create new work item to support more than five

Resolving patch:
diff --git a/tools/c7n_azure/c7n_azure/policy.py b/tools/c7n_azure/c7n_azure/policy.py
--- a/tools/c7n_azure/c7n_azure/policy.py
+++ b/tools/c7n_azure/c7n_azure/policy.py
@@ -328,15 +328,16 @@ class AzureEventGridMode(AzureFunctionMode):
     azure event."""
 
     schema = utils.type_schema(FUNCTION_EVENT_TRIGGER_MODE,
-                               events={'type': 'array', 'items': {
-                                   'oneOf': [
-                                       {'type': 'string'},
-                                       {'type': 'object',
-                                        'required': ['resourceProvider', 'event'],
-                                        'properties': {
-                                            'resourceProvider': {'type': 'string'},
-                                            'event': {'type': 'string'}}}]
-                               }},
+                               events={'type': 'array',
+                                    'maxItems': 5,
+                                    'items': {
+                                        'oneOf': [
+                                            {'type': 'string'},
+                                            {'type': 'object',
+                                                'required': ['resourceProvider', 'event'],
+                                                'properties': {
+                                                    'resourceProvider': {'type': 'string'},
+                                                    'event': {'type': 'string'}}}]}},
                                required=['events'],
                                rinherit=AzureFunctionMode.schema)
 


Test patch:
diff --git a/tools/c7n_azure/tests/test_policy_mode.py b/tools/c7n_azure/tests/test_policy_mode.py
--- a/tools/c7n_azure/tests/test_policy_mode.py
+++ b/tools/c7n_azure/tests/test_policy_mode.py
@@ -46,9 +46,28 @@ def test_azure_function_event_mode_schema_validation(self):
                              'name': 'testschemaname'
                          }
                      }}
-            })
+            }, validate=True)
             self.assertTrue(p)
 
+    def test_azure_function_event_mode_too_many_events_throws(self):
+        with self.sign_out_patch():
+            with self.assertRaises(ValidationError):
+                self.load_policy({
+                    'name': 'test-azure-serverless-mode',
+                    'resource': 'azure.vm',
+                    'mode': {
+                        'type': FUNCTION_EVENT_TRIGGER_MODE,
+                        'events': [
+                            'VmWrite',
+                            'AppServicePlanWrite',
+                            'CognitiveServiceWrite',
+                            'CosmosDbWrite',
+                            'DataFactoryWrite',
+                            'DataLakeWrite'
+                        ]
+                    }
+                }, validate=True)
+
     def test_azure_function_periodic_mode_schema_validation(self):
         with self.sign_out_patch():
             p = self.load_policy({
@@ -69,7 +88,7 @@ def test_azure_function_periodic_mode_schema_validation(self):
                              'name': 'testschemaname'
                          }
                      }}
-            })
+            }, validate=True)
             self.assertTrue(p)
 
     def test_azure_function_periodic_schema_schedule_valid(self):
@@ -173,7 +192,7 @@ def test_container_event_mode_schema_validation(self):
                 'mode':
                     {'type': CONTAINER_EVENT_TRIGGER_MODE,
                      'events': ['VmWrite']}
-            })
+            }, validate=True)
             self.assertTrue(p)
 
     def test_container_periodic_mode_schema_validation(self):
@@ -184,7 +203,7 @@ def test_container_periodic_mode_schema_validation(self):
                 'mode':
                     {'type': CONTAINER_TIME_TRIGGER_MODE,
                      'schedule': '*/5 * * * *'}
-            })
+            }, validate=True)
             self.assertTrue(p)
 
     def test_init_azure_function_mode_with_service_plan(self):