Previously called: Security Hub Findings Suppressor | Based on: https://github.com/schubergphilis/aws-security-hub-suppressor
The Security Hub Findings Manager is a framework designed to automatically suppress findings recorded by the AWS Security Hub service based on a pre-defined and configurable suppression list. This suppression is needed in case some controls or rules are not completely applicable to the resources of a given account. For example, you might want to suppress all DynamoDB Autoscaling configuration findings related to the control DynamoDB.1
, simply because this feature is not applicable for your workload. Besides the suppression of findings this module is also able to create Jira tickets for all NEW
findings with a severity higher than a definable threshold.
This logic is intended to be executed in the Audit Account which is part of the AWS Control Tower default account posture and therefore receives events from all child accounts in an organization.
- The lambda's are built and zipped during runtime, this means that the terraform runners/agents needs to have python 3.8 installed.
- Remark about Terraform Cloud: The
remote
runners from Terraform Cloud have python installed. If you run your own agents make sure that you use a custom TFC agent image with python installed.
- DynamoDB Table, referenced as
suppression list
- 3 Lambda Functions:
- Security Hub Events: triggered by EventBridge on events from SecurityHub.
- Security Hub Streams: triggered by changes in the DynamoDB suppression table using a DynamoDB Stream.
- (optional) Security Hub Jira: triggered by EventBridge on events from SecurityHub with a normalized severity higher than a definable threshold (by default
70
)- Normalized severity levels:
- 0 - INFORMATIONAL
- 1–39 - LOW
- 40–69 - MEDIUM
- 70–89 - HIGH
- 90–100 - CRITICAL
- Normalized severity levels:
- (optional) Step Function, to orchestrate the Suppressor and Jira lambdas.
- YML Configuration File (
suppressor.yaml
) that contains the list of products and the field mapping
There are 3 different deployment modes for this module. All the modes deploy a Lambda function which triggers in response to upserts in DynamoDB table and a EventBridge rule with a pattern which detects the import of a new Security Hub finding. In addition to these, additional resources are deployed depending on the chosen deployment mode.
- The module deploys 1 Lambda function:
Suppressor
and configures this Lambda as a target to the EventBridge rule.
- This deployment method can be used by setting the value of the variable
jira_integration
totrue
(default = false). - The module deploys two Lambda functions:
Suppressor
andJira
along with a Step function which orchestrates these Lambda functions and Step Function as a target to the EventBridge rule. - If the finding is not suppressed a ticket is created for findings with a normalized severity higher than a definable threshold. The workflow status in Security Hub is updated from
NEW
toNOTIFIED
.
- This deployment method can be used by setting the value of the variable
servicenow_integration
totrue
(default = false). - The module will deploy all the needed resources to support integration with ServiceNow, including (but not limited to): An SQS Queue, EventBridge Rule and the needed IAM user.
- When an event in SecurityHub fires, an event will be created by EventBridge and dropped onto an SQS Queue.
- ServiceNow will pull the events from the SQS queue with the
SCSyncUser
usingacccess_key
&secret_access_key
.
Note : The user will be created by the module, but the acccess_key
& secret_access_key
need to be generated in the AWS Console, to prevent storing this data in the Terraform state. If you want Terraform to create the acccess_key
& secret_access_key
(and output them), set variable create_servicenow_access_keys
to true
(default = false)
The Security Hub Findings Suppressor listens to AWS EventBridge event bus and triggers an execution when a Security Hub Findings - Imported
event happens.
Once the event is delivered, the function securityhub-events-suppressor
will be triggered and will perform the following steps:
- Parse the event to determine what is the linked product. For example: Firewall Manager, Inspector or Security Hub.
- Check whether this product is properly mapped and configured in the YAML configuration file.
- Extract the AWS resource from the event payload.
- Upon having the resource and its ARN, the logic checks if that resource is listed in the suppression list.
- The suppression list contains a collection of items, one per controlId.
-
All resources required by The Security Hub Findings Manager are deployed by this module. But the module does not update the DynamoDB Table (the
suppression list
). This can be updates using a variety of methods, via GitHub actions is described below: -
In the repository calling this module, create a folder called
sechub-suppressor
, addrequirements.txt
,put_suppressions.py
, andsuppressions.yml
to this folder. Example files are stored in this module underfiles/dynamodb-upserts-artifacts
. An example GitHub action is stored in this folder as well. -
Add a new element to the
suppressions.yml
configuration file containing the product name, key and status. Key and status fields must be JMESPath expressions.- Fields:
controlId
: the key field from the event (it is usually a Control Id or a RuleId present in the event)action
: the status that will be applied in Security Hubdry_run
: a read-only mode to preview what the logic will be handlingnotes
: notes added to the security hub finding. Usually it is a Jira Ticket with the exception approvalrules
: a list of regular expressions to be matched against the resource ARN present in the EventBridge Event
- Fields:
-
Commit your changes, push and merge. The pipeline will automatically maintain the set of suppressions and store them in DynamoDB. If all above steps succeed, the finding is suppressed.
Suppress a finding where the resource is the account, i.e. the 'MFA should be enabled for all IAM users that have a console password' finding:
Suppressions:
"1.13":
- action: SUPPRESSED
rules:
- ^AWS::::Account:[0-9]{12}$
notes: A note about this suppression
Suppress a finding for all resources in a specific account:
Suppressions:
"EC2.17":
- action: SUPPRESSED
rules:
- ^arn:aws:[^:]*:[^:]*:111111111111:.*$
notes: A note about this suppression
Suppress a finding in some accounts (with comments):
Suppressions:
EC2.17:
- action: SUPPRESSED
rules:
- ^arn:aws:ec2:eu-west-1:111111111111:instance/i-[0-9a-z]+$ # can add comments here like
- ^arn:aws:ec2:eu-west-1:222222222222:instance/i-[0-9a-z]+$ # the friendly IAM alias to more
- ^arn:aws:ec2:eu-west-1:333333333333:instance/i-[0-9a-z]+$ # easily identify matches resources
notes: A note about this suppression
Suppress finding for specific resources:
EC2.18:
- action: SUPPRESSED
rules:
- ^arn:aws:ec2:eu-west-1:111111111111:security-group/sg-0ae8d23e1d28b1437$
- ^arn:aws:ec2:eu-west-1:222222222222:security-group/sg-01f1aa5f8407c98b9$
notes: A note about this suppression
Note There is also a leading
^
and trailing$
as the rule is always matched as a regexp. This means that if you do not start with a^
and end with a$
it will be matched as a substring and you might match more than anticipated.
Name | Version |
---|---|
terraform | >= 1.3.0 |
aws | >= 4.9 |
local | >= 1.0 |
null | >= 2.0 |
Name | Version |
---|---|
aws | >= 4.9 |
Name | Source | Version |
---|---|---|
eventbridge_security_hub_suppressor_role | github.com/schubergphilis/terraform-aws-mcaf-role | v0.3.2 |
lambda_artifacts_bucket | github.com/schubergphilis/terraform-aws-mcaf-s3 | v0.6.0 |
lambda_jira_deployment_package | terraform-aws-modules/lambda/aws | ~> 3.3.0 |
lambda_jira_security_hub | github.com/schubergphilis/terraform-aws-mcaf-lambda | v0.3.3 |
lambda_jira_security_hub_role | github.com/schubergphilis/terraform-aws-mcaf-role | v0.3.2 |
lambda_security_hub_suppressor_role | github.com/schubergphilis/terraform-aws-mcaf-role | v0.3.2 |
lambda_securityhub_events_suppressor | github.com/schubergphilis/terraform-aws-mcaf-lambda | v0.3.3 |
lambda_securityhub_streams_suppressor | github.com/schubergphilis/terraform-aws-mcaf-lambda | v0.3.3 |
lambda_suppressor_deployment_package | terraform-aws-modules/lambda/aws | ~> 3.3.0 |
servicenow_integration | ./modules/servicenow/ | n/a |
step_function_security_hub_suppressor_role | github.com/schubergphilis/terraform-aws-mcaf-role | v0.3.2 |
Name | Description | Type | Default | Required |
---|---|---|---|---|
kms_key_arn | The ARN of the KMS key used to encrypt the resources | string |
n/a | yes |
s3_bucket_name | The name for the S3 bucket which will be created for storing the function's deployment package | string |
n/a | yes |
create_allow_all_egress_rule | Whether to create a default any/any egress sg rule for lambda | bool |
false |
no |
dynamodb_table | The DynamoDB table containing the items to be suppressed in Security Hub | string |
"securityhub-suppression-list" |
no |
eventbridge_suppressor_iam_role_name | The name of the role which will be assumed by EventBridge rules | string |
"EventBridgeSecurityHubSuppressorRole" |
no |
jira_integration | Jira integration settings | object({ |
{ |
no |
lambda_events_suppressor | Lambda Events Suppressor settings - Supresses the Security Hub findings in response to EventBridge Trigger | object({ |
{} |
no |
lambda_streams_suppressor | Lambda Streams Suppressor settings - Supresses the Security Hub findings in response to DynamoDB streams | object({ |
{} |
no |
lambda_suppressor_iam_role_name | The name of the role which will be assumed by both Suppressor Lambda functions | string |
"LambdaSecurityHubSuppressorRole" |
no |
servicenow_integration | ServiceNow integration settings | object({ |
{ |
no |
step_function_suppressor_iam_role_name | The name of the role which will be assumed by Suppressor Step function | string |
"StepFunctionSecurityHubSuppressorRole" |
no |
subnet_ids | The subnet ids where the lambda's needs to run | list(string) |
null |
no |
tags | A mapping of tags to assign to the resources | map(string) |
{} |
no |
Name | Description |
---|---|
dynamodb_arn | ARN of the DynamoDB table |
lambda_jira_security_hub_sg_id | This will output the security group id attached to the jira_security_hub Lambda. This can be used to tune ingress and egress rules. |
lambda_securityhub_events_suppressor_sg_id | This will output the security group id attached to the securityhub_events_suppressor Lambda. This can be used to tune ingress and egress rules. |
lambda_securityhub_streams_suppressor_sg_id | This will output the security group id attached to the securityhub_streams_suppressor Lambda. This can be used to tune ingress and egress rules. |