diff --git a/foundational_security/docs/foundational_security_s3_12.md b/foundational_security/docs/foundational_security_s3_12.md new file mode 100644 index 00000000..443f9297 --- /dev/null +++ b/foundational_security/docs/foundational_security_s3_12.md @@ -0,0 +1,9 @@ +## Description + +This control checks whether Amazon S3 buckets provide user permissions via ACLs. The control fails if ACLs are configured for managing user access on S3 buckets. + +ACLs are legacy access control mechanisms that predate IAM. Instead of ACLs, we recommend using IAM policies or S3 bucket policies to more easily manage access to your S3 buckets. + +## Remediation + +For more information on managing access to S3 buckets, see [Bucket policies and user policies](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-iam-policies.html) in the Amazon S3 User Guide. For details on how to review your current ACL permissions, see [Access control list (ACL) overview](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html) in the Amazon S3 User Guide. \ No newline at end of file diff --git a/foundational_security/s3.sp b/foundational_security/s3.sp index 9bb12704..0d78ccd2 100644 --- a/foundational_security/s3.sp +++ b/foundational_security/s3.sp @@ -17,7 +17,8 @@ benchmark "foundational_security_s3" { control.foundational_security_s3_8, control.foundational_security_s3_9, control.foundational_security_s3_10, - control.foundational_security_s3_11 + control.foundational_security_s3_11, + control.foundational_security_s3_12 ] tags = merge(local.foundational_security_s3_common_tags, { @@ -153,4 +154,17 @@ control "foundational_security_s3_11" { foundational_security_item_id = "s3_11" foundational_security_category = "logging" }) +} + +control "foundational_security_s3_12" { + title = "12 S3 access control lists (ACLs) should not be used to manage user access to buckets" + description = "This control checks whether Amazon S3 buckets provide user permissions via ACLs. The control fails if ACLs are configured for managing user access on S3 buckets." + severity = "medium" + sql = query.s3_bucket_acls_should_prohibit_user_access.sql + documentation = file("./foundational_security/docs/foundational_security_s3_12.md") + + tags = merge(local.foundational_security_s3_common_tags, { + foundational_security_item_id = "s3_12" + foundational_security_category = "access_control" + }) } \ No newline at end of file diff --git a/query/s3/s3_bucket_acls_should_prohibit_user_access.sql b/query/s3/s3_bucket_acls_should_prohibit_user_access.sql new file mode 100644 index 00000000..9cc066e0 --- /dev/null +++ b/query/s3/s3_bucket_acls_should_prohibit_user_access.sql @@ -0,0 +1,44 @@ +with bucket_acl_details as ( + select + arn, + title, + ARRAY[acl -> 'Owner' ->> 'ID'] as bucket_owner, + array_agg(grantee_id) as bucket_acl_permissions, + region, + account_id + from + aws_s3_bucket, + jsonb_path_query(acl, '$.Grants.Grantee.ID') as grantee_id + group by + arn, + title, + acl, + region, + account_id +), +bucket_acl_checks as ( + select + arn, + title, + to_jsonb(bucket_acl_permissions) - bucket_owner as additional_permissions, + region, + account_id + from + bucket_acl_details +) +select + -- Required Columns + arn as resource, + case + when jsonb_array_length(additional_permissions) = 0 then 'ok' + else 'alarm' + end status, + case + when jsonb_array_length(additional_permissions) = 0 then title || ' does not have ACLs for user access.' + else title || ' has ACLs for user access.' + end reason, + -- Additional Dimensions + region, + account_id +from + bucket_acl_checks; \ No newline at end of file