From 31bff99b3dbf18e1ab36b831d38136dffb4b47f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Thu, 26 Sep 2024 16:14:02 +0200 Subject: [PATCH] feat(codebuild): add tags support to projects (#5207) --- .../codebuild_project_no_secrets_in_variables.py | 1 + .../codebuild_project_older_90_days.py | 1 + ...t_source_repo_url_no_sensitive_credentials.py | 1 + ...odebuild_project_user_controlled_buildspec.py | 1 + .../aws/services/codebuild/codebuild_service.py | 2 ++ ...build_project_no_secrets_in_variables_test.py | 16 ++++++++++++++++ .../codebuild_project_older_90_days_test.py | 3 +++ ...rce_repo_url_no_sensitive_credentials_test.py | 4 ++++ ...ild_project_user_controlled_buildspec_test.py | 4 ++++ .../services/codebuild/codebuild_service_test.py | 14 ++++++++------ 10 files changed, 41 insertions(+), 6 deletions(-) diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables.py b/prowler/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables.py index a8057fcd17..d21dc660b5 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables.py +++ b/prowler/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables.py @@ -19,6 +19,7 @@ class codebuild_project_no_secrets_in_variables(Check): report.region = project.region report.resource_id = project.name report.resource_arn = project.arn + report.resource_tags = project.tags report.status = "PASS" report.status_extended = f"CodeBuild project {project.name} does not have sensitive environment plaintext credentials." secrets_found = [] diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days.py b/prowler/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days.py index bc730a61bf..91567cb2cc 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days.py +++ b/prowler/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days.py @@ -12,6 +12,7 @@ class codebuild_project_older_90_days(Check): report.region = project.region report.resource_id = project.name report.resource_arn = project.arn + report.resource_tags = project.tags report.status = "PASS" report.status_extended = f"CodeBuild project {project.name} has been invoked in the last 90 days." if project.last_invoked_time: diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials.py b/prowler/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials.py index 4473279a4f..efd98f8bc1 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials.py +++ b/prowler/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials.py @@ -14,6 +14,7 @@ class codebuild_project_source_repo_url_no_sensitive_credentials(Check): report.region = project.region report.resource_id = project.name report.resource_arn = project.arn + report.resource_tags = project.tags report.status = "PASS" report.status_extended = f"CodeBuild project {project.name} does not contain sensitive credentials in any source repository URLs." secrets_found = [] diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec.py b/prowler/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec.py index d41d76641e..b687de137f 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec.py +++ b/prowler/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec.py @@ -12,6 +12,7 @@ class codebuild_project_user_controlled_buildspec(Check): report.region = project.region report.resource_id = project.name report.resource_arn = project.arn + report.resource_tags = project.tags report.status = "PASS" report.status_extended = f"CodeBuild project {project.name} does not use an user controlled buildspec." if project.buildspec: diff --git a/prowler/providers/aws/services/codebuild/codebuild_service.py b/prowler/providers/aws/services/codebuild/codebuild_service.py index 541293f6fb..5704078fdd 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_service.py +++ b/prowler/providers/aws/services/codebuild/codebuild_service.py @@ -93,6 +93,7 @@ class Codebuild(AWSService): EnvironmentVariable(**var) for var in env_vars ] project.buildspec = project_info.get("source", {}).get("buildspec", "") + project.tags = project_info.get("tags", []) except Exception as error: logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" @@ -124,3 +125,4 @@ class Project(BaseModel): source: Optional[Source] secondary_sources: Optional[list[Source]] = [] environment_variables: Optional[List[EnvironmentVariable]] + tags: Optional[list] diff --git a/tests/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables_test.py b/tests/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables_test.py index 7d99d95861..c719626296 100644 --- a/tests/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables_test.py +++ b/tests/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables_test.py @@ -41,6 +41,7 @@ class Test_codebuild_project_no_secrets_in_variables: last_invoked_time=None, buildspec=None, environment_variables=[], + tags=[], ) } @@ -69,6 +70,7 @@ class Test_codebuild_project_no_secrets_in_variables: assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == "SensitiveProject" assert result[0].resource_arn == project_arn + assert result[0].resource_tags == [] def test_project_with_no_plaintext_credentials(self): codebuild_client = mock.MagicMock @@ -90,6 +92,7 @@ class Test_codebuild_project_no_secrets_in_variables: "type": "PARAMETER_STORE", } ], + tags=[], ) } @@ -118,6 +121,7 @@ class Test_codebuild_project_no_secrets_in_variables: assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == "SensitiveProject" assert result[0].resource_arn == project_arn + assert result[0].resource_tags == [] def test_project_with_plaintext_credentials_but_not_sensitive(self): codebuild_client = mock.MagicMock @@ -139,6 +143,7 @@ class Test_codebuild_project_no_secrets_in_variables: "type": "PLAINTEXT", } ], + tags=[], ) } @@ -167,6 +172,7 @@ class Test_codebuild_project_no_secrets_in_variables: assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == "SensitiveProject" assert result[0].resource_arn == project_arn + assert result[0].resource_tags == [] def test_project_with_sensitive_plaintext_credentials(self): codebuild_client = mock.MagicMock @@ -188,6 +194,7 @@ class Test_codebuild_project_no_secrets_in_variables: "type": "PLAINTEXT", } ], + tags=[], ) } @@ -216,6 +223,7 @@ class Test_codebuild_project_no_secrets_in_variables: assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == "SensitiveProject" assert result[0].resource_arn == project_arn + assert result[0].resource_tags == [] def test_project_with_sensitive_plaintext_credentials_exluded(self): codebuild_client = mock.MagicMock @@ -237,6 +245,7 @@ class Test_codebuild_project_no_secrets_in_variables: "type": "PLAINTEXT", } ], + tags=[], ) } @@ -267,6 +276,7 @@ class Test_codebuild_project_no_secrets_in_variables: assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == "SensitiveProject" assert result[0].resource_arn == project_arn + assert result[0].resource_tags == [] def test_project_with_sensitive_plaintext_credentials_excluded_and_not(self): codebuild_client = mock.MagicMock() @@ -293,6 +303,7 @@ class Test_codebuild_project_no_secrets_in_variables: "type": "PARAMETER_STORE", }, ], + tags=[], ) } @@ -323,6 +334,7 @@ class Test_codebuild_project_no_secrets_in_variables: assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == "SensitiveProject" assert result[0].resource_arn == project_arn + assert result[0].resource_tags == [] def test_project_with_sensitive_plaintext_credentials_excluded_and_failed(self): codebuild_client = mock.MagicMock() @@ -349,6 +361,7 @@ class Test_codebuild_project_no_secrets_in_variables: "type": "PLAINTEXT", }, ], + tags=[], ) } @@ -379,6 +392,7 @@ class Test_codebuild_project_no_secrets_in_variables: assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == "SensitiveProject" assert result[0].resource_arn == project_arn + assert result[0].resource_tags == [] def test_project_with_multiple_sensitive_credentials(self): codebuild_client = mock.MagicMock() @@ -405,6 +419,7 @@ class Test_codebuild_project_no_secrets_in_variables: "type": "PLAINTEXT", }, ], + tags=[], ) } @@ -433,3 +448,4 @@ class Test_codebuild_project_no_secrets_in_variables: assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_id == "SensitiveProject" assert result[0].resource_arn == project_arn + assert result[0].resource_tags == [] diff --git a/tests/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days_test.py b/tests/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days_test.py index 236c0820ae..c89f163e6f 100644 --- a/tests/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days_test.py +++ b/tests/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days_test.py @@ -20,6 +20,7 @@ class Test_codebuild_project_older_90_days: region="eu-west-1", last_invoked_time=datetime.now(timezone.utc) - timedelta(days=100), buildspec=None, + tags=[], ) } @@ -55,6 +56,7 @@ class Test_codebuild_project_older_90_days: region="eu-west-1", last_invoked_time=None, buildspec=None, + tags=[], ) } @@ -88,6 +90,7 @@ class Test_codebuild_project_older_90_days: region="eu-west-1", last_invoked_time=datetime.now(timezone.utc) - timedelta(days=10), buildspec=None, + tags=[], ) } diff --git a/tests/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials_test.py b/tests/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials_test.py index b3e7f1b967..c99e9ecf5c 100644 --- a/tests/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials_test.py +++ b/tests/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials_test.py @@ -20,6 +20,7 @@ class Test_codebuild_project_source_repo_url_no_sensitive_credentials: buildspec="", source=None, secondary_sources=[], + tags=[], ) } with mock.patch( @@ -60,6 +61,7 @@ class Test_codebuild_project_source_repo_url_no_sensitive_credentials: location="https://bitbucket.org/exampleuser/my-repo.git", ), secondary_sources=[], + tags=[], ) } with mock.patch( @@ -100,6 +102,7 @@ class Test_codebuild_project_source_repo_url_no_sensitive_credentials: location="https://user:pass123@bitbucket.org/exampleuser/my-repo2.git", ), secondary_sources=[], + tags=[], ) } with mock.patch( @@ -140,6 +143,7 @@ class Test_codebuild_project_source_repo_url_no_sensitive_credentials: location="https://x-token-auth:7saBEbfXpRg-zlO-YQC9Lvh8vtKmdETITD_-GCqYw0ZHbV7ZbMDbUCybDGM4=053EA782@bitbucket.org/testissue4244/test4244.git", ), secondary_sources=[], + tags=[], ) } with mock.patch( diff --git a/tests/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec_test.py b/tests/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec_test.py index bd213e29bd..61021d704e 100644 --- a/tests/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec_test.py +++ b/tests/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec_test.py @@ -19,6 +19,7 @@ class Test_codebuild_project_user_controlled_buildspec: region="eu-west-1", last_invoked_time=None, buildspec=None, + tags=[], ) } with mock.patch( @@ -54,6 +55,7 @@ class Test_codebuild_project_user_controlled_buildspec: region="eu-west-1", last_invoked_time=None, buildspec="arn:aws:s3:::my-codebuild-sample2/buildspec.out", + tags=[], ) } @@ -90,6 +92,7 @@ class Test_codebuild_project_user_controlled_buildspec: region="eu-west-1", last_invoked_time=None, buildspec="arn:aws:s3:::my-codebuild-sample2/buildspec.yaml", + tags=[], ) } with mock.patch( @@ -124,6 +127,7 @@ class Test_codebuild_project_user_controlled_buildspec: region="eu-west-1", last_invoked_time=None, buildspec="arn:aws:s3:::my-codebuild-sample2/buildspecyaml", + tags=[], ) } with mock.patch( diff --git a/tests/providers/aws/services/codebuild/codebuild_service_test.py b/tests/providers/aws/services/codebuild/codebuild_service_test.py index 0741f180c1..0ea15166eb 100644 --- a/tests/providers/aws/services/codebuild/codebuild_service_test.py +++ b/tests/providers/aws/services/codebuild/codebuild_service_test.py @@ -51,6 +51,7 @@ def mock_make_api_call(self, operation_name, kwarg): "buildspec": "", } ], + "tags": [{"key": "Name", "value": project_name}], } ] } @@ -66,13 +67,12 @@ def mock_generate_regional_clients(provider, service): return {AWS_REGION_EU_WEST_1: regional_client} -@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call) -@patch( - "prowler.providers.aws.aws_provider.AwsProvider.generate_regional_clients", - new=mock_generate_regional_clients, -) class Test_Codebuild_Service: - # Test Codebuild Session + @patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call) + @patch( + "prowler.providers.aws.aws_provider.AwsProvider.generate_regional_clients", + new=mock_generate_regional_clients, + ) def test_codebuild_service(self): codebuild = Codebuild(set_mocked_aws_provider()) @@ -93,3 +93,5 @@ class Test_Codebuild_Service: secondary_bitbucket_url in codebuild.projects[project_arn].secondary_sources[0].location ) + assert codebuild.projects[project_arn].tags[0]["key"] == "Name" + assert codebuild.projects[project_arn].tags[0]["value"] == project_name