Skip to content

Commit 109e6fd

Browse files
authored
feat: Adding include_account_filter to support inclusion case for Jira integration (#75)
1 parent e2cd629 commit 109e6fd

8 files changed

+26
-8
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ A lambda layer provides aws-lambda-powertools. To have these dependencies locall
144144
| <a name="input_findings_manager_trigger_lambda"></a> [findings\_manager\_trigger\_lambda](#input\_findings\_manager\_trigger\_lambda) | Findings Manager Lambda settings - Manage Security Hub findings in response to S3 file upload triggers | <pre>object({<br/> name = optional(string, "securityhub-findings-manager-trigger")<br/> log_level = optional(string, "ERROR")<br/> memory_size = optional(number, 256)<br/> timeout = optional(number, 300)<br/><br/> security_group_egress_rules = optional(list(object({<br/> cidr_ipv4 = optional(string)<br/> cidr_ipv6 = optional(string)<br/> description = string<br/> from_port = optional(number, 0)<br/> ip_protocol = optional(string, "-1")<br/> prefix_list_id = optional(string)<br/> referenced_security_group_id = optional(string)<br/> to_port = optional(number, 0)<br/> })), [])<br/> })</pre> | `{}` | no |
145145
| <a name="input_findings_manager_worker_lambda"></a> [findings\_manager\_worker\_lambda](#input\_findings\_manager\_worker\_lambda) | Findings Manager Lambda settings - Manage Security Hub findings in response to SQS trigger | <pre>object({<br/> name = optional(string, "securityhub-findings-manager-worker")<br/> log_level = optional(string, "ERROR")<br/> memory_size = optional(number, 256)<br/> timeout = optional(number, 900)<br/><br/> security_group_egress_rules = optional(list(object({<br/> cidr_ipv4 = optional(string)<br/> cidr_ipv6 = optional(string)<br/> description = string<br/> from_port = optional(number, 0)<br/> ip_protocol = optional(string, "-1")<br/> prefix_list_id = optional(string)<br/> referenced_security_group_id = optional(string)<br/> to_port = optional(number, 0)<br/> })), [])<br/> })</pre> | `{}` | no |
146146
| <a name="input_jira_eventbridge_iam_role_name"></a> [jira\_eventbridge\_iam\_role\_name](#input\_jira\_eventbridge\_iam\_role\_name) | The name of the role which will be assumed by EventBridge rules for Jira integration | `string` | `"SecurityHubFindingsManagerJiraEventBridge"` | no |
147-
| <a name="input_jira_integration"></a> [jira\_integration](#input\_jira\_integration) | Findings Manager - Jira integration settings | <pre>object({<br/> enabled = optional(bool, false)<br/> autoclose_enabled = optional(bool, false)<br/> autoclose_comment = optional(string, "Security Hub finding has been resolved. Autoclosing the issue.")<br/> autoclose_transition_name = optional(string, "Close Issue")<br/> credentials_secretsmanager_arn = optional(string)<br/> credentials_ssm_secret_arn = optional(string)<br/> exclude_account_ids = optional(list(string), [])<br/> finding_severity_normalized_threshold = optional(number, 70)<br/> issue_custom_fields = optional(map(string), {})<br/> issue_type = optional(string, "Security Advisory")<br/> project_key = string<br/><br/> security_group_egress_rules = optional(list(object({<br/> cidr_ipv4 = optional(string)<br/> cidr_ipv6 = optional(string)<br/> description = string<br/> from_port = optional(number, 0)<br/> ip_protocol = optional(string, "-1")<br/> prefix_list_id = optional(string)<br/> referenced_security_group_id = optional(string)<br/> to_port = optional(number, 0)<br/> })), [])<br/><br/> lambda_settings = optional(object({<br/> name = optional(string, "securityhub-findings-manager-jira")<br/> log_level = optional(string, "INFO")<br/> memory_size = optional(number, 256)<br/> timeout = optional(number, 60)<br/> }), {<br/> name = "securityhub-findings-manager-jira"<br/> iam_role_name = "SecurityHubFindingsManagerJiraLambda"<br/> log_level = "INFO"<br/> memory_size = 256<br/> timeout = 60<br/> security_group_egress_rules = []<br/> })<br/><br/> step_function_settings = optional(object({<br/> log_level = optional(string, "ERROR")<br/> retention = optional(number, 90)<br/> }), {<br/> log_level = "ERROR"<br/> retention = 90<br/> })<br/><br/> })</pre> | <pre>{<br/> "enabled": false,<br/> "project_key": null<br/>}</pre> | no |
147+
| <a name="input_jira_integration"></a> [jira\_integration](#input\_jira\_integration) | Findings Manager - Jira integration settings | <pre>object({<br/> enabled = optional(bool, false)<br/> autoclose_enabled = optional(bool, false)<br/> autoclose_comment = optional(string, "Security Hub finding has been resolved. Autoclosing the issue.")<br/> autoclose_transition_name = optional(string, "Close Issue")<br/> credentials_secretsmanager_arn = optional(string)<br/> credentials_ssm_secret_arn = optional(string)<br/> exclude_account_ids = optional(list(string), [])<br/> finding_severity_normalized_threshold = optional(number, 70)<br/> include_account_ids = optional(list(string), [])<br/> issue_custom_fields = optional(map(string), {})<br/> issue_type = optional(string, "Security Advisory")<br/> project_key = string<br/><br/> security_group_egress_rules = optional(list(object({<br/> cidr_ipv4 = optional(string)<br/> cidr_ipv6 = optional(string)<br/> description = string<br/> from_port = optional(number, 0)<br/> ip_protocol = optional(string, "-1")<br/> prefix_list_id = optional(string)<br/> referenced_security_group_id = optional(string)<br/> to_port = optional(number, 0)<br/> })), [])<br/><br/> lambda_settings = optional(object({<br/> name = optional(string, "securityhub-findings-manager-jira")<br/> log_level = optional(string, "INFO")<br/> memory_size = optional(number, 256)<br/> timeout = optional(number, 60)<br/> }), {<br/> name = "securityhub-findings-manager-jira"<br/> iam_role_name = "SecurityHubFindingsManagerJiraLambda"<br/> log_level = "INFO"<br/> memory_size = 256<br/> timeout = 60<br/> security_group_egress_rules = []<br/> })<br/><br/> step_function_settings = optional(object({<br/> log_level = optional(string, "ERROR")<br/> retention = optional(number, 90)<br/> }), {<br/> log_level = "ERROR"<br/> retention = 90<br/> })<br/><br/> })</pre> | <pre>{<br/> "enabled": false,<br/> "project_key": null<br/>}</pre> | no |
148148
| <a name="input_jira_step_function_iam_role_name"></a> [jira\_step\_function\_iam\_role\_name](#input\_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 |
149149
| <a name="input_lambda_runtime"></a> [lambda\_runtime](#input\_lambda\_runtime) | The version of Python to use for the Lambda functions | `string` | `"python3.12"` | no |
150150
| <a name="input_rules_filepath"></a> [rules\_filepath](#input\_rules\_filepath) | Pathname to the file that stores the manager rules | `string` | `""` | no |

files/lambda-artifacts/findings-manager-jira/findings_manager_jira.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
ssm = boto3.client('ssm')
1313

1414
REQUIRED_ENV_VARS = [
15-
'EXCLUDE_ACCOUNT_FILTER', 'JIRA_ISSUE_CUSTOM_FIELDS', 'JIRA_ISSUE_TYPE', 'JIRA_PROJECT_KEY', 'JIRA_SECRET_ARN', 'JIRA_SECRET_TYPE'
15+
'EXCLUDE_ACCOUNT_FILTER', 'INCLUDE_ACCOUNT_FILTER', 'JIRA_ISSUE_CUSTOM_FIELDS', 'JIRA_ISSUE_TYPE', 'JIRA_PROJECT_KEY', 'JIRA_SECRET_ARN', 'JIRA_SECRET_TYPE'
1616
]
1717

1818
DEFAULT_JIRA_AUTOCLOSE_COMMENT = 'Security Hub finding has been resolved. Autoclosing the issue.'
@@ -40,7 +40,8 @@ def lambda_handler(event: dict, context: LambdaContext):
4040
raise RuntimeError("Required environment variables are missing.") from e
4141

4242
# Retrieve environment variables
43-
exclude_account_filter = os.environ['EXCLUDE_ACCOUNT_FILTER']
43+
exclude_account_filter = json.loads(os.environ['EXCLUDE_ACCOUNT_FILTER'])
44+
include_account_filter = json.loads(os.environ['INCLUDE_ACCOUNT_FILTER'])
4445
jira_autoclose_comment = os.getenv(
4546
'JIRA_AUTOCLOSE_COMMENT', DEFAULT_JIRA_AUTOCLOSE_COMMENT)
4647
jira_autoclose_transition = os.getenv(
@@ -85,11 +86,21 @@ def lambda_handler(event: dict, context: LambdaContext):
8586
compliance_status = finding['Compliance']['Status'] if 'Compliance' in finding else COMPLIANCE_STATUS_MISSING
8687
record_state = finding['RecordState']
8788

88-
# Only process finding if account is not excluded
89-
if finding_account_id in exclude_account_filter:
90-
logger.info(
91-
f"Account {finding_account_id} is excluded from Jira ticket creation.")
92-
return
89+
# Apply account filtering logic
90+
# Priority: include_account_filter > exclude_account_filter
91+
if include_account_filter:
92+
# If include list is provided, only process accounts in the list
93+
if finding_account_id not in include_account_filter:
94+
logger.info(
95+
f"Account {finding_account_id} is not in the include list. Skipping Jira ticket creation.")
96+
return
97+
elif exclude_account_filter:
98+
# If exclude list is provided (and no include list), skip accounts in the list
99+
if finding_account_id in exclude_account_filter:
100+
logger.info(
101+
f"Account {finding_account_id} is excluded from Jira ticket creation.")
102+
return
103+
# If neither list is provided, process all accounts
93104

94105
# Handle new findings
95106
# Ticket is created when Workflow Status is NEW and Compliance Status is FAILED, WARNING or is missing from the finding (case with e.g. Inspector findings)
136 Bytes
Binary file not shown.
136 Bytes
Binary file not shown.
1.38 KB
Binary file not shown.
1.58 KB
Binary file not shown.

jira_lambda.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ module "jira_lambda" {
106106

107107
environment = {
108108
EXCLUDE_ACCOUNT_FILTER = jsonencode(var.jira_integration.exclude_account_ids)
109+
INCLUDE_ACCOUNT_FILTER = jsonencode(var.jira_integration.include_account_ids)
109110
JIRA_AUTOCLOSE_COMMENT = var.jira_integration.autoclose_comment
110111
JIRA_AUTOCLOSE_TRANSITION = var.jira_integration.autoclose_transition_name
111112
JIRA_ISSUE_CUSTOM_FIELDS = jsonencode(var.jira_integration.issue_custom_fields)

variables.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ variable "jira_integration" {
9595
credentials_ssm_secret_arn = optional(string)
9696
exclude_account_ids = optional(list(string), [])
9797
finding_severity_normalized_threshold = optional(number, 70)
98+
include_account_ids = optional(list(string), [])
9899
issue_custom_fields = optional(map(string), {})
99100
issue_type = optional(string, "Security Advisory")
100101
project_key = string
@@ -148,6 +149,11 @@ variable "jira_integration" {
148149
condition = var.jira_integration.enabled == false || (var.jira_integration.credentials_secretsmanager_arn != null && var.jira_integration.credentials_ssm_secret_arn == null) || (var.jira_integration.credentials_secretsmanager_arn == null && var.jira_integration.credentials_ssm_secret_arn != null)
149150
error_message = "You must provide either 'credentials_secretsmanager_arn' or 'credentials_ssm_secret_arn' for jira credentials, but not both."
150151
}
152+
153+
validation {
154+
condition = !(length(var.jira_integration.exclude_account_ids) > 0 && length(var.jira_integration.include_account_ids) > 0)
155+
error_message = "You cannot provide both 'exclude_account_ids' and 'include_account_ids'. Use only one filtering method."
156+
}
151157
}
152158

153159
variable "jira_step_function_iam_role_name" {

0 commit comments

Comments
 (0)