Skip to content

Commit 161e0e3

Browse files
authored
Sechub fix 138 - INCOMPLETE status, InvalidResourceId error (#153)
1 parent a1e2321 commit 161e0e3

File tree

1 file changed

+59
-13
lines changed
  • aws_sra_examples/solutions/securityhub/securityhub_org/lambda/src

1 file changed

+59
-13
lines changed

aws_sra_examples/solutions/securityhub/securityhub_org/lambda/src/securityhub.py

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -342,13 +342,7 @@ def configure_member_account(account_id: str, configuration_role_name: str, regi
342342

343343

344344
def get_standard_dictionary(
345-
account_id: str,
346-
region: str,
347-
aws_partition: str,
348-
sbp_version: str,
349-
cis_version: str,
350-
pci_version: str,
351-
nist_version: str,
345+
account_id: str, region: str, aws_partition: str, sbp_version: str, cis_version: str, pci_version: str, nist_version: str
352346
) -> dict:
353347
"""Get Standard ARNs.
354348
@@ -359,7 +353,7 @@ def get_standard_dictionary(
359353
sbp_version: AWS Security Best Practices Standard Version
360354
cis_version: CIS Standard Version
361355
pci_version: PCI Standard Version
362-
nist_version: NIST Standard
356+
nist_version: NIST version
363357
364358
Returns:
365359
Standard ARN Dictionary
@@ -419,18 +413,70 @@ def get_enabled_standards(securityhub_client: SecurityHubClient) -> list:
419413
return standards_subscriptions
420414

421415

422-
def all_standards_in_status(standards_subscriptions: list, standards_status: str) -> bool:
416+
def disable_then_enable_standard(securityhub_client: SecurityHubClient, standards_subscription_arn: str, standards_arn: str) -> bool:
417+
"""Disable and then re-enable standard.
418+
419+
Args:
420+
securityhub_client: Security Hub boto3 client
421+
standards_subscription_arn: Standard subscription ARN
422+
standards_arn: Standard ARN
423+
424+
Returns:
425+
bool: True if no error when re-enabling standard; false if there was a problem doing so.
426+
"""
427+
LOGGER.info("Entered disable_then_enable_standard function...")
428+
LOGGER.info(f"...disabling {standards_subscription_arn} standard")
429+
securityhub_client.batch_disable_standards(
430+
StandardsSubscriptionArns=[
431+
standards_subscription_arn,
432+
]
433+
)
434+
sleep(5)
435+
standard_enable_retry_sleep = 5
436+
standard_enable_retry = 0
437+
while standard_enable_retry < 10:
438+
try:
439+
LOGGER.info(f"...enabling {standards_subscription_arn} standard")
440+
securityhub_client.batch_enable_standards(
441+
StandardsSubscriptionRequests=[
442+
{
443+
"StandardsArn": standards_arn,
444+
},
445+
]
446+
)
447+
return True
448+
except securityhub_client.exceptions.InvalidInputException as error:
449+
standard_enable_retry = standard_enable_retry + 1
450+
LOGGER.error(
451+
f"Retry {standard_enable_retry} due to InvalidInputException "
452+
+ f"while enabling standard: {error.response['Error']['Code']} - {error.response['Error']['Message']}"
453+
)
454+
sleep(standard_enable_retry_sleep)
455+
return False
456+
457+
458+
def all_standards_in_status(standards_subscriptions: list, standards_status: str, securityhub_client: SecurityHubClient) -> bool:
423459
"""All standards in status.
424460
425461
Args:
426462
standards_subscriptions: list of standards subscriptions
427463
standards_status: standards status 'PENDING'|'READY'|'FAILED'|'DELETING'|'INCOMPLETE'
464+
securityhub_client: Security hub boto3 client
428465
429466
Returns:
430-
True or False
467+
bool: True or False
431468
"""
432469
for standards_subscription in standards_subscriptions: # noqa: SIM111
433-
if standards_subscription.get("StandardsStatus") != standards_status:
470+
LOGGER.info("entered all_standards_in_status function...")
471+
LOGGER.info(f"standard - {standards_subscription} : {standards_subscription.get('StandardsStatus')}")
472+
incomplete_status_resolved = True
473+
if standards_subscription.get("StandardsStatus") == "INCOMPLETE":
474+
incomplete_status_resolved = disable_then_enable_standard(
475+
securityhub_client, standards_subscription.get("StandardsSubscriptionArn"), standards_subscription.get("StandardsArn")
476+
)
477+
if standards_subscription.get("StandardsStatus") != standards_status and standards_subscription.get("StandardsStatus") != "INCOMPLETE":
478+
return False
479+
if incomplete_status_resolved is False:
434480
return False
435481
return True
436482

@@ -446,7 +492,7 @@ def get_current_enabled_standards(securityhub_client: SecurityHubClient, standar
446492
Standard Dictionary
447493
"""
448494
standards_subscriptions = get_enabled_standards(securityhub_client)
449-
if all_standards_in_status(standards_subscriptions, "READY"):
495+
if all_standards_in_status(standards_subscriptions, "READY", securityhub_client):
450496
for item in standards_subscriptions:
451497
if standard_dict["sbp"]["standard_arn"] == item["StandardsArn"]:
452498
standard_dict["sbp"]["enabled"] = True
@@ -470,7 +516,7 @@ def all_standards_ready(securityhub_client: SecurityHubClient) -> bool:
470516
"""
471517
for i in range(10):
472518
standards_subscriptions = get_enabled_standards(securityhub_client)
473-
if all_standards_in_status(standards_subscriptions, "READY"):
519+
if all_standards_in_status(standards_subscriptions, "READY", securityhub_client):
474520
return True
475521
LOGGER.info(f"Waiting 20 seconds before checking if standards are in READY status. {i} of 10")
476522
sleep(20)

0 commit comments

Comments
 (0)