From ddb3336bf9d073f47bfcb7c8248866de02e38163 Mon Sep 17 00:00:00 2001 From: Givanildo Alves Date: Thu, 26 Dec 2024 11:38:27 -0300 Subject: [PATCH] Narrow down CloudWatch permissions on Lambda functions --- .../back-end/stack/sfn/__init__.py | 4 +- .../stack_constructs/lambda_constructs.py | 53 +++++++------------ 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/samples/contract-compliance-analysis/back-end/stack/sfn/__init__.py b/samples/contract-compliance-analysis/back-end/stack/sfn/__init__.py index 0299c189..d072dc90 100644 --- a/samples/contract-compliance-analysis/back-end/stack/sfn/__init__.py +++ b/samples/contract-compliance-analysis/back-end/stack/sfn/__init__.py @@ -154,12 +154,14 @@ def __init__( tracing_enabled=True, ) + # Not all X-Ray actions support resource-level permissions + # Reference: https://docs.aws.amazon.com/xray/latest/devguide/security_iam_service-with-iam.html NagSuppressions.add_resource_suppressions( construct=self.state_machine.role, suppressions=[ NagPackSuppression( id="AwsSolutions-IAM5", - reason="Wildcard used because to support multiple function versions", + reason="Not all X-Ray / CloudWatch actions support resource-level permissions", ), ], apply_to_children=True, diff --git a/samples/contract-compliance-analysis/back-end/stack_constructs/lambda_constructs.py b/samples/contract-compliance-analysis/back-end/stack_constructs/lambda_constructs.py index a07c67c4..715eb808 100644 --- a/samples/contract-compliance-analysis/back-end/stack_constructs/lambda_constructs.py +++ b/samples/contract-compliance-analysis/back-end/stack_constructs/lambda_constructs.py @@ -15,6 +15,7 @@ aws_lambda_python_alpha as lambda_python, aws_lambda as lambda_, aws_iam as iam, + Stack ) from constructs import Construct from cdk_nag import NagSuppressions, NagPackSuppression @@ -39,8 +40,11 @@ def __init__( role=role, **kwargs, ) - role.attach_inline_policy(_lambda_basic_policy(scope, construct_id)) - role.attach_inline_policy(_lambda_vpc_policy(scope, construct_id)) + + # Get the actual function name after initialization + function_name = self.function_name + + role.attach_inline_policy(_lambda_basic_policy(scope, construct_id, function_name)) class DockerImageFunctionConstruct(lambda_.DockerImageFunction): @@ -62,14 +66,21 @@ def __init__( role=role, **kwargs, ) - role.attach_inline_policy(_lambda_basic_policy(scope, construct_id)) - role.attach_inline_policy(_lambda_vpc_policy(scope, construct_id)) + + # Get the actual function name after initialization + function_name = self.function_name + + role.attach_inline_policy(_lambda_basic_policy(scope, construct_id, function_name)) def _lambda_basic_policy( scope: Construct, construct_id: str, + function_name: str ): + region = Stack.of(scope).region + account = Stack.of(scope).account + policy = iam.Policy( scope, f"{construct_id}LambdaBasicExecPolicy", @@ -81,40 +92,16 @@ def _lambda_basic_policy( "logs:CreateLogStream", "logs:PutLogEvents", ], - resources=["*"], - ), - ], - ) - NagSuppressions.add_resource_suppressions( - construct=policy, - suppressions=[NagPackSuppression(id="AwsSolutions-IAM5", reason="AWSLambdaBasicExecutionRole")], - ) - return policy - - -def _lambda_vpc_policy( - scope: Construct, - construct_id: str, -): - policy = iam.Policy( - scope, - f"{construct_id}LambdaVPCExecPolicy", - statements=[ - iam.PolicyStatement( - effect=iam.Effect.ALLOW, - actions=[ - "ec2:CreateNetworkInterface", - "ec2:DescribeNetworkInterfaces", - "ec2:DeleteNetworkInterface", - "ec2:AssignPrivateIpAddresses", - "ec2:UnassignPrivateIpAddresses", + resources=[ + f"arn:aws:logs:{region}:{account}:log-group:/aws/lambda/{function_name}", + f"arn:aws:logs:{region}:{account}:log-group:/aws/lambda/{function_name}:*" ], - resources=["*"], ), ], ) NagSuppressions.add_resource_suppressions( construct=policy, - suppressions=[NagPackSuppression(id="AwsSolutions-IAM5", reason="AWSLambdaVPCAccessExecutionRole")], + suppressions=[NagPackSuppression(id="AwsSolutions-IAM5", reason="CloudWatch log groups")], ) return policy +