Skip to content

Terraform module to suppress specific events from security hub based on a dynamodb based configuration.

License

Notifications You must be signed in to change notification settings

schubergphilis/terraform-aws-mcaf-securityhub-findings-manager

Repository files navigation

Security Hub Findings Manager

Automated scanning and finding consolidation is a cornerstone in evaluating your security posture. AWS Security Hub is the native solution to perform this job in AWS. As with any scanning and reporting tool, the amount of findings it generates can be overwhelming at first. Also, you may find that some findings are not relevant or have less urgency to fix in your specific situation.

The Security Hub Findings Manager is a framework designed to automatically manage findings recorded by the AWS Security Hub service including it's AWS service integrations based on a pre-defined and configurable rules list. At its core, the Security Hub Findings Manager aims to reduce noise and help you prioritize real security issues.

Currently, it supports:

  • Suppressing findings, ensuring you can manage irrelevant or less urgent findings effectively.
  • Automated ticket creation in Jira and ServiceNow for non-suppressed findings with a severity higher than a definable threshold.

Tip

We recommend deploying this module in the Audit/Security Account of an AWS reference multi-account setup. This account receives events from all child accounts in an organization. This way, a comprehensive overview of the organization's security posture can be easily maintained.

Important

This module relies extensively on the awsfindingsmanagerlib.
For detailed information about the suppression logic, refer to the library's documentation.

Components

This is a high-level overview of the constituent components. For a more complete overview see Resources and Modules.

  • A rules backend (currently only S3 is supported).
  • 2 Lambda Functions:
    • Security Hub Findings Manager Events: triggered by EventBridge events for new Security Hub findings.
    • Security Hub Findings Manager Triggers: triggered by changes in the S3 backend rules list.
  • Infrastructure to facilitate the Lambda functions (IAM role, EventBridge integration, S3 Trigger Notifications).
  • (optional) Jira integration components.
  • (optional) ServiceNow integration components.

Deployment Modes

There are 3 different deployment modes for this module:

Important

In case of first time deploy, be mindful that there can be a delay between creating S3 triggers and those being fully functional. Re-create the rules object later to have rules run on your findings history in that case.

(Default) Without Jira & ServiceNow Integration

The module deploys 2 Lambda functions:

  • securityhub-findings-manager-events, this function is the target for the EventBridge rule Security Hub Findings - Imported events.
  • securityhub-findings-manager-trigger, this function is the target to the S3 PutObject trigger.

With Jira Integration

  • This deployment method can be used by setting the value of the variable jira_integration to true (default = false).
  • The module deploys an additional Jira lambda function 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 to NOTIFIED.
  • You can enable auto-closing functionality by setting the value of the variable jira_integration.autoclose_enabled to true (default = false). If you do so, the step function will also forward findings updated to status RESOLVED to the lambda function. The function will then use the ticket number saved in the finding note and transition the issue using the transition defined in jira_integration.autoclose_transition_name with comment defined in jira_integration.autoclose_comment

Only events from Security Hub with a normalized severity level higher than a definable threshold (by default 70) trigger the Jira integration.

Normalized severity levels:

  • 0 - INFORMATIONAL
  • 1–39 - LOW
  • 40–69 - MEDIUM
  • 70–89 - HIGH
  • 90–100 - CRITICAL

Step Function Graph

With ServiceNow Integration

Reference design

  • This deployment method can be used by setting the value of the variable servicenow_integration to true (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 Security Hub fires, an event will be created by EventBridge and dropped onto an SQS Queue.
  • With the variable severity_label_filter it can be configured which findings will be forwarded based on the severity label.
  • ServiceNow will pull the events from the SQS queue with the SCSyncUser using acccess_key & secret_access_key.

Warning

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)

How to format the rules.yaml file?

An example file is stored in this module under examples/rules.yaml. For more detailed information check out the Rule Syntax section in the awsfindingsmanagerlib documentation.

Local development on the Python code

Since a lambda layer is used to provide the aws-lambda-powertools if you want to have the same dependencies available locally then install them using requirements-dev.txt stored with the source code.

Requirements

Name Version
terraform >= 1.3.0
archive >= 2.0
aws >= 4.9
external >= 2.0
local >= 1.0
null >= 2.0

Providers

Name Version
aws >= 4.9

Modules

Name Source Version
findings_manager_bucket schubergphilis/mcaf-s3/aws ~> 0.14.1
findings_manager_events_lambda schubergphilis/mcaf-lambda/aws ~> 1.4.1
findings_manager_trigger_lambda schubergphilis/mcaf-lambda/aws ~> 1.4.1
jira_eventbridge_iam_role schubergphilis/mcaf-role/aws ~> 0.3.2
jira_lambda schubergphilis/mcaf-lambda/aws ~> 1.4.1
jira_step_function_iam_role schubergphilis/mcaf-role/aws ~> 0.3.2
servicenow_integration ./modules/servicenow/ n/a

Resources

Name Type
aws_cloudwatch_event_rule.securityhub_findings_events resource
aws_cloudwatch_event_target.findings_manager_events_lambda resource
aws_cloudwatch_event_target.jira_orchestrator resource
aws_cloudwatch_log_group.log_group_jira_orchestrator_sfn resource
aws_lambda_permission.eventbridge_invoke_findings_manager_events_lambda resource
aws_lambda_permission.s3_invoke_findings_manager_trigger_lambda resource
aws_s3_bucket_notification.findings_manager_trigger resource
aws_s3_object.findings_manager_lambdas_deployment_package resource
aws_s3_object.jira_lambda_deployment_package resource
aws_s3_object.rules resource
aws_sfn_state_machine.jira_orchestrator resource
aws_caller_identity.current data source
aws_iam_policy_document.findings_manager_lambda_iam_role data source
aws_iam_policy_document.jira_eventbridge_iam_role data source
aws_iam_policy_document.jira_lambda_iam_role data source
aws_iam_policy_document.jira_step_function_iam_role data source
aws_region.current data source

Inputs

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
findings_manager_events_lambda Findings Manager Lambda settings - Manage Security Hub findings in response to EventBridge events
object({
name = optional(string, "securityhub-findings-manager-events")
log_level = optional(string, "INFO")
memory_size = optional(number, 256)
timeout = optional(number, 300)

security_group_egress_rules = optional(list(object({
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = string
from_port = optional(number, 0)
ip_protocol = optional(string, "-1")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
to_port = optional(number, 0)
})), [])
})
{} no
findings_manager_trigger_lambda Findings Manager Lambda settings - Manage Security Hub findings in response to S3 file upload triggers
object({
name = optional(string, "securityhub-findings-manager-trigger")
log_level = optional(string, "INFO")
memory_size = optional(number, 1024)
timeout = optional(number, 900)

security_group_egress_rules = optional(list(object({
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = string
from_port = optional(number, 0)
ip_protocol = optional(string, "-1")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
to_port = optional(number, 0)
})), [])
})
{} no
jira_eventbridge_iam_role_name The name of the role which will be assumed by EventBridge rules for Jira integration string "SecurityHubFindingsManagerJiraEventBridge" no
jira_integration Findings Manager - Jira integration settings
object({
enabled = optional(bool, false)
autoclose_enabled = optional(bool, false)
autoclose_comment = optional(string, "Security Hub finding has been resolved. Autoclosing the issue.")
autoclose_transition_name = optional(string, "Close Issue")
credentials_secret_arn = string
exclude_account_ids = optional(list(string), [])
finding_severity_normalized_threshold = optional(number, 70)
issue_custom_fields = optional(map(string), {})
issue_type = optional(string, "Security Advisory")
project_key = string

security_group_egress_rules = optional(list(object({
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = string
from_port = optional(number, 0)
ip_protocol = optional(string, "-1")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
to_port = optional(number, 0)
})), [])

lambda_settings = optional(object({
name = optional(string, "securityhub-findings-manager-jira")
log_level = optional(string, "INFO")
memory_size = optional(number, 256)
timeout = optional(number, 60)
}), {
name = "securityhub-findings-manager-jira"
iam_role_name = "SecurityHubFindingsManagerJiraLambda"
log_level = "INFO"
memory_size = 256
timeout = 60
security_group_egress_rules = []
})

step_function_settings = optional(object({
log_level = optional(string, "ERROR")
retention = optional(number, 90)
}), {
log_level = "ERROR"
retention = 90
})

})
{
"credentials_secret_arn": null,
"enabled": false,
"project_key": null
}
no
jira_step_function_iam_role_name The name of the role which will be assumed by AWS Step Function for Jira integration string "SecurityHubFindingsManagerJiraStepFunction" no
lambda_runtime The version of Python to use for the Lambda functions string "python3.12" no
rules_filepath Pathname to the file that stores the manager rules string "" no
rules_s3_object_name The S3 object containing the rules to be applied to Security Hub findings manager string "rules.yaml" no
servicenow_integration ServiceNow integration settings
object({
enabled = optional(bool, false)
create_access_keys = optional(bool, false)
cloudwatch_retention_days = optional(number, 365)
severity_label_filter = optional(list(string), [])
})
{
"enabled": false
}
no
subnet_ids The subnet ids where the Lambda functions needs to run list(string) null no
tags A mapping of tags to assign to the resources map(string) {} no

Outputs

Name Description
findings_manager_events_lambda_sg_id This will output the security group id attached to the lambda_findings_manager_events Lambda. This can be used to tune ingress and egress rules.
findings_manager_trigger_lambda_sg_id This will output the security group id attached to the lambda_findings_manager_trigger Lambda. This can be used to tune ingress and egress rules.
jira_lambda_sg_id This will output the security group id attached to the jira_lambda Lambda. This can be used to tune ingress and egress rules.

About

Terraform module to suppress specific events from security hub based on a dynamodb based configuration.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published