Skip to content

Commit 4a66f58

Browse files
committed
add iam+lambda resources to state table
1 parent 8b30fc1 commit 4a66f58

File tree

2 files changed

+152
-15
lines changed

2 files changed

+152
-15
lines changed

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

Lines changed: 137 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -609,29 +609,22 @@ def deploy_config_rules(region, accounts, resource_properties):
609609

610610
for acct in accounts:
611611

612-
# for rule in repo.CONFIG_RULES[SOLUTION_NAME]:
613-
# rule_name = rule.replace("_", "-")
614-
# Get bedrock solution rule accounts and regions
615-
# rule_deploy, rule_accounts, rule_regions, rule_input_params = get_rule_params(rule_name, event)
616612
if rule_deploy is False:
617613
continue
618614
if rule_accounts:
619615
LOGGER.info(f"{rule_name} accounts: {rule_accounts}")
620616
if acct not in rule_accounts:
621617
LOGGER.info(f"{rule_name} does not apply to {acct}; skipping...")
622618
continue
623-
# for acct in rule_accounts:
624619
if DRY_RUN is False:
625620
# 3a) Deploy IAM role for custom config rule lambda
626621
LOGGER.info(f"Deploying IAM role for custom config rule lambda in {acct}")
627622
role_arn = deploy_iam_role(acct, rule_name)
628623
LIVE_RUN_DATA[f"{rule_name}_{acct}_IAMRole"] = "Deployed IAM role for custom config rule lambda"
624+
629625
else:
630626
LOGGER.info(f"DRY_RUN: Deploying IAM role for custom config rule lambda in {acct}")
631627
DRY_RUN_DATA[f"{rule_name}_{acct}_IAMRole"] = "DRY_RUN: Deploy IAM role for custom config rule lambda"
632-
633-
# for acct in rule_accounts:
634-
# for region in rule_regions:
635628
# 3b) Deploy lambda for custom config rule
636629
if DRY_RUN is False:
637630
# download rule zip file
@@ -1390,18 +1383,12 @@ def process_sns_records(event) -> None:
13901383
records: list of SNS event records
13911384
"""
13921385
LOGGER.info("Processing SNS records...")
1393-
# for record in records:
1394-
# sns_info = record["Sns"]
1395-
# LOGGER.info(f"SNS INFO: {sns_info}")
1396-
# message = json.loads(sns_info["Message"])
1397-
# deploy_config_rule(message["AccountId"], message["ConfigRuleName"], message["Regions"])
13981386
for record in event["Records"]:
13991387
record["Sns"]["Message"] = json.loads(record["Sns"]["Message"])
14001388
LOGGER.info({"SNS Record": record})
14011389
message = record["Sns"]["Message"]
14021390
if message["Action"] == "configure":
14031391
LOGGER.info("Continuing process to enable SRA security controls for Bedrock (sns event)")
1404-
# rule_deploy, rule_accounts, rule_regions, rule_input_params = get_rule_params(rule_name, event)
14051392

14061393
# 3) Deploy config rules (regional)
14071394
message['Accounts'].append(sts.MANAGEMENT_ACCOUNT)
@@ -1447,6 +1434,41 @@ def deploy_iam_role(account_id: str, rule_name: str) -> str:
14471434
LOGGER.info(f"{rule_name} IAM role already exists.")
14481435
role_arn = iam_role_search[1]
14491436

1437+
# IAM role state table record
1438+
# TODO(liamschn): move dynamodb resource to the dynamo class object/module
1439+
dynamodb_resource = sts.assume_role_resource(ssm_params.SRA_SECURITY_ACCT, sts.CONFIGURATION_ROLE, "dynamodb", sts.HOME_REGION)
1440+
1441+
item_found, find_result = dynamodb.find_item(
1442+
STATE_TABLE,
1443+
dynamodb_resource,
1444+
SOLUTION_NAME,
1445+
{
1446+
"arn": role_arn,
1447+
},
1448+
)
1449+
if item_found is False:
1450+
role_record_id, role_date_time = dynamodb.insert_item(STATE_TABLE, dynamodb_resource, SOLUTION_NAME)
1451+
else:
1452+
role_record_id = find_result["record_id"]
1453+
1454+
dynamodb.update_item(
1455+
STATE_TABLE,
1456+
dynamodb_resource,
1457+
SOLUTION_NAME,
1458+
role_record_id,
1459+
{
1460+
"aws_service": "iam",
1461+
"component_state": "implemented",
1462+
"account": account_id,
1463+
"description": "role for config rule",
1464+
"component_region": "Global",
1465+
"component_type": "role",
1466+
"component_name": rule_name,
1467+
"arn": role_arn,
1468+
"date_time": dynamodb.get_date_time(),
1469+
},
1470+
)
1471+
14501472
iam.SRA_POLICY_DOCUMENTS["sra-lambda-basic-execution"]["Statement"][0]["Resource"] = iam.SRA_POLICY_DOCUMENTS["sra-lambda-basic-execution"][
14511473
"Statement"
14521474
][0]["Resource"].replace("ACCOUNT_ID", account_id)
@@ -1470,6 +1492,38 @@ def deploy_iam_role(account_id: str, rule_name: str) -> str:
14701492
else:
14711493
LOGGER.info(f"{rule_name}-lamdba-basic-execution IAM policy already exists")
14721494

1495+
# IAM policy state table record
1496+
item_found, find_result = dynamodb.find_item(
1497+
STATE_TABLE,
1498+
dynamodb_resource,
1499+
SOLUTION_NAME,
1500+
{
1501+
"arn": policy_arn,
1502+
},
1503+
)
1504+
if item_found is False:
1505+
policy1_record_id, policy1_date_time = dynamodb.insert_item(STATE_TABLE, dynamodb_resource, SOLUTION_NAME)
1506+
else:
1507+
policy1_record_id = find_result["record_id"]
1508+
1509+
dynamodb.update_item(
1510+
STATE_TABLE,
1511+
dynamodb_resource,
1512+
SOLUTION_NAME,
1513+
policy1_record_id,
1514+
{
1515+
"aws_service": "iam",
1516+
"component_state": "implemented",
1517+
"account": account_id,
1518+
"description": "policy for config rule role",
1519+
"component_region": "Global",
1520+
"component_type": "policy",
1521+
"component_name": f"{rule_name}-lamdba-basic-execution",
1522+
"arn": policy_arn,
1523+
"date_time": dynamodb.get_date_time(),
1524+
},
1525+
)
1526+
14731527
policy_arn2 = f"arn:{sts.PARTITION}:iam::{account_id}:policy/{rule_name}"
14741528
iam_policy_search2 = iam.check_iam_policy_exists(policy_arn2)
14751529
if iam_policy_search2 is False:
@@ -1483,6 +1537,38 @@ def deploy_iam_role(account_id: str, rule_name: str) -> str:
14831537
else:
14841538
LOGGER.info(f"{rule_name} IAM policy already exists")
14851539

1540+
# IAM policy state table record
1541+
item_found, find_result = dynamodb.find_item(
1542+
STATE_TABLE,
1543+
dynamodb_resource,
1544+
SOLUTION_NAME,
1545+
{
1546+
"arn": policy_arn2,
1547+
},
1548+
)
1549+
if item_found is False:
1550+
policy2_record_id, policy2_date_time = dynamodb.insert_item(STATE_TABLE, dynamodb_resource, SOLUTION_NAME)
1551+
else:
1552+
policy2_record_id = find_result["record_id"]
1553+
1554+
dynamodb.update_item(
1555+
STATE_TABLE,
1556+
dynamodb_resource,
1557+
SOLUTION_NAME,
1558+
policy2_record_id,
1559+
{
1560+
"aws_service": "iam",
1561+
"component_state": "implemented",
1562+
"account": account_id,
1563+
"description": "policy for config rule role",
1564+
"component_region": "Global",
1565+
"component_type": "policy",
1566+
"component_name": f"{rule_name}-lamdba-basic-execution",
1567+
"arn": policy_arn2,
1568+
"date_time": dynamodb.get_date_time(),
1569+
},
1570+
)
1571+
14861572
policy_attach_search1 = iam.check_iam_policy_attached(rule_name, policy_arn)
14871573
if policy_attach_search1 is False:
14881574
if DRY_RUN is False:
@@ -1556,6 +1642,43 @@ def deploy_lambda_function(account_id: str, rule_name: str, role_arn: str, regio
15561642
else:
15571643
LOGGER.info(f"{rule_name} already exists in {account_id}. Search result: {lambda_function_search}")
15581644
lambda_arn = lambda_function_search["Configuration"]["FunctionArn"]
1645+
1646+
# Lambda state table record
1647+
# TODO(liamschn): move dynamodb resource to the dynamo class object/module
1648+
dynamodb_resource = sts.assume_role_resource(ssm_params.SRA_SECURITY_ACCT, sts.CONFIGURATION_ROLE, "dynamodb", sts.HOME_REGION)
1649+
1650+
item_found, find_result = dynamodb.find_item(
1651+
STATE_TABLE,
1652+
dynamodb_resource,
1653+
SOLUTION_NAME,
1654+
{
1655+
"arn": lambda_arn,
1656+
},
1657+
)
1658+
if item_found is False:
1659+
lambda_record_id, lambda_date_time = dynamodb.insert_item(STATE_TABLE, dynamodb_resource, SOLUTION_NAME)
1660+
else:
1661+
lambda_record_id = find_result["record_id"]
1662+
1663+
dynamodb.update_item(
1664+
STATE_TABLE,
1665+
dynamodb_resource,
1666+
SOLUTION_NAME,
1667+
lambda_record_id,
1668+
{
1669+
"aws_service": "lambda",
1670+
"component_state": "implemented",
1671+
"account": account_id,
1672+
"description": "lambda for config rule",
1673+
"component_region": region,
1674+
"component_type": "function",
1675+
"component_name": rule_name,
1676+
"arn": lambda_arn,
1677+
"date_time": dynamodb.get_date_time(),
1678+
},
1679+
)
1680+
1681+
15591682
return lambda_arn
15601683

15611684

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,30 @@
77
from datetime import datetime
88
from time import sleep
99
import botocore
10+
from boto3.session import Session
11+
from typing import TYPE_CHECKING
12+
if TYPE_CHECKING:
13+
from mypy_boto3_dynamodb.service_resource import DynamoDBServiceResource, Table
14+
from mypy_boto3_dynamodb.client import DynamoDBClient
1015

16+
1117

1218
class sra_dynamodb:
1319
PROFILE = "default"
1420
UNEXPECTED = "Unexpected!"
1521

16-
LOGGER = logging.getLogger(__name__)
22+
LOGGER = logging.getLogger(__name__)
1723
log_level: str = os.environ.get("LOG_LEVEL", "INFO")
1824
LOGGER.setLevel(log_level)
1925

26+
try:
27+
MANAGEMENT_ACCOUNT_SESSION: Session = boto3.Session()
28+
DYNAMODB_RESOURCE: DynamoDBServiceResource = MANAGEMENT_ACCOUNT_SESSION.resource("dynamodb")
29+
DYNAMODB_CLIENT: DynamoDBClient = MANAGEMENT_ACCOUNT_SESSION.client("dynamodb")
30+
except Exception:
31+
LOGGER.exception(UNEXPECTED)
32+
raise ValueError("Unexpected error executing Lambda function. Review CloudWatch logs for details.") from None
33+
2034
def __init__(self, profile="default") -> None:
2135
self.PROFILE = profile
2236
try:

0 commit comments

Comments
 (0)