mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 14:55:00 +00:00
fix(security group): check if security groups are used by Lambda (#2944)
This commit is contained in:
@@ -50,6 +50,9 @@ class Lambda(AWSService):
|
||||
self.functions[lambda_arn] = Function(
|
||||
name=lambda_name,
|
||||
arn=lambda_arn,
|
||||
security_groups=function.get("VpcConfig", {}).get(
|
||||
"SecurityGroupIds", []
|
||||
),
|
||||
region=regional_client.region,
|
||||
)
|
||||
if "Runtime" in function:
|
||||
@@ -183,6 +186,7 @@ class URLConfig(BaseModel):
|
||||
class Function(BaseModel):
|
||||
name: str
|
||||
arn: str
|
||||
security_groups: list
|
||||
runtime: Optional[str]
|
||||
environment: dict = None
|
||||
region: str
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.awslambda.awslambda_client import awslambda_client
|
||||
from prowler.providers.aws.services.ec2.ec2_client import ec2_client
|
||||
|
||||
|
||||
@@ -16,7 +17,11 @@ class ec2_securitygroup_not_used(Check):
|
||||
report.resource_tags = security_group.tags
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Security group {security_group.name} ({security_group.id}) it is being used."
|
||||
if len(security_group.network_interfaces) == 0:
|
||||
sg_in_lambda = False
|
||||
for function in awslambda_client.functions.values():
|
||||
if security_group.id in function.security_groups:
|
||||
sg_in_lambda = True
|
||||
if len(security_group.network_interfaces) == 0 and not sg_in_lambda:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Security group {security_group.name} ({security_group.id}) it is not being used."
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ class Test_awslambda_function_invoke_api_operations_cloudtrail_logging_enabled:
|
||||
lambda_client.functions = {
|
||||
function_name: Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -164,6 +165,7 @@ class Test_awslambda_function_invoke_api_operations_cloudtrail_logging_enabled:
|
||||
lambda_client.functions = {
|
||||
function_name: Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -240,6 +242,7 @@ class Test_awslambda_function_invoke_api_operations_cloudtrail_logging_enabled:
|
||||
lambda_client.functions = {
|
||||
function_name: Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -317,6 +320,7 @@ class Test_awslambda_function_invoke_api_operations_cloudtrail_logging_enabled:
|
||||
lambda_client.functions = {
|
||||
function_name: Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
|
||||
@@ -47,6 +47,7 @@ class Test_awslambda_function_no_secrets_in_code:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -95,6 +96,7 @@ class Test_awslambda_function_no_secrets_in_code:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
|
||||
@@ -37,6 +37,7 @@ class Test_awslambda_function_no_secrets_in_variables:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -77,6 +78,7 @@ class Test_awslambda_function_no_secrets_in_variables:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -118,6 +120,7 @@ class Test_awslambda_function_no_secrets_in_variables:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
|
||||
@@ -51,6 +51,7 @@ class Test_awslambda_function_not_publicly_accessible:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -106,6 +107,7 @@ class Test_awslambda_function_not_publicly_accessible:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -161,6 +163,7 @@ class Test_awslambda_function_not_publicly_accessible:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
|
||||
@@ -41,6 +41,7 @@ class Test_awslambda_function_url_cors_policy:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -85,6 +86,7 @@ class Test_awslambda_function_url_cors_policy:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -129,6 +131,7 @@ class Test_awslambda_function_url_cors_policy:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
|
||||
@@ -41,6 +41,7 @@ class Test_awslambda_function_url_public:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -85,6 +86,7 @@ class Test_awslambda_function_url_public:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
|
||||
@@ -36,6 +36,7 @@ class Test_awslambda_function_using_supported_runtimes:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -93,6 +94,7 @@ class Test_awslambda_function_using_supported_runtimes:
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
runtime=function_runtime,
|
||||
@@ -148,7 +150,10 @@ class Test_awslambda_function_using_supported_runtimes:
|
||||
)
|
||||
lambda_client.functions = {
|
||||
"function_name": Function(
|
||||
name=function_name, arn=function_arn, region=AWS_REGION
|
||||
name=function_name,
|
||||
security_groups=[],
|
||||
arn=function_arn,
|
||||
region=AWS_REGION,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ from re import search
|
||||
from unittest import mock
|
||||
|
||||
from boto3 import client, resource, session
|
||||
from moto import mock_ec2
|
||||
from moto import mock_ec2, mock_iam, mock_lambda
|
||||
|
||||
from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info
|
||||
from prowler.providers.common.models import Audit_Metadata
|
||||
@@ -169,3 +169,81 @@ class Test_ec2_securitygroup_not_used:
|
||||
assert result[0].resource_id == sg.id
|
||||
assert result[0].resource_details == sg_name
|
||||
assert result[0].resource_tags == []
|
||||
|
||||
@mock_ec2
|
||||
@mock_lambda
|
||||
@mock_iam
|
||||
def test_ec2_used_default_sg_by_lambda(self):
|
||||
# Create EC2 Mocked Resources
|
||||
ec2 = resource("ec2", AWS_REGION)
|
||||
ec2_client = client("ec2", region_name=AWS_REGION)
|
||||
vpc_id = ec2_client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"]
|
||||
sg_name = "test-sg"
|
||||
sg = ec2.create_security_group(
|
||||
GroupName=sg_name, Description="test", VpcId=vpc_id
|
||||
)
|
||||
subnet = ec2.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/18")
|
||||
subnet.create_network_interface(Groups=[sg.id])
|
||||
iam_client = client("iam", region_name=AWS_REGION)
|
||||
iam_role = iam_client.create_role(
|
||||
RoleName="my-role",
|
||||
AssumeRolePolicyDocument="some policy",
|
||||
Path="/my-path/",
|
||||
)["Role"]["Arn"]
|
||||
lambda_client = client("lambda", AWS_REGION)
|
||||
lambda_client.create_function(
|
||||
FunctionName="test-function",
|
||||
Runtime="python3.11",
|
||||
Role=iam_role,
|
||||
Handler="lambda_function.lambda_handler",
|
||||
Code={
|
||||
"ImageUri": f"{AWS_ACCOUNT_NUMBER}.dkr.ecr.us-east-1.amazonaws.com/testlambdaecr:prod"
|
||||
},
|
||||
Description="test lambda function",
|
||||
Timeout=3,
|
||||
MemorySize=128,
|
||||
Publish=True,
|
||||
VpcConfig={
|
||||
"SecurityGroupIds": [sg.id],
|
||||
"SubnetIds": [subnet.id],
|
||||
},
|
||||
)
|
||||
|
||||
from prowler.providers.aws.services.ec2.ec2_service import EC2
|
||||
|
||||
current_audit_info = self.set_mocked_audit_info()
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.lib.audit_info.audit_info.current_audit_info",
|
||||
new=current_audit_info,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.ec2.ec2_securitygroup_not_used.ec2_securitygroup_not_used.ec2_client",
|
||||
new=EC2(current_audit_info),
|
||||
):
|
||||
# Test Check
|
||||
from prowler.providers.aws.services.ec2.ec2_securitygroup_not_used.ec2_securitygroup_not_used import (
|
||||
ec2_securitygroup_not_used,
|
||||
)
|
||||
|
||||
check = ec2_securitygroup_not_used()
|
||||
result = check.execute()
|
||||
|
||||
# One custom sg
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert result[0].region == AWS_REGION
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Security group {sg_name} ({sg.id}) it is being used."
|
||||
)
|
||||
assert search(
|
||||
"it is being used",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{current_audit_info.audited_partition}:ec2:{AWS_REGION}:{current_audit_info.audited_account}:security-group/{sg.id}"
|
||||
)
|
||||
assert result[0].resource_id == sg.id
|
||||
assert result[0].resource_details == sg_name
|
||||
assert result[0].resource_tags == []
|
||||
|
||||
Reference in New Issue
Block a user