AWS S3 Bucket Object Lock Configured


Description

This policy validates that S3 buckets have an Object Lock configuration enabled. This should be used with specific suppression lists to ensure it is applied only to appropriate S3 buckets, such as those containing CloudTrail or other auditable records.

Query · python

from panther_base_helpers import deep_get

RETENTION_PERIOD_DAYS = 365


def policy(resource):

    object_lock = resource["ObjectLockConfiguration"]

    # Object lock configuration is not enabled, or enabled without a rule
    if not object_lock or object_lock["ObjectLockEnabled"] != "Enabled" or not object_lock["Rule"]:
        return False

    # Ensure ObjectLockConfiguration is in COMPLIANCE mode, not GOVERNANCE mode
    if deep_get(object_lock, "Rule", "DefaultRetention", "Mode") != "COMPLIANCE":
        return False

    return (
        deep_get(object_lock, "Rule", "DefaultRetention", "Days", default=0)
        >= RETENTION_PERIOD_DAYS
    )

Analyst notes

Create a new S3 bucket with an appropriate Object Lock configuration and point audit records to that bucket.

Raw source AWS S3 Bucket Object Lock Configured · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: policy
Filename: aws_s3_bucket_object_lock_configured.py
PolicyID: "AWS.S3.BucketObjectLockConfigured"
DisplayName: "AWS S3 Bucket Object Lock Configured"
Enabled: false
ResourceTypes:
  - AWS.S3.Bucket
Tags:
  - AWS
  - S3
  - PCI
  - Impact:Data Destruction
Reports:
  PCI:
    - 10.5.3
  MITRE ATT&CK:
    - TA0040:T1485
Severity: Low
Description: >
  This policy validates that S3 buckets have an Object Lock configuration enabled. This should be used with specific suppression lists to ensure it is applied only to appropriate S3 buckets, such as those containing CloudTrail or other auditable records.
Runbook: Create a new S3 bucket with an appropriate Object Lock configuration and point audit records to that bucket.
Reference: https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock.html
Tests:
  - Name: Object Lock Configured With Governance
    ExpectedResult: false
    Resource:
      {
        "AccountId": "123456789012",
        "Arn": "arn:aws:s3:::example-bucket",
        "EncryptionRules":
          [
            {
              "ApplyServerSideEncryptionByDefault":
                { "KMSMasterKeyID": null, "SSEAlgorithm": "AES256" },
            },
          ],
        "Grants":
          [
            {
              "Grantee":
                {
                  "DisplayName": "example.user",
                  "EmailAddress": null,
                  "ID": "1",
                  "Type": "CanonicalUser",
                  "URI": null,
                },
              "Permission": "FULL_CONTROL",
            },
          ],
        "LifecycleRules": null,
        "LoggingPolicy": null,
        "MFADelete": "Disabled",
        "Name": "example-bucket",
        "ObjectLockConfiguration":
          {
            "ObjectLockEnabled": "Enabled",
            "Rule":
              {
                "DefaultRetention":
                  { "Days": 1, "Mode": "GOVERNANCE", "Years": null },
              },
          },
        "Owner": { "DisplayName": "example.user", "ID": "1" },
        "Policy": null,
        "PublicAccessBlockConfiguration":
          {
            "BlockPublicAcls": true,
            "BlockPublicPolicy": true,
            "IgnorePublicAcls": true,
            "RestrictPublicBuckets": true,
          },
        "Region": "us-west-2",
        "ResourceId": "arn:aws:s3:::example-bucket",
        "ResourceType": "AWS.S3.Bucket",
        "Tags": { "environment": "pci" },
        "TimeCreated": "2019-01-01T00:00:00.000Z",
        "Versioning": "Enabled",
      }
  - Name: Object Lock Configured With Compliance
    ExpectedResult: true
    Resource:
      {
        "AccountId": "123456789012",
        "Arn": "arn:aws:s3:::example-bucket",
        "EncryptionRules":
          [
            {
              "ApplyServerSideEncryptionByDefault":
                { "KMSMasterKeyID": null, "SSEAlgorithm": "AES256" },
            },
          ],
        "Grants":
          [
            {
              "Grantee":
                {
                  "DisplayName": "example.user",
                  "EmailAddress": null,
                  "ID": "1",
                  "Type": "CanonicalUser",
                  "URI": null,
                },
              "Permission": "FULL_CONTROL",
            },
          ],
        "LifecycleRules": null,
        "LoggingPolicy": null,
        "MFADelete": "Disabled",
        "Name": "example-bucket",
        "ObjectLockConfiguration":
          {
            "ObjectLockEnabled": "Enabled",
            "Rule":
              {
                "DefaultRetention":
                  { "Days": 365, "Mode": "COMPLIANCE", "Years": null },
              },
          },
        "Owner": { "DisplayName": "example.user", "ID": "1" },
        "Policy": null,
        "PublicAccessBlockConfiguration":
          {
            "BlockPublicAcls": true,
            "BlockPublicPolicy": true,
            "IgnorePublicAcls": true,
            "RestrictPublicBuckets": true,
          },
        "Region": "us-west-2",
        "ResourceId": "arn:aws:s3:::example-bucket",
        "ResourceType": "AWS.S3.Bucket",
        "Tags": { "environment": "pci" },
        "TimeCreated": "2019-01-01T00:00:00.000Z",
        "Versioning": "Enabled",
      }
  - Name: Object Lock Not Configured
    ExpectedResult: false
    Resource:
      {
        "AccountId": "123456789012",
        "Arn": "arn:aws:s3:::example-bucket",
        "EncryptionRules":
          [
            {
              "ApplyServerSideEncryptionByDefault":
                { "KMSMasterKeyID": null, "SSEAlgorithm": "AES256" },
            },
          ],
        "Grants":
          [
            {
              "Grantee":
                {
                  "DisplayName": "example.user",
                  "EmailAddress": null,
                  "ID": "1",
                  "Type": "CanonicalUser",
                  "URI": null,
                },
              "Permission": "FULL_CONTROL",
            },
          ],
        "LifecycleRules": null,
        "LoggingPolicy": null,
        "MFADelete": "Disabled",
        "Name": "example-bucket",
        "ObjectLockConfiguration":
          { "ObjectLockEnabled": "Disabled", "Rule": null },
        "Owner": { "DisplayName": "example.user", "ID": "1" },
        "Policy": null,
        "PublicAccessBlockConfiguration":
          {
            "BlockPublicAcls": true,
            "BlockPublicPolicy": true,
            "IgnorePublicAcls": true,
            "RestrictPublicBuckets": true,
          },
        "Region": "us-west-2",
        "ResourceId": "arn:aws:s3:::example-bucket",
        "ResourceType": "AWS.S3.Bucket",
        "Tags": { "environment": "pci" },
        "TimeCreated": "2019-01-01T00:00:00.000Z",
        "Versioning": "Enabled",
      }


# ------ paired body: aws_s3_bucket_object_lock_configured.py ------

from panther_base_helpers import deep_get

RETENTION_PERIOD_DAYS = 365


def policy(resource):

    object_lock = resource["ObjectLockConfiguration"]

    # Object lock configuration is not enabled, or enabled without a rule
    if not object_lock or object_lock["ObjectLockEnabled"] != "Enabled" or not object_lock["Rule"]:
        return False

    # Ensure ObjectLockConfiguration is in COMPLIANCE mode, not GOVERNANCE mode
    if deep_get(object_lock, "Rule", "DefaultRetention", "Mode") != "COMPLIANCE":
        return False

    return (
        deep_get(object_lock, "Rule", "DefaultRetention", "Days", default=0)
        >= RETENTION_PERIOD_DAYS
    )

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.