feat(iam): add new check to ensure user does not have policies with admin access (#4802)

This commit is contained in:
Rubén De la Torre Vico
2024-08-20 17:08:51 +02:00
committed by GitHub
parent 8129b174f1
commit 78042063cb
4 changed files with 182 additions and 0 deletions
@@ -0,0 +1,30 @@
{
"Provider": "aws",
"CheckID": "iam_user_administrator_access_policy",
"CheckTitle": "Ensure No IAM Users Have Administrator Access Policy",
"CheckType": [],
"ServiceName": "iam",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
"Severity": "high",
"ResourceType": "AwsIamUser",
"Description": "This check ensures that no IAM users 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 users 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_users.html",
"Remediation": {
"Code": {
"CLI": "aws iam detach-user-policy --user-name <username> --policy-arn arn:aws:iam::aws:policy/AdministratorAccess",
"NativeIaC": "",
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/IAM/admin-permissions.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": ""
}
@@ -0,0 +1,30 @@
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_user_administrator_access_policy(Check):
def execute(self) -> List[Check_Report_AWS]:
findings = []
for user in iam_client.users:
report = Check_Report_AWS(self.metadata())
report.region = iam_client.region
report.resource_arn = user.arn
report.resource_id = user.name
report.resource_tags = user.tags
report.status = "PASS"
report.status_extended = (
f"IAM User {user.name} does not have AdministratorAccess policy."
)
for policy in user.attached_policies:
if policy["PolicyName"] == "AdministratorAccess":
report.status = "FAIL"
report.status_extended = (
f"IAM User {user.name} has AdministratorAccess policy attached."
)
break
findings.append(report)
return findings
@@ -0,0 +1,122 @@
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_user_administrator_access_policy:
@mock_aws
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_user_administrator_access_policy.iam_user_administrator_access_policy.iam_client",
new=IAM(aws_provider),
):
# Test Check
from prowler.providers.aws.services.iam.iam_user_administrator_access_policy.iam_user_administrator_access_policy import (
iam_user_administrator_access_policy,
)
check = iam_user_administrator_access_policy()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_no_admin_users(self):
iam_client = client("iam", region_name=AWS_REGION_EU_WEST_1)
# Create non-admin user
user_arn = iam_client.create_user(UserName="non-admin-user")["User"]["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_user_administrator_access_policy.iam_user_administrator_access_policy.iam_client",
new=IAM(aws_provider),
):
from prowler.providers.aws.services.iam.iam_user_administrator_access_policy.iam_user_administrator_access_policy import (
iam_user_administrator_access_policy,
)
check = iam_user_administrator_access_policy()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "IAM User non-admin-user does not have AdministratorAccess policy."
)
assert result[0].region == AWS_REGION_EU_WEST_1
assert result[0].resource_id == "non-admin-user"
assert result[0].resource_arn == user_arn
assert result[0].resource_tags == []
@mock_aws
def test_admin_user(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 admin user
user_name = "admin-user"
user_arn = iam_client.create_user(UserName=user_name)["User"]["Arn"]
# Attach AdministratorAccess policy
iam_client.attach_user_policy(
UserName=user_name,
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_user_administrator_access_policy.iam_user_administrator_access_policy.iam_client",
new=IAM(aws_provider),
):
from prowler.providers.aws.services.iam.iam_user_administrator_access_policy.iam_user_administrator_access_policy import (
iam_user_administrator_access_policy,
)
check = iam_user_administrator_access_policy()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "IAM User admin-user has AdministratorAccess policy attached."
)
assert result[0].region == AWS_REGION_EU_WEST_1
assert result[0].resource_id == user_name
assert result[0].resource_arn == user_arn
assert result[0].resource_tags == []