Repository: cloud-custodian/cloud-custodian

Issue:
modes/lambda - validate function name length
follow up on #3344 

aws lambda function names have a maximum length of 64 characters. currently if a policy name + prefix is greater than 64, an error occurs on policy execution, not on validation. In this case, it doesn't seem to me that this would be a breaking change considering the policies that are in violation of the max name length would not be able to be deployed and instead return an error:

```
InvalidParameterValueException: An error occurred (InvalidParameterValueException) when calling the CreateFunction operation: 1 validation error detected: Value 'custodian-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at 'functionName' failed to satisfy constraint: Member must have length less than or equal to 64
```

policy validation should assert that the final length of the policy name + prefix is less than 64 characters.


Discussion:

Resolving patch:
diff --git a/c7n/policy.py b/c7n/policy.py
--- a/c7n/policy.py
+++ b/c7n/policy.py
@@ -361,6 +361,14 @@ class LambdaMode(ServerlessExecutionMode):
         }
     }
 
+    def validate(self):
+        super(LambdaMode, self).validate()
+        prefix = self.policy.data.get('function-prefix', 'custodian-')
+        if len(prefix + self.policy.name) > 64:
+            raise PolicyValidationError(
+                "Custodian Lambda policies have a max length with prefix of 64"
+                " policy:%s prefix:%s" % (prefix, self.policy.name))
+
     def get_metrics(self, start, end, period):
         from c7n.mu import LambdaManager, PolicyLambda
         manager = LambdaManager(self.policy.session_factory)
@@ -529,6 +537,7 @@ class CloudTrailMode(LambdaMode):
         rinherit=LambdaMode.schema)
 
     def validate(self):
+        super(CloudTrailMode, self).validate()
         from c7n import query
         events = self.policy.data['mode'].get('events')
         assert events, "cloud trail mode requires specifiying events to subscribe"
@@ -598,6 +607,7 @@ def resolve_resources(self, event):
         return resources
 
     def validate(self):
+        super(GuardDutyMode, self).validate()
         if self.policy.data['resource'] not in self.supported_resources:
             raise ValueError(
                 "Policy:%s resource:%s Guard duty mode only supported for %s" % (


Test patch:
diff --git a/tests/test_policy.py b/tests/test_policy.py
--- a/tests/test_policy.py
+++ b/tests/test_policy.py
@@ -21,7 +21,7 @@
 import tempfile
 
 from c7n import policy, manager
-from c7n.exceptions import ResourceLimitExceeded
+from c7n.exceptions import ResourceLimitExceeded, PolicyValidationError
 from c7n.resources.aws import AWS
 from c7n.resources.ec2 import EC2
 from c7n.utils import dumps
@@ -873,6 +873,16 @@ def test_unsupported_resource(self):
             validate=True,
         )
 
+    def test_lambda_policy_validate_name(self):
+        name = "ec2-instance-guard-D8488F01-0E3E-4772-A3CB-E66EEBB9BDF4"
+        with self.assertRaises(PolicyValidationError) as e_cm:
+            self.load_policy(
+                {"name": name,
+                 "resource": "ec2",
+                 "mode": {"type": "guard-duty"}},
+                validate=True)
+        self.assertTrue("max length with prefix" in str(e_cm.exception))
+
     @mock.patch("c7n.mu.LambdaManager.publish")
     def test_ec2_guard_event_pattern(self, publish):