Repository: prowler-cloud/prowler
Pull request: fix(security hub): solve Security Hub format requirements
### Description

Solve Security Hub format requirements:
- Description should NOT be longer than 1024 characters
- AssociatedStandards should NOT have more than 20 items

### License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.


Problem statement:
[Bug]: Additional output formats causing errors reporting to Security Hub, preventing findings from being recorded.
### Steps to Reproduce

```bash
prowler aws --region us-east-2 us-west-2 \
    --allowlist-file allowlist.yaml \
    --output-modes json json-asff \
    --log-level WARNING \
    --security-hub \
    --excluded-checks ec2_elastic_ip_shodan
```

### Expected behavior

Prowler should run and do it's thing, and report all findings to Security Hub.

### Actual Result with Screenshots or Logs

Several errors due to formatting in the finding details:

1. `data.Types` is invalid for a handful of checks. I think this is `[""]` being set where it should be `[]` instead. One example is the finding from cloudfront_distributions_using_deprecated_ssl_protocols. This may be something else, but I think this is it, which should be a quick fix.
```
2023-06-20 14:50:05,265 [File: security_hub.py:50]      [Module: security_hub]   ERROR: Failed to send archived findings to AWS Security Hub -- InvalidInput -- Finding does not adhere to Amazon Finding Format. data.Types[0] should match pattern "^([^/]+)(/[^/]+){0,2}$".
```

2. `data.Description` is too long for some check output from `cloudwatch_log_group_no_secrets_in_logs`.  This should get trimmed to 1024 characters, even through it loses some information.
```
2023-06-20 14:52:51,312 [File: security_hub.py:50]      [Module: security_hub]   ERROR: Failed to send archived findings to AWS Security Hub -- InvalidInput -- Finding does not adhere to Amazon Finding Format. data.Description should NOT be longer than 1024 characters.
```

3. `data.Remediation.Recommendation.Text` is blank, and should be provided. This is the `prowler-rds_instance_deprecated_engine_version` check. This should be a quick fix. 
```
2023-06-20 15:12:55,123 [File: security_hub.py:50]      [Module: security_hub]   ERROR: Failed to send archived findings to AWS Security Hub -- InvalidInput -- Finding does not adhere to Amazon Finding Format. data.Remediation.Recommendation.Text should NOT be shorter than 1 characters.
```

### How did you install Prowler?

From pip package (pip install prowler)

### Environment Resource

Docker container locally

### OS used

Wolfi

### Prowler version

3.6.1

### Pip version

23.1.2

### Context

_No response_

Hints from issue discussion:
Hi @ckdake, thank you for this information!
Can you try it again from the branch `2519-bug-additional-output-formats-causing-errors-reporting-to-security-hub-preventing-findings-from-being-recorded`, please?
Sure thing! I have to run things a bit differently in order to run from git instead of inside the container builds we run in production. I'm now running "locally" in a Debian/bullseye container with a `git clone` (instead of in a Wolfi container with prowler from pip). Running from this branch (which still appears at 3.6.1 in the initial output of `python prowler.py [...]`), I am no longer seeing the 3 errors described above. 🎉 

I am now seeing a new error appear 2 times, probably because we cleared a few earlier on in the chain:

```
023-06-20 16:31:13,729 [File: security_hub.py:50]      [Module: security_hub]   ERROR: Failed to send archived findings to AWS Security Hub -- InvalidInput -- Finding does not adhere to Amazon Finding Format. data.Compliance.AssociatedStandards should NOT have more than 20 items.
```

This is coming from `cloudtrail_multi_region_enabled` running once for each configured region we are scanning.

Commit message: solve Security Hub issues

Patch to review:
diff --git a/prowler/lib/outputs/json.py b/prowler/lib/outputs/json.py
index 331837389c..4a0095e8dc 100644
--- a/prowler/lib/outputs/json.py
+++ b/prowler/lib/outputs/json.py
@@ -55,7 +55,12 @@ def fill_json_asff(finding_output, audit_info, finding, output_options):
             Label=finding.check_metadata.Severity.upper()
         )
         finding_output.Title = finding.check_metadata.CheckTitle
-        finding_output.Description = finding.status_extended
+        # Description should NOT be longer than 1024 characters
+        finding_output.Description = (
+            (finding.status_extended[:1000] + "..")
+            if len(finding.status_extended) > 100
+            else finding.status_extended
+        )
         finding_output.Resources = [
             Resource(
                 Id=finding.resource_arn,
@@ -69,11 +74,14 @@ def fill_json_asff(finding_output, audit_info, finding, output_options):
         associated_standards = []
         check_compliance = get_check_compliance(finding, "aws", output_options)
         for key, value in check_compliance.items():
-            associated_standards.append({"StandardsId": key})
-            item = f"{key} {' '.join(value)}"
-            if len(item) > 64:
-                item = item[0:63]
-            compliance_summary.append(item)
+            if (
+                len(associated_standards) < 20
+            ):  # AssociatedStandards should NOT have more than 20 items
+                associated_standards.append({"StandardsId": key})
+                item = f"{key} {' '.join(value)}"
+                if len(item) > 64:
+                    item = item[0:63]
+                compliance_summary.append(item)
 
         # Ensures finding_status matches allowed values in ASFF
         finding_status = generate_json_asff_status(finding.status)
diff --git a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_field_level_encryption_enabled/cloudfront_distributions_field_level_encryption_enabled.metadata.json b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_field_level_encryption_enabled/cloudfront_distributions_field_level_encryption_enabled.metadata.json
index ef5e1aa75d..79c7c7ccd6 100644
--- a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_field_level_encryption_enabled/cloudfront_distributions_field_level_encryption_enabled.metadata.json
+++ b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_field_level_encryption_enabled/cloudfront_distributions_field_level_encryption_enabled.metadata.json
@@ -2,9 +2,7 @@
   "Provider": "aws",
   "CheckID": "cloudfront_distributions_field_level_encryption_enabled",
   "CheckTitle": "Check if CloudFront distributions have Field Level Encryption enabled.",
-  "CheckType": [
-    ""
-  ],
+  "CheckType": [],
   "ServiceName": "cloudfront",
   "SubServiceName": "",
   "ResourceIdTemplate": "arn:partition:cloudfront:region:account-id:distribution/resource-id",
diff --git a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_geo_restrictions_enabled/cloudfront_distributions_geo_restrictions_enabled.metadata.json b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_geo_restrictions_enabled/cloudfront_distributions_geo_restrictions_enabled.metadata.json
index 6170a52043..111a7062bb 100644
--- a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_geo_restrictions_enabled/cloudfront_distributions_geo_restrictions_enabled.metadata.json
+++ b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_geo_restrictions_enabled/cloudfront_distributions_geo_restrictions_enabled.metadata.json
@@ -2,9 +2,7 @@
   "Provider": "aws",
   "CheckID": "cloudfront_distributions_geo_restrictions_enabled",
   "CheckTitle": "Check if Geo restrictions are enabled in CloudFront distributions.",
-  "CheckType": [
-    ""
-  ],
+  "CheckType": [],
   "ServiceName": "cloudfront",
   "SubServiceName": "",
   "ResourceIdTemplate": "arn:partition:cloudfront:region:account-id:distribution/resource-id",
diff --git a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_https_enabled/cloudfront_distributions_https_enabled.metadata.json b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_https_enabled/cloudfront_distributions_https_enabled.metadata.json
index 5e4d232787..12d9d89855 100644
--- a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_https_enabled/cloudfront_distributions_https_enabled.metadata.json
+++ b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_https_enabled/cloudfront_distributions_https_enabled.metadata.json
@@ -2,9 +2,7 @@
   "Provider": "aws",
   "CheckID": "cloudfront_distributions_https_enabled",
   "CheckTitle": "Check if CloudFront distributions are set to HTTPS.",
-  "CheckType": [
-    ""
-  ],
+  "CheckType": [],
   "ServiceName": "cloudfront",
   "SubServiceName": "",
   "ResourceIdTemplate": "arn:partition:cloudfront:region:account-id:distribution/resource-id",
diff --git a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_logging_enabled/cloudfront_distributions_logging_enabled.metadata.json b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_logging_enabled/cloudfront_distributions_logging_enabled.metadata.json
index ba58ff9244..e368af1733 100644
--- a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_logging_enabled/cloudfront_distributions_logging_enabled.metadata.json
+++ b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_logging_enabled/cloudfront_distributions_logging_enabled.metadata.json
@@ -2,9 +2,7 @@
   "Provider": "aws",
   "CheckID": "cloudfront_distributions_logging_enabled",
   "CheckTitle": "Check if CloudFront distributions have logging enabled.",
-  "CheckType": [
-    ""
-  ],
+  "CheckType": [],
   "ServiceName": "cloudfront",
   "SubServiceName": "",
   "ResourceIdTemplate": "arn:partition:cloudfront:region:account-id:distribution/resource-id",
diff --git a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_using_deprecated_ssl_protocols/cloudfront_distributions_using_deprecated_ssl_protocols.metadata.json b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_using_deprecated_ssl_protocols/cloudfront_distributions_using_deprecated_ssl_protocols.metadata.json
index 507739ed39..653b892ab2 100644
--- a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_using_deprecated_ssl_protocols/cloudfront_distributions_using_deprecated_ssl_protocols.metadata.json
+++ b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_using_deprecated_ssl_protocols/cloudfront_distributions_using_deprecated_ssl_protocols.metadata.json
@@ -2,9 +2,7 @@
   "Provider": "aws",
   "CheckID": "cloudfront_distributions_using_deprecated_ssl_protocols",
   "CheckTitle": "Check if CloudFront distributions are using deprecated SSL protocols.",
-  "CheckType": [
-    ""
-  ],
+  "CheckType": [],
   "ServiceName": "cloudfront",
   "SubServiceName": "",
   "ResourceIdTemplate": "arn:partition:cloudfront:region:account-id:distribution/resource-id",
diff --git a/prowler/providers/aws/services/rds/rds_instance_deprecated_engine_version/rds_instance_deprecated_engine_version.metadata.json b/prowler/providers/aws/services/rds/rds_instance_deprecated_engine_version/rds_instance_deprecated_engine_version.metadata.json
index affb983673..73b43cebbb 100644
--- a/prowler/providers/aws/services/rds/rds_instance_deprecated_engine_version/rds_instance_deprecated_engine_version.metadata.json
+++ b/prowler/providers/aws/services/rds/rds_instance_deprecated_engine_version/rds_instance_deprecated_engine_version.metadata.json
@@ -19,7 +19,7 @@
       "Terraform": ""
     },
     "Recommendation": {
-      "Text": "",
+      "Text": "Ensure all the RDS instances are using a supported engine version",
       "Url": "https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-engine-versions.html"
     }
   },


Code review comments:
diff_hunk: @@ -55,7 +55,12 @@ def fill_json_asff(finding_output, audit_info, finding, output_options):
             Label=finding.check_metadata.Severity.upper()
         )
         finding_output.Title = finding.check_metadata.CheckTitle
-        finding_output.Description = finding.status_extended
+        # Description should NOT be longer than 1024 characters
+        finding_output.Description = (
+            (finding.status_extended[:1000] + "..")
+            if len(finding.status_extended) > 100
path: prowler/lib/outputs/json.py
text: @author:
```suggestion
            if len(finding.status_extended) > 1000
```