mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-01-25 02:08:11 +00:00
fix(codebuild): enhance service functions (#4319)
Co-authored-by: Pepe Fagoaga <pepe@prowler.com>
This commit is contained in:
@@ -7,7 +7,7 @@ from prowler.providers.aws.services.codebuild.codebuild_client import codebuild_
|
||||
class codebuild_project_older_90_days(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for project in codebuild_client.projects:
|
||||
for project in codebuild_client.projects.values():
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = project.region
|
||||
report.resource_id = project.name
|
||||
|
||||
@@ -7,7 +7,7 @@ from prowler.providers.aws.services.codebuild.codebuild_client import codebuild_
|
||||
class codebuild_project_user_controlled_buildspec(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for project in codebuild_client.projects:
|
||||
for project in codebuild_client.projects.values():
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = project.region
|
||||
report.resource_id = project.name
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import datetime
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.lib.scan_filters.scan_filters import is_resource_filtered
|
||||
from prowler.providers.aws.lib.service.service import AWSService
|
||||
@@ -12,12 +13,14 @@ class Codebuild(AWSService):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.projects = []
|
||||
self.projects = {}
|
||||
self.__threading_call__(self.__list_projects__)
|
||||
self.__list_builds_for_project__()
|
||||
self.__threading_call__(self.__list_builds_for_project__)
|
||||
self.__threading_call__(self.__batch_get_builds__)
|
||||
self.__threading_call__(self.__batch_get_projects__)
|
||||
|
||||
def __list_projects__(self, regional_client):
|
||||
logger.info("Codebuild - listing projects")
|
||||
logger.info("Codebuild - Listing projects...")
|
||||
try:
|
||||
list_projects_paginator = regional_client.get_paginator("list_projects")
|
||||
for page in list_projects_paginator.paginate():
|
||||
@@ -26,14 +29,10 @@ class Codebuild(AWSService):
|
||||
if not self.audit_resources or (
|
||||
is_resource_filtered(project_arn, self.audit_resources)
|
||||
):
|
||||
self.projects.append(
|
||||
Project(
|
||||
name=project,
|
||||
arn=project_arn,
|
||||
region=regional_client.region,
|
||||
last_invoked_time=None,
|
||||
buildspec=None,
|
||||
)
|
||||
self.projects[project_arn] = Project(
|
||||
name=project,
|
||||
arn=project_arn,
|
||||
region=regional_client.region,
|
||||
)
|
||||
|
||||
except Exception as error:
|
||||
@@ -41,38 +40,78 @@ class Codebuild(AWSService):
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __list_builds_for_project__(self):
|
||||
logger.info("Codebuild - listing builds from projects")
|
||||
def __list_builds_for_project__(self, regional_client):
|
||||
logger.info("Codebuild - Listing builds...")
|
||||
try:
|
||||
for project in self.projects:
|
||||
for region, client in self.regional_clients.items():
|
||||
if project.region == region:
|
||||
ids = client.list_builds_for_project(projectName=project.name)
|
||||
if "ids" in ids:
|
||||
if len(ids["ids"]) > 0:
|
||||
builds = client.batch_get_builds(ids=[ids["ids"][0]])
|
||||
if "builds" in builds:
|
||||
if "endTime" in builds["builds"][0]:
|
||||
project.last_invoked_time = builds["builds"][0][
|
||||
"endTime"
|
||||
]
|
||||
for project in self.projects.values():
|
||||
if project.region == regional_client.region:
|
||||
try:
|
||||
build_ids = regional_client.list_builds_for_project(
|
||||
projectName=project.name
|
||||
).get("ids", [])
|
||||
if len(build_ids) > 0:
|
||||
project.last_build = Build(id=build_ids[0])
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region}: {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
projects = client.batch_get_projects(names=[project.name])[
|
||||
"projects"
|
||||
][0]["source"]
|
||||
if "buildspec" in projects:
|
||||
project.buildspec = projects["buildspec"]
|
||||
def __batch_get_builds__(self, regional_client):
|
||||
logger.info("Codebuild - Getting builds...")
|
||||
try:
|
||||
for project in self.projects.values():
|
||||
if (
|
||||
project.region == regional_client.region
|
||||
and project.last_build
|
||||
and project.last_build.id
|
||||
):
|
||||
try:
|
||||
builds_by_id = regional_client.batch_get_builds(
|
||||
ids=[project.last_build.id]
|
||||
).get("builds", [])
|
||||
if len(builds_by_id) > 0:
|
||||
project.last_invoked_time = builds_by_id[0].get("endTime")
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region}: {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __batch_get_projects__(self, regional_client):
|
||||
logger.info("Codebuild - Getting projects...")
|
||||
try:
|
||||
for project in self.projects.values():
|
||||
if project.region == regional_client.region:
|
||||
try:
|
||||
project_source = regional_client.batch_get_projects(
|
||||
names=[project.name]
|
||||
)["projects"][0]["source"]
|
||||
project.buildspec = project_source.get("buildspec", "")
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region}: {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Project:
|
||||
class Build(BaseModel):
|
||||
id: str
|
||||
|
||||
|
||||
class Project(BaseModel):
|
||||
name: str
|
||||
arn: str
|
||||
region: str
|
||||
last_build: Optional[Build]
|
||||
last_invoked_time: Optional[datetime.datetime]
|
||||
buildspec: Optional[str]
|
||||
|
||||
@@ -13,15 +13,16 @@ class Test_codebuild_project_older_90_days:
|
||||
codebuild_client = mock.MagicMock
|
||||
project_name = "test-project"
|
||||
project_arn = f"arn:aws:codebuild:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:project/{project_name}"
|
||||
codebuild_client.projects = [
|
||||
Project(
|
||||
codebuild_client.projects = {
|
||||
project_arn: Project(
|
||||
name=project_name,
|
||||
arn=project_arn,
|
||||
region="eu-west-1",
|
||||
last_invoked_time=datetime.now(timezone.utc) - timedelta(days=100),
|
||||
buildspec=None,
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_service.Codebuild",
|
||||
codebuild_client,
|
||||
@@ -47,15 +48,16 @@ class Test_codebuild_project_older_90_days:
|
||||
codebuild_client = mock.MagicMock
|
||||
project_name = "test-project"
|
||||
project_arn = f"arn:aws:codebuild:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:project/{project_name}"
|
||||
codebuild_client.projects = [
|
||||
Project(
|
||||
codebuild_client.projects = {
|
||||
project_arn: Project(
|
||||
name=project_name,
|
||||
arn=project_arn,
|
||||
region="eu-west-1",
|
||||
last_invoked_time=None,
|
||||
buildspec=None,
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_service.Codebuild",
|
||||
codebuild_client,
|
||||
@@ -79,15 +81,16 @@ class Test_codebuild_project_older_90_days:
|
||||
codebuild_client = mock.MagicMock
|
||||
project_name = "test-project"
|
||||
project_arn = f"arn:aws:codebuild:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:project/{project_name}"
|
||||
codebuild_client.projects = [
|
||||
Project(
|
||||
codebuild_client.projects = {
|
||||
project_arn: Project(
|
||||
name=project_name,
|
||||
arn=project_arn,
|
||||
region="eu-west-1",
|
||||
last_invoked_time=datetime.now(timezone.utc) - timedelta(days=10),
|
||||
buildspec=None,
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_service.Codebuild",
|
||||
codebuild_client,
|
||||
|
||||
@@ -12,15 +12,15 @@ class Test_codebuild_project_user_controlled_buildspec:
|
||||
codebuild_client = mock.MagicMock
|
||||
project_name = "test-project"
|
||||
project_arn = f"arn:aws:codebuild:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:project/{project_name}"
|
||||
codebuild_client.projects = [
|
||||
Project(
|
||||
codebuild_client.projects = {
|
||||
project_arn: Project(
|
||||
name=project_name,
|
||||
arn=project_arn,
|
||||
region="eu-west-1",
|
||||
last_invoked_time=None,
|
||||
buildspec=None,
|
||||
)
|
||||
]
|
||||
}
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_service.Codebuild",
|
||||
codebuild_client,
|
||||
@@ -47,15 +47,16 @@ class Test_codebuild_project_user_controlled_buildspec:
|
||||
codebuild_client = mock.MagicMock
|
||||
project_name = "test-project"
|
||||
project_arn = f"arn:aws:codebuild:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:project/{project_name}"
|
||||
codebuild_client.projects = [
|
||||
Project(
|
||||
codebuild_client.projects = {
|
||||
project_arn: Project(
|
||||
name=project_name,
|
||||
arn=project_arn,
|
||||
region="eu-west-1",
|
||||
last_invoked_time=None,
|
||||
buildspec="arn:aws:s3:::my-codebuild-sample2/buildspec.out",
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_service.Codebuild",
|
||||
codebuild_client,
|
||||
@@ -82,15 +83,15 @@ class Test_codebuild_project_user_controlled_buildspec:
|
||||
codebuild_client = mock.MagicMock
|
||||
project_name = "test-project"
|
||||
project_arn = f"arn:aws:codebuild:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:project/{project_name}"
|
||||
codebuild_client.projects = [
|
||||
Project(
|
||||
codebuild_client.projects = {
|
||||
project_arn: Project(
|
||||
name=project_name,
|
||||
arn=project_arn,
|
||||
region="eu-west-1",
|
||||
last_invoked_time=None,
|
||||
buildspec="arn:aws:s3:::my-codebuild-sample2/buildspec.yaml",
|
||||
)
|
||||
]
|
||||
}
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_service.Codebuild",
|
||||
codebuild_client,
|
||||
@@ -116,15 +117,15 @@ class Test_codebuild_project_user_controlled_buildspec:
|
||||
codebuild_client = mock.MagicMock
|
||||
project_name = "test-project"
|
||||
project_arn = f"arn:aws:codebuild:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:project/{project_name}"
|
||||
codebuild_client.projects = [
|
||||
Project(
|
||||
codebuild_client.projects = {
|
||||
project_arn: Project(
|
||||
name=project_name,
|
||||
arn=project_arn,
|
||||
region="eu-west-1",
|
||||
last_invoked_time=None,
|
||||
buildspec="arn:aws:s3:::my-codebuild-sample2/buildspecyaml",
|
||||
)
|
||||
]
|
||||
}
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_service.Codebuild",
|
||||
codebuild_client,
|
||||
|
||||
@@ -3,22 +3,34 @@ from unittest.mock import patch
|
||||
|
||||
import botocore
|
||||
|
||||
from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild
|
||||
from tests.providers.aws.utils import AWS_REGION_EU_WEST_1, set_mocked_aws_provider
|
||||
from prowler.providers.aws.services.codebuild.codebuild_service import (
|
||||
Build,
|
||||
Codebuild,
|
||||
Project,
|
||||
)
|
||||
from tests.providers.aws.utils import (
|
||||
AWS_ACCOUNT_NUMBER,
|
||||
AWS_COMMERCIAL_PARTITION,
|
||||
AWS_REGION_EU_WEST_1,
|
||||
set_mocked_aws_provider,
|
||||
)
|
||||
|
||||
# last time invoked time
|
||||
project_name = "test"
|
||||
project_arn = f"arn:{AWS_COMMERCIAL_PARTITION}:codebuild:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:project/{project_name}"
|
||||
build_spec_project_arn = "arn:aws:s3:::my-codebuild-sample2/buildspec.yml"
|
||||
buildspec_type = "S3"
|
||||
build_id = "test:93f838a7-cd20-48ae-90e5-c10fbbc78ca6"
|
||||
last_invoked_time = datetime.now() - timedelta(days=2)
|
||||
|
||||
|
||||
# Mocking batch_get_projects
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
|
||||
|
||||
def mock_make_api_call(self, operation_name, kwarg):
|
||||
if operation_name == "ListProjects":
|
||||
return {"projects": ["test"]}
|
||||
return {"projects": [project_name]}
|
||||
if operation_name == "ListBuildsForProject":
|
||||
return {"ids": ["test:93f838a7-cd20-48ae-90e5-c10fbbc78ca6"]}
|
||||
return {"ids": [build_id]}
|
||||
if operation_name == "BatchGetBuilds":
|
||||
return {"builds": [{"endTime": last_invoked_time}]}
|
||||
if operation_name == "BatchGetProjects":
|
||||
@@ -26,7 +38,8 @@ def mock_make_api_call(self, operation_name, kwarg):
|
||||
"projects": [
|
||||
{
|
||||
"source": {
|
||||
"buildspec": "arn:aws:s3:::my-codebuild-sample2/buildspec.yml"
|
||||
"type": buildspec_type,
|
||||
"buildspec": build_spec_project_arn,
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -50,28 +63,18 @@ def mock_generate_regional_clients(provider, service):
|
||||
)
|
||||
class Test_Codebuild_Service:
|
||||
# Test Codebuild Session
|
||||
def test__get_session__(self):
|
||||
def test_codebuild_service(self):
|
||||
codebuild = Codebuild(set_mocked_aws_provider())
|
||||
assert codebuild.session.__class__.__name__ == "Session"
|
||||
|
||||
# Test Codebuild Service
|
||||
def test__get_service__(self):
|
||||
codebuild = Codebuild(set_mocked_aws_provider())
|
||||
assert codebuild.session.__class__.__name__ == "Session"
|
||||
assert codebuild.service == "codebuild"
|
||||
|
||||
def test__list_projects__(self):
|
||||
codebuild = Codebuild(set_mocked_aws_provider())
|
||||
assert len(codebuild.projects) == 1
|
||||
assert codebuild.projects[0].name == "test"
|
||||
assert codebuild.projects[0].region == AWS_REGION_EU_WEST_1
|
||||
|
||||
def test__list_builds_for_project__(self):
|
||||
codebuild = Codebuild(set_mocked_aws_provider())
|
||||
assert len(codebuild.projects) == 1
|
||||
assert codebuild.projects[0].name == "test"
|
||||
assert codebuild.projects[0].region == AWS_REGION_EU_WEST_1
|
||||
assert codebuild.projects[0].last_invoked_time == last_invoked_time
|
||||
assert (
|
||||
codebuild.projects[0].buildspec
|
||||
== "arn:aws:s3:::my-codebuild-sample2/buildspec.yml"
|
||||
)
|
||||
assert isinstance(codebuild.projects, dict)
|
||||
assert isinstance(codebuild.projects[project_arn], Project)
|
||||
assert codebuild.projects[project_arn].name == project_name
|
||||
assert codebuild.projects[project_arn].arn == project_arn
|
||||
assert codebuild.projects[project_arn].region == AWS_REGION_EU_WEST_1
|
||||
assert codebuild.projects[project_arn].last_invoked_time == last_invoked_time
|
||||
assert codebuild.projects[project_arn].last_build == Build(id=build_id)
|
||||
assert codebuild.projects[project_arn].buildspec == build_spec_project_arn
|
||||
|
||||
Reference in New Issue
Block a user