Skip to content

Commit ed14a72

Browse files
committed
add link creation; add sink/link deletes
1 parent 9e57911 commit ed14a72

File tree

2 files changed

+94
-3
lines changed

2 files changed

+94
-3
lines changed

aws_sra_examples/solutions/genai/bedrock_org/lambda/src/app.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -632,9 +632,35 @@ def create_event(event, context):
632632
"arn:aws:iam::aws:policy/CloudWatchAutomaticDashboardsAccess",
633633
"arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess"
634634
]
635-
636-
635+
for policy_arn in cross_account_policies:
636+
search_attached_policies = iam.check_iam_policy_attached(cloudwatch.CROSS_ACCOUNT_ROLE_NAME, policy_arn)
637+
if search_attached_policies is False:
638+
LOGGER.info(f"Attaching {policy_arn} policy to {cloudwatch.CROSS_ACCOUNT_ROLE_NAME} IAM role...")
639+
if DRY_RUN is False:
640+
iam.attach_policy(cloudwatch.CROSS_ACCOUNT_ROLE_NAME, policy_arn)
641+
LIVE_RUN_DATA["OAMCrossAccountRolePolicyAttach"] = f"Attached {policy_arn} policy to {cloudwatch.CROSS_ACCOUNT_ROLE_NAME} IAM role"
642+
CFN_RESPONSE_DATA["deployment_info"]["action_count"] += 1
643+
CFN_RESPONSE_DATA["deployment_info"]["configuration_changes"] += 1
644+
LOGGER.info(f"Attached {policy_arn} policy to {cloudwatch.CROSS_ACCOUNT_ROLE_NAME} IAM role")
645+
else:
646+
DRY_RUN_DATA["OAMCrossAccountRolePolicyAttach"] = f"DRY_RUN: Attach {policy_arn} policy to {cloudwatch.CROSS_ACCOUNT_ROLE_NAME} IAM role"
637647

648+
# 5d) OAM link
649+
cloudwatch.CWOAM_CLIENT = sts.assume_role(bedrock_account, sts.CONFIGURATION_ROLE, "cloudwatch", region)
650+
search_oam_link = cloudwatch.find_oam_link(oam_sink_arn)
651+
if search_oam_link[0] is False:
652+
if DRY_RUN is False:
653+
LOGGER.info("CloudWatch observability access manager link not found, creating...")
654+
cloudwatch.create_oam_link(oam_sink_arn)
655+
LIVE_RUN_DATA["OAMLinkCreate"] = "Created CloudWatch observability access manager link"
656+
CFN_RESPONSE_DATA["deployment_info"]["action_count"] += 1
657+
CFN_RESPONSE_DATA["deployment_info"]["resources_deployed"] += 1
658+
LOGGER.info("Created CloudWatch observability access manager link")
659+
else:
660+
LOGGER.info("DRY_RUN: CloudWatch observability access manager link not found, creating...")
661+
DRY_RUN_DATA["OAMLinkCreate"] = "DRY_RUN: Create CloudWatch observability access manager link"
662+
else:
663+
LOGGER.info("CloudWatch observability access manager link found")
638664

639665
# End
640666
# TODO(liamschn): Consider the 256 KB limit for any cloudwatch log message

aws_sra_examples/solutions/genai/bedrock_org/lambda/src/sra_cloudwatch.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class sra_cloudwatch:
4646
SOLUTION_NAME: str = "sra-set-solution-name"
4747
SINK_POLICY = ""
4848
CROSS_ACCOUNT_ROLE_NAME = "CloudWatch-CrossAccountSharingRole"
49+
CROSS_ACCOUNT_TRUST_POLICY = ""
4950

5051
try:
5152
MANAGEMENT_ACCOUNT_SESSION = boto3.Session()
@@ -317,6 +318,22 @@ def put_oam_sink_policy(self, sink_arn: str, sink_policy: dict) -> None:
317318
except ClientError as e:
318319
self.LOGGER.info(self.UNEXPECTED)
319320
raise ValueError(f"Unexpected error executing Lambda function. {e}") from None
321+
322+
def delete_oam_sink(self, sink_arn: str) -> None:
323+
"""Delete the Observability Access Manager sink for SRA in the organization.
324+
325+
Args:
326+
sink_arn (str): ARN of the sink
327+
328+
Returns:
329+
None
330+
"""
331+
try:
332+
self.CWOAM_CLIENT.delete_sink(Identifier=sink_arn)
333+
self.LOGGER.info(f"Observability access manager sink {sink_arn} deleted")
334+
except ClientError as e:
335+
self.LOGGER.info(self.UNEXPECTED)
336+
raise ValueError(f"Unexpected error executing Lambda function. {e}") from None
320337

321338
def find_oam_link(self, sink_arn: str) -> tuple[bool, str]:
322339
"""Find the Observability Access Manager link for SRA in the organization.
@@ -341,4 +358,52 @@ def find_oam_link(self, sink_arn: str) -> tuple[bool, str]:
341358
return False, ""
342359
else:
343360
self.LOGGER.info(self.UNEXPECTED)
344-
raise ValueError(f"Unexpected error executing Lambda function. {error}") from None
361+
raise ValueError(f"Unexpected error executing Lambda function. {error}") from None
362+
363+
def create_oam_link(self, sink_arn: str) -> str:
364+
"""Create the Observability Access Manager link for SRA in the organization.
365+
366+
Args:
367+
sink_arn (str): ARN of the sink
368+
369+
Returns:
370+
str: ARN of the created link
371+
"""
372+
try:
373+
response = self.CWOAM_CLIENT.create_link(
374+
LabelTemplate='$AccountName',
375+
ResourceTypes=[
376+
"AWS::ApplicationInsights::Application",
377+
"AWS::InternetMonitor::Monitor",
378+
"AWS::Logs::LogGroup",
379+
"AWS::CloudWatch::Metric",
380+
"AWS::XRay::Trace"
381+
],
382+
SinkIdentifier=sink_arn,
383+
Tags={"sra-solution": self.SOLUTION_NAME}
384+
)
385+
self.LOGGER.info(f"Observability access manager link for {sink_arn} created: {response['Arn']}")
386+
return response["Arn"]
387+
except ClientError as error:
388+
if error.response["Error"]["Code"] == "ConflictException":
389+
self.LOGGER.info(f"Observability access manager link for {sink_arn} already exists")
390+
return self.find_oam_link(sink_arn)[1]
391+
else:
392+
self.LOGGER.info(self.UNEXPECTED)
393+
raise ValueError(f"Unexpected error executing Lambda function. {error}") from None
394+
395+
def delete_oam_link(self, link_arn: str) -> None:
396+
"""Delete the Observability Access Manager link for SRA in the organization.
397+
398+
Args:
399+
link_arn (str): ARN of the link
400+
401+
Returns:
402+
None
403+
"""
404+
try:
405+
self.CWOAM_CLIENT.delete_link(Identifier=link_arn)
406+
self.LOGGER.info(f"Observability access manager link for {link_arn} deleted")
407+
except ClientError as e:
408+
self.LOGGER.info(self.UNEXPECTED)
409+
raise ValueError(f"Unexpected error executing Lambda function. {e}") from None

0 commit comments

Comments
 (0)