You're reading for free via Ekant Mate (AWS APN Ambassador)'s Friend Link. Become a member to access the best of Medium.
Member-only story
How to Suppress Particular Findings in AWS Security Hub Using Terraform?
Learn how to effectively suppress specific findings in AWS Security Hub using Terraform with a practical workaround. This guide provides a step-by-step approach to managing Security Hub alerts seamlessly.

Introduction
AWS Security Hub provides a comprehensive view of your security state within AWS and helps you check your environment against security industry standards and best practices. However, sometimes you might encounter findings that are known issues or not relevant to your security posture, which you wish to suppress to reduce noise. Since Terraform doesn’t offer native support for this specific task, we’ll explore a workaround to achieve this using Terraform and AWS CLI tools.
Understanding the Need for Suppressing Findings
Suppressing findings in AWS Security Hub can help in managing the alert fatigue that security teams might face. By suppressing findings that are identified as non-issues or known issues, teams can focus on alerts that pose real threats.
Terraform and Security Hub: A Workaround Approach
Since Terraform does not directly support suppression of Security Hub findings, we utilize a combination of Terraform’s null_resource
and AWS CLI commands to update the findings.
Step-by-Step Guide to Suppress Security Hub Findings Using Terraform
Below, we provide a detailed guide on how to set up Terraform to suppress specific findings in Security Hub.
1. Prerequisites
- AWS CLI installed and configured
- Terraform installed
- Permissions to access AWS Security Hub and update findings
- jq installed for handling JSON data, if necessary.
2. Create a JSON File with Findings to Suppress
First, create a findings.json
file that lists the findings you wish to suppress. This file will contain the identifiers of each finding, ensuring that you can target them specifically. Here’s an example of what this file should look like:
[
{
"Id": "arn:aws:securityhub:ap-southeast-2:1234567890:subscription/aws-foundational-security-best-practices/v/1.0.0/IAM.6/finding/6fc8d9fa-bf70-4fa2-b39f-5f0e88c079e4",
"ProductArn": "arn:aws:securityhub:ap-southeast-2::product/aws/securityhub"
},
{
"Id": "arn:aws:securityhub:ap-southeast-2:1234567890:subscription/cis-aws-foundations-benchmark/v/1.2.0/1.14/finding/282bd054-ea17-422b-a2be-47f98ce211c0",
"ProductArn": "arn:aws:securityhub:ap-southeast-2::product/aws/securityhub"
}
]
3. Terraform Configuration to Suppress Findings
The Terraform configuration uses a null_resource
with a local-exec provisioner that executes an AWS CLI command to update the findings as suppressed. Here is the necessary Terraform code:
resource "null_resource" "update_security_hub_findings" {
triggers = {
findings_hash = filemd5("findings.json")
}
provisioner "local-exec" {
command = <<EOT
bash -c "aws securityhub batch-update-findings --finding-identifiers '$(cat findings.json)' --note '{\"Text\": \"Known issue that is not a risk.\", \"UpdatedBy\": \"user1\"}' --severity '{\"Label\": \"LOW\"}' --workflow '{\"Status\": \"SUPPRESSED\"}'"
EOT
}
}
4. Applying the Terraform Plan and Apply
Execute the Terraform plan to apply the changes. The plan will trigger the local-exec command, which calls the AWS CLI to update the findings status to “SUPPRESSED”.
terraform plan
terraform apply


More advanced way is to use terraform_data.
Below is a comprehensive Terraform template that runs every time to maintain our automation. This approach reverts any manual changes and ensures our SecurityHub findings remain in sync.
Also, The script is optimized to handle large numbers of findings (e.g., 1000 or 2000) by processing them in batches. This avoids command-line length limits and performance bottlenecks.
It ensures that any findings removed from the configuration file (findings.json
) are reverted to their original status, maintaining an accurate and up-to-date state.
Batch Processing: It uses the BatchUpdateFindings
API, which has a throttling limit of 10 requests per second, to update up to 100 findings at a time efficiently.
resource "terraform_data" "update_findings" {
triggers_replace = [timestamp()]
#Handling a large number of findings (e.g., 1000 or 2000) can potentially lead to issues such as command-line length limits or performance bottlenecks.
#To address this, the below script is optimized to handle findings in batches. This way, we can ensure that the AWS CLI commands don’t exceed any limits and can process the findings more efficiently.
# The API 'BatchUpdateFindings' has a throttling limit of 10 reqs/second. "https://docs.aws.amazon.com/securityhub/1.0/APIReference/Welcome.html" We can use the API BatchUpdateFindings to update upto 100 findings at a time.
provisioner "local-exec" {
command = <<EOT
set -e # Exit immediately if a command exits with a non-zero status
# Fetch current suppressed findings
echo "Fetching current suppressed findings..."
current_findings=$(aws securityhub get-findings --filters "{\"WorkflowStatus\":[{\"Value\":\"SUPPRESSED\",\"Comparison\":\"EQUALS\"}], \"RecordState\":[{\"Value\":\"ACTIVE\",\"Comparison\":\"EQUALS\"}], \"Title\":[{\"Value\":\"1.6 Ensure hardware MFA is enabled for the 'root' user account\",\"Comparison\":\"EQUALS\"}, {\"Value\":\"IAM.6 Hardware MFA should be enabled for the root user\",\"Comparison\":\"EQUALS\"}]}" --query 'Findings[*].[Id,ProductArn]' --output text)
# Check if the above command was successful
if [ $? -ne 0 ]; then
echo "Error fetching current suppressed findings"
exit 1
fi
# Read the findings from findings.json
echo "Reading findings from findings.json..."
new_findings=$(jq -r '.[].Id' findings.json)
# Check if the above command was successful
if [ $? -ne 0 ]; then
echo "Error reading findings from findings.json"
exit 1
fi
# Create JSON for findings to be updated
echo "Creating JSON for findings to be updated..."
findings_to_update=$(jq -c '.[] | {Id: .Id, ProductArn: .ProductArn}' findings.json | jq -s .)
# Check if the above command was successful
if [ $? -ne 0 ]; then
echo "Error creating JSON for findings to be updated"
exit 1
fi
# Update findings in findings.json to suppressed in batches of 80
echo "Updating findings to suppressed in batches of 80..."
batch_size=80
findings_length=$(echo $findings_to_update | jq length)
for ((i=0; i<findings_length; i+=batch_size)); do
batch=$(echo $findings_to_update | jq -c ".[$i:$((i+batch_size))]")
echo "Processing batch $((i/batch_size + 1)): $i to $((i+batch_size-1))"
aws securityhub batch-update-findings --finding-identifiers "$batch" --note '{"Text": "Known issue that is not a risk.", "UpdatedBy": "Admin"}' --severity '{"Label": "LOW"}' --workflow '{"Status": "SUPPRESSED"}'
# Check if the above command was successful
if [ $? -ne 0 ]; then
echo "Error updating findings for batch $((i/batch_size + 1))"
exit 1
fi
done
echo "All batches processed."
# Revert status of removed findings to NEW
echo "Reverting status of removed findings to NEW..."
while IFS=$'\t' read -r id productArn; do
if ! echo "$new_findings" | grep -q "$id"; then
echo "Reverting finding with Id: $id and ProductArn: $productArn to NEW"
aws securityhub batch-update-findings --finding-identifiers "[{\"Id\": \"$id\", \"ProductArn\": \"$productArn\"}]" --workflow '{"Status": "NEW"}'
# Check if the above command was successful
if [ $? -ne 0 ]; then
echo "Error reverting finding with Id: $id and ProductArn: $productArn to NEW"
exit 1
fi
fi
done <<< "$current_findings"
echo "Reverting of removed findings complete."
EOT
}
}
Conclusion
Using Terraform to manage AWS Security Hub findings by suppressing them provides a streamlined approach to handle security alerts more efficiently. This workaround not only automates the suppression process but also integrates smoothly with your existing Terraform workflows for AWS management.
Please follow me for more such innovative blogs And if you find my blogs helpful, I’d really appreciate your claps — they motivate me to keep sharing more valuable insights.
Thank you for being awesome!
In Plain English 🚀
Thank you for being a part of the In Plain English community! Before you go:
- Be sure to clap and follow the writer ️👏️️
- Follow us: X | LinkedIn | YouTube | Discord | Newsletter
- Visit our other platforms: Stackademic | CoFeed | Venture | Cubed
- Tired of blogging platforms that force you to deal with algorithmic content? Try Differ
- More content at PlainEnglish.io