Skip to content

Commit 97e9968

Browse files
IevIeievgeniia ieromenko
andauthored
Added GuardDuty EKS, Malware, RDS, and Lambda protections (#149)
* added GuardDuty protection plans * linting fixes * more linting fixes --------- Co-authored-by: ievgeniia ieromenko <ieviero@amazon.com>
1 parent 2c84aad commit 97e9968

File tree

15 files changed

+638
-35
lines changed

15 files changed

+638
-35
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Table of Contents<!-- omit in toc -->
44

55
- [Introduction](#introduction)
6+
- [2023-05-30](#2023-05-31)
67
- [2023-05-12](#2023-05-12)
78
- [2023-05-05](#2023-05-05)
89
- [2023-04-10](#2023-04-10)
@@ -37,6 +38,12 @@ All notable changes to this project will be documented in this file.
3738

3839
---
3940

41+
## 2023-06-01
42+
43+
### Changed<!-- omit in toc -->
44+
45+
- Added GuardDuty EKS, Malware, RDS, and Lambda protections [GuardDuty Organization](aws_sra_examples/solutions/guardduty/guardduty_org)
46+
4047
## 2023-05-12
4148

4249
### Changed<!-- omit in toc -->

aws_sra_examples/quick_setup/customizations_for_aws_control_tower/manifest-v2.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,19 @@ resources:
122122
parameter_value: 'No'
123123
- parameter_key: pAutoEnableS3Logs
124124
parameter_value: 'true'
125+
- parameter_key: pAutoEnableKubernetesAuditLogs
126+
parameter_value: 'true'
127+
- parameter_key: pAutoEnableMalwareProtection
128+
parameter_value: 'true'
129+
- parameter_key: pEnableRdsLoginEvents
130+
parameter_value: 'true'
131+
- parameter_key: pEnableEksRuntimeMonitoring
132+
parameter_value: 'true'
133+
- parameter_key: pEnableEksAddonManagement
134+
parameter_value: 'true'
135+
- parameter_key: pEnableLambdaNetworkLogs
136+
parameter_value: 'true'
137+
- parameter_key: pControlTowerRegionsOnly
125138
- parameter_key: pGuardDutyFindingPublishingFrequency
126139
parameter_value: 'FIFTEEN_MINUTES'
127140
- parameter_key: pGuardDutyOrgDeliveryBucketPrefix

aws_sra_examples/solutions/guardduty/guardduty_org/README.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ future AWS Organization accounts. GuardDuty is also configured to send the findi
6161
- GuardDuty is enabled for each existing active account and region during the initial setup
6262
- GuardDuty will automatically enable new member accounts/regions when added to the AWS Organization
6363

64+
#### 1.9 Lambda Layer<!-- omit in toc -->
65+
66+
- The python boto3 SDK lambda layer to enable capability for Lambda to enable protection features of the GuardDuty service.
67+
- This is downloaded during the deployment process and packaged into a layer that is used by the Lambda function in this solution.
68+
- The GuardDuty API available in the current Lambda environment (as of 05/24/2023) is boto3-1.20.32, however, enhanced functionality of the GuardDuty API used in this solution requires at least 1.26.117 (see references below).
69+
- Note: Future revisions to this solution will remove this layer when boto3 is updated within the Lambda environment.
70+
6471
---
6572

6673
### 2.0 Log Archive Account<!-- omit in toc -->
@@ -75,7 +82,7 @@ future AWS Organization accounts. GuardDuty is also configured to send the findi
7582

7683
#### 2.3 GuardDuty<!-- omit in toc -->
7784

78-
- See [1.5 GuardDuty](#15-guardduty)
85+
- See [1.8 GuardDuty](#18-guardduty)
7986

8087
---
8188

@@ -98,15 +105,15 @@ populated from the `SecurityAccountId` parameter within the `AWSControlTowerBP-B
98105

99106
#### 3.4 GuardDuty<!-- omit in toc -->
100107

101-
- See [1.5 GuardDuty](#15-guardduty)
108+
- See [1.8 GuardDuty](#18-guardduty)
102109

103110
---
104111

105112
### 4.0 All Existing and Future Organization Member Accounts<!-- omit in toc -->
106113

107114
#### 4.1 GuardDuty<!-- omit in toc -->
108115

109-
- See [1.5 GuardDuty](#15-guardduty)
116+
- See [1.8 GuardDuty](#18-guardduty)
110117

111118
#### 4.2 Delete Detector Role<!-- omit in toc -->
112119

@@ -159,12 +166,16 @@ In the `management account (home region)`, launch an AWS CloudFormation **Stack*
159166

160167
#### Solution Delete Instructions<!-- omit in toc -->
161168

162-
1. In the `management account (home region)`, delete the AWS CloudFormation **Stack** (`sra-guardduty-org-main-ssm` or `sra-guardduty-org-main`) created above.
163-
2. In the `management account (home region)`, delete the AWS CloudWatch **Log Group** (e.g. /aws/lambda/<solution_name>) for the Lambda function deployed.
164-
3. In the `log archive acccount (home region)`, delete the S3 bucket (e.g. sra-guardduty-delivery-<account_id>-<aws_region>) created by the solution.
169+
1. In the `management account (home region)`, change the `Disable GuardDuty` parameter to `true` and update the AWS CloudFormation **Stack** (`sra-guardduty-org-main-ssm` or `sra-guardduty-org-main`). This will disable the solutions within each of the member accounts/regions.
170+
2. In the `management account (home region)`, delete the AWS CloudFormation **Stack** (`sra-guardduty-org-main-ssm` or `sra-guardduty-org-main`).
171+
3. In the `management account (home region)`, delete the AWS CloudWatch **Log Group** (e.g. /aws/lambda/<solution_name>) for the Lambda function deployed.
172+
4. In the `log archive acccount (home region)`, delete the S3 bucket (e.g. sra-guardduty-delivery-<account_id>-<aws_region>) created by the solution.
165173

166174
---
167175

168176
## References
169177

170178
- [Managing GuardDuty Accounts with AWS Organizations](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_organizations.html)
179+
- [Managing AWS SDKs in Lambda Functions](https://docs.aws.amazon.com/lambda/latest/operatorguide/sdks-functions.html)
180+
- [Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html)
181+
- [Python Boto3 SDK changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)

aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/manifest-v2.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@ resources:
1313
parameters:
1414
- parameter_key: pAutoEnableS3Logs
1515
parameter_value: 'true'
16+
- parameter_key: pAutoEnableKubernetesAuditLogs
17+
parameter_value: 'true'
18+
- parameter_key: pAutoEnableMalwareProtection
19+
parameter_value: 'true'
20+
- parameter_key: pEnableRdsLoginEvents
21+
parameter_value: 'true'
22+
- parameter_key: pEnableEksRuntimeMonitoring
23+
parameter_value: 'true'
24+
- parameter_key: pEnableEksAddonManagement
25+
parameter_value: 'true'
26+
- parameter_key: pEnableLambdaNetworkLogs
27+
parameter_value: 'true'
1628
- parameter_key: pControlTowerRegionsOnly
1729
parameter_value: 'true'
1830
- parameter_key: pCreateLambdaLogGroup
@@ -47,6 +59,18 @@ resources:
4759
# parameter_value: ''
4860
# - parameter_key: pAutoEnableS3Logs
4961
# parameter_value: 'true'
62+
# - parameter_key: pAutoEnableKubernetesAuditLogs
63+
# parameter_value: 'true'
64+
# - parameter_key: pAutoEnableMalwareProtection
65+
# parameter_value: 'true'
66+
# - parameter_key: pEnableRdsLoginEvents
67+
# parameter_value: 'true'
68+
# - parameter_key: pEnableEksRuntimeMonitoring
69+
# parameter_value: 'true'
70+
# - parameter_key: pEnableEksAddonManagement
71+
# parameter_value: 'true'
72+
# - parameter_key: pEnableLambdaNetworkLogs
73+
# parameter_value: 'true'
5074
# - parameter_key: pControlTowerRegionsOnly
5175
# parameter_value: 'true'
5276
# - parameter_key: pCreateLambdaLogGroup

aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-main-ssm.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,30 @@
33
"ParameterKey": "pAutoEnableS3Logs",
44
"ParameterValue": "true"
55
},
6+
{
7+
"ParameterKey": "pAutoEnableKubernetesAuditLogs",
8+
"ParameterValue": "true"
9+
},
10+
{
11+
"ParameterKey": "pAutoEnableMalwareProtection",
12+
"ParameterValue": "true"
13+
},
14+
{
15+
"ParameterKey": "pEnableRdsLoginEvents",
16+
"ParameterValue": "true"
17+
},
18+
{
19+
"ParameterKey": "pEnableEksRuntimeMonitoring",
20+
"ParameterValue": "true"
21+
},
22+
{
23+
"ParameterKey": "pEnableEksAddonManagement",
24+
"ParameterValue": "true"
25+
},
26+
{
27+
"ParameterKey": "pEnableLambdaNetworkLogs",
28+
"ParameterValue": "true"
29+
},
630
{
731
"ParameterKey": "pControlTowerRegionsOnly",
832
"ParameterValue": "true"

aws_sra_examples/solutions/guardduty/guardduty_org/customizations_for_aws_control_tower/parameters/sra-guardduty-org-main.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,30 @@
77
"ParameterKey": "pAutoEnableS3Logs",
88
"ParameterValue": "true"
99
},
10+
{
11+
"ParameterKey": "pAutoEnableKubernetesAuditLogs",
12+
"ParameterValue": "true"
13+
},
14+
{
15+
"ParameterKey": "pAutoEnableMalwareProtection",
16+
"ParameterValue": "true"
17+
},
18+
{
19+
"ParameterKey": "pEnableRdsLoginEvents",
20+
"ParameterValue": "true"
21+
},
22+
{
23+
"ParameterKey": "pEnableEksRuntimeMonitoring",
24+
"ParameterValue": "true"
25+
},
26+
{
27+
"ParameterKey": "pEnableEksAddonManagement",
28+
"ParameterValue": "true"
29+
},
30+
{
31+
"ParameterKey": "pEnableLambdaNetworkLogs",
32+
"ParameterValue": "true"
33+
},
1034
{
1135
"ParameterKey": "pControlTowerRegionsOnly",
1236
"ParameterValue": "true"
Loading

aws_sra_examples/solutions/guardduty/guardduty_org/lambda/src/app.py

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
if TYPE_CHECKING:
3131
from aws_lambda_typing.context import Context
3232
from aws_lambda_typing.events import CloudFormationCustomResourceEvent
33+
from mypy_boto3_organizations import OrganizationsClient
3334

3435
# Setup Default Logger
3536
LOGGER = logging.getLogger("sra")
@@ -40,13 +41,15 @@
4041
helper = CfnResource(json_logging=True, log_level=log_level, boto_level="CRITICAL", sleep_on_delete=120)
4142

4243
# Global variables
44+
PRINCIPAL_NAME = "malware-protection.guardduty.amazonaws.com"
4345
UNEXPECTED = "Unexpected!"
4446
MAX_RUN_COUNT = 30 # 5 minute wait = 30 x 10 seconds
4547
SLEEP_SECONDS = 10
4648
BOTO3_CONFIG = Config(retries={"max_attempts": 10, "mode": "standard"})
4749

4850
try:
4951
MANAGEMENT_ACCOUNT_SESSION = boto3.Session()
52+
ORG_CLIENT: OrganizationsClient = MANAGEMENT_ACCOUNT_SESSION.client("organizations")
5053
except Exception:
5154
LOGGER.exception(UNEXPECTED)
5255
raise ValueError("Unexpected error executing Lambda function. Review CloudWatch logs for details.") from None
@@ -83,6 +86,12 @@ def get_validated_parameters(event: CloudFormationCustomResourceEvent) -> dict:
8386
true_false_pattern = r"(?i)^true|false$"
8487

8588
parameter_pattern_validator("AUTO_ENABLE_S3_LOGS", params.get("AUTO_ENABLE_S3_LOGS", ""), pattern=true_false_pattern)
89+
parameter_pattern_validator("ENABLE_EKS_AUDIT_LOGS", params.get("ENABLE_EKS_AUDIT_LOGS", ""), pattern=true_false_pattern)
90+
parameter_pattern_validator("AUTO_ENABLE_MALWARE_PROTECTION", params.get("AUTO_ENABLE_MALWARE_PROTECTION", ""), pattern=true_false_pattern)
91+
parameter_pattern_validator("ENABLE_RDS_LOGIN_EVENTS", params.get("ENABLE_RDS_LOGIN_EVENTS", ""), pattern=true_false_pattern)
92+
parameter_pattern_validator("ENABLE_EKS_RUNTIME_MONITORING", params.get("ENABLE_EKS_RUNTIME_MONITORING", ""), pattern=true_false_pattern)
93+
parameter_pattern_validator("ENABLE_EKS_ADDON_MANAGEMENT", params.get("ENABLE_EKS_ADDON_MANAGEMENT", ""), pattern=true_false_pattern)
94+
parameter_pattern_validator("ENABLE_LAMBDA_NETWORK_LOGS", params.get("ENABLE_LAMBDA_NETWORK_LOGS", ""), pattern=true_false_pattern)
8695
parameter_pattern_validator("CONFIGURATION_ROLE_NAME", params.get("CONFIGURATION_ROLE_NAME", ""), pattern=r"^[\w+=,.@-]{1,64}$")
8796
parameter_pattern_validator("CONTROL_TOWER_REGIONS_ONLY", params.get("CONTROL_TOWER_REGIONS_ONLY", ""), pattern=true_false_pattern)
8897
parameter_pattern_validator("DELEGATED_ADMIN_ACCOUNT_ID", params.get("DELEGATED_ADMIN_ACCOUNT_ID", ""), pattern=r"^\d{12}$")
@@ -111,6 +120,50 @@ def get_validated_parameters(event: CloudFormationCustomResourceEvent) -> dict:
111120
return params
112121

113122

123+
def check_aws_service_access(service_principal: str = PRINCIPAL_NAME) -> bool:
124+
"""Check service access for the provided service principal within AWS Organizations.
125+
126+
Args:
127+
service_principal: Service Principal. Defaults to SERVICE_NAME.
128+
129+
Returns:
130+
bool: service access enabled true/false
131+
"""
132+
aws_service_access_enabled = False
133+
LOGGER.info(f"Checking service access for {service_principal}...")
134+
try:
135+
org_svc_response = ORG_CLIENT.list_aws_service_access_for_organization()
136+
api_call_details = {
137+
"API_Call": "organizations:ListAwsServiceAccessForOrganization",
138+
"API_Response": org_svc_response,
139+
}
140+
LOGGER.info(api_call_details)
141+
142+
for service in org_svc_response["EnabledServicePrincipals"]:
143+
if service["ServicePrincipal"] == service_principal:
144+
aws_service_access_enabled = True
145+
return True
146+
except ORG_CLIENT.exceptions.AccessDeniedException as error:
147+
LOGGER.info(f"Unable to check service access for {service_principal}: {error}")
148+
return aws_service_access_enabled
149+
150+
151+
def enable_aws_service_access(service_principal: str = PRINCIPAL_NAME) -> None:
152+
"""Enable service access for the provided service principal within AWS Organizations.
153+
154+
Args:
155+
service_principal: Service Principal
156+
"""
157+
if check_aws_service_access(service_principal) is False:
158+
try:
159+
LOGGER.info(f"Enabling service access for {service_principal} in Management Account")
160+
ORG_CLIENT.enable_aws_service_access(ServicePrincipal=service_principal)
161+
except ORG_CLIENT.exceptions.AccessDeniedException as error:
162+
LOGGER.info(f"Failed to enable service access for {service_principal} in organizations: {error}")
163+
else:
164+
LOGGER.info(f"Organizations service access for {service_principal} is already enabled")
165+
166+
114167
def process_create_update_event(params: dict, regions: list) -> None:
115168
"""Process create update events.
116169
@@ -125,11 +178,17 @@ def process_create_update_event(params: dict, regions: list) -> None:
125178
account_ids = common.get_account_ids([], params["DELEGATED_ADMIN_ACCOUNT_ID"])
126179
guardduty.process_delete_event(params, regions, account_ids, True)
127180
else:
181+
enable_aws_service_access(PRINCIPAL_NAME)
128182
common.create_service_linked_role(
129183
"AWSServiceRoleForAmazonGuardDuty",
130184
"guardduty.amazonaws.com",
131185
"A service-linked role required for Amazon GuardDuty to access your resources.",
132186
)
187+
common.create_service_linked_role(
188+
"AWSServiceRoleForAmazonGuardDutyMalwareProtection",
189+
"malware-protection.guardduty.amazonaws.com",
190+
"A service-linked role required for Amazon GuardDuty to access your resources.",
191+
)
133192
guardduty.process_organization_admin_account(params.get("DELEGATED_ADMIN_ACCOUNT_ID", ""), regions)
134193
sleep(60)
135194
session = common.assume_role(params.get("CONFIGURATION_ROLE_NAME", ""), "CreateGuardDuty", params.get("DELEGATED_ADMIN_ACCOUNT_ID", ""))
@@ -147,11 +206,23 @@ def process_create_update_event(params: dict, regions: list) -> None:
147206
raise ValueError("GuardDuty Detectors did not get created in the allowed time. Check the Org Management delegated admin setup.")
148207
else:
149208
auto_enable_s3_logs = (params.get("AUTO_ENABLE_S3_LOGS", "false")).lower() in "true"
209+
enable_eks_audit_logs = (params.get("ENABLE_EKS_AUDIT_LOGS", "false")).lower() in "true"
210+
auto_enable_malware_protection = (params.get("AUTO_ENABLE_MALWARE_PROTECTION", "false")).lower() in "true"
211+
enable_rds_login_events = (params.get("ENABLE_RDS_LOGIN_EVENTS", "false")).lower() in "true"
212+
enable_eks_runtime_monitoring = (params.get("ENABLE_EKS_RUNTIME_MONITORING", "false")).lower() in "true"
213+
enable_eks_addon_management = (params.get("ENABLE_EKS_ADDON_MANAGEMENT", "false")).lower() in "true"
214+
enable_lambda_network_logs = (params.get("ENABLE_LAMBDA_NETWORK_LOGS", "false")).lower() in "true"
150215

151216
guardduty.configure_guardduty(
152217
session,
153218
params["DELEGATED_ADMIN_ACCOUNT_ID"],
154219
auto_enable_s3_logs,
220+
enable_eks_audit_logs,
221+
auto_enable_malware_protection,
222+
enable_rds_login_events,
223+
enable_eks_runtime_monitoring,
224+
enable_eks_addon_management,
225+
enable_lambda_network_logs,
155226
regions,
156227
params.get("FINDING_PUBLISHING_FREQUENCY", "FIFTEEN_MINUTES"),
157228
params["KMS_KEY_ARN"],
@@ -194,11 +265,12 @@ def process_cloudformation_event(event: CloudFormationCustomResourceEvent, conte
194265

195266
if params["action"] in "Add, Update":
196267
process_create_update_event(params, regions)
197-
elif params["action"] == "Remove":
268+
else:
269+
LOGGER.info("...Disable GuardDuty from (process_cloudformation_event)")
198270
account_ids = common.get_account_ids([], params["DELEGATED_ADMIN_ACCOUNT_ID"])
199271
guardduty.process_delete_event(params, regions, account_ids, False)
200272

201-
return f"sra-guardduty-{params['DELEGATED_ADMIN_ACCOUNT_ID']}-{(params.get('AUTO_ENABLE_S3_LOGS', 'false')).lower() in 'true'}"
273+
return f"sra-guardduty-{params['DELEGATED_ADMIN_ACCOUNT_ID']}"
202274

203275

204276
def lambda_handler(event: Dict[str, Any], context: Context) -> None:

0 commit comments

Comments
 (0)