diff --git a/prowler/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible.py b/prowler/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible.py index 20c6526b92..bbaad4c92b 100644 --- a/prowler/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible.py +++ b/prowler/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible.py @@ -13,6 +13,7 @@ class awslambda_function_not_publicly_accessible(Check): report.resource_tags = function.tags report.status = "PASS" +<<<<<<< HEAD report.status_extended = f"Lambda function {function.name} has a policy resource-based policy not public." public_access = False @@ -45,8 +46,16 @@ class awslambda_function_not_publicly_accessible(Check): break if public_access: +======= + report.status_extended = f"Lambda function {function.name} has a resource-based policy without public access." + if is_policy_public( + function.policy, + awslambda_client.audited_account, + is_cross_account_allowed=True, + ): +>>>>>>> 3f03dd20e (fix(aws) wording of report.status_extended in awslambda_function_not_publicly_accessible (#6824)) report.status = "FAIL" - report.status_extended = f"Lambda function {function.name} has a policy resource-based policy with public access." + report.status_extended = f"Lambda function {function.name} has a resource-based policy with public access." findings.append(report) diff --git a/tests/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible_test.py b/tests/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible_test.py index 8816120bed..0bb3ac5aba 100644 --- a/tests/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible_test.py +++ b/tests/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible_test.py @@ -88,10 +88,91 @@ class Test_awslambda_function_not_publicly_accessible: assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"Lambda function {function_name} has a policy resource-based policy with public access." + == f"Lambda function {function_name} has a resource-based policy with public access." ) assert result[0].resource_tags == [] +<<<<<<< HEAD +======= + @mock_aws + def test_function_public_with_source_account(self): + # Create the mock IAM role + iam_client = client("iam", region_name=AWS_REGION_EU_WEST_1) + role_name = "test-role" + assume_role_policy_document = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "lambda.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + role_arn = iam_client.create_role( + RoleName=role_name, + AssumeRolePolicyDocument=dumps(assume_role_policy_document), + )["Role"]["Arn"] + + function_name = "test-lambda" + + # Create the lambda function using boto3 client + lambda_client = client("lambda", region_name=AWS_REGION_EU_WEST_1) + function_arn = lambda_client.create_function( + FunctionName=function_name, + Runtime="nodejs4.3", + Role=role_arn, + Handler="index.handler", + Code={"ZipFile": b"fileb://file-path/to/your-deployment-package.zip"}, + Description="Test Lambda function", + Timeout=3, + MemorySize=128, + Publish=True, + Tags={"tag1": "value1", "tag2": "value2"}, + )["FunctionArn"] + + # Attach the policy to the lambda function with a wildcard principal + lambda_client.add_permission( + FunctionName=function_name, + StatementId="non-public-access", + Action="lambda:InvokeFunction", + Principal="*", + SourceArn=function_arn, + SourceAccount=AWS_ACCOUNT_NUMBER, + ) + + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + + from prowler.providers.aws.services.awslambda.awslambda_service import Lambda + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), mock.patch( + "prowler.providers.aws.services.awslambda.awslambda_function_not_publicly_accessible.awslambda_function_not_publicly_accessible.awslambda_client", + new=Lambda(aws_provider), + ): + # Test Check + from prowler.providers.aws.services.awslambda.awslambda_function_not_publicly_accessible.awslambda_function_not_publicly_accessible import ( + awslambda_function_not_publicly_accessible, + ) + + check = awslambda_function_not_publicly_accessible() + result = check.execute() + + assert len(result) == 1 + assert result[0].region == AWS_REGION_EU_WEST_1 + assert result[0].resource_id == function_name + assert result[0].resource_arn == function_arn + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Lambda function {function_name} has a resource-based policy without public access." + ) + assert result[0].resource_tags == [{"tag1": "value1", "tag2": "value2"}] + + @mock_aws +>>>>>>> 3f03dd20e (fix(aws) wording of report.status_extended in awslambda_function_not_publicly_accessible (#6824)) def test_function_not_public(self): lambda_client = mock.MagicMock function_name = "test-lambda" @@ -145,7 +226,7 @@ class Test_awslambda_function_not_publicly_accessible: assert result[0].status == "PASS" assert ( result[0].status_extended - == f"Lambda function {function_name} has a policy resource-based policy not public." + == f"Lambda function {function_name} has a resource-based policy without public access." ) assert result[0].resource_tags == [] @@ -202,7 +283,7 @@ class Test_awslambda_function_not_publicly_accessible: assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"Lambda function {function_name} has a policy resource-based policy with public access." + == f"Lambda function {function_name} has a resource-based policy with public access." ) assert result[0].resource_tags == [] @@ -375,7 +456,7 @@ class Test_awslambda_function_not_publicly_accessible: assert result[0].status == "FAIL" assert ( result[0].status_extended - == "Lambda function test-public-lambda has a policy resource-based policy with public access." + == "Lambda function test-public-lambda has a resource-based policy with public access." ) assert result[0].resource_tags == [{"tag1": "value1", "tag2": "value2"}] @@ -425,6 +506,7 @@ class Test_awslambda_function_not_publicly_accessible: # check = awslambda_function_not_publicly_accessible() # result = check.execute() +<<<<<<< HEAD # assert len(result) == 1 # assert result[0].region == AWS_REGION_EU_WEST_1 # assert result[0].resource_id == function_name @@ -435,3 +517,146 @@ class Test_awslambda_function_not_publicly_accessible: # == f"Lambda function {function_name} has a policy resource-based policy with public access." # ) # assert result[0].resource_tags == [] +======= + assert len(result) == 1 + assert result[0].region == AWS_REGION_EU_WEST_1 + assert result[0].resource_id == function_name + assert result[0].resource_arn == function_arn + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Lambda function {function_name} has a resource-based policy without public access." + ) + assert result[0].resource_tags == [] + + def test_function_could_be_invoked_by_specific_other_aws_account(self): + lambda_client = mock.MagicMock + lambda_client.audited_account = AWS_ACCOUNT_NUMBER + lambda_client.audit_config = {} + function_name = "test-lambda" + function_runtime = "nodejs4.3" + function_arn = f"arn:aws:lambda:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:function/{function_name}" + lambda_policy = { + "Version": "2012-10-17", + "Id": "default", + "Statement": [ + { + "Sid": "awslambda-myLambdaScript-LambdaInvokePermission", + "Effect": "Allow", + "Principal": {"Service": "ses.amazonaws.com"}, + "Action": "lambda:InvokeFunction", + "Resource": f"arn:aws:lambda:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:function:{function_name}", + "Condition": { + "StringEquals": {"AWS:SourceAccount": "000000000000"} + }, + } + ], + } + + lambda_client.functions = { + "function_name": Function( + name=function_name, + security_groups=[], + arn=function_arn, + region=AWS_REGION_EU_WEST_1, + runtime=function_runtime, + policy=lambda_policy, + ) + } + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider(), + ), mock.patch( + "prowler.providers.aws.services.awslambda.awslambda_function_not_publicly_accessible.awslambda_function_not_publicly_accessible.awslambda_client", + new=lambda_client, + ): + from prowler.providers.aws.services.awslambda.awslambda_function_not_publicly_accessible.awslambda_function_not_publicly_accessible import ( + awslambda_function_not_publicly_accessible, + ) + + check = awslambda_function_not_publicly_accessible() + result = check.execute() + + assert len(result) == 1 + assert result[0].region == AWS_REGION_EU_WEST_1 + assert result[0].resource_id == function_name + assert result[0].resource_arn == function_arn + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Lambda function {function_name} has a resource-based policy without public access." + ) + assert result[0].resource_tags == [] + + def test_function_public_policy_with_several_statements(self): + lambda_client = mock.MagicMock + lambda_client.audited_account = AWS_ACCOUNT_NUMBER + lambda_client.audit_config = {} + function_name = "test-lambda" + function_runtime = "nodejs4.3" + function_arn = f"arn:aws:lambda:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:function/{function_name}" + lambda_policy = { + "Version": "2012-10-17", + "Id": "default", + "Statement": [ + { + "Sid": "AllowExecutionFromAPIGateway", + "Effect": "Allow", + "Principal": {"Service": "apigateway.amazonaws.com"}, + "Action": "lambda:InvokeFunction", + "Resource": f"arn:aws:lambda:eu-central-1:{AWS_ACCOUNT_NUMBER}:function:foo", + "Condition": { + "ArnLike": { + "AWS:SourceArn": f"arn:aws:execute-api:eu-central-1:{AWS_ACCOUNT_NUMBER}:bar/*/GET/proxy+" + } + }, + }, + { + "Sid": "FunctionURLAllowPublicAccess", + "Effect": "Allow", + "Principal": "*", + "Action": "lambda:InvokeFunctionUrl", + "Resource": f"arn:aws:lambda:eu-central-1:{AWS_ACCOUNT_NUMBER}:function:foo", + "Condition": { + "StringEquals": {"lambda:FunctionUrlAuthType": "NONE"} + }, + }, + ], + } + + lambda_client.functions = { + "function_name": Function( + name=function_name, + security_groups=[], + arn=function_arn, + region=AWS_REGION_EU_WEST_1, + runtime=function_runtime, + policy=lambda_policy, + ) + } + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider(), + ), mock.patch( + "prowler.providers.aws.services.awslambda.awslambda_function_not_publicly_accessible.awslambda_function_not_publicly_accessible.awslambda_client", + new=lambda_client, + ): + from prowler.providers.aws.services.awslambda.awslambda_function_not_publicly_accessible.awslambda_function_not_publicly_accessible import ( + awslambda_function_not_publicly_accessible, + ) + + check = awslambda_function_not_publicly_accessible() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Lambda function {function_name} has a resource-based policy with public access." + ) + assert result[0].resource_id == function_name + assert result[0].resource_arn == function_arn + assert result[0].region == AWS_REGION_EU_WEST_1 +>>>>>>> 3f03dd20e (fix(aws) wording of report.status_extended in awslambda_function_not_publicly_accessible (#6824))