From dec3e652c59870ac5a772eb73801bfff7c98a0c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Thu, 22 Aug 2024 16:14:45 +0200 Subject: [PATCH] feat(IAM): add new check `iam_group_administrator_access_policy` (#4831) Co-authored-by: Sergio Garcia <38561120+sergargar@users.noreply.github.com> --- .../__init__.py | 0 ..._administrator_access_policy.metadata.json | 30 +++++ .../iam_group_administrator_access_policy.py | 27 ++++ ..._group_administrator_access_policy_test.py | 116 ++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 prowler/providers/aws/services/iam/iam_group_administrator_access_policy/__init__.py create mode 100644 prowler/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy.metadata.json create mode 100644 prowler/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy.py create mode 100644 tests/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy_test.py diff --git a/prowler/providers/aws/services/iam/iam_group_administrator_access_policy/__init__.py b/prowler/providers/aws/services/iam/iam_group_administrator_access_policy/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy.metadata.json b/prowler/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy.metadata.json new file mode 100644 index 0000000000..ba1b9df0f6 --- /dev/null +++ b/prowler/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy.metadata.json @@ -0,0 +1,30 @@ +{ + "Provider": "aws", + "CheckID": "iam_group_administrator_access_policy", + "CheckTitle": "Ensure No IAM Groups Have Administrator Access Policy", + "CheckType": [], + "ServiceName": "iam", + "SubServiceName": "", + "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "Severity": "high", + "ResourceType": "AwsIamGroup", + "Description": "This check ensures that no IAM groups in your AWS account have the 'AdministratorAccess' policy attached. IAM users with this policy have unrestricted access to all AWS services and resources, which poses a significant security risk if misused.", + "Risk": "IAM groups with administrator-level permissions can perform any action on any resource in your AWS environment. If these permissions are granted to users unnecessarily or to individuals without sufficient knowledge, it can lead to security vulnerabilities, data leaks, data loss, or unexpected charges.", + "RelatedUrl": "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups_manage.html", + "Remediation": { + "Code": { + "CLI": "aws iam detach-group-policy --group-name --policy-arn arn:aws:iam::aws:policy/AdministratorAccess", + "NativeIaC": "", + "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/IAM/group-with-privileged-access.html", + "Terraform": "" + }, + "Recommendation": { + "Text": "Replace the 'AdministratorAccess' policy with more specific permissions that follow the Principle of Least Privilege. Consider implementing IAM roles such as 'IAM Master' and 'IAM Manager' to manage permissions more securely.", + "Url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy.py b/prowler/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy.py new file mode 100644 index 0000000000..0bf208feeb --- /dev/null +++ b/prowler/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy.py @@ -0,0 +1,27 @@ +from typing import List + +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.iam.iam_client import iam_client + + +class iam_group_administrator_access_policy(Check): + def execute(self) -> List[Check_Report_AWS]: + findings = [] + for group in iam_client.groups: + report = Check_Report_AWS(self.metadata()) + report.region = iam_client.region + report.resource_arn = group.arn + report.resource_id = group.name + report.status = "PASS" + report.status_extended = ( + f"IAM Group {group.name} does not have AdministratorAccess policy." + ) + for policy in group.attached_policies: + if policy["PolicyName"] == "AdministratorAccess": + report.status = "FAIL" + report.status_extended = f"IAM Group {group.name} has AdministratorAccess policy attached." + break + + findings.append(report) + + return findings diff --git a/tests/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy_test.py b/tests/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy_test.py new file mode 100644 index 0000000000..3c7c86d395 --- /dev/null +++ b/tests/providers/aws/services/iam/iam_group_administrator_access_policy/iam_group_administrator_access_policy_test.py @@ -0,0 +1,116 @@ +from json import dumps +from unittest import mock + +from boto3 import client +from moto import mock_aws + +from tests.providers.aws.utils import AWS_REGION_EU_WEST_1, set_mocked_aws_provider + + +class Test_iam_group_administrator_access_policy: + def test_no_users(self): + from prowler.providers.aws.services.iam.iam_service import IAM + + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), mock.patch( + "prowler.providers.aws.services.iam.iam_group_administrator_access_policy.iam_group_administrator_access_policy.iam_client", + new=IAM(aws_provider), + ): + # Test Check + from prowler.providers.aws.services.iam.iam_group_administrator_access_policy.iam_group_administrator_access_policy import ( + iam_group_administrator_access_policy, + ) + + check = iam_group_administrator_access_policy() + result = check.execute() + + assert len(result) == 0 + + @mock_aws + def test_no_admin_groups(self): + iam = client("iam", region_name=AWS_REGION_EU_WEST_1) + group_arn = iam.create_group(GroupName="test_group")["Group"]["Arn"] + + from prowler.providers.aws.services.iam.iam_service import IAM + + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), mock.patch( + "prowler.providers.aws.services.iam.iam_group_administrator_access_policy.iam_group_administrator_access_policy.iam_client", + new=IAM(aws_provider), + ): + # Test Check + from prowler.providers.aws.services.iam.iam_group_administrator_access_policy.iam_group_administrator_access_policy import ( + iam_group_administrator_access_policy, + ) + + check = iam_group_administrator_access_policy() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "IAM Group test_group does not have AdministratorAccess policy." + ) + assert result[0].region == AWS_REGION_EU_WEST_1 + assert result[0].resource_id == "test_group" + assert result[0].resource_arn == group_arn + + @mock_aws + def test_admin_groups(self): + iam_client = client("iam", region_name=AWS_REGION_EU_WEST_1) + + # Create the AdministratorAccess policy + policy_document = { + "Version": "2012-10-17", + "Statement": [{"Effect": "Allow", "Action": "*", "Resource": "*"}], + } + + policy_arn = iam_client.create_policy( + PolicyName="AdministratorAccess", + PolicyDocument=dumps(policy_document), + Path="/", + )["Policy"]["Arn"] + + # Create the test group + group_arn = iam_client.create_group(GroupName="test_group")["Group"]["Arn"] + + # Attach the AdministratorAccess policy to the test group + iam_client.attach_group_policy(GroupName="test_group", PolicyArn=policy_arn) + + from prowler.providers.aws.services.iam.iam_service import IAM + + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), mock.patch( + "prowler.providers.aws.services.iam.iam_group_administrator_access_policy.iam_group_administrator_access_policy.iam_client", + new=IAM(aws_provider), + ): + # Test Check + from prowler.providers.aws.services.iam.iam_group_administrator_access_policy.iam_group_administrator_access_policy import ( + iam_group_administrator_access_policy, + ) + + check = iam_group_administrator_access_policy() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == "IAM Group test_group has AdministratorAccess policy attached." + ) + assert result[0].region == AWS_REGION_EU_WEST_1 + assert result[0].resource_id == "test_group" + assert result[0].resource_arn == group_arn