@@ -566,7 +566,7 @@ def create_event(event, context):
566566 else :
567567 LOGGER .info (f"DRY_RUN: Filter deploy parameter is 'false'; Skip { filter } CloudWatch metric filter deployment" )
568568 DRY_RUN_DATA [f"{ filter } _CloudWatch" ] = "DRY_RUN: Filter deploy parameter is 'false'; Skip CloudWatch metric filter deployment"
569-
569+
570570 # 5) Central CloudWatch Observability
571571 # TODO(liamschn): determine if we need the CloudWatch-CrossAccountListAccountsRole (needed for "Enable account selector"?).
572572 # TRUST
@@ -599,7 +599,7 @@ def create_event(event, context):
599599 central_observability_params = json .loads (event ["ResourceProperties" ]["SRA-BEDROCK-CENTRAL-OBSERVABILITY" ])
600600 # TODO(liamschn): create a parameter to choose to deploy central observability or not: deploy_central_observability = true/false
601601 # 5a) OAM Sink in security account
602- cloudwatch .CWOAM_CLIENT = sts .assume_role (SECURITY_ACCOUNT , sts .CONFIGURATION_ROLE , "oam" , region )
602+ cloudwatch .CWOAM_CLIENT = sts .assume_role (SECURITY_ACCOUNT , sts .CONFIGURATION_ROLE , "oam" , sts . HOME_REGION )
603603 search_oam_sink = cloudwatch .find_oam_sink ()
604604 if search_oam_sink [0 ] is False :
605605 if DRY_RUN is False :
@@ -615,7 +615,7 @@ def create_event(event, context):
615615 else :
616616 oam_sink_arn = search_oam_sink [1 ]
617617 LOGGER .info (f"CloudWatch observability access manager sink found: { oam_sink_arn } " )
618-
618+
619619 # 5b) OAM Sink policy in security account
620620 cloudwatch .SINK_POLICY = CLOUDWATCH_OAM_SINK_POLICY ["sra-oam-sink-policy" ]
621621 cloudwatch .SINK_POLICY ["Statement" ][0 ]["Condition" ]["ForAnyValue:StringEquals" ]["aws:PrincipalOrgID" ] = ORGANIZATION_ID
@@ -650,7 +650,7 @@ def create_event(event, context):
650650 DRY_RUN_DATA ["OAMSinkPolicyUpdate" ] = "DRY_RUN: Update CloudWatch observability access manager sink policy"
651651 else :
652652 LOGGER .info ("CloudWatch observability access manager sink policy is correct" )
653-
653+
654654 # 5c) OAM CloudWatch-CrossAccountSharingRole IAM role
655655 # Add management account to the bedrock accounts list
656656 central_observability_params ["bedrock_accounts" ].append (sts .MANAGEMENT_ACCOUNT )
@@ -673,7 +673,7 @@ def create_event(event, context):
673673 DRY_RUN_DATA ["OAMCrossAccountRoleCreate" ] = f"DRY_RUN: Create { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role"
674674 else :
675675 LOGGER .info (f"CloudWatch observability access manager cross-account role found: { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } " )
676-
676+
677677 # 5d) Attach managed policies to CloudWatch-CrossAccountSharingRole IAM role
678678 cross_account_policies = [
679679 "arn:aws:iam::aws:policy/AWSXrayReadOnlyAccess" ,
@@ -767,6 +767,91 @@ def delete_event(event, context):
767767 else :
768768 LOGGER .info (f"{ SOLUTION_NAME } -configuration SNS topic does not exist." )
769769
770+
771+ # 2) Delete Central CloudWatch Observability
772+ central_observability_params = json .loads (event ["ResourceProperties" ]["SRA-BEDROCK-CENTRAL-OBSERVABILITY" ])
773+
774+ cloudwatch .CWOAM_CLIENT = sts .assume_role (SECURITY_ACCOUNT , sts .CONFIGURATION_ROLE , "oam" , sts .HOME_REGION )
775+ search_oam_sink = cloudwatch .find_oam_sink ()
776+ if search_oam_sink [0 ] is True :
777+ oam_sink_arn = search_oam_sink [1 ]
778+ else :
779+ LOGGER .info ("Error deleting: CloudWatch observability access manager sink not found; may have to manually delete OAM links" )
780+ oam_sink_arn = "Error:Sink:Arn:Not:Found"
781+
782+ # Add management account to the bedrock accounts list
783+ central_observability_params ["bedrock_accounts" ].append (sts .MANAGEMENT_ACCOUNT )
784+ for bedrock_account in central_observability_params ["bedrock_accounts" ]:
785+ for bedrock_region in central_observability_params ["regions" ]:
786+ # 2a) OAM link in bedrock account
787+ cloudwatch .CWOAM_CLIENT = sts .assume_role (bedrock_account , sts .CONFIGURATION_ROLE , "oam" , bedrock_region )
788+ search_oam_link = cloudwatch .find_oam_link (oam_sink_arn )
789+ if search_oam_link [0 ] is True :
790+ if DRY_RUN is False :
791+ LOGGER .info (f"CloudWatch observability access manager link ({ oam_sink_arn } ) found, deleting..." )
792+ cloudwatch .delete_oam_link (oam_sink_arn )
793+ LIVE_RUN_DATA ["OAMLinkDelete" ] = "Deleted CloudWatch observability access manager link"
794+ CFN_RESPONSE_DATA ["deployment_info" ]["action_count" ] += 1
795+ CFN_RESPONSE_DATA ["deployment_info" ]["resources_deployed" ] -= 1
796+ LOGGER .info ("Deleted CloudWatch observability access manager link" )
797+ else :
798+ LOGGER .info ("DRY_RUN: CloudWatch observability access manager link found, deleting..." )
799+ DRY_RUN_DATA ["OAMLinkDelete" ] = "DRY_RUN: Delete CloudWatch observability access manager link"
800+ else :
801+ LOGGER .info (f"CloudWatch observability access manager link ({ oam_sink_arn } ) not found" )
802+
803+ iam .IAM_CLIENT = sts .assume_role (bedrock_account , sts .CONFIGURATION_ROLE , "iam" , iam .get_iam_global_region ())
804+
805+ # 2b) Detach managed policies to CloudWatch-CrossAccountSharingRole IAM role
806+ cross_account_policies = iam .list_attached_iam_policies (cloudwatch .CROSS_ACCOUNT_ROLE_NAME )
807+ if cross_account_policies is not None :
808+ if DRY_RUN is False :
809+ for policy in cross_account_policies :
810+ LOGGER .info (f"Detaching { policy ['PolicyArn' ]} policy from { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role..." )
811+ iam .detach_policy (cloudwatch .CROSS_ACCOUNT_ROLE_NAME , policy ["PolicyArn" ])
812+ LIVE_RUN_DATA ["OAMCrossAccountRolePolicyDetach" ] = f"Detached { policy ['PolicyArn' ]} policy from { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role"
813+ CFN_RESPONSE_DATA ["deployment_info" ]["action_count" ] += 1
814+ CFN_RESPONSE_DATA ["deployment_info" ]["configuration_changes" ] += 1
815+ LOGGER .info (f"Detached { policy ['PolicyArn' ]} policy from { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role" )
816+ else :
817+ for policy in cross_account_policies :
818+ LOGGER .info (f"DRY_RUN: Detaching { policy ['PolicyArn' ]} policy from { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role..." )
819+ DRY_RUN_DATA ["OAMCrossAccountRolePolicyDetach" ] = f"DRY_RUN: Detach { policy ['PolicyArn' ]} policy from { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role"
820+ else :
821+ LOGGER .info (f"No policies attached to { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role" )
822+
823+ # 2c) Delete CloudWatch-CrossAccountSharingRole IAM role
824+ search_iam_role = iam .check_iam_role_exists (cloudwatch .CROSS_ACCOUNT_ROLE_NAME )
825+ if search_iam_role [0 ] is True :
826+ if DRY_RUN is False :
827+ LOGGER .info (f"Deleting { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role..." )
828+ iam .delete_role (cloudwatch .CROSS_ACCOUNT_ROLE_NAME )
829+ LIVE_RUN_DATA ["OAMCrossAccountRoleDelete" ] = f"Deleted { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role"
830+ CFN_RESPONSE_DATA ["deployment_info" ]["action_count" ] += 1
831+ CFN_RESPONSE_DATA ["deployment_info" ]["resources_deployed" ] -= 1
832+ LOGGER .info (f"Deleted { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role" )
833+ else :
834+ LOGGER .info (f"DRY_RUN: Deleting { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role..." )
835+ DRY_RUN_DATA ["OAMCrossAccountRoleDelete" ] = f"DRY_RUN: Delete { cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role"
836+ else :
837+ LOGGER .info (f"{ cloudwatch .CROSS_ACCOUNT_ROLE_NAME } IAM role does not exist" )
838+
839+ # 2d) Delete OAM Sink in security account
840+ cloudwatch .CWOAM_CLIENT = sts .assume_role (SECURITY_ACCOUNT , sts .CONFIGURATION_ROLE , "oam" , sts .HOME_REGION )
841+ if search_oam_sink [0 ] is True :
842+ if DRY_RUN is False :
843+ LOGGER .info ("CloudWatch observability access manager sink found, deleting..." )
844+ cloudwatch .delete_oam_sink (oam_sink_arn )
845+ LIVE_RUN_DATA ["OAMSinkDelete" ] = "Deleted CloudWatch observability access manager sink"
846+ CFN_RESPONSE_DATA ["deployment_info" ]["action_count" ] += 1
847+ CFN_RESPONSE_DATA ["deployment_info" ]["resources_deployed" ] -= 1
848+ LOGGER .info ("Deleted CloudWatch observability access manager sink" )
849+ else :
850+ LOGGER .info ("DRY_RUN: CloudWatch observability access manager sink found, deleting..." )
851+ DRY_RUN_DATA ["OAMSinkDelete" ] = "DRY_RUN: Delete CloudWatch observability access manager sink"
852+ else :
853+ LOGGER .info ("CloudWatch observability access manager sink not found" )
854+
770855 # 3) Delete metric alarms and filters
771856 for filter in CLOUDWATCH_METRIC_FILTERS :
772857 filter_deploy , filter_accounts , filter_regions , filter_params = get_filter_params (filter , event )
0 commit comments