Skip to content

Commit 04edf02

Browse files
committed
search for kms key before creating; remove comments/cleanup
1 parent 26aa9ac commit 04edf02

File tree

2 files changed

+69
-98
lines changed

2 files changed

+69
-98
lines changed

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

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ def deploy_config_rules(region, accounts, resource_properties):
719719
LOGGER.info(f"DRY_RUN: Deploying custom config rule in {acct} in {region}")
720720
DRY_RUN_DATA[f"{rule_name}_{acct}_{region}_Config"] = "DRY_RUN: Deploy custom config rule"
721721

722-
def deploy_metric_filters_and_alarms(region, accounts, resource_properties):
722+
def deploy_metric_filters_and_alarms(region: str, accounts: list, resource_properties: dict) -> None:
723723
global DRY_RUN_DATA
724724
global LIVE_RUN_DATA
725725
global CFN_RESPONSE_DATA
@@ -770,11 +770,10 @@ def deploy_metric_filters_and_alarms(region, accounts, resource_properties):
770770
if acct not in filter_accounts:
771771
LOGGER.info(f"{filter_name} filter not requested for {acct}. Skipping...")
772772
continue
773-
kms.KMS_CLIENT = sts.assume_role(acct, sts.CONFIGURATION_ROLE, "kms", region)
773+
kms.KMS_CLIENT = sts.assume_role(acct, sts.CONFIGURATION_ROLE, "kms", region, config=kms.BOTO3_CONFIG)
774774
search_alarm_kms_key, alarm_key_alias, alarm_key_id, alarm_key_arn = kms.check_alias_exists(kms.KMS_CLIENT, f"alias/{ALARM_SNS_KEY_ALIAS}")
775775
if search_alarm_kms_key is False:
776776
LOGGER.info(f"alias/{ALARM_SNS_KEY_ALIAS} not found.")
777-
# TODO(liamschn): search for key itself (by policy) before creating the key; then separate the alias creation from this section
778777
if DRY_RUN is False:
779778
LOGGER.info("Creating SRA alarm KMS key")
780779
LOGGER.info("Customizing key policy...")
@@ -786,11 +785,21 @@ def deploy_metric_filters_and_alarms(region, accounts, resource_properties):
786785

787786
kms_key_policy["Statement"][2]["Principal"]["AWS"] = execution_role_arn
788787
LOGGER.info(f"Customizing key policy...done: {kms_key_policy}")
789-
alarm_key_id = kms.create_kms_key(kms.KMS_CLIENT, json.dumps(kms_key_policy), "Key for CloudWatch Alarm SNS Topic Encryption")
790-
LOGGER.info(f"Created SRA alarm KMS key: {alarm_key_id}")
791-
LIVE_RUN_DATA["KMSKeyCreate"] = "Created SRA alarm KMS key"
792-
CFN_RESPONSE_DATA["deployment_info"]["action_count"] += 1
793-
CFN_RESPONSE_DATA["deployment_info"]["resources_deployed"] += 1
788+
# TODO(liamschn): search for key itself (by policy) before creating the key; then separate the alias creation from this section (in progress)
789+
LOGGER.info(f"Searching for existing keys with proper policy...")
790+
kms_search_result, kms_found_id = kms.search_key_policies(kms.KMS_CLIENT, kms_key_policy)
791+
if kms_search_result is True:
792+
LOGGER.info(f"Found existing key with proper policy: {kms_found_id}")
793+
alarm_key_id = kms_found_id
794+
else:
795+
LOGGER.info("No existing key found with proper policy. Creating new key...")
796+
alarm_key_id = kms.create_kms_key(kms.KMS_CLIENT, json.dumps(kms_key_policy), "Key for CloudWatch Alarm SNS Topic Encryption")
797+
LOGGER.info(f"Created SRA alarm KMS key: {alarm_key_id}")
798+
LIVE_RUN_DATA["KMSKeyCreate"] = "Created SRA alarm KMS key"
799+
CFN_RESPONSE_DATA["deployment_info"]["action_count"] += 1
800+
CFN_RESPONSE_DATA["deployment_info"]["resources_deployed"] += 1
801+
# Add KMS resource records to sra state table
802+
add_state_table_record("kms", "implemented", "alarms sns kms key", "key", f"arn:aws:kms:{region}:{acct}:key/{alarm_key_id}", acct, region, alarm_key_id, alarm_key_id)
794803

795804
# 4aii KMS alias for SNS topic used by CloudWatch alarms
796805
LOGGER.info("Creating SRA alarm KMS key alias")
@@ -799,7 +808,6 @@ def deploy_metric_filters_and_alarms(region, accounts, resource_properties):
799808
CFN_RESPONSE_DATA["deployment_info"]["action_count"] += 1
800809
CFN_RESPONSE_DATA["deployment_info"]["resources_deployed"] += 1
801810
# Add KMS resource records to sra state table
802-
add_state_table_record("kms", "implemented", "alarms sns kms key", "key", f"arn:aws:kms:{region}:{acct}:key/{alarm_key_id}", acct, region, alarm_key_id, alarm_key_id)
803811
add_state_table_record("kms", "implemented", "alarms sns kms alias", "alias", f"arn:aws:kms:{region}:{acct}:alias/{ALARM_SNS_KEY_ALIAS}", acct, region, ALARM_SNS_KEY_ALIAS, alarm_key_id)
804812

805813
else:

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

Lines changed: 52 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
from typing import TYPE_CHECKING
1717
from typing import cast
18+
from typing import Literal
1819

1920
if TYPE_CHECKING:
2021
from mypy_boto3_kms.client import KMSClient
@@ -38,22 +39,10 @@ class sra_kms:
3839
LOGGER.setLevel(log_level)
3940

4041
# Global Variables
41-
# RESOURCE_TYPE: str = ""
4242
UNEXPECTED = "Unexpected!"
4343
BOTO3_CONFIG = Config(retries={"max_attempts": 10, "mode": "standard"})
44-
# SRA_SOLUTION_NAME = "sra-common-prerequisites"
45-
# CFN_RESOURCE_ID: str = "sra-iam-function"
46-
# CFN_CUSTOM_RESOURCE: str = "Custom::LambdaCustomResource"
47-
48-
# CONFIGURATION_ROLE: str = ""
49-
# TARGET_ACCOUNT_ID: str = ""
50-
# ORG_ID: str = ""
51-
52-
# KEY_ALIAS: str = "alias/sra-secrets-key" # TODO(liamschn): parameterize this alias name
53-
# KEY_DESCRIPTION: str = "SRA Secrets Key" # TODO(liamschn): parameterize this description
54-
# EXECUTION_ROLE: str = "sra-execution" # TODO(liamschn): parameterize this role name
55-
# SECRETS_PREFIX: str = "sra" # TODO(liamschn): parameterize this?
56-
SECRETS_KEY_POLICY: str = ""
44+
SERVICE_NAME: Literal["kms"] = "kms"
45+
# SECRETS_KEY_POLICY: str = ""
5746

5847
try:
5948
MANAGEMENT_ACCOUNT_SESSION: Session = boto3.Session()
@@ -64,85 +53,59 @@ class sra_kms:
6453
MANAGEMENT_ACCOUNT = STS_CLIENT.get_caller_identity().get("Account")
6554
PARTITION: str = boto3.session.Session().get_partition_for_region(HOME_REGION)
6655
LOGGER.info(f"Detected management account (current account): {MANAGEMENT_ACCOUNT}")
67-
KMS_CLIENT: KMSClient = MANAGEMENT_ACCOUNT_SESSION.client("kms", config=BOTO3_CONFIG)
56+
KMS_CLIENT: KMSClient = MANAGEMENT_ACCOUNT_SESSION.client(SERVICE_NAME, config=BOTO3_CONFIG)
6857
except Exception:
6958
LOGGER.exception(UNEXPECTED)
7059
raise ValueError("Unexpected error executing Lambda function. Review CloudWatch logs for details.") from None
7160

72-
def define_key_policy(self, target_account_id: str, partition: str, home_region: str, org_id: str, management_account: str) -> str:
73-
policy_template = { # noqa ECE001
74-
"Version": "2012-10-17",
75-
"Id": "sra-secrets-key",
76-
"Statement": [
77-
{
78-
"Sid": "Enable IAM User Permissions",
79-
"Effect": "Allow",
80-
"Principal": {"AWS": "arn:" + partition + ":iam::" + target_account_id + ":root"},
81-
"Action": "kms:*",
82-
"Resource": "*",
83-
},
84-
{
85-
"Sid": "Allow access through AWS Secrets Manager for all principals in the account that are authorized to use AWS Secrets Manager",
86-
"Effect": "Allow",
87-
"Principal": {"AWS": "*"},
88-
"Action": ["kms:Decrypt", "kms:Encrypt", "kms:GenerateDataKey*", "kms:ReEncrypt*", "kms:CreateGrant", "kms:DescribeKey"],
89-
"Resource": "*",
90-
"Condition": {
91-
"StringEquals": {"kms:ViaService": "secretsmanager." + home_region + ".amazonaws.com", "aws:PrincipalOrgId": org_id},
92-
"StringLike": {
93-
"kms:EncryptionContext:SecretARN": "arn:aws:secretsmanager:" + home_region + ":*:secret:sra/*",
94-
"aws:PrincipalArn": "arn:" + partition + ":iam::*:role/sra-execution",
95-
},
96-
},
97-
},
98-
{
99-
"Sid": "Allow direct access to key metadata",
100-
"Effect": "Allow",
101-
"Principal": {"AWS": "arn:" + partition + ":iam::" + management_account + ":root"},
102-
"Action": ["kms:Decrypt", "kms:Describe*", "kms:Get*", "kms:List*"],
103-
"Resource": "*",
104-
},
105-
{
106-
"Sid": "Allow alias creation during setup",
107-
"Effect": "Allow",
108-
"Principal": {"AWS": "arn:" + partition + ":iam::" + target_account_id + ":root"},
109-
"Action": "kms:CreateAlias",
110-
"Resource": "*",
111-
"Condition": {
112-
"StringEquals": {"kms:ViaService": "cloudformation." + home_region + ".amazonaws.com", "kms:CallerAccount": target_account_id}
113-
},
114-
},
115-
],
116-
}
117-
self.LOGGER.info(f"Key Policy:\n{json.dumps(policy_template)}")
118-
self.SECRETS_KEY_POLICY = json.dumps(policy_template)
119-
return json.dumps(policy_template)
120-
121-
# def assume_role(self, account: str, role_name: str, service: str, region_name: str) -> BaseClient:
122-
# """Get boto3 client assumed into an account for a specified service.
123-
124-
# Args:
125-
# account: aws account id
126-
# service: aws service
127-
# region_name: aws region
128-
129-
# Returns:
130-
# client: boto3 client
131-
# """
132-
# sts_client: STSClient = self.MANAGEMENT_ACCOUNT_SESSION.client("sts")
133-
# sts_response: AssumeRoleResponseTypeDef = sts_client.assume_role(
134-
# RoleArn=f"arn:{self.PARTITION}:iam::{account}:role/{role_name}",
135-
# RoleSessionName="SRA-AssumeCrossAccountRole",
136-
# DurationSeconds=900,
137-
# )
138-
# client: BaseClient = self.MANAGEMENT_ACCOUNT_SESSION.client(
139-
# service, # type: ignore
140-
# region_name=region_name,
141-
# aws_access_key_id=sts_response["Credentials"]["AccessKeyId"],
142-
# aws_secret_access_key=sts_response["Credentials"]["SecretAccessKey"],
143-
# aws_session_token=sts_response["Credentials"]["SessionToken"],
144-
# )
145-
# return client
61+
# def define_key_policy(self, target_account_id: str, partition: str, home_region: str, org_id: str, management_account: str) -> str:
62+
# policy_template = { # noqa ECE001
63+
# "Version": "2012-10-17",
64+
# "Id": "sra-secrets-key",
65+
# "Statement": [
66+
# {
67+
# "Sid": "Enable IAM User Permissions",
68+
# "Effect": "Allow",
69+
# "Principal": {"AWS": "arn:" + partition + ":iam::" + target_account_id + ":root"},
70+
# "Action": "kms:*",
71+
# "Resource": "*",
72+
# },
73+
# {
74+
# "Sid": "Allow access through AWS Secrets Manager for all principals in the account that are authorized to use AWS Secrets Manager",
75+
# "Effect": "Allow",
76+
# "Principal": {"AWS": "*"},
77+
# "Action": ["kms:Decrypt", "kms:Encrypt", "kms:GenerateDataKey*", "kms:ReEncrypt*", "kms:CreateGrant", "kms:DescribeKey"],
78+
# "Resource": "*",
79+
# "Condition": {
80+
# "StringEquals": {"kms:ViaService": "secretsmanager." + home_region + ".amazonaws.com", "aws:PrincipalOrgId": org_id},
81+
# "StringLike": {
82+
# "kms:EncryptionContext:SecretARN": "arn:aws:secretsmanager:" + home_region + ":*:secret:sra/*",
83+
# "aws:PrincipalArn": "arn:" + partition + ":iam::*:role/sra-execution",
84+
# },
85+
# },
86+
# },
87+
# {
88+
# "Sid": "Allow direct access to key metadata",
89+
# "Effect": "Allow",
90+
# "Principal": {"AWS": "arn:" + partition + ":iam::" + management_account + ":root"},
91+
# "Action": ["kms:Decrypt", "kms:Describe*", "kms:Get*", "kms:List*"],
92+
# "Resource": "*",
93+
# },
94+
# {
95+
# "Sid": "Allow alias creation during setup",
96+
# "Effect": "Allow",
97+
# "Principal": {"AWS": "arn:" + partition + ":iam::" + target_account_id + ":root"},
98+
# "Action": "kms:CreateAlias",
99+
# "Resource": "*",
100+
# "Condition": {
101+
# "StringEquals": {"kms:ViaService": "cloudformation." + home_region + ".amazonaws.com", "kms:CallerAccount": target_account_id}
102+
# },
103+
# },
104+
# ],
105+
# }
106+
# self.LOGGER.info(f"Key Policy:\n{json.dumps(policy_template)}")
107+
# self.SECRETS_KEY_POLICY = json.dumps(policy_template)
108+
# return json.dumps(policy_template)
146109

147110
def create_kms_key(self, kms_client: KMSClient, key_policy: str, description: str = "Key description") -> str:
148111
"""Create KMS key

0 commit comments

Comments
 (0)