Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(aws): disallow child-accounts to overwrite policy for ai_services_opt_out #6229

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"Provider": "aws",
"CheckID": "organizations_opt_out_ai_services_policy",
"CheckTitle": "Ensure that AWS Organizations opt-out of AI services policy is enabled.",
"CheckTitle": "Ensure that AWS Organizations opt-out of AI services policy is enabled and disallow child-accounts to overwrite this policy.",
"CheckType": [],
"ServiceName": "organizations",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:service::account-id:organization/organization-id",
"Severity": "low",
"ResourceType": "Other",
"Description": "This control checks whether the AWS Organizations opt-out of AI services policy is enabled. The control fails if the policy is not enabled.",
"Description": "This control checks whether the AWS Organizations opt-out of AI services policy is enabled and whether child-accounts are disallowed to overwrite this policy. The control fails if the policy is not enabled or if child-accounts are not disallowed to overwrite this policy.",
"Risk": "By default, AWS may be using your data to train its AI models. This may include data from your AWS CloudTrail logs, AWS Config rules, and AWS GuardDuty findings. If you opt out of AI services, AWS will not use your data to train its AI models.",
"RelatedUrl": "https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_ai-opt-out_all.html",
"Remediation": {
MrCloudSec marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -19,7 +19,7 @@
"Terraform": ""
},
"Recommendation": {
"Text": "Artificial Intelligence (AI) services opt-out policies enable you to control whether AWS AI services can store and use your content. Enable the AWS Organizations opt-out of AI services policy.",
"Text": "Artificial Intelligence (AI) services opt-out policies enable you to control whether AWS AI services can store and use your content. Enable the AWS Organizations opt-out of AI services policy and disallow child-accounts to overwrite this policy.",
"Url": "https://docs.aws.amazon.com/organizations/latest/userguide/disable-policy-type.html"
}
},
Expand Down
kagahd marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,24 @@ def execute(self):
"AWS Organizations is not in-use for this AWS Account."
)
if organizations_client.organization.status == "ACTIVE":
report.status_extended = f"AWS Organization {organizations_client.organization.id} has not opted out of all AI services, granting consent for AWS to access its data."
report.status_extended = f"AWS Organization {organizations_client.organization.id} has not opted out of all AI services, granting consent for AWS to access its data, or does not disallow child-accounts to overwrite this policy."
for policy in organizations_client.organization.policies.get(
"AISERVICES_OPT_OUT_POLICY", []
):
if (
opt_out_policy = (
policy.content.get("services", {})
.get("default", {})
.get("opt_out_policy", {})
.get("@@assign")
== "optOut"
):
)
if opt_out_policy.get(
"@@assign"
) == "optOut" and opt_out_policy.get(
"@@operators_allowed_for_child_policies"
) == [
"@@none"
]:
report.status = "PASS"
report.status_extended = f"AWS Organization {organizations_client.organization.id} has opted out of all AI services, not granting consent for AWS to access its data."
report.status_extended = f"AWS Organization {organizations_client.organization.id} has opted out of all AI services, not granting consent for AWS to access its data, and also disallows child-accounts to overwrite this policy."
break

findings.append(report)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def test_organization_with_AI_optout_no_policies(self):
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "AWS Organization o-1234567890 has not opted out of all AI services, granting consent for AWS to access its data."
== "AWS Organization o-1234567890 has not opted out of all AI services, granting consent for AWS to access its data, or does not disallow child-accounts to overwrite this policy."
)
assert result[0].resource_id == "o-1234567890"
assert (
Expand All @@ -96,7 +96,7 @@ def test_organization_with_AI_optout_no_policies(self):
)
assert result[0].region == AWS_REGION_EU_WEST_1

def test_organization_with_AI_optout_policy(self):
def test_organization_with_AI_optout_policy_complete(self):
organizations_client = mock.MagicMock
organizations_client.region = AWS_REGION_EU_WEST_1
organizations_client.audited_partition = "aws"
Expand All @@ -118,7 +118,14 @@ def test_organization_with_AI_optout_policy(self):
aws_managed=False,
content={
"services": {
"default": {"opt_out_policy": {"@@assign": "optOut"}}
"default": {
"opt_out_policy": {
"@@operators_allowed_for_child_policies": [
"@@none"
],
"@@assign": "optOut",
}
}
}
},
targets=[],
Expand Down Expand Up @@ -153,7 +160,7 @@ def test_organization_with_AI_optout_policy(self):
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "AWS Organization o-1234567890 has opted out of all AI services, not granting consent for AWS to access its data."
== "AWS Organization o-1234567890 has opted out of all AI services, not granting consent for AWS to access its data, and also disallows child-accounts to overwrite this policy."
)
assert result[0].resource_id == "o-1234567890"
assert (
Expand Down Expand Up @@ -209,7 +216,133 @@ def test_organization_with_AI_optout_policy_no_content(self):
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "AWS Organization o-1234567890 has not opted out of all AI services, granting consent for AWS to access its data."
== "AWS Organization o-1234567890 has not opted out of all AI services, granting consent for AWS to access its data, or does not disallow child-accounts to overwrite this policy."
)
assert result[0].resource_id == "o-1234567890"
assert (
result[0].resource_arn
== "arn:aws:organizations::1234567890:organization/o-1234567890"
)
assert result[0].region == AWS_REGION_EU_WEST_1

def test_organization_with_AI_optout_policy_no_disallow(self):
organizations_client = mock.MagicMock
organizations_client.region = AWS_REGION_EU_WEST_1
organizations_client.audited_partition = "aws"
organizations_client.audited_account = "0123456789012"
organizations_client.organization = Organization(
id="o-1234567890",
arn="arn:aws:organizations::1234567890:organization/o-1234567890",
status="ACTIVE",
master_id="1234567890",
policies={
"AISERVICES_OPT_OUT_POLICY": [
Policy(
id="p-1234567890",
arn="arn:aws:organizations::1234567890:policy/o-1234567890/p-1234567890",
type="AISERVICES_OPT_OUT_POLICY",
aws_managed=False,
content={
"services": {
"default": {"opt_out_policy": {"@@assign": "optOut"}}
}
},
targets=[],
)
]
},
delegated_administrators=None,
)

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,
):
with mock.patch(
"prowler.providers.aws.services.organizations.organizations_opt_out_ai_services_policy.organizations_opt_out_ai_services_policy.organizations_client",
new=organizations_client,
):
# Test Check
from prowler.providers.aws.services.organizations.organizations_opt_out_ai_services_policy.organizations_opt_out_ai_services_policy import (
organizations_opt_out_ai_services_policy,
)

check = organizations_opt_out_ai_services_policy()
result = check.execute()

assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "AWS Organization o-1234567890 has not opted out of all AI services, granting consent for AWS to access its data, or does not disallow child-accounts to overwrite this policy."
)
assert result[0].resource_id == "o-1234567890"
assert (
result[0].resource_arn
== "arn:aws:organizations::1234567890:organization/o-1234567890"
)
assert result[0].region == AWS_REGION_EU_WEST_1

def test_organization_with_AI_optout_policy_no_opt_out(self):
organizations_client = mock.MagicMock
organizations_client.region = AWS_REGION_EU_WEST_1
organizations_client.audited_partition = "aws"
organizations_client.audited_account = "0123456789012"
organizations_client.organization = Organization(
id="o-1234567890",
arn="arn:aws:organizations::1234567890:organization/o-1234567890",
status="ACTIVE",
master_id="1234567890",
policies={
"AISERVICES_OPT_OUT_POLICY": [
Policy(
id="p-1234567890",
arn="arn:aws:organizations::1234567890:policy/o-1234567890/p-1234567890",
type="AISERVICES_OPT_OUT_POLICY",
aws_managed=False,
content={
"services": {
"default": {
"opt_out_policy": {
"@@operators_allowed_for_child_policies": [
"@@none"
]
}
}
}
},
targets=[],
)
]
},
delegated_administrators=None,
)

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,
):
with mock.patch(
"prowler.providers.aws.services.organizations.organizations_opt_out_ai_services_policy.organizations_opt_out_ai_services_policy.organizations_client",
new=organizations_client,
):
# Test Check
from prowler.providers.aws.services.organizations.organizations_opt_out_ai_services_policy.organizations_opt_out_ai_services_policy import (
organizations_opt_out_ai_services_policy,
)

check = organizations_opt_out_ai_services_policy()
result = check.execute()

assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "AWS Organization o-1234567890 has not opted out of all AI services, granting consent for AWS to access its data, or does not disallow child-accounts to overwrite this policy."
)
assert result[0].resource_id == "o-1234567890"
assert (
Expand Down
Loading