From 18d3bf9cc939b939eaaca8ae2a0e08cee4ce88a5 Mon Sep 17 00:00:00 2001 From: "Andoni A." <14891798+andoniaf@users.noreply.github.com> Date: Thu, 17 Apr 2025 16:40:18 +0200 Subject: [PATCH 1/8] feat(aws): add check to ensure Codebuild Github projects are only using allowed Github orgs Can be used to attempt to detect long term persistence using Github Actions and Codebuild as explained in this article: https://medium.com/@adan.alvarez/gaining-long-term-aws-access-with-codebuild-and-github-873324638784 --- prowler/config/config.yaml | 6 + ...red_iam_roles_github_actions.metadata.json | 30 ++ ...ild_backdoored_iam_roles_github_actions.py | 42 +++ .../services/codebuild/codebuild_service.py | 4 + ...ackdoored_iam_roles_github_actions_test.py | 269 ++++++++++++++++++ 5 files changed, 351 insertions(+) create mode 100644 prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.metadata.json create mode 100644 prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.py create mode 100644 tests/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions_test.py diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index 26b196e178..9eb912172d 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -417,6 +417,12 @@ aws: {"name": "TwilioKeyDetector"}, ] + # AWS CodeBuild Configuration + # aws.codebuild_backdoored_iam_roles_github_actions + codebuild_github_allowed_organizations: + [ + "", + ] # Azure Configuration azure: diff --git a/prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.metadata.json b/prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.metadata.json new file mode 100644 index 0000000000..fccd62db5d --- /dev/null +++ b/prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.metadata.json @@ -0,0 +1,30 @@ +{ + "Provider": "aws", + "CheckID": "codebuild_backdoored_iam_roles_github_actions", + "CheckTitle": "Ensure AWS CodeBuild projects using GitHub connect only to whitelisted organizations", + "CheckType": [], + "ServiceName": "codebuild", + "SubServiceName": "", + "ResourceIdTemplate": "arn:aws:codebuild:region:account-id:project:project-name", + "Severity": "high", + "ResourceType": "AwsCodeBuildProject", + "Description": "Check for CodeBuild projects using GitHub repositories from untrusted organizations that could lead to backdoored IAM roles", + "Risk": "Attackers can use GitHub Actions in untrusted repositories to backdoor IAM roles used by CodeBuild projects, gaining persistent access to AWS accounts.", + "RelatedUrl": "https://medium.com/@adan.alvarez/gaining-long-term-aws-access-with-codebuild-and-github-873324638784", + "Remediation": { + "Code": { + "NativeIaC": "", + "Terraform": "", + "CLI": "", + "Other": "" + }, + "Recommendation": { + "Text": "Only use GitHub repositories from trusted organizations with CodeBuild projects. Configure the allowed GitHub organizations in your Prowler configuration.", + "Url": "https://docs.aws.amazon.com/codebuild/latest/userguide/auth-and-access-control-iam-identity-based-access-control.html" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} \ No newline at end of file diff --git a/prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.py b/prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.py new file mode 100644 index 0000000000..e38d6c43fb --- /dev/null +++ b/prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.py @@ -0,0 +1,42 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.codebuild.codebuild_client import codebuild_client +from prowler.providers.aws.services.iam.iam_client import iam_client + +# Inspired by https://medium.com/@adan.alvarez/gaining-long-term-aws-access-with-codebuild-and-github-873324638784 + +class codebuild_backdoored_iam_roles_github_actions(Check): + def execute(self): + findings = [] + allowed_organizations = codebuild_client.audit_config.get( + "codebuild_github_allowed_organizations", [] + ) + + for project in codebuild_client.projects.values(): + report = Check_Report_AWS(metadata=self.metadata(), resource=project) + report.status = "PASS" + + if project.source.type == "GITHUB": + project_github_repo_url = project.source.location + project_role = next((role for role in iam_client.roles if role.arn == project.service_role_arn), None) + project_iam_trust_policy = project_role.assume_role_policy + + if project_iam_trust_policy: + if isinstance(project_iam_trust_policy["Statement"], list): + for statement in project_iam_trust_policy["Statement"]: + if ( + statement["Effect"] == "Allow" + and "codebuild.amazonaws.com" in statement["Principal"]["Service"] + ): + if project_github_repo_url: + org_name = project_github_repo_url.split("/")[3] + if org_name not in allowed_organizations: + report.status = "FAIL" + report.status_extended = f"CodeBuild project {project.name} uses GitHub organization '{org_name}', which is not in the allowed organizations." + else: + report.status_extended = f"CodeBuild project {project.name} uses GitHub organization '{org_name}', which is in the allowed organizations." + else: + report.status_extended = f"CodeBuild project {project.name} does not use an IAM role with codebuild.amazonaws.com as a trusted principal, skipping GitHub organization check." + + findings.append(report) + + return findings \ No newline at end of file diff --git a/prowler/providers/aws/services/codebuild/codebuild_service.py b/prowler/providers/aws/services/codebuild/codebuild_service.py index a1e00790bb..55ea2d1af9 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_service.py +++ b/prowler/providers/aws/services/codebuild/codebuild_service.py @@ -1,6 +1,7 @@ import datetime from typing import List, Optional +from botocore.exceptions import ClientError from pydantic import BaseModel from prowler.lib.logger import logger @@ -120,6 +121,7 @@ def _batch_get_projects(self, project): stream_name=cloudwatch_logs.get("streamName", ""), ) project.tags = project_info.get("tags", []) + project.service_role_arn = project_info.get("serviceRole", "") except Exception as error: logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" @@ -220,6 +222,7 @@ class Project(BaseModel): s3_logs: Optional[s3Logs] cloudwatch_logs: Optional[CloudWatchLogs] tags: Optional[list] + service_role_arn: Optional[str] = None class ExportConfig(BaseModel): @@ -236,3 +239,4 @@ class ReportGroup(BaseModel): status: Optional[str] export_config: Optional[ExportConfig] tags: Optional[list] + diff --git a/tests/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions_test.py b/tests/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions_test.py new file mode 100644 index 0000000000..334d25a075 --- /dev/null +++ b/tests/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions_test.py @@ -0,0 +1,269 @@ +from unittest.mock import patch + +from boto3 import client +from moto import mock_aws + +from tests.providers.aws.utils import AWS_REGION_EU_WEST_1, set_mocked_aws_provider + +# Import these once at the module level +from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild +from prowler.providers.aws.services.iam.iam_service import IAM + + +class Test_codebuild_backdoored_iam_roles_github_actions: + def setup_codebuild_iam_mocks(self, audit_config=None): + """Helper method to set up common mocks""" + if audit_config is None: + audit_config = {} + + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + + # Create mock Codebuild client with audit_config + codebuild_mock = Codebuild(aws_provider) + codebuild_mock.audit_config = audit_config + + # Create mock IAM client + iam_mock = IAM(aws_provider) + + return aws_provider, codebuild_mock, iam_mock + + def create_codebuild_role(self, role_name="codebuild-test-role", service="codebuild.amazonaws.com"): + """Helper method to create an IAM role""" + iam_client = client("iam") + assume_role_policy_document = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": service}, + "Action": "sts:AssumeRole", + } + ], + } + role = iam_client.create_role( + RoleName=role_name, + AssumeRolePolicyDocument=str(assume_role_policy_document).replace("'", '"'), + ) + return role["Role"]["Arn"] + + def create_codebuild_project(self, project_name, source_type, source_location, role_arn): + """Helper method to create a CodeBuild project""" + codebuild_client = client("codebuild", region_name=AWS_REGION_EU_WEST_1) + project = codebuild_client.create_project( + name=project_name, + source={ + "type": source_type, + "location": source_location, + }, + artifacts={ + "type": "NO_ARTIFACTS", + }, + environment={ + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/standard:4.0", + "computeType": "BUILD_GENERAL1_SMALL", + }, + serviceRole=role_arn, + ) + return project["project"]["arn"] + + @mock_aws + def test_no_projects(self): + aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.codebuild_client", + codebuild_mock, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.iam_client", + iam_mock, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions import ( + codebuild_backdoored_iam_roles_github_actions, + ) + + check = codebuild_backdoored_iam_roles_github_actions() + result = check.execute() + + assert len(result) == 0 + + @mock_aws + def test_project_not_github(self): + # Create IAM role and CodeBuild project + role_arn = self.create_codebuild_role() + project_name = "test-project-not-github" + project_arn = self.create_codebuild_project( + project_name, + "S3", + "test-bucket/source.zip", + role_arn + ) + + # Set up mocks + aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks() + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.codebuild_client", + codebuild_mock, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.iam_client", + iam_mock, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions import ( + codebuild_backdoored_iam_roles_github_actions, + ) + + check = codebuild_backdoored_iam_roles_github_actions() + result = check.execute() + + # Non-GitHub projects should not be reported + assert len(result) == 0 + + @mock_aws + def test_project_github_allowed_organization(self): + # Create IAM role and CodeBuild project + role_arn = self.create_codebuild_role() + project_name = "test-project-github-allowed" + project_arn = self.create_codebuild_project( + project_name, + "GITHUB", + "https://github.com/allowed-org/repo", + role_arn + ) + + # Set up mocks with allowed organizations + aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( + {"codebuild_github_allowed_organizations": ["allowed-org"]} + ) + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.codebuild_client", + codebuild_mock, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.iam_client", + iam_mock, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions import ( + codebuild_backdoored_iam_roles_github_actions, + ) + + check = codebuild_backdoored_iam_roles_github_actions() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert "which is in the allowed organizations" in result[0].status_extended + assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_project_github_not_allowed_organization(self): + # Create IAM role and CodeBuild project + role_arn = self.create_codebuild_role() + project_name = "test-project-github-not-allowed" + project_arn = self.create_codebuild_project( + project_name, + "GITHUB", + "https://github.com/not-allowed-org/repo", + role_arn + ) + + # Set up mocks with allowed organizations + aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( + {"codebuild_github_allowed_organizations": ["allowed-org"]} + ) + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.codebuild_client", + codebuild_mock, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.iam_client", + iam_mock, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions import ( + codebuild_backdoored_iam_roles_github_actions, + ) + + check = codebuild_backdoored_iam_roles_github_actions() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert "which is not in the allowed organizations" in result[0].status_extended + assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_project_github_no_codebuild_trusted_principal(self): + # Create IAM role for Lambda (not CodeBuild) and CodeBuild project + role_arn = self.create_codebuild_role("lambda-test-role", "lambda.amazonaws.com") + project_name = "test-project-github-lambda-role" + project_arn = self.create_codebuild_project( + project_name, + "GITHUB", + "https://github.com/not-allowed-org/repo", + role_arn + ) + + # Set up mocks with allowed organizations + aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( + {"codebuild_github_allowed_organizations": ["allowed-org"]} + ) + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.codebuild_client", + codebuild_mock, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.iam_client", + iam_mock, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions import ( + codebuild_backdoored_iam_roles_github_actions, + ) + + check = codebuild_backdoored_iam_roles_github_actions() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert "does not use an IAM role with codebuild.amazonaws.com as a trusted principal" in result[0].status_extended + assert result[0].region == AWS_REGION_EU_WEST_1 \ No newline at end of file From 8b4457b36d56784a8b4018470b0ad2139502fb19 Mon Sep 17 00:00:00 2001 From: "Andoni A." <14891798+andoniaf@users.noreply.github.com> Date: Wed, 23 Apr 2025 16:59:54 +0200 Subject: [PATCH 2/8] refactor(codebuild): rename check --- prowler/config/config.yaml | 2 +- ...llowed_github_organizations.metadata.json} | 6 +- ...ject_uses_allowed_github_organizations.py} | 17 ++- .../services/codebuild/codebuild_service.py | 2 - ...ject_uses_allowed_github_organizations.py} | 123 ++++++++---------- 5 files changed, 71 insertions(+), 79 deletions(-) rename prowler/providers/aws/services/codebuild/{codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.metadata.json => codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.metadata.json} (92%) rename prowler/providers/aws/services/codebuild/{codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.py => codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py} (80%) rename tests/providers/aws/services/codebuild/{codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions_test.py => codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py} (65%) diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index 9eb912172d..e370688985 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -418,7 +418,7 @@ aws: ] # AWS CodeBuild Configuration - # aws.codebuild_backdoored_iam_roles_github_actions + # aws.codebuild_project_uses_allowed_github_organizations codebuild_github_allowed_organizations: [ "", diff --git a/prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.metadata.json b/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.metadata.json similarity index 92% rename from prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.metadata.json rename to prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.metadata.json index fccd62db5d..7f6bc0c024 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.metadata.json +++ b/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.metadata.json @@ -1,7 +1,7 @@ { "Provider": "aws", - "CheckID": "codebuild_backdoored_iam_roles_github_actions", - "CheckTitle": "Ensure AWS CodeBuild projects using GitHub connect only to whitelisted organizations", + "CheckID": "codebuild_project_uses_allowed_github_organizations", + "CheckTitle": "Ensure AWS CodeBuild projects using GitHub connect only to allowed organizations", "CheckType": [], "ServiceName": "codebuild", "SubServiceName": "", @@ -27,4 +27,4 @@ "DependsOn": [], "RelatedTo": [], "Notes": "" -} \ No newline at end of file +} diff --git a/prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.py b/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py similarity index 80% rename from prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.py rename to prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py index e38d6c43fb..f69dd40405 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions.py +++ b/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py @@ -2,9 +2,8 @@ from prowler.providers.aws.services.codebuild.codebuild_client import codebuild_client from prowler.providers.aws.services.iam.iam_client import iam_client -# Inspired by https://medium.com/@adan.alvarez/gaining-long-term-aws-access-with-codebuild-and-github-873324638784 -class codebuild_backdoored_iam_roles_github_actions(Check): +class codebuild_project_uses_allowed_github_organizations(Check): def execute(self): findings = [] allowed_organizations = codebuild_client.audit_config.get( @@ -17,7 +16,14 @@ def execute(self): if project.source.type == "GITHUB": project_github_repo_url = project.source.location - project_role = next((role for role in iam_client.roles if role.arn == project.service_role_arn), None) + project_role = next( + ( + role + for role in iam_client.roles + if role.arn == project.service_role_arn + ), + None, + ) project_iam_trust_policy = project_role.assume_role_policy if project_iam_trust_policy: @@ -25,7 +31,8 @@ def execute(self): for statement in project_iam_trust_policy["Statement"]: if ( statement["Effect"] == "Allow" - and "codebuild.amazonaws.com" in statement["Principal"]["Service"] + and "codebuild.amazonaws.com" + in statement["Principal"]["Service"] ): if project_github_repo_url: org_name = project_github_repo_url.split("/")[3] @@ -39,4 +46,4 @@ def execute(self): findings.append(report) - return findings \ No newline at end of file + return findings diff --git a/prowler/providers/aws/services/codebuild/codebuild_service.py b/prowler/providers/aws/services/codebuild/codebuild_service.py index 55ea2d1af9..5fcf1d335f 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_service.py +++ b/prowler/providers/aws/services/codebuild/codebuild_service.py @@ -1,7 +1,6 @@ import datetime from typing import List, Optional -from botocore.exceptions import ClientError from pydantic import BaseModel from prowler.lib.logger import logger @@ -239,4 +238,3 @@ class ReportGroup(BaseModel): status: Optional[str] export_config: Optional[ExportConfig] tags: Optional[list] - diff --git a/tests/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions_test.py b/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py similarity index 65% rename from tests/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions_test.py rename to tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py index 334d25a075..bc1ad86ed7 100644 --- a/tests/providers/aws/services/codebuild/codebuild_backdoored_iam_roles_github_actions/codebuild_backdoored_iam_roles_github_actions_test.py +++ b/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py @@ -3,31 +3,29 @@ from boto3 import client from moto import mock_aws -from tests.providers.aws.utils import AWS_REGION_EU_WEST_1, set_mocked_aws_provider - -# Import these once at the module level from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild from prowler.providers.aws.services.iam.iam_service import IAM +from tests.providers.aws.utils import AWS_REGION_EU_WEST_1, set_mocked_aws_provider -class Test_codebuild_backdoored_iam_roles_github_actions: +class Test_codebuild_project_uses_allowed_github_organizations: def setup_codebuild_iam_mocks(self, audit_config=None): """Helper method to set up common mocks""" if audit_config is None: audit_config = {} - + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) - - # Create mock Codebuild client with audit_config + codebuild_mock = Codebuild(aws_provider) codebuild_mock.audit_config = audit_config - - # Create mock IAM client + iam_mock = IAM(aws_provider) - + return aws_provider, codebuild_mock, iam_mock - - def create_codebuild_role(self, role_name="codebuild-test-role", service="codebuild.amazonaws.com"): + + def create_codebuild_role( + self, role_name="codebuild-test-role", service="codebuild.amazonaws.com" + ): """Helper method to create an IAM role""" iam_client = client("iam") assume_role_policy_document = { @@ -45,8 +43,10 @@ def create_codebuild_role(self, role_name="codebuild-test-role", service="codebu AssumeRolePolicyDocument=str(assume_role_policy_document).replace("'", '"'), ) return role["Role"]["Arn"] - - def create_codebuild_project(self, project_name, source_type, source_location, role_arn): + + def create_codebuild_project( + self, project_name, source_type, source_location, role_arn + ): """Helper method to create a CodeBuild project""" codebuild_client = client("codebuild", region_name=AWS_REGION_EU_WEST_1) project = codebuild_client.create_project( @@ -77,36 +77,31 @@ def test_no_projects(self): return_value=aws_provider, ), patch( - "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.codebuild_client", + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", codebuild_mock, ), patch( - "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.iam_client", + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", iam_mock, ), ): - from prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions import ( - codebuild_backdoored_iam_roles_github_actions, + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, ) - check = codebuild_backdoored_iam_roles_github_actions() + check = codebuild_project_uses_allowed_github_organizations() result = check.execute() assert len(result) == 0 @mock_aws def test_project_not_github(self): - # Create IAM role and CodeBuild project role_arn = self.create_codebuild_role() project_name = "test-project-not-github" - project_arn = self.create_codebuild_project( - project_name, - "S3", - "test-bucket/source.zip", - role_arn + self.create_codebuild_project( + project_name, "S3", "test-bucket/source.zip", role_arn ) - # Set up mocks aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks() with ( @@ -115,19 +110,19 @@ def test_project_not_github(self): return_value=aws_provider, ), patch( - "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.codebuild_client", + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", codebuild_mock, ), patch( - "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.iam_client", + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", iam_mock, ), ): - from prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions import ( - codebuild_backdoored_iam_roles_github_actions, + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, ) - check = codebuild_backdoored_iam_roles_github_actions() + check = codebuild_project_uses_allowed_github_organizations() result = check.execute() # Non-GitHub projects should not be reported @@ -135,17 +130,12 @@ def test_project_not_github(self): @mock_aws def test_project_github_allowed_organization(self): - # Create IAM role and CodeBuild project role_arn = self.create_codebuild_role() project_name = "test-project-github-allowed" project_arn = self.create_codebuild_project( - project_name, - "GITHUB", - "https://github.com/allowed-org/repo", - role_arn + project_name, "GITHUB", "https://github.com/allowed-org/repo", role_arn ) - # Set up mocks with allowed organizations aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( {"codebuild_github_allowed_organizations": ["allowed-org"]} ) @@ -156,19 +146,19 @@ def test_project_github_allowed_organization(self): return_value=aws_provider, ), patch( - "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.codebuild_client", + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", codebuild_mock, ), patch( - "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.iam_client", + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", iam_mock, ), ): - from prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions import ( - codebuild_backdoored_iam_roles_github_actions, + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, ) - check = codebuild_backdoored_iam_roles_github_actions() + check = codebuild_project_uses_allowed_github_organizations() result = check.execute() assert len(result) == 1 @@ -180,17 +170,12 @@ def test_project_github_allowed_organization(self): @mock_aws def test_project_github_not_allowed_organization(self): - # Create IAM role and CodeBuild project role_arn = self.create_codebuild_role() project_name = "test-project-github-not-allowed" project_arn = self.create_codebuild_project( - project_name, - "GITHUB", - "https://github.com/not-allowed-org/repo", - role_arn + project_name, "GITHUB", "https://github.com/not-allowed-org/repo", role_arn ) - # Set up mocks with allowed organizations aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( {"codebuild_github_allowed_organizations": ["allowed-org"]} ) @@ -201,41 +186,40 @@ def test_project_github_not_allowed_organization(self): return_value=aws_provider, ), patch( - "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.codebuild_client", + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", codebuild_mock, ), patch( - "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.iam_client", + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", iam_mock, ), ): - from prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions import ( - codebuild_backdoored_iam_roles_github_actions, + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, ) - check = codebuild_backdoored_iam_roles_github_actions() + check = codebuild_project_uses_allowed_github_organizations() result = check.execute() assert len(result) == 1 assert result[0].status == "FAIL" assert result[0].resource_id == project_name assert result[0].resource_arn == project_arn - assert "which is not in the allowed organizations" in result[0].status_extended + assert ( + "which is not in the allowed organizations" in result[0].status_extended + ) assert result[0].region == AWS_REGION_EU_WEST_1 @mock_aws def test_project_github_no_codebuild_trusted_principal(self): - # Create IAM role for Lambda (not CodeBuild) and CodeBuild project - role_arn = self.create_codebuild_role("lambda-test-role", "lambda.amazonaws.com") + role_arn = self.create_codebuild_role( + "lambda-test-role", "lambda.amazonaws.com" + ) project_name = "test-project-github-lambda-role" project_arn = self.create_codebuild_project( - project_name, - "GITHUB", - "https://github.com/not-allowed-org/repo", - role_arn + project_name, "GITHUB", "https://github.com/not-allowed-org/repo", role_arn ) - # Set up mocks with allowed organizations aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( {"codebuild_github_allowed_organizations": ["allowed-org"]} ) @@ -246,24 +230,27 @@ def test_project_github_no_codebuild_trusted_principal(self): return_value=aws_provider, ), patch( - "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.codebuild_client", + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", codebuild_mock, ), patch( - "prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions.iam_client", + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", iam_mock, ), ): - from prowler.providers.aws.services.codebuild.codebuild_backdoored_iam_roles_github_actions.codebuild_backdoored_iam_roles_github_actions import ( - codebuild_backdoored_iam_roles_github_actions, + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, ) - check = codebuild_backdoored_iam_roles_github_actions() + check = codebuild_project_uses_allowed_github_organizations() result = check.execute() assert len(result) == 1 assert result[0].status == "PASS" assert result[0].resource_id == project_name assert result[0].resource_arn == project_arn - assert "does not use an IAM role with codebuild.amazonaws.com as a trusted principal" in result[0].status_extended - assert result[0].region == AWS_REGION_EU_WEST_1 \ No newline at end of file + assert ( + "does not use an IAM role with codebuild.amazonaws.com as a trusted principal" + in result[0].status_extended + ) + assert result[0].region == AWS_REGION_EU_WEST_1 From 1115ba9cf1d774d04276f08bc6a964afc762fee8 Mon Sep 17 00:00:00 2001 From: "Andoni A." <14891798+andoniaf@users.noreply.github.com> Date: Thu, 24 Apr 2025 07:41:18 +0200 Subject: [PATCH 3/8] fix: solve Incomplete URL substring sanitization --- .../codebuild_project_uses_allowed_github_organizations.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py b/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py index f69dd40405..da4d2560d9 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py +++ b/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py @@ -31,8 +31,8 @@ def execute(self): for statement in project_iam_trust_policy["Statement"]: if ( statement["Effect"] == "Allow" - and "codebuild.amazonaws.com" - in statement["Principal"]["Service"] + and statement["Principal"]["Service"] + == "codebuild.amazonaws.com" ): if project_github_repo_url: org_name = project_github_repo_url.split("/")[3] From 7be1dac9d7cd32125a18969dc610619e3be6ce1b Mon Sep 17 00:00:00 2001 From: "Andoni A." <14891798+andoniaf@users.noreply.github.com> Date: Wed, 30 Apr 2025 15:14:30 +0200 Subject: [PATCH 4/8] docs(aws): add codebuild_github_allowed_organizations to configuration docs --- docs/tutorials/configuration_file.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/tutorials/configuration_file.md b/docs/tutorials/configuration_file.md index 9ee25ea7e7..953d65179d 100644 --- a/docs/tutorials/configuration_file.md +++ b/docs/tutorials/configuration_file.md @@ -31,6 +31,7 @@ The following list includes all the AWS checks with configurable variables that | `cloudtrail_threat_detection_privilege_escalation` | `threat_detection_privilege_escalation_minutes` | Integer | | `cloudwatch_log_group_no_secrets_in_logs` | `secrets_ignore_patterns` | List of Strings | | `cloudwatch_log_group_retention_policy_specific_days_enabled` | `log_group_retention_days` | Integer | +| `codebuild_github_allowed_organizations` | `github_allowed_organizations` | List of Strings | | `codebuild_project_no_secrets_in_variables` | `excluded_sensitive_environment_variables` | List of Strings | | `codebuild_project_no_secrets_in_variables` | `secrets_ignore_patterns` | List of Strings | | `config_recorder_all_regions_enabled` | `mute_non_default_regions` | Boolean | From 6c52c550c9da70b99417b05d1a77d1ffbea1aa15 Mon Sep 17 00:00:00 2001 From: "Andoni A." <14891798+andoniaf@users.noreply.github.com> Date: Mon, 19 May 2025 19:20:46 +0200 Subject: [PATCH 5/8] refactor: move policy logic from check to iam policy file --- prowler/config/config.yaml | 2 +- ...oject_uses_allowed_github_organizations.py | 42 +-- .../providers/aws/services/iam/lib/policy.py | 53 ++++ ...oject_uses_allowed_github_organizations.py | 250 ++++++++++++++++++ 4 files changed, 329 insertions(+), 18 deletions(-) diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index e370688985..5efb26cf5c 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -421,7 +421,7 @@ aws: # aws.codebuild_project_uses_allowed_github_organizations codebuild_github_allowed_organizations: [ - "", + "andoniaf", ] # Azure Configuration diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py b/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py index da4d2560d9..7accdc6b1f 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py +++ b/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py @@ -1,6 +1,10 @@ from prowler.lib.check.models import Check, Check_Report_AWS from prowler.providers.aws.services.codebuild.codebuild_client import codebuild_client from prowler.providers.aws.services.iam.iam_client import iam_client +from prowler.providers.aws.services.iam.lib.policy import ( + has_codebuild_trusted_principal, + is_codebuild_using_allowed_github_org, +) class codebuild_project_uses_allowed_github_organizations(Check): @@ -14,7 +18,7 @@ def execute(self): report = Check_Report_AWS(metadata=self.metadata(), resource=project) report.status = "PASS" - if project.source.type == "GITHUB": + if project.source.type in ("GITHUB", "GITHUB_ENTERPRISE"): project_github_repo_url = project.source.location project_role = next( ( @@ -24,25 +28,29 @@ def execute(self): ), None, ) - project_iam_trust_policy = project_role.assume_role_policy + project_iam_trust_policy = ( + project_role.assume_role_policy if project_role else None + ) if project_iam_trust_policy: - if isinstance(project_iam_trust_policy["Statement"], list): - for statement in project_iam_trust_policy["Statement"]: - if ( - statement["Effect"] == "Allow" - and statement["Principal"]["Service"] - == "codebuild.amazonaws.com" - ): - if project_github_repo_url: - org_name = project_github_repo_url.split("/")[3] - if org_name not in allowed_organizations: - report.status = "FAIL" - report.status_extended = f"CodeBuild project {project.name} uses GitHub organization '{org_name}', which is not in the allowed organizations." - else: - report.status_extended = f"CodeBuild project {project.name} uses GitHub organization '{org_name}', which is in the allowed organizations." + if not has_codebuild_trusted_principal(project_iam_trust_policy): + report.status_extended = f"CodeBuild project {project.name} does not use an IAM role with codebuild.amazonaws.com as a trusted principal, skipping GitHub organization check." + else: + is_allowed, org_name = is_codebuild_using_allowed_github_org( + project_iam_trust_policy, + project_github_repo_url, + allowed_organizations, + ) + if org_name is not None: + if is_allowed: + report.status_extended = f"CodeBuild project {project.name} uses GitHub organization '{org_name}', which is in the allowed organizations." else: - report.status_extended = f"CodeBuild project {project.name} does not use an IAM role with codebuild.amazonaws.com as a trusted principal, skipping GitHub organization check." + report.status = "FAIL" + report.status_extended = f"CodeBuild project {project.name} uses GitHub organization '{org_name}', which is not in the allowed organizations." + else: + report.status_extended = f"CodeBuild project {project.name} uses a GitHub repository with an invalid or unrecognized organization in the URL." + else: + report.status_extended = f"CodeBuild project {project.name} does not use an IAM role with codebuild.amazonaws.com as a trusted principal, skipping GitHub organization check." findings.append(report) diff --git a/prowler/providers/aws/services/iam/lib/policy.py b/prowler/providers/aws/services/iam/lib/policy.py index b45dd1bd30..fe8f09426b 100644 --- a/prowler/providers/aws/services/iam/lib/policy.py +++ b/prowler/providers/aws/services/iam/lib/policy.py @@ -520,3 +520,56 @@ def is_valid_aws_service(service): if service in read_aws_regions_file()["services"]: return True return False + + +def is_codebuild_using_allowed_github_org( + trust_policy: dict, github_repo_url: str, allowed_organizations: list +) -> tuple[bool, str | None]: + """ + Checks if the trust policy allows codebuild.amazonaws.com as a trusted principal and if the GitHub organization + in the repo URL is in the allowed organizations list. + Returns (is_allowed: bool, org_name: str or None) + """ + if not trust_policy or not github_repo_url: + return False, None + + statements = trust_policy.get("Statement", []) + if not isinstance(statements, list): + statements = [statements] + + for statement in statements: + if ( + statement.get("Effect") == "Allow" + and "Principal" in statement + and isinstance(statement["Principal"], dict) + and statement["Principal"].get("Service") == "codebuild.amazonaws.com" + ): + # Extract org name from GitHub repo URL + try: + org_name = github_repo_url.split("/")[3] + if not org_name: + org_name = None + except IndexError: + org_name = None + if org_name and org_name in allowed_organizations: + return True, org_name + return False, org_name + return False, None + + +def has_codebuild_trusted_principal(trust_policy: dict) -> bool: + """ + Returns True if the trust policy allows codebuild.amazonaws.com as a trusted principal, otherwise False. + """ + if not trust_policy: + return False + statements = trust_policy.get("Statement", []) + if not isinstance(statements, list): + statements = [statements] + return any( + s.get("Effect") == "Allow" + and "Principal" in s + and isinstance(s["Principal"], dict) + and s["Principal"].get("Service") == "codebuild.amazonaws.com" + for s in statements + ) diff --git a/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py b/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py index bc1ad86ed7..6e07f03f8b 100644 --- a/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py +++ b/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py @@ -5,6 +5,7 @@ from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild from prowler.providers.aws.services.iam.iam_service import IAM +from prowler.providers.aws.services.iam.lib import policy from tests.providers.aws.utils import AWS_REGION_EU_WEST_1, set_mocked_aws_provider @@ -254,3 +255,252 @@ def test_project_github_no_codebuild_trusted_principal(self): in result[0].status_extended ) assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_project_github_enterprise_allowed_organization(self): + role_arn = self.create_codebuild_role() + project_name = "test-project-github-enterprise-allowed" + project_arn = self.create_codebuild_project( + project_name, + "GITHUB_ENTERPRISE", + "https://github.enterprise.com/allowed-org/repo", + role_arn, + ) + + aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( + {"codebuild_github_allowed_organizations": ["allowed-org"]} + ) + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", + codebuild_mock, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", + iam_mock, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, + ) + + check = codebuild_project_uses_allowed_github_organizations() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert "which is in the allowed organizations" in result[0].status_extended + assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_project_github_enterprise_not_allowed_organization(self): + role_arn = self.create_codebuild_role() + project_name = "test-project-github-enterprise-not-allowed" + project_arn = self.create_codebuild_project( + project_name, + "GITHUB_ENTERPRISE", + "https://github.enterprise.com/not-allowed-org/repo", + role_arn, + ) + + aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( + {"codebuild_github_allowed_organizations": ["allowed-org"]} + ) + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", + codebuild_mock, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", + iam_mock, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, + ) + + check = codebuild_project_uses_allowed_github_organizations() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert ( + "which is not in the allowed organizations" in result[0].status_extended + ) + assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_project_github_enterprise_no_codebuild_trusted_principal(self): + role_arn = self.create_codebuild_role( + "lambda-test-role-enterprise", "lambda.amazonaws.com" + ) + project_name = "test-project-github-enterprise-lambda-role" + project_arn = self.create_codebuild_project( + project_name, + "GITHUB_ENTERPRISE", + "https://github.enterprise.com/not-allowed-org/repo", + role_arn, + ) + + aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( + {"codebuild_github_allowed_organizations": ["allowed-org"]} + ) + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", + codebuild_mock, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", + iam_mock, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, + ) + + check = codebuild_project_uses_allowed_github_organizations() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert ( + "does not use an IAM role with codebuild.amazonaws.com as a trusted principal" + in result[0].status_extended + ) + assert result[0].region == AWS_REGION_EU_WEST_1 + + +def test_check_codebuild_trust_and_github_org_allows(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + github_repo_url = "https://github.com/allowed-org/repo" + allowed_organizations = ["allowed-org"] + is_allowed, org_name = policy.is_codebuild_using_allowed_github_org( + trust_policy, github_repo_url, allowed_organizations + ) + assert is_allowed is True + assert org_name == "allowed-org" + + +def test_check_codebuild_trust_and_github_org_denies(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + github_repo_url = "https://github.com/not-allowed-org/repo" + allowed_organizations = ["allowed-org"] + is_allowed, org_name = policy.is_codebuild_using_allowed_github_org( + trust_policy, github_repo_url, allowed_organizations + ) + assert is_allowed is False + assert org_name == "not-allowed-org" + + +def test_check_codebuild_trust_and_github_org_no_codebuild_principal(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "lambda.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + github_repo_url = "https://github.com/allowed-org/repo" + allowed_organizations = ["allowed-org"] + is_allowed, org_name = policy.is_codebuild_using_allowed_github_org( + trust_policy, github_repo_url, allowed_organizations + ) + assert is_allowed is False + assert org_name is None + + +def test_check_codebuild_trust_and_github_org_invalid_url(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + github_repo_url = "https://github.com/" + allowed_organizations = ["allowed-org"] + is_allowed, org_name = policy.is_codebuild_using_allowed_github_org( + trust_policy, github_repo_url, allowed_organizations + ) + assert is_allowed is False + assert org_name is None + + +def test_has_codebuild_trusted_principal_true(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + assert policy.has_codebuild_trusted_principal(trust_policy) is True + + +def test_has_codebuild_trusted_principal_false(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "lambda.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + assert policy.has_codebuild_trusted_principal(trust_policy) is False + + +def test_has_codebuild_trusted_principal_empty(): + trust_policy = {} + assert policy.has_codebuild_trusted_principal(trust_policy) is False From 84c90fb228bb325ee56d5ade315471c5a758e3e2 Mon Sep 17 00:00:00 2001 From: "Andoni A." <14891798+andoniaf@users.noreply.github.com> Date: Tue, 20 May 2025 08:27:42 +0200 Subject: [PATCH 6/8] chore: add policy tests --- .../aws/services/iam/lib/policy_test.py | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/tests/providers/aws/services/iam/lib/policy_test.py b/tests/providers/aws/services/iam/lib/policy_test.py index bac84355ac..4dda383f41 100644 --- a/tests/providers/aws/services/iam/lib/policy_test.py +++ b/tests/providers/aws/services/iam/lib/policy_test.py @@ -1,6 +1,8 @@ from prowler.providers.aws.services.iam.lib.policy import ( check_admin_access, check_full_service_access, + has_codebuild_trusted_principal, + is_codebuild_using_allowed_github_org, is_condition_block_restrictive, is_condition_block_restrictive_organization, is_condition_restricting_from_private_ip, @@ -2073,3 +2075,116 @@ def test_check_admin_access_not_resource_with_random_resource(self): ], } assert check_admin_access(policy) + + +def test_is_codebuild_using_allowed_github_org_allows(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + github_repo_url = "https://github.com/allowed-org/repo" + allowed_organizations = ["allowed-org"] + is_allowed, org_name = is_codebuild_using_allowed_github_org( + trust_policy, github_repo_url, allowed_organizations + ) + assert is_allowed is True + assert org_name == "allowed-org" + + +def test_is_codebuild_using_allowed_github_org_denies(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + github_repo_url = "https://github.com/not-allowed-org/repo" + allowed_organizations = ["allowed-org"] + is_allowed, org_name = is_codebuild_using_allowed_github_org( + trust_policy, github_repo_url, allowed_organizations + ) + assert is_allowed is False + assert org_name == "not-allowed-org" + + +def test_is_codebuild_using_allowed_github_org_no_codebuild_principal(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "lambda.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + github_repo_url = "https://github.com/allowed-org/repo" + allowed_organizations = ["allowed-org"] + is_allowed, org_name = is_codebuild_using_allowed_github_org( + trust_policy, github_repo_url, allowed_organizations + ) + assert is_allowed is False + assert org_name is None + + +def test_is_codebuild_using_allowed_github_org_invalid_url(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + github_repo_url = "https://github.com/" + allowed_organizations = ["allowed-org"] + is_allowed, org_name = is_codebuild_using_allowed_github_org( + trust_policy, github_repo_url, allowed_organizations + ) + assert is_allowed is False + assert org_name is None + + +def test_has_codebuild_trusted_principal_true(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + assert has_codebuild_trusted_principal(trust_policy) is True + + +def test_has_codebuild_trusted_principal_false(): + trust_policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "lambda.amazonaws.com"}, + "Action": "sts:AssumeRole", + } + ], + } + assert has_codebuild_trusted_principal(trust_policy) is False + + +def test_has_codebuild_trusted_principal_empty(): + trust_policy = {} + assert has_codebuild_trusted_principal(trust_policy) is False From e4e62217e25b2ca4bdd9bf0a2673df0139072b29 Mon Sep 17 00:00:00 2001 From: "Andoni A." <14891798+andoniaf@users.noreply.github.com> Date: Tue, 20 May 2025 08:53:54 +0200 Subject: [PATCH 7/8] refactor: check tests --- ...oject_uses_allowed_github_organizations.py | 506 ------------------ ..._uses_allowed_github_organizations_test.py | 397 ++++++++++++++ 2 files changed, 397 insertions(+), 506 deletions(-) delete mode 100644 tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py create mode 100644 tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py diff --git a/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py b/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py deleted file mode 100644 index 6e07f03f8b..0000000000 --- a/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py +++ /dev/null @@ -1,506 +0,0 @@ -from unittest.mock import patch - -from boto3 import client -from moto import mock_aws - -from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild -from prowler.providers.aws.services.iam.iam_service import IAM -from prowler.providers.aws.services.iam.lib import policy -from tests.providers.aws.utils import AWS_REGION_EU_WEST_1, set_mocked_aws_provider - - -class Test_codebuild_project_uses_allowed_github_organizations: - def setup_codebuild_iam_mocks(self, audit_config=None): - """Helper method to set up common mocks""" - if audit_config is None: - audit_config = {} - - aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) - - codebuild_mock = Codebuild(aws_provider) - codebuild_mock.audit_config = audit_config - - iam_mock = IAM(aws_provider) - - return aws_provider, codebuild_mock, iam_mock - - def create_codebuild_role( - self, role_name="codebuild-test-role", service="codebuild.amazonaws.com" - ): - """Helper method to create an IAM role""" - iam_client = client("iam") - assume_role_policy_document = { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": {"Service": service}, - "Action": "sts:AssumeRole", - } - ], - } - role = iam_client.create_role( - RoleName=role_name, - AssumeRolePolicyDocument=str(assume_role_policy_document).replace("'", '"'), - ) - return role["Role"]["Arn"] - - def create_codebuild_project( - self, project_name, source_type, source_location, role_arn - ): - """Helper method to create a CodeBuild project""" - codebuild_client = client("codebuild", region_name=AWS_REGION_EU_WEST_1) - project = codebuild_client.create_project( - name=project_name, - source={ - "type": source_type, - "location": source_location, - }, - artifacts={ - "type": "NO_ARTIFACTS", - }, - environment={ - "type": "LINUX_CONTAINER", - "image": "aws/codebuild/standard:4.0", - "computeType": "BUILD_GENERAL1_SMALL", - }, - serviceRole=role_arn, - ) - return project["project"]["arn"] - - @mock_aws - def test_no_projects(self): - aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks() - - with ( - patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=aws_provider, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", - codebuild_mock, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", - iam_mock, - ), - ): - from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( - codebuild_project_uses_allowed_github_organizations, - ) - - check = codebuild_project_uses_allowed_github_organizations() - result = check.execute() - - assert len(result) == 0 - - @mock_aws - def test_project_not_github(self): - role_arn = self.create_codebuild_role() - project_name = "test-project-not-github" - self.create_codebuild_project( - project_name, "S3", "test-bucket/source.zip", role_arn - ) - - aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks() - - with ( - patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=aws_provider, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", - codebuild_mock, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", - iam_mock, - ), - ): - from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( - codebuild_project_uses_allowed_github_organizations, - ) - - check = codebuild_project_uses_allowed_github_organizations() - result = check.execute() - - # Non-GitHub projects should not be reported - assert len(result) == 0 - - @mock_aws - def test_project_github_allowed_organization(self): - role_arn = self.create_codebuild_role() - project_name = "test-project-github-allowed" - project_arn = self.create_codebuild_project( - project_name, "GITHUB", "https://github.com/allowed-org/repo", role_arn - ) - - aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( - {"codebuild_github_allowed_organizations": ["allowed-org"]} - ) - - with ( - patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=aws_provider, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", - codebuild_mock, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", - iam_mock, - ), - ): - from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( - codebuild_project_uses_allowed_github_organizations, - ) - - check = codebuild_project_uses_allowed_github_organizations() - result = check.execute() - - assert len(result) == 1 - assert result[0].status == "PASS" - assert result[0].resource_id == project_name - assert result[0].resource_arn == project_arn - assert "which is in the allowed organizations" in result[0].status_extended - assert result[0].region == AWS_REGION_EU_WEST_1 - - @mock_aws - def test_project_github_not_allowed_organization(self): - role_arn = self.create_codebuild_role() - project_name = "test-project-github-not-allowed" - project_arn = self.create_codebuild_project( - project_name, "GITHUB", "https://github.com/not-allowed-org/repo", role_arn - ) - - aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( - {"codebuild_github_allowed_organizations": ["allowed-org"]} - ) - - with ( - patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=aws_provider, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", - codebuild_mock, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", - iam_mock, - ), - ): - from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( - codebuild_project_uses_allowed_github_organizations, - ) - - check = codebuild_project_uses_allowed_github_organizations() - result = check.execute() - - assert len(result) == 1 - assert result[0].status == "FAIL" - assert result[0].resource_id == project_name - assert result[0].resource_arn == project_arn - assert ( - "which is not in the allowed organizations" in result[0].status_extended - ) - assert result[0].region == AWS_REGION_EU_WEST_1 - - @mock_aws - def test_project_github_no_codebuild_trusted_principal(self): - role_arn = self.create_codebuild_role( - "lambda-test-role", "lambda.amazonaws.com" - ) - project_name = "test-project-github-lambda-role" - project_arn = self.create_codebuild_project( - project_name, "GITHUB", "https://github.com/not-allowed-org/repo", role_arn - ) - - aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( - {"codebuild_github_allowed_organizations": ["allowed-org"]} - ) - - with ( - patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=aws_provider, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", - codebuild_mock, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", - iam_mock, - ), - ): - from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( - codebuild_project_uses_allowed_github_organizations, - ) - - check = codebuild_project_uses_allowed_github_organizations() - result = check.execute() - - assert len(result) == 1 - assert result[0].status == "PASS" - assert result[0].resource_id == project_name - assert result[0].resource_arn == project_arn - assert ( - "does not use an IAM role with codebuild.amazonaws.com as a trusted principal" - in result[0].status_extended - ) - assert result[0].region == AWS_REGION_EU_WEST_1 - - @mock_aws - def test_project_github_enterprise_allowed_organization(self): - role_arn = self.create_codebuild_role() - project_name = "test-project-github-enterprise-allowed" - project_arn = self.create_codebuild_project( - project_name, - "GITHUB_ENTERPRISE", - "https://github.enterprise.com/allowed-org/repo", - role_arn, - ) - - aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( - {"codebuild_github_allowed_organizations": ["allowed-org"]} - ) - - with ( - patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=aws_provider, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", - codebuild_mock, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", - iam_mock, - ), - ): - from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( - codebuild_project_uses_allowed_github_organizations, - ) - - check = codebuild_project_uses_allowed_github_organizations() - result = check.execute() - - assert len(result) == 1 - assert result[0].status == "PASS" - assert result[0].resource_id == project_name - assert result[0].resource_arn == project_arn - assert "which is in the allowed organizations" in result[0].status_extended - assert result[0].region == AWS_REGION_EU_WEST_1 - - @mock_aws - def test_project_github_enterprise_not_allowed_organization(self): - role_arn = self.create_codebuild_role() - project_name = "test-project-github-enterprise-not-allowed" - project_arn = self.create_codebuild_project( - project_name, - "GITHUB_ENTERPRISE", - "https://github.enterprise.com/not-allowed-org/repo", - role_arn, - ) - - aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( - {"codebuild_github_allowed_organizations": ["allowed-org"]} - ) - - with ( - patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=aws_provider, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", - codebuild_mock, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", - iam_mock, - ), - ): - from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( - codebuild_project_uses_allowed_github_organizations, - ) - - check = codebuild_project_uses_allowed_github_organizations() - result = check.execute() - - assert len(result) == 1 - assert result[0].status == "FAIL" - assert result[0].resource_id == project_name - assert result[0].resource_arn == project_arn - assert ( - "which is not in the allowed organizations" in result[0].status_extended - ) - assert result[0].region == AWS_REGION_EU_WEST_1 - - @mock_aws - def test_project_github_enterprise_no_codebuild_trusted_principal(self): - role_arn = self.create_codebuild_role( - "lambda-test-role-enterprise", "lambda.amazonaws.com" - ) - project_name = "test-project-github-enterprise-lambda-role" - project_arn = self.create_codebuild_project( - project_name, - "GITHUB_ENTERPRISE", - "https://github.enterprise.com/not-allowed-org/repo", - role_arn, - ) - - aws_provider, codebuild_mock, iam_mock = self.setup_codebuild_iam_mocks( - {"codebuild_github_allowed_organizations": ["allowed-org"]} - ) - - with ( - patch( - "prowler.providers.common.provider.Provider.get_global_provider", - return_value=aws_provider, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", - codebuild_mock, - ), - patch( - "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", - iam_mock, - ), - ): - from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( - codebuild_project_uses_allowed_github_organizations, - ) - - check = codebuild_project_uses_allowed_github_organizations() - result = check.execute() - - assert len(result) == 1 - assert result[0].status == "PASS" - assert result[0].resource_id == project_name - assert result[0].resource_arn == project_arn - assert ( - "does not use an IAM role with codebuild.amazonaws.com as a trusted principal" - in result[0].status_extended - ) - assert result[0].region == AWS_REGION_EU_WEST_1 - - -def test_check_codebuild_trust_and_github_org_allows(): - trust_policy = { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": {"Service": "codebuild.amazonaws.com"}, - "Action": "sts:AssumeRole", - } - ], - } - github_repo_url = "https://github.com/allowed-org/repo" - allowed_organizations = ["allowed-org"] - is_allowed, org_name = policy.is_codebuild_using_allowed_github_org( - trust_policy, github_repo_url, allowed_organizations - ) - assert is_allowed is True - assert org_name == "allowed-org" - - -def test_check_codebuild_trust_and_github_org_denies(): - trust_policy = { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": {"Service": "codebuild.amazonaws.com"}, - "Action": "sts:AssumeRole", - } - ], - } - github_repo_url = "https://github.com/not-allowed-org/repo" - allowed_organizations = ["allowed-org"] - is_allowed, org_name = policy.is_codebuild_using_allowed_github_org( - trust_policy, github_repo_url, allowed_organizations - ) - assert is_allowed is False - assert org_name == "not-allowed-org" - - -def test_check_codebuild_trust_and_github_org_no_codebuild_principal(): - trust_policy = { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": {"Service": "lambda.amazonaws.com"}, - "Action": "sts:AssumeRole", - } - ], - } - github_repo_url = "https://github.com/allowed-org/repo" - allowed_organizations = ["allowed-org"] - is_allowed, org_name = policy.is_codebuild_using_allowed_github_org( - trust_policy, github_repo_url, allowed_organizations - ) - assert is_allowed is False - assert org_name is None - - -def test_check_codebuild_trust_and_github_org_invalid_url(): - trust_policy = { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": {"Service": "codebuild.amazonaws.com"}, - "Action": "sts:AssumeRole", - } - ], - } - github_repo_url = "https://github.com/" - allowed_organizations = ["allowed-org"] - is_allowed, org_name = policy.is_codebuild_using_allowed_github_org( - trust_policy, github_repo_url, allowed_organizations - ) - assert is_allowed is False - assert org_name is None - - -def test_has_codebuild_trusted_principal_true(): - trust_policy = { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": {"Service": "codebuild.amazonaws.com"}, - "Action": "sts:AssumeRole", - } - ], - } - assert policy.has_codebuild_trusted_principal(trust_policy) is True - - -def test_has_codebuild_trusted_principal_false(): - trust_policy = { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": {"Service": "lambda.amazonaws.com"}, - "Action": "sts:AssumeRole", - } - ], - } - assert policy.has_codebuild_trusted_principal(trust_policy) is False - - -def test_has_codebuild_trusted_principal_empty(): - trust_policy = {} - assert policy.has_codebuild_trusted_principal(trust_policy) is False diff --git a/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py b/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py new file mode 100644 index 0000000000..4dbb0cf800 --- /dev/null +++ b/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py @@ -0,0 +1,397 @@ +from unittest.mock import patch + +from boto3 import client +from moto import mock_aws + +from tests.providers.aws.utils import AWS_REGION_EU_WEST_1, set_mocked_aws_provider + +AWS_ACCOUNT_NUMBER = "123456789012" + + +class Test_codebuild_project_uses_allowed_github_organizations: + @mock_aws + def test_no_projects(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", + {"codebuild_github_allowed_organizations": ["allowed-org"]}, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, + ) + + check = codebuild_project_uses_allowed_github_organizations() + result = check.execute() + + assert len(result) == 0 + + @mock_aws + def test_project_github_allowed_organization(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + codebuild_client = client("codebuild", region_name=AWS_REGION_EU_WEST_1) + iam_client = client("iam", region_name=AWS_REGION_EU_WEST_1) + project_name = "test-project-github-allowed" + role_name = "codebuild-test-role" + role_arn = iam_client.create_role( + RoleName=role_name, + AssumeRolePolicyDocument="""{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole" + } + ] + }""", + )["Role"]["Arn"] + project_arn = codebuild_client.create_project( + name=project_name, + source={ + "type": "GITHUB", + "location": "https://github.com/allowed-org/repo", + }, + artifacts={"type": "NO_ARTIFACTS"}, + environment={ + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/standard:4.0", + "computeType": "BUILD_GENERAL1_SMALL", + "environmentVariables": [], + }, + serviceRole=role_arn, + tags=[{"key": "Name", "value": "test"}], + )["project"]["arn"] + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", + {"codebuild_github_allowed_organizations": ["allowed-org"]}, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, + ) + + check = codebuild_project_uses_allowed_github_organizations() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert "which is in the allowed organizations" in result[0].status_extended + assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_project_github_not_allowed_organization(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + codebuild_client = client("codebuild", region_name=AWS_REGION_EU_WEST_1) + iam_client = client("iam", region_name=AWS_REGION_EU_WEST_1) + project_name = "test-project-github-not-allowed" + role_name = "codebuild-test-role" + role_arn = iam_client.create_role( + RoleName=role_name, + AssumeRolePolicyDocument="""{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole" + } + ] + }""", + )["Role"]["Arn"] + project_arn = codebuild_client.create_project( + name=project_name, + source={ + "type": "GITHUB", + "location": "https://github.com/not-allowed-org/repo", + }, + artifacts={"type": "NO_ARTIFACTS"}, + environment={ + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/standard:4.0", + "computeType": "BUILD_GENERAL1_SMALL", + "environmentVariables": [], + }, + serviceRole=role_arn, + tags=[{"key": "Name", "value": "test"}], + )["project"]["arn"] + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", + {"codebuild_github_allowed_organizations": ["allowed-org"]}, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, + ) + + check = codebuild_project_uses_allowed_github_organizations() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert ( + "which is not in the allowed organizations" in result[0].status_extended + ) + assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_project_github_no_codebuild_trusted_principal(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + codebuild_client = client("codebuild", region_name=AWS_REGION_EU_WEST_1) + iam_client = client("iam", region_name=AWS_REGION_EU_WEST_1) + project_name = "test-project-github-lambda-role" + role_name = "lambda-test-role" + role_arn = iam_client.create_role( + RoleName=role_name, + AssumeRolePolicyDocument="""{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "lambda.amazonaws.com"}, + "Action": "sts:AssumeRole" + } + ] + }""", + )["Role"]["Arn"] + project_arn = codebuild_client.create_project( + name=project_name, + source={ + "type": "GITHUB", + "location": "https://github.com/not-allowed-org/repo", + }, + artifacts={"type": "NO_ARTIFACTS"}, + environment={ + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/standard:4.0", + "computeType": "BUILD_GENERAL1_SMALL", + "environmentVariables": [], + }, + serviceRole=role_arn, + tags=[{"key": "Name", "value": "test"}], + )["project"]["arn"] + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", + {"codebuild_github_allowed_organizations": ["allowed-org"]}, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, + ) + + check = codebuild_project_uses_allowed_github_organizations() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert ( + "does not use an IAM role with codebuild.amazonaws.com as a trusted principal" + in result[0].status_extended + ) + assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_project_github_enterprise_allowed_organization(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + codebuild_client = client("codebuild", region_name=AWS_REGION_EU_WEST_1) + iam_client = client("iam", region_name=AWS_REGION_EU_WEST_1) + project_name = "test-project-github-enterprise-allowed" + role_name = "codebuild-test-role" + role_arn = iam_client.create_role( + RoleName=role_name, + AssumeRolePolicyDocument="""{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole" + } + ] + }""", + )["Role"]["Arn"] + project_arn = codebuild_client.create_project( + name=project_name, + source={ + "type": "GITHUB_ENTERPRISE", + "location": "https://github.enterprise.com/allowed-org/repo", + }, + artifacts={"type": "NO_ARTIFACTS"}, + environment={ + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/standard:4.0", + "computeType": "BUILD_GENERAL1_SMALL", + "environmentVariables": [], + }, + serviceRole=role_arn, + tags=[{"key": "Name", "value": "test"}], + )["project"]["arn"] + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", + {"codebuild_github_allowed_organizations": ["allowed-org"]}, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, + ) + + check = codebuild_project_uses_allowed_github_organizations() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert "which is in the allowed organizations" in result[0].status_extended + assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_project_github_enterprise_not_allowed_organization(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + codebuild_client = client("codebuild", region_name=AWS_REGION_EU_WEST_1) + iam_client = client("iam", region_name=AWS_REGION_EU_WEST_1) + project_name = "test-project-github-enterprise-not-allowed" + role_name = "codebuild-test-role" + role_arn = iam_client.create_role( + RoleName=role_name, + AssumeRolePolicyDocument="""{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "codebuild.amazonaws.com"}, + "Action": "sts:AssumeRole" + } + ] + }""", + )["Role"]["Arn"] + project_arn = codebuild_client.create_project( + name=project_name, + source={ + "type": "GITHUB_ENTERPRISE", + "location": "https://github.enterprise.com/not-allowed-org/repo", + }, + artifacts={"type": "NO_ARTIFACTS"}, + environment={ + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/standard:4.0", + "computeType": "BUILD_GENERAL1_SMALL", + "environmentVariables": [], + }, + serviceRole=role_arn, + tags=[{"key": "Name", "value": "test"}], + )["project"]["arn"] + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", + {"codebuild_github_allowed_organizations": ["allowed-org"]}, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, + ) + + check = codebuild_project_uses_allowed_github_organizations() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert ( + "which is not in the allowed organizations" in result[0].status_extended + ) + assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_project_github_enterprise_no_codebuild_trusted_principal(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + codebuild_client = client("codebuild", region_name=AWS_REGION_EU_WEST_1) + iam_client = client("iam", region_name=AWS_REGION_EU_WEST_1) + project_name = "test-project-github-enterprise-lambda-role" + role_name = "lambda-test-role-enterprise" + role_arn = iam_client.create_role( + RoleName=role_name, + AssumeRolePolicyDocument="""{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": {"Service": "lambda.amazonaws.com"}, + "Action": "sts:AssumeRole" + } + ] + }""", + )["Role"]["Arn"] + project_arn = codebuild_client.create_project( + name=project_name, + source={ + "type": "GITHUB_ENTERPRISE", + "location": "https://github.enterprise.com/not-allowed-org/repo", + }, + artifacts={"type": "NO_ARTIFACTS"}, + environment={ + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/standard:4.0", + "computeType": "BUILD_GENERAL1_SMALL", + "environmentVariables": [], + }, + serviceRole=role_arn, + tags=[{"key": "Name", "value": "test"}], + )["project"]["arn"] + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", + {"codebuild_github_allowed_organizations": ["allowed-org"]}, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, + ) + + check = codebuild_project_uses_allowed_github_organizations() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].resource_id == project_name + assert result[0].resource_arn == project_arn + assert ( + "does not use an IAM role with codebuild.amazonaws.com as a trusted principal" + in result[0].status_extended + ) + assert result[0].region == AWS_REGION_EU_WEST_1 From 7a177f12fefe4f16ee9f87314dde880663c11f2d Mon Sep 17 00:00:00 2001 From: "Andoni A." <14891798+andoniaf@users.noreply.github.com> Date: Tue, 27 May 2025 09:38:11 +0200 Subject: [PATCH 8/8] fix: tests --- .../providers/aws/services/iam/lib/policy.py | 3 +- ..._uses_allowed_github_organizations_test.py | 78 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/prowler/providers/aws/services/iam/lib/policy.py b/prowler/providers/aws/services/iam/lib/policy.py index 9f82322542..ba1bdb9e5e 100644 --- a/prowler/providers/aws/services/iam/lib/policy.py +++ b/prowler/providers/aws/services/iam/lib/policy.py @@ -1,5 +1,6 @@ from ipaddress import ip_address, ip_network import re +from typing import Optional, Tuple from prowler.lib.logger import logger from prowler.providers.aws.aws_provider import read_aws_regions_file @@ -574,7 +575,7 @@ def is_valid_aws_service(service): def is_codebuild_using_allowed_github_org( trust_policy: dict, github_repo_url: str, allowed_organizations: list -) -> tuple[bool, str | None]: +) -> Tuple[bool, Optional[str]]: """ Checks if the trust policy allows codebuild.amazonaws.com as a trusted principal and if the GitHub organization in the repo URL is in the allowed organizations list. diff --git a/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py b/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py index 4dbb0cf800..1f1e84dd63 100644 --- a/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py +++ b/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py @@ -13,11 +13,17 @@ class Test_codebuild_project_uses_allowed_github_organizations: def test_no_projects(self): aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild + with ( patch( "prowler.providers.common.provider.Provider.get_global_provider", return_value=aws_provider, ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", + new=Codebuild(aws_provider), + ), patch( "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", {"codebuild_github_allowed_organizations": ["allowed-org"]}, @@ -68,11 +74,23 @@ def test_project_github_allowed_organization(self): serviceRole=role_arn, tags=[{"key": "Name", "value": "test"}], )["project"]["arn"] + + from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild + from prowler.providers.aws.services.iam.iam_service import IAM + with ( patch( "prowler.providers.common.provider.Provider.get_global_provider", return_value=aws_provider, ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", + new=Codebuild(aws_provider), + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", + new=IAM(aws_provider), + ), patch( "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", {"codebuild_github_allowed_organizations": ["allowed-org"]}, @@ -127,11 +145,23 @@ def test_project_github_not_allowed_organization(self): serviceRole=role_arn, tags=[{"key": "Name", "value": "test"}], )["project"]["arn"] + + from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild + from prowler.providers.aws.services.iam.iam_service import IAM + with ( patch( "prowler.providers.common.provider.Provider.get_global_provider", return_value=aws_provider, ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", + new=Codebuild(aws_provider), + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", + new=IAM(aws_provider), + ), patch( "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", {"codebuild_github_allowed_organizations": ["allowed-org"]}, @@ -188,11 +218,23 @@ def test_project_github_no_codebuild_trusted_principal(self): serviceRole=role_arn, tags=[{"key": "Name", "value": "test"}], )["project"]["arn"] + + from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild + from prowler.providers.aws.services.iam.iam_service import IAM + with ( patch( "prowler.providers.common.provider.Provider.get_global_provider", return_value=aws_provider, ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", + new=Codebuild(aws_provider), + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", + new=IAM(aws_provider), + ), patch( "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", {"codebuild_github_allowed_organizations": ["allowed-org"]}, @@ -250,11 +292,23 @@ def test_project_github_enterprise_allowed_organization(self): serviceRole=role_arn, tags=[{"key": "Name", "value": "test"}], )["project"]["arn"] + + from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild + from prowler.providers.aws.services.iam.iam_service import IAM + with ( patch( "prowler.providers.common.provider.Provider.get_global_provider", return_value=aws_provider, ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", + new=Codebuild(aws_provider), + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", + new=IAM(aws_provider), + ), patch( "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", {"codebuild_github_allowed_organizations": ["allowed-org"]}, @@ -309,11 +363,23 @@ def test_project_github_enterprise_not_allowed_organization(self): serviceRole=role_arn, tags=[{"key": "Name", "value": "test"}], )["project"]["arn"] + + from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild + from prowler.providers.aws.services.iam.iam_service import IAM + with ( patch( "prowler.providers.common.provider.Provider.get_global_provider", return_value=aws_provider, ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", + new=Codebuild(aws_provider), + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", + new=IAM(aws_provider), + ), patch( "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", {"codebuild_github_allowed_organizations": ["allowed-org"]}, @@ -370,11 +436,23 @@ def test_project_github_enterprise_no_codebuild_trusted_principal(self): serviceRole=role_arn, tags=[{"key": "Name", "value": "test"}], )["project"]["arn"] + + from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild + from prowler.providers.aws.services.iam.iam_service import IAM + with ( patch( "prowler.providers.common.provider.Provider.get_global_provider", return_value=aws_provider, ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", + new=Codebuild(aws_provider), + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", + new=IAM(aws_provider), + ), patch( "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", {"codebuild_github_allowed_organizations": ["allowed-org"]},