Repository: cloud-custodian/cloud-custodian

Issue:
AWS S3 Intelligent-Tiering Adds Archive Access Tiers
Hi All,

A couple of times ago AWS added support S3 Intelligent-Tiering Adds Archive Access Tiers
Is it possible to get it over CloudCustodian? I would like to assign some policies for S3 buckets in automatic approach.

https://aws.amazon.com/ru/blogs/aws/s3-intelligent-tiering-adds-archive-access-tiers/

Also, I see that boto3 already has a support:
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html?highlight=resource#S3.Client.put_bucket_intelligent_tiering_configuration



Discussion:

Resolving patch:
diff --git a/c7n/resources/s3.py b/c7n/resources/s3.py
--- a/c7n/resources/s3.py
+++ b/c7n/resources/s3.py
@@ -53,7 +53,8 @@
 from c7n.exceptions import PolicyValidationError, PolicyExecutionError
 from c7n.filters import (
     FilterRegistry, Filter, CrossAccountAccessFilter, MetricsFilter,
-    ValueFilter)
+    ValueFilter, ListItemFilter)
+from .aws import shape_validate
 import c7n.filters.policystatement as polstmt_filter
 from c7n.manager import resources
 from c7n.output import NullBlobOutput
@@ -2762,6 +2763,237 @@ def get_inventory_delta(self, client, inventory, b):
         return found
 
 
+@filters.register('intelligent-tiering')
+class IntelligentTiering(ListItemFilter):
+    """Filter for S3 buckets to look at intelligent tiering configurations
+
+    The schema to supply to the attrs follows the schema here:
+     https://botocore.amazonaws.com/v1/documentation/api/latest/reference/services/s3/client/list_bucket_intelligent_tiering_configurations.html
+
+    :example:
+
+    .. code-block:: yaml
+
+            policies:
+              - name: s3-intelligent-tiering-configuration
+                resource: s3
+                filters:
+                  - type: intelligent-tiering
+                    attrs:
+                      - Status: Enabled
+                      - Filter:
+                          And:
+                            Prefix: test
+                            Tags:
+                              - Key: Owner
+                                Value: c7n
+                      - Tierings:
+                          - Days: 100
+                          - AccessTier: ARCHIVE_ACCESS
+
+    """
+    schema = type_schema(
+        'intelligent-tiering',
+        attrs={'$ref': '#/definitions/filters_common/list_item_attrs'},
+        count={'type': 'number'},
+        count_op={'$ref': '#/definitions/filters_common/comparison_operators'}
+    )
+    permissions = ('s3:GetIntelligentTieringConfiguration',)
+    annotation_key = "c7n:IntelligentTiering"
+    annotate_items = True
+
+    def __init__(self, data, manager=None):
+        super().__init__(data, manager)
+        self.data['key'] = self.annotation_key
+
+    def process(self, buckets, event=None):
+        with self.executor_factory(max_workers=2) as w:
+            futures = {w.submit(self.get_item_values, b): b for b in buckets}
+            for future in as_completed(futures):
+                b = futures[future]
+                if future.exception():
+                    self.log.error("Message: %s Bucket: %s", future.exception(), b['Name'])
+                    continue
+        return super().process(buckets, event)
+
+    def get_item_values(self, b):
+        if self.annotation_key not in b:
+            client = bucket_client(local_session(self.manager.session_factory), b)
+            try:
+                int_tier_config = client.list_bucket_intelligent_tiering_configurations(
+                    Bucket=b['Name'])
+                b[self.annotation_key] = int_tier_config.get(
+                    'IntelligentTieringConfigurationList', [])
+            except ClientError as e:
+                if e.response['Error']['Code'] == 'AccessDenied':
+                    method = 'list_bucket_intelligent_tiering_configurations'
+                    log.warning(
+                        "Bucket:%s unable to invoke method:%s error:%s ",
+                          b['Name'], method, e.response['Error']['Message'])
+                    b.setdefault('c7n:DeniedMethods', []).append(method)
+        return b.get(self.annotation_key)
+
+
+@actions.register('set-intelligent-tiering')
+class ConfigureIntelligentTiering(BucketActionBase):
+    """Action applies an intelligent tiering configuration to a S3 bucket
+
+    The schema to supply to the configuration follows the schema here:
+     https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3/client/put_bucket_intelligent_tiering_configuration.html
+
+    To delete a configuration, supply Status=delete with the either the Id or Id: matched
+
+    :example:
+
+    .. code-block:: yaml
+
+            policies:
+              - name: s3-apply-intelligent-tiering-config
+                resource: aws.s3
+                filters:
+                  - not:
+                    - type: intelligent-tiering
+                      attrs:
+                        - Status: Enabled
+                        - Filter:
+                            And:
+                              Prefix: helloworld
+                              Tags:
+                                - Key: Hello
+                                  Value: World
+                        - Tierings:
+                          - Days: 123
+                            AccessTier: ARCHIVE_ACCESS
+                actions:
+                  - type: set-intelligent-tiering
+                    Id: c7n-default
+                    IntelligentTieringConfiguration:
+                      Id: c7n-default
+                      Status: Enabled
+                      Tierings:
+                        - Days: 149
+                          AccessTier: ARCHIVE_ACCESS
+
+              - name: s3-delete-intelligent-tiering-configuration
+                resource: aws.s3
+                filters:
+                  - type: intelligent-tiering
+                    attrs:
+                      - Status: Enabled
+                      - Id: test-config
+                actions:
+                  - type: set-intelligent-tiering
+                    Id: test-config
+                    State: delete
+
+              - name: s3-delete-intelligent-tiering-matched-configs
+                resource: aws.s3
+                filters:
+                  - type: intelligent-tiering
+                    attrs:
+                      - Status: Enabled
+                      - Id: test-config
+                actions:
+                  - type: set-intelligent-tiering
+                    Id: matched
+                    State: delete
+
+    """
+
+    annotation_key = 'c7n:ListItemMatches'
+    shape = 'PutBucketIntelligentTieringConfigurationRequest'
+    schema = {
+        'type': 'object',
+        'additionalProperties': False,
+        'oneOf': [
+            {'required': ['type', 'Id', 'IntelligentTieringConfiguration']},
+            {'required': ['type', 'Id', 'State']}],
+        'properties': {
+            'type': {'enum': ['set-intelligent-tiering']},
+            'Id': {'type': 'string'},
+            # delete intelligent tier configurations via state: delete
+            'State': {'type': 'string', 'enum': ['delete']},
+            'IntelligentTieringConfiguration': {'type': 'object'}
+        },
+    }
+
+    permissions = ('s3:PutIntelligentTieringConfiguration',)
+
+    def validate(self):
+        # You can have up to 1,000 S3 Intelligent-Tiering configurations per bucket.
+        # Hence, always use it with a filter
+        found = False
+        for f in self.manager.iter_filters():
+            if isinstance(f, IntelligentTiering):
+                found = True
+                break
+        if not found:
+            raise PolicyValidationError(
+                '`set-intelligent-tiering` may only be used in '
+                'conjunction with `intelligent-tiering` filter on %s' % (self.manager.data,))
+        cfg = dict(self.data)
+        if 'IntelligentTieringConfiguration' in cfg:
+            cfg['Bucket'] = 'bucket'
+            cfg.pop('type')
+            return shape_validate(
+                cfg, self.shape, self.manager.resource_type.service)
+
+    def process(self, buckets):
+        with self.executor_factory(max_workers=3) as w:
+            futures = {}
+
+            for b in buckets:
+                futures[w.submit(self.process_bucket, b)] = b
+
+            for future in as_completed(futures):
+                if future.exception():
+                    bucket = futures[future]
+                    self.log.error(
+                      'error modifying bucket intelligent tiering configuration: %s\n%s',
+                        bucket['Name'], future.exception())
+                    continue
+
+    def process_bucket(self, bucket):
+        s3 = bucket_client(local_session(self.manager.session_factory), bucket)
+
+        if 'list_bucket_intelligent_tiering_configurations' in bucket.get(
+            'c7n:DeniedMethods', []):
+            log.warning("Access Denied Bucket:%s while reading intelligent tiering configurations"
+                        % bucket['Name'])
+            return
+
+        if self.data.get('Id') and self.data.get('IntelligentTieringConfiguration'):
+            try:
+                s3.put_bucket_intelligent_tiering_configuration(
+                    Bucket=bucket['Name'], Id=self.data.get(
+                      'Id'), IntelligentTieringConfiguration=self.data.get(
+                        'IntelligentTieringConfiguration'))
+            except ClientError as e:
+                if e.response['Error']['Code'] == 'AccessDenied':
+                    log.warning(
+                        "Access Denied Bucket:%s while applying intelligent tiering configuration"
+                          % bucket['Name'])
+        if self.data.get('State'):
+            if self.data.get('Id') == 'matched':
+                for config in bucket.get(self.annotation_key):
+                    self.delete_intelligent_tiering_configurations(s3, config.get('Id'), bucket)
+            else:
+                self.delete_intelligent_tiering_configurations(s3, self.data.get('Id'), bucket)
+
+    def delete_intelligent_tiering_configurations(self, s3_client, id, bucket):
+        try:
+            s3_client.delete_bucket_intelligent_tiering_configuration(Bucket=bucket['Name'], Id=id)
+        except ClientError as e:
+            if e.response['Error']['Code'] == 'AccessDenied':
+                log.warning(
+                    "Access Denied Bucket:%s while deleting intelligent tiering configuration"
+                      % bucket['Name'])
+            elif e.response['Error']['Code'] == 'NoSuchConfiguration':
+                log.warning(
+                  "No such configuration found:%s while deleting intelligent tiering configuration"
+                    % bucket['Name'])
+
+
 @actions.register('delete')
 class DeleteBucket(ScanBucket):
     """Action deletes a S3 bucket


Test patch:
diff --git a/tests/data/placebo/test_delete_int_tier_config_not_present/s3.DeleteBucketIntelligentTieringConfiguration_1.json b/tests/data/placebo/test_delete_int_tier_config_not_present/s3.DeleteBucketIntelligentTieringConfiguration_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_delete_int_tier_config_not_present/s3.DeleteBucketIntelligentTieringConfiguration_1.json
@@ -0,0 +1,10 @@
+{
+    "status_code": 404,
+    "data": {
+        "Error": {
+            "Code": "NoSuchConfiguration",
+            "Message": "The specified configuration does not exist."
+        },
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBucketIntelligentTieringConfigurations_1.json b/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBucketIntelligentTieringConfigurations_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBucketIntelligentTieringConfigurations_1.json
@@ -0,0 +1,19 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "present",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 99,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBucketIntelligentTieringConfigurations_2.json b/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBucketIntelligentTieringConfigurations_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBucketIntelligentTieringConfigurations_2.json
@@ -0,0 +1,19 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "present",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 99,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBucketIntelligentTieringConfigurations_3.json b/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBucketIntelligentTieringConfigurations_3.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBucketIntelligentTieringConfigurations_3.json
@@ -0,0 +1,19 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "present",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 99,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBuckets_1.json b/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBuckets_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_delete_int_tier_config_not_present/s3.ListBuckets_1.json
@@ -0,0 +1,38 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "Buckets": [
+            {
+                "Name": "example-abc-123",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2020,
+                    "month": 10,
+                    "day": 17,
+                    "hour": 13,
+                    "minute": 24,
+                    "second": 10,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "test-c7n-firehose",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2023,
+                    "month": 7,
+                    "day": 5,
+                    "hour": 20,
+                    "minute": 11,
+                    "second": 53,
+                    "microsecond": 0
+                }
+            }
+        ],
+        "Owner": {
+            "DisplayName": "mandeep.bal",
+            "ID": "e7c8bb65a5fc49cf906715eae09de9e4bb7861a96361ba79b833aa45f6833b15"
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.DeleteBucketIntelligentTieringConfiguration_1.json b/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.DeleteBucketIntelligentTieringConfiguration_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.DeleteBucketIntelligentTieringConfiguration_1.json
@@ -0,0 +1,6 @@
+{
+    "status_code": 204,
+    "data": {
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBucketIntelligentTieringConfigurations_1.json b/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBucketIntelligentTieringConfigurations_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBucketIntelligentTieringConfigurations_1.json
@@ -0,0 +1,48 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "c7n-default",
+                "Filter": {
+                    "And": {
+                        "Prefix": "test",
+                        "Tags": [
+                            {
+                                "Key": "Owner",
+                                "Value": "c7n"
+                            },
+                            {
+                                "Key": "AnotherOnwer",
+                                "Value": "Enterprise"
+                            }
+                        ]
+                    }
+                },
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 150,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    },
+                    {
+                        "Days": 200,
+                        "AccessTier": "DEEP_ARCHIVE_ACCESS"
+                    }
+                ]
+            },
+            {
+                "Id": "hello-1",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 105,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBucketIntelligentTieringConfigurations_2.json b/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBucketIntelligentTieringConfigurations_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBucketIntelligentTieringConfigurations_2.json
@@ -0,0 +1,48 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "c7n-default",
+                "Filter": {
+                    "And": {
+                        "Prefix": "test",
+                        "Tags": [
+                            {
+                                "Key": "Owner",
+                                "Value": "c7n"
+                            },
+                            {
+                                "Key": "AnotherOnwer",
+                                "Value": "Enterprise"
+                            }
+                        ]
+                    }
+                },
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 150,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    },
+                    {
+                        "Days": 200,
+                        "AccessTier": "DEEP_ARCHIVE_ACCESS"
+                    }
+                ]
+            },
+            {
+                "Id": "hello-1",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 105,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBucketIntelligentTieringConfigurations_3.json b/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBucketIntelligentTieringConfigurations_3.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBucketIntelligentTieringConfigurations_3.json
@@ -0,0 +1,19 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "hello-1",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 105,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBuckets_1.json b/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBuckets_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_int_tiering_delete_configurations_id/s3.ListBuckets_1.json
@@ -0,0 +1,90 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "Buckets": [
+            {
+                "Name": "c7n-test-1",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2021,
+                    "month": 2,
+                    "day": 2,
+                    "hour": 4,
+                    "minute": 47,
+                    "second": 57,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "c7n-test-glue",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2020,
+                    "month": 3,
+                    "day": 23,
+                    "hour": 15,
+                    "minute": 59,
+                    "second": 5,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "demo-pratyush-s3-bucket-2022",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2022,
+                    "month": 3,
+                    "day": 28,
+                    "hour": 1,
+                    "minute": 3,
+                    "second": 17,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "example-abc-123",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2020,
+                    "month": 10,
+                    "day": 17,
+                    "hour": 13,
+                    "minute": 24,
+                    "second": 10,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "sagemaker-labeler-kms",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2020,
+                    "month": 5,
+                    "day": 24,
+                    "hour": 23,
+                    "minute": 30,
+                    "second": 30,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "test-c7n-firehose",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2023,
+                    "month": 7,
+                    "day": 5,
+                    "hour": 20,
+                    "minute": 11,
+                    "second": 53,
+                    "microsecond": 0
+                }
+            }
+        ],
+        "Owner": {
+            "DisplayName": "mandeep.bal",
+            "ID": "e7c8bb65a5fc49cf906715eae09de9e4bb7861a96361ba79b833aa45f6833b15"
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.DeleteBucketIntelligentTieringConfiguration_1.json b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.DeleteBucketIntelligentTieringConfiguration_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.DeleteBucketIntelligentTieringConfiguration_1.json
@@ -0,0 +1,6 @@
+{
+    "status_code": 204,
+    "data": {
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBucketIntelligentTieringConfigurations_1.json b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBucketIntelligentTieringConfigurations_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBucketIntelligentTieringConfigurations_1.json
@@ -0,0 +1,40 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "hello-1",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 149,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            },
+            {
+                "Id": "test-config",
+                "Filter": {
+                    "And": {
+                        "Prefix": "test",
+                        "Tags": [
+                            {
+                                "Key": "Owner",
+                                "Value": "c7n"
+                            }
+                        ]
+                    }
+                },
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 100,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBucketIntelligentTieringConfigurations_2.json b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBucketIntelligentTieringConfigurations_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBucketIntelligentTieringConfigurations_2.json
@@ -0,0 +1,40 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "hello-1",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 149,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            },
+            {
+                "Id": "test-config",
+                "Filter": {
+                    "And": {
+                        "Prefix": "test",
+                        "Tags": [
+                            {
+                                "Key": "Owner",
+                                "Value": "c7n"
+                            }
+                        ]
+                    }
+                },
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 100,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBucketIntelligentTieringConfigurations_3.json b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBucketIntelligentTieringConfigurations_3.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBucketIntelligentTieringConfigurations_3.json
@@ -0,0 +1,48 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "c7n-default",
+                "Filter": {
+                    "And": {
+                        "Prefix": "test",
+                        "Tags": [
+                            {
+                                "Key": "Owner",
+                                "Value": "c7n"
+                            },
+                            {
+                                "Key": "AnotherOnwer",
+                                "Value": "Enterprise"
+                            }
+                        ]
+                    }
+                },
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 150,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    },
+                    {
+                        "Days": 200,
+                        "AccessTier": "DEEP_ARCHIVE_ACCESS"
+                    }
+                ]
+            },
+            {
+                "Id": "hello-1",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 149,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBuckets_1.json b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBuckets_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.ListBuckets_1.json
@@ -0,0 +1,77 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "Buckets": [
+            {
+                "Name": "c7n-test-1",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2021,
+                    "month": 2,
+                    "day": 2,
+                    "hour": 4,
+                    "minute": 47,
+                    "second": 57,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "demo-pratyush-s3-bucket-2022",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2022,
+                    "month": 3,
+                    "day": 28,
+                    "hour": 1,
+                    "minute": 3,
+                    "second": 17,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "example-abc-123",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2020,
+                    "month": 10,
+                    "day": 17,
+                    "hour": 13,
+                    "minute": 24,
+                    "second": 10,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "sagemaker-labeler-kms",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2020,
+                    "month": 5,
+                    "day": 24,
+                    "hour": 23,
+                    "minute": 30,
+                    "second": 30,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "test-c7n-firehose",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2023,
+                    "month": 7,
+                    "day": 5,
+                    "hour": 20,
+                    "minute": 11,
+                    "second": 53,
+                    "microsecond": 0
+                }
+            }
+        ],
+        "Owner": {
+            "DisplayName": "mandeep.bal",
+            "ID": "e7c8bb65a5fc49cf906715eae09de9e4bb7861a96361ba79b833aa45f6833b15"
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.PutBucketIntelligentTieringConfiguration_1.json b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.PutBucketIntelligentTieringConfiguration_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_int_tiering_set_configurations/s3.PutBucketIntelligentTieringConfiguration_1.json
@@ -0,0 +1,6 @@
+{
+    "status_code": 204,
+    "data": {
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.DeleteBucketIntelligentTieringConfiguration_1.json b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.DeleteBucketIntelligentTieringConfiguration_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.DeleteBucketIntelligentTieringConfiguration_1.json
@@ -0,0 +1,10 @@
+{
+    "status_code": 403,
+    "data": {
+        "Error": {
+            "Code": "AccessDenied",
+            "Message": "Access Denied"
+        },
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBucketIntelligentTieringConfigurations_1.json b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBucketIntelligentTieringConfigurations_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBucketIntelligentTieringConfigurations_1.json
@@ -0,0 +1,29 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "present",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 99,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            },
+            {
+                "Id": "test",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 198,
+                        "AccessTier": "DEEP_ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBucketIntelligentTieringConfigurations_2.json b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBucketIntelligentTieringConfigurations_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBucketIntelligentTieringConfigurations_2.json
@@ -0,0 +1,29 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "present",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 99,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            },
+            {
+                "Id": "test",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 198,
+                        "AccessTier": "DEEP_ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBuckets_1.json b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBuckets_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBuckets_1.json
@@ -0,0 +1,38 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "Buckets": [
+            {
+                "Name": "example-abc-123",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2020,
+                    "month": 10,
+                    "day": 17,
+                    "hour": 13,
+                    "minute": 24,
+                    "second": 10,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "test-c7n-firehose",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2023,
+                    "month": 7,
+                    "day": 5,
+                    "hour": 20,
+                    "minute": 11,
+                    "second": 53,
+                    "microsecond": 0
+                }
+            }
+        ],
+        "Owner": {
+            "DisplayName": "mandeep.bal",
+            "ID": "e7c8bb65a5fc49cf906715eae09de9e4bb7861a96361ba79b833aa45f6833b15"
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBuckets_2.json b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBuckets_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.ListBuckets_2.json
@@ -0,0 +1,38 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "Buckets": [
+            {
+                "Name": "example-abc-123",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2020,
+                    "month": 10,
+                    "day": 17,
+                    "hour": 13,
+                    "minute": 24,
+                    "second": 10,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "test-c7n-firehose",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2023,
+                    "month": 7,
+                    "day": 5,
+                    "hour": 20,
+                    "minute": 11,
+                    "second": 53,
+                    "microsecond": 0
+                }
+            }
+        ],
+        "Owner": {
+            "DisplayName": "mandeep.bal",
+            "ID": "e7c8bb65a5fc49cf906715eae09de9e4bb7861a96361ba79b833aa45f6833b15"
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.PutBucketIntelligentTieringConfiguration_1.json b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.PutBucketIntelligentTieringConfiguration_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_intel_tier_config_access_denied/s3.PutBucketIntelligentTieringConfiguration_1.json
@@ -0,0 +1,10 @@
+{
+    "status_code": 403,
+    "data": {
+        "Error": {
+            "Code": "AccessDenied",
+            "Message": "Access Denied"
+        },
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_intel_tier_config_filter_count/s3.ListBucketIntelligentTieringConfigurations_1.json b/tests/data/placebo/test_s3_intel_tier_config_filter_count/s3.ListBucketIntelligentTieringConfigurations_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_intel_tier_config_filter_count/s3.ListBucketIntelligentTieringConfigurations_1.json
@@ -0,0 +1,29 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "IsTruncated": false,
+        "IntelligentTieringConfigurationList": [
+            {
+                "Id": "present",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 99,
+                        "AccessTier": "ARCHIVE_ACCESS"
+                    }
+                ]
+            },
+            {
+                "Id": "test",
+                "Status": "Enabled",
+                "Tierings": [
+                    {
+                        "Days": 198,
+                        "AccessTier": "DEEP_ARCHIVE_ACCESS"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_intel_tier_config_filter_count/s3.ListBuckets_1.json b/tests/data/placebo/test_s3_intel_tier_config_filter_count/s3.ListBuckets_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_intel_tier_config_filter_count/s3.ListBuckets_1.json
@@ -0,0 +1,38 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "Buckets": [
+            {
+                "Name": "example-abc-123",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2020,
+                    "month": 10,
+                    "day": 17,
+                    "hour": 13,
+                    "minute": 24,
+                    "second": 10,
+                    "microsecond": 0
+                }
+            },
+            {
+                "Name": "test-c7n-firehose",
+                "CreationDate": {
+                    "__class__": "datetime",
+                    "year": 2023,
+                    "month": 7,
+                    "day": 5,
+                    "hour": 20,
+                    "minute": 11,
+                    "second": 53,
+                    "microsecond": 0
+                }
+            }
+        ],
+        "Owner": {
+            "DisplayName": "mandeep.bal",
+            "ID": "e7c8bb65a5fc49cf906715eae09de9e4bb7861a96361ba79b833aa45f6833b15"
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/test_s3.py b/tests/test_s3.py
--- a/tests/test_s3.py
+++ b/tests/test_s3.py
@@ -3,6 +3,7 @@
 import datetime
 import functools
 import json
+import logging
 import os
 import io
 import shutil
@@ -23,7 +24,7 @@
 from c7n.resources import s3
 from c7n.mu import LambdaManager
 from c7n.ufuncs import s3crypt
-from c7n.utils import get_account_alias_from_sts
+from c7n.utils import get_account_alias_from_sts, jmespath_search
 
 from .common import (
     BaseTest,
@@ -4014,3 +4015,322 @@ def test_s3_access_analyzer_filter_with_no_results(self, test, s3_ownership):
             ]
         }, session_factory=factory)
         test.assertRaises(PolicyExecutionError, p.run)
+
+
+class IntelligentTieringConfiguration(BaseTest):
+
+    def test_set_intelligent_configuration_validation_error(self):
+        with self.assertRaises(PolicyValidationError) as e:
+            self.load_policy({
+                'name': 's3-apply-int-tier-config',
+                'resource': 'aws.s3',
+                'actions': [
+                    {
+                        'type': 'set-intelligent-tiering',
+                        'Id': 'xyz',
+                        'State': 'delete'
+                    }
+                ]
+            })
+        self.assertIn(
+            "may only be used in conjunction with `intelligent-tiering`", str(e.exception))
+
+
+    def test_s3_int_tiering_set_configurations(self):
+        self.patch(s3.S3, "executor_factory", MainThreadExecutor)
+        self.patch(s3, "S3_AUGMENT_TABLE", [])
+        bname = "example-abc-123"
+        session_factory = self.replay_flight_data("test_s3_int_tiering_set_configurations")
+        session = session_factory()
+        client = session.client("s3")
+        configs = client.list_bucket_intelligent_tiering_configurations(Bucket=bname)
+        filtered_config =  {
+            'Id': 'test-config',
+            'Filter': {'And': {'Prefix': 'test', 'Tags': [{'Key': 'Owner', 'Value': 'c7n'}]}},
+            'Status': 'Enabled',
+            'Tierings': [
+                {'Days': 100, 'AccessTier': 'ARCHIVE_ACCESS'}
+            ]
+        }
+        applied_config = {
+            'Id': 'c7n-default',
+            'Filter': {
+                'And': {
+                    'Prefix': 'test',
+                    'Tags': [
+                        {'Key': 'Owner', 'Value': 'c7n'},
+                        {"Key": "AnotherOnwer", "Value": "Enterprise"}]}},
+            'Status': 'Enabled',
+            'Tierings': [
+                {'Days': 150, 'AccessTier': 'ARCHIVE_ACCESS'},
+                {'Days': 200, 'AccessTier': 'DEEP_ARCHIVE_ACCESS'}
+            ]
+        }
+        self.assertTrue(filtered_config in configs.get('IntelligentTieringConfigurationList'))
+        p = self.load_policy(
+            {
+                "name": "s3-filter-configs-and-apply",
+                "resource": "s3",
+                "filters": [
+                    {"Name": bname},
+                    {
+                        "type": "intelligent-tiering",
+                        "attrs": [
+                          {"Status": "Enabled"},
+                          {"Filter": {
+                              "And": {
+                                  "Prefix": "test", "Tags": [{"Key": "Owner", "Value": "c7n"}]}}},
+                          {"Tierings": [{"Days": 100, "AccessTier": "ARCHIVE_ACCESS"}]}]
+                    }
+                ],
+                "actions": [
+                    {
+                        "type": "set-intelligent-tiering",
+                        "State": "delete",
+                        "Id": "matched",
+                    },
+                    {
+                        "type": "set-intelligent-tiering",
+                        "Id": "c7n-default",
+                        "IntelligentTieringConfiguration": {
+                            "Id": "c7n-default",
+                            "Status": "Enabled",
+                            "Filter": {
+                                "And": {
+                                    "Prefix": "test",
+                                    "Tags": [
+                                        {"Key": "Owner", "Value": "c7n"},
+                                        {"Key": "AnotherOnwer", "Value": "Enterprise"}]}},
+                            "Tierings": [
+                                {
+                                    "Days": 150,
+                                    "AccessTier": "ARCHIVE_ACCESS"
+                                },
+                                {
+                                    "Days": 200,
+                                    "AccessTier": "DEEP_ARCHIVE_ACCESS"
+                                }
+                            ]
+                        }
+                    }],
+            },
+            session_factory=session_factory,
+        )
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        self.assertTrue("c7n:IntelligentTiering" in resources[0])
+        self.assertEqual(len(resources[0].get("c7n:ListItemMatches")), 1)
+        self.assertEqual(resources[0].get("c7n:ListItemMatches")[0].get("Id"), "test-config")
+        check_config = client.list_bucket_intelligent_tiering_configurations(Bucket=bname)
+        self.assertFalse(filtered_config in check_config.get('IntelligentTieringConfigurationList'))
+        self.assertTrue(applied_config in check_config.get('IntelligentTieringConfigurationList'))
+
+    def test_s3_int_tiering_delete_configurations_id(self):
+        self.patch(s3.S3, "executor_factory", MainThreadExecutor)
+        self.patch(s3, "S3_AUGMENT_TABLE", [])
+        bname = "example-abc-123"
+        session_factory = self.replay_flight_data("test_s3_int_tiering_delete_configurations_id")
+        session = session_factory()
+        client = session.client("s3")
+        ids = []
+        configs = client.list_bucket_intelligent_tiering_configurations(
+            Bucket=bname).get('IntelligentTieringConfigurationList')
+        self.assertEquals(len(configs), 2)
+        for config in configs:
+            ids.append(jmespath_search("Id", config))
+        self.assertTrue("c7n-default" in ids)
+        p = self.load_policy(
+            {
+                "name": "s3-filter-configs-and-apply",
+                "resource": "s3",
+                "filters": [
+                    {"Name": bname},
+                    {
+                        "type": "intelligent-tiering",
+                        "attrs": [
+                          {"Status": "Enabled"},
+                          {"Id": "c7n-default"}]
+                    }
+                ],
+                "actions": [
+                    {
+                        "type": "set-intelligent-tiering",
+                        "State": "delete",
+                        "Id": "c7n-default",
+                    }],
+            },
+            session_factory=session_factory,
+        )
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        self.assertEqual(resources[0].get("c7n:ListItemMatches")[0].get("Id"), "c7n-default")
+        check_config = client.list_bucket_intelligent_tiering_configurations(
+            Bucket=bname).get('IntelligentTieringConfigurationList')
+        self.assertEquals(len(check_config), 1)
+        self.assertFalse('c7n-default' in check_config[0].get('Id'))
+
+    def test_delete_int_tier_config_not_present(self):
+        self.patch(s3.S3, "executor_factory", MainThreadExecutor)
+        self.patch(s3, "S3_AUGMENT_TABLE", [])
+        bname = "example-abc-123"
+        session_factory = self.replay_flight_data("test_delete_int_tier_config_not_present")
+        session = session_factory()
+        client = session.client("s3")
+        config = client.list_bucket_intelligent_tiering_configurations(
+            Bucket=bname).get('IntelligentTieringConfigurationList')
+        self.assertEquals(len(config), 1)
+        id = config[0].get('Id')
+        self.assertTrue("present" in id)
+        log_output = self.capture_logging('custodian.s3', level=logging.WARNING)
+        p = self.load_policy(
+            {
+                "name": "s3-filter-configs-and-apply",
+                "resource": "s3",
+                "filters": [
+                    {"Name": bname},
+                    {
+                        "type": "intelligent-tiering",
+                        "attrs": [{"Status": "Enabled"}]
+                    }
+                ],
+                "actions": [
+                    {
+                        "type": "set-intelligent-tiering",
+                        "State": "delete",
+                        "Id": "not-present",
+                    }],
+            },
+            session_factory=session_factory,
+        )
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        check_config = client.list_bucket_intelligent_tiering_configurations(
+            Bucket=bname).get('IntelligentTieringConfigurationList')
+        self.assertEquals(len(check_config), 1)
+        self.assertTrue('present' in check_config[0].get('Id'))
+        self.assertIn(
+          'No such configuration found:example-abc-123 while deleting '
+          'intelligent tiering configuration',
+            log_output.getvalue())
+
+    def test_s3_intel_tier_config_access_denied(self):
+        self.patch(s3.S3, "executor_factory", MainThreadExecutor)
+        self.patch(s3, "S3_AUGMENT_TABLE", [])
+        bname = "example-abc-123"
+        session_factory = self.replay_flight_data("test_s3_intel_tier_config_access_denied")
+        log_output = self.capture_logging('custodian.s3', level=logging.WARNING)
+        p = self.load_policy(
+            {
+                "name": "s3-filter-configs-and-apply",
+                "resource": "s3",
+                "filters": [
+                    {"Name": bname},
+                    {"type": "intelligent-tiering"}],
+                "actions": [
+                    {
+                        "type": "set-intelligent-tiering",
+                        "State": "delete",
+                        "Id": "not-present",
+                    }],
+            },
+            session_factory=session_factory,
+        )
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        self.assertIn(
+          'Access Denied Bucket:example-abc-123 while deleting intelligent tiering configuration',
+            log_output.getvalue())
+
+        p1 = self.load_policy(
+            {
+                "name": "s3-filter-configs-and-apply",
+                "resource": "s3",
+                "filters": [
+                    {"Name": bname},
+                    {"type": "intelligent-tiering"}],
+                "actions": [
+                    {
+                        "type": "set-intelligent-tiering",
+                        "Id": "not-present",
+                        "IntelligentTieringConfiguration": {
+                        "Id": "not-present",
+                        "Status": "Enabled",
+                        "Filter": {
+                            "And": {
+                                "Prefix": "test",
+                                "Tags": [
+                                    {"Key": "Owner", "Value": "c7n"}]}},
+                            "Tierings": [{
+                                    "Days": 150,
+                                    "AccessTier": "ARCHIVE_ACCESS"
+                                }],
+                        }
+                    }],
+            },
+            session_factory=session_factory,
+        )
+        resources = p1.run()
+        self.assertEqual(len(resources), 1)
+        self.assertIn(
+          'Access Denied Bucket:example-abc-123 while applying intelligent tiering configuration',
+            log_output.getvalue())
+
+    def test_s3_intel_tier_config_filter_count(self):
+        self.patch(s3.S3, "executor_factory", MainThreadExecutor)
+        self.patch(s3, "S3_AUGMENT_TABLE", [])
+        bname = "example-abc-123"
+        session_factory = self.replay_flight_data("test_s3_intel_tier_config_filter_count")
+        p = self.load_policy(
+            {
+                "name": "s3-filter-configs-and-apply",
+                "resource": "s3",
+                "filters": [
+                    {"Name": bname},
+                    {
+                        "type": "intelligent-tiering",
+                        "count": 2,
+                        "count_op": "eq"
+                    }
+                ],
+            },
+            session_factory=session_factory,
+        )
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        self.assertEqual(len(resources[0]["c7n:IntelligentTiering"]), 2)
+
+    def test_set_intelligent_configuration_schema_validation(self):
+        with self.assertRaises(PolicyValidationError) as e:
+            self.load_policy({
+                'name': 's3-apply-int-tier-config',
+                'resource': 'aws.s3',
+                'filters': [{'type': 'intelligent-tiering'}],
+                'actions': [
+                    {
+                        'type': 'set-intelligent-tiering',
+                        'Id': 'xyz',
+                        'IntelligentTieringConfiguration': {
+                          'Id': 'xyz',
+                          'Status': 'Enabled'}
+                    }
+                ]
+            })
+        self.assertIn(
+            'Missing required parameter in IntelligentTieringConfiguration: "Tierings"', str(
+              e.exception))
+
+    def test_s3_list_tiering_config_denied_method(self):
+        b = {'Name': 'example-abc-123',
+            'c7n:DeniedMethods': ['list_bucket_intelligent_tiering_configurations']}
+        log_output = self.capture_logging('custodian.s3', level=logging.WARNING)
+        p = self.load_policy({'name': 's3-apply-int-tier-config-filter',
+                'resource': 'aws.s3',
+                'filters': [{'type': 'intelligent-tiering'}],
+                'actions': [{'type': 'set-intelligent-tiering', 'Id': 'test', 'State': 'delete'}]
+            },
+        )
+        action_set_config = p.resource_manager.actions[0]
+        self.assertEqual(action_set_config.process_bucket(b), None)
+        self.assertIn(
+          'Access Denied Bucket:example-abc-123 while reading intelligent tiering configurations',
+            log_output.getvalue())