Repository: cloud-custodian/cloud-custodian

Issue:
Add support for encrypted S3 inventory
AWS [recently](https://aws.amazon.com/about-aws/whats-new/2017/11/amazon-s3-adds-new-features-for-data-security-and-compliance/) [announced](http://docs.aws.amazon.com/AmazonS3/latest/dev/storage-inventory.html) support for encrypted S3 inventory:
* Inventory list file can be encrypted on delivery
* Encryption status can be included in the list file

Enhance the Custodian S3 `set-inventory` action to support these features.


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
@@ -2109,11 +2109,13 @@ class SetInventory(BucketActionBase):
         name={'type': 'string', 'description': 'Name of inventory'},
         destination={'type': 'string', 'description': 'Name of destination bucket'},
         prefix={'type': 'string', 'description': 'Destination prefix'},
+        encryption={'enum': ['SSES3', 'SSEKMS']},
+        key_id={'type': 'string', 'description': 'Optional Customer KMS KeyId for SSE-KMS'},
         versions={'enum': ['All', 'Current']},
         schedule={'enum': ['Daily', 'Weekly']},
         fields={'type': 'array', 'items': {'enum': [
             'Size', 'LastModifiedDate', 'StorageClass', 'ETag',
-            'IsMultipartUploaded', 'ReplicationStatus']}})
+            'IsMultipartUploaded', 'ReplicationStatus', 'EncryptionStatus']}})
 
     permissions = ('s3:PutInventoryConfiguration', 's3:GetInventoryConfiguration')
 
@@ -2135,6 +2137,7 @@ def process_bucket(self, b):
         fields = self.data.get('fields', ['LastModifiedDate', 'Size'])
         versions = self.data.get('versions', 'Current')
         state = self.data.get('state', 'enabled')
+        encryption = self.data.get('encryption')
 
         if not prefix:
             prefix = "Inventories/%s" % (self.manager.config.account_id)
@@ -2149,11 +2152,14 @@ def process_bucket(self, b):
                     raise
             return
 
+        bucket = {
+            'Bucket': "arn:aws:s3:::%s" % destination,
+            'Format': 'CSV'
+        }
+
         inventory = {
             'Destination': {
-                'S3BucketDestination': {
-                    'Bucket': "arn:aws:s3:::%s" % destination,
-                    'Format': 'CSV'}
+                'S3BucketDestination': bucket
             },
             'IsEnabled': state == 'enabled' and True or False,
             'Id': inventory_name,
@@ -2165,7 +2171,14 @@ def process_bucket(self, b):
         }
 
         if prefix:
-            inventory['Destination']['S3BucketDestination']['Prefix'] = prefix
+            bucket['Prefix'] = prefix
+
+        if encryption:
+            bucket['Encryption'] = {encryption: {}}
+            if encryption == 'SSEKMS' and self.data.get('key_id'):
+                bucket['Encryption'] = {encryption: {
+                    'KeyId': self.data['key_id']
+                }}
 
         found = self.get_inventory_delta(client, inventory, b)
         if found:


Test patch:
diff --git a/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.CreateBucket_1.json b/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.CreateBucket_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.CreateBucket_1.json
@@ -0,0 +1,20 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Location": "/delete_inventory", 
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200, 
+            "RetryAttempts": 0, 
+            "HostId": "dBSh7boO/cYWqofwJpNbT+ReHd7/QcUPmQUjb1uM9cMFx4xBCHTBUiCeSC86BVeN/5JhhCG4GKs=", 
+            "RequestId": "DDA33FC56FCD3893", 
+            "HTTPHeaders": {
+                "content-length": "0", 
+                "x-amz-id-2": "dBSh7boO/cYWqofwJpNbT+ReHd7/QcUPmQUjb1uM9cMFx4xBCHTBUiCeSC86BVeN/5JhhCG4GKs=", 
+                "server": "AmazonS3", 
+                "x-amz-request-id": "DDA33FC56FCD3893", 
+                "location": "/delete_inventory", 
+                "date": "Wed, 15 Nov 2017 13:59:08 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.DeleteBucketInventoryConfiguration_1.json b/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.DeleteBucketInventoryConfiguration_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.DeleteBucketInventoryConfiguration_1.json
@@ -0,0 +1,23 @@
+{
+    "status_code": 404, 
+    "data": {
+        "ResponseMetadata": {
+            "HTTPStatusCode": 404, 
+            "RetryAttempts": 0, 
+            "HostId": "fpNbvsW4Ep5o0yWL8/zQ116Y2ZVWeQJUNLwYAkf2Te341Qc4tPzEsZAjAHalZtcOU+csHfHvnBk=", 
+            "RequestId": "DC4098F4BA93B262", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "fpNbvsW4Ep5o0yWL8/zQ116Y2ZVWeQJUNLwYAkf2Te341Qc4tPzEsZAjAHalZtcOU+csHfHvnBk=", 
+                "server": "AmazonS3", 
+                "transfer-encoding": "chunked", 
+                "x-amz-request-id": "DC4098F4BA93B262", 
+                "date": "Wed, 15 Nov 2017 13:59:08 GMT", 
+                "content-type": "application/xml"
+            }
+        }, 
+        "Error": {
+            "Message": "The specified configuration does not exist.", 
+            "Code": "NoSuchConfiguration"
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.DeleteBucket_1.json b/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.DeleteBucket_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.DeleteBucket_1.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 204, 
+    "data": {
+        "ResponseMetadata": {
+            "HTTPStatusCode": 204, 
+            "RetryAttempts": 0, 
+            "HostId": "BH+65V5luSCk5bmjcpF99yFLSiau29yu5vMg2pIAOnESGSsfRuhRD44cUc+byebGrnp4fsrbXs0=", 
+            "RequestId": "449B5F92C773AE37", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "BH+65V5luSCk5bmjcpF99yFLSiau29yu5vMg2pIAOnESGSsfRuhRD44cUc+byebGrnp4fsrbXs0=", 
+                "date": "Wed, 15 Nov 2017 13:59:10 GMT", 
+                "x-amz-request-id": "449B5F92C773AE37", 
+                "server": "AmazonS3"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.ListBucketInventoryConfigurations_1.json b/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.ListBucketInventoryConfigurations_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.ListBucketInventoryConfigurations_1.json
@@ -0,0 +1,19 @@
+{
+    "status_code": 200, 
+    "data": {
+        "IsTruncated": false, 
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200, 
+            "RetryAttempts": 0, 
+            "HostId": "4w7UzF19MljHb52zHWGAo2ve/S1Zbbm9R4NNxQ1mAxvE+CI5VRy2Z9jpLpUi65urhb893akOE68=", 
+            "RequestId": "5F4429B72B269E27", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "4w7UzF19MljHb52zHWGAo2ve/S1Zbbm9R4NNxQ1mAxvE+CI5VRy2Z9jpLpUi65urhb893akOE68=", 
+                "date": "Wed, 15 Nov 2017 13:59:10 GMT", 
+                "content-length": "189", 
+                "x-amz-request-id": "5F4429B72B269E27", 
+                "server": "AmazonS3"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.ListBuckets_1.json b/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.ListBuckets_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_delete_inventory_inventory_not_set/s3.ListBuckets_1.json
@@ -0,0 +1,38 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Owner": {
+            "DisplayName": "jnelson11", 
+            "ID": "cb8b9d465982cf7cc480d18ccfe6fd8e017a49374af0d4f5e764ab65a3773e8f"
+        }, 
+        "Buckets": [
+            {
+                "CreationDate": {
+                    "hour": 13, 
+                    "__class__": "datetime", 
+                    "month": 11, 
+                    "second": 9, 
+                    "microsecond": 0, 
+                    "year": 2017, 
+                    "day": 15, 
+                    "minute": 59
+                }, 
+                "Name": "delete_inventory"
+            }
+        ], 
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200, 
+            "RetryAttempts": 0, 
+            "HostId": "sUAPZ6pj92zf/D11Xl1vsg92MPTiUT3hnyaEvhoq5/pcCSsqI1k7V4xzMa8Of9j0ChL3LwwQLFs=", 
+            "RequestId": "13043984F2E703CF", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "sUAPZ6pj92zf/D11Xl1vsg92MPTiUT3hnyaEvhoq5/pcCSsqI1k7V4xzMa8Of9j0ChL3LwwQLFs=", 
+                "server": "AmazonS3", 
+                "transfer-encoding": "chunked", 
+                "x-amz-request-id": "13043984F2E703CF", 
+                "date": "Wed, 15 Nov 2017 13:59:09 GMT", 
+                "content-type": "application/xml"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.CreateBucket_1.json b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.CreateBucket_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.CreateBucket_1.json
@@ -0,0 +1,20 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Location": "/custodian-inventory-test", 
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200, 
+            "RetryAttempts": 0, 
+            "HostId": "Ia1tBQEHoUfbOect/5tK2ujKfjOJElnGa7NYfs+9AJ63LJrj7qybRbzj34OBWOL4oPgliECwGus=", 
+            "RequestId": "AA74E8B09804A689", 
+            "HTTPHeaders": {
+                "content-length": "0", 
+                "x-amz-id-2": "Ia1tBQEHoUfbOect/5tK2ujKfjOJElnGa7NYfs+9AJ63LJrj7qybRbzj34OBWOL4oPgliECwGus=", 
+                "server": "AmazonS3", 
+                "x-amz-request-id": "AA74E8B09804A689", 
+                "location": "/custodian-inventory-test", 
+                "date": "Tue, 14 Nov 2017 20:05:14 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.DeleteBucket_1.json b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.DeleteBucket_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.DeleteBucket_1.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 204, 
+    "data": {
+        "ResponseMetadata": {
+            "HTTPStatusCode": 204, 
+            "RetryAttempts": 0, 
+            "HostId": "MtXIZYuO8NCkhtgngtIIDmQ62VJ7jp/v9hgJN/9LAoXLoE/+ACln4RSR63h5YsN2LrRL9Ji1oPI=", 
+            "RequestId": "3015837E86847FF1", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "MtXIZYuO8NCkhtgngtIIDmQ62VJ7jp/v9hgJN/9LAoXLoE/+ACln4RSR63h5YsN2LrRL9Ji1oPI=", 
+                "date": "Tue, 14 Nov 2017 20:05:15 GMT", 
+                "x-amz-request-id": "3015837E86847FF1", 
+                "server": "AmazonS3"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.ListBucketInventoryConfigurations_1.json b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.ListBucketInventoryConfigurations_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.ListBucketInventoryConfigurations_1.json
@@ -0,0 +1,19 @@
+{
+    "status_code": 200, 
+    "data": {
+        "IsTruncated": false, 
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200, 
+            "RetryAttempts": 0, 
+            "HostId": "JYIxh/4fa0cCPPn9aTLfYLSQYv0vPY8qySLfIygn7MTpus2XwXUW0Dnns25YXEQadztZgr/g6jM=", 
+            "RequestId": "5904BF44460D65E3", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "JYIxh/4fa0cCPPn9aTLfYLSQYv0vPY8qySLfIygn7MTpus2XwXUW0Dnns25YXEQadztZgr/g6jM=", 
+                "date": "Tue, 14 Nov 2017 20:05:14 GMT", 
+                "content-length": "189", 
+                "x-amz-request-id": "5904BF44460D65E3", 
+                "server": "AmazonS3"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.ListBucketInventoryConfigurations_2.json b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.ListBucketInventoryConfigurations_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.ListBucketInventoryConfigurations_2.json
@@ -0,0 +1,45 @@
+{
+    "status_code": 200, 
+    "data": {
+        "InventoryConfigurationList": [
+            {
+                "Schedule": {
+                    "Frequency": "Daily"
+                }, 
+                "IsEnabled": true, 
+                "Destination": {
+                    "S3BucketDestination": {
+                        "Encryption": {
+                            "SSEKMS": {
+                                "KeyId": "arn:valid:kms"
+                            }
+                        }, 
+                        "Prefix": "Inventories/644160558196", 
+                        "Bucket": "arn:aws:s3:::inv-dest", 
+                        "Format": "CSV"
+                    }
+                }, 
+                "OptionalFields": [
+                    "Size", 
+                    "EncryptionStatus"
+                ], 
+                "IncludedObjectVersions": "Current", 
+                "Id": "inv-name"
+            }
+        ], 
+        "IsTruncated": false, 
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200, 
+            "RetryAttempts": 0, 
+            "HostId": "z6B1JQbY43VPfhBWtExa4YK5DT50eakuy6WoZHBzPkHPRZzngMpo1QcFpPnPFLH5S/4yWhMj5Yw=", 
+            "RequestId": "72C0BD438E533198", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "z6B1JQbY43VPfhBWtExa4YK5DT50eakuy6WoZHBzPkHPRZzngMpo1QcFpPnPFLH5S/4yWhMj5Yw=", 
+                "date": "Tue, 14 Nov 2017 20:05:15 GMT", 
+                "content-length": "711", 
+                "x-amz-request-id": "72C0BD438E533198", 
+                "server": "AmazonS3"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.ListBuckets_1.json b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.ListBuckets_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.ListBuckets_1.json
@@ -0,0 +1,38 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Owner": {
+            "DisplayName": "jnelson11", 
+            "ID": "cb8b9d465982cf7cc480d18ccfe6fd8e017a49374af0d4f5e764ab65a3773e8f"
+        }, 
+        "Buckets": [
+            {
+                "CreationDate": {
+                    "hour": 20, 
+                    "__class__": "datetime", 
+                    "month": 11, 
+                    "second": 14, 
+                    "microsecond": 0, 
+                    "year": 2017, 
+                    "day": 14, 
+                    "minute": 5
+                }, 
+                "Name": "custodian-inventory-test"
+            }
+        ], 
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200, 
+            "RetryAttempts": 0, 
+            "HostId": "Qvc3WZmtCJLw3NX2Ykl4dMWTmWdGyCGR5A6/LHOGwhX1eY407OPmnq5s1oqGRFVrIWuaM0myXAA=", 
+            "RequestId": "CD29D168F98B4D96", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "Qvc3WZmtCJLw3NX2Ykl4dMWTmWdGyCGR5A6/LHOGwhX1eY407OPmnq5s1oqGRFVrIWuaM0myXAA=", 
+                "server": "AmazonS3", 
+                "transfer-encoding": "chunked", 
+                "x-amz-request-id": "CD29D168F98B4D96", 
+                "date": "Tue, 14 Nov 2017 20:05:14 GMT", 
+                "content-type": "application/xml"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.PutBucketInventoryConfiguration_1.json b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.PutBucketInventoryConfiguration_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_ssekms/s3.PutBucketInventoryConfiguration_1.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 204, 
+    "data": {
+        "ResponseMetadata": {
+            "HTTPStatusCode": 204, 
+            "RetryAttempts": 0, 
+            "HostId": "sl9wQkooZ9IZ7yKmwldsjCTKwkWv0PnMsKyAy04J1drv05dixOJKqdrSk0coQKzP1BzcT0rOVgo=", 
+            "RequestId": "82E64C219230B39F", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "sl9wQkooZ9IZ7yKmwldsjCTKwkWv0PnMsKyAy04J1drv05dixOJKqdrSk0coQKzP1BzcT0rOVgo=", 
+                "date": "Tue, 14 Nov 2017 20:05:14 GMT", 
+                "x-amz-request-id": "82E64C219230B39F", 
+                "server": "AmazonS3"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.CreateBucket_1.json b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.CreateBucket_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.CreateBucket_1.json
@@ -0,0 +1,20 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Location": "/custodian-inventory-test", 
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200, 
+            "RetryAttempts": 0, 
+            "HostId": "92z8iQI+RkO/BK7d+16s7HbCtJyQVMv5UN6StxRROO3hO3d3/R0HcAB4w2V8KyAfEcGAWz+MAsg=", 
+            "RequestId": "E2ACC88230E0D094", 
+            "HTTPHeaders": {
+                "content-length": "0", 
+                "x-amz-id-2": "92z8iQI+RkO/BK7d+16s7HbCtJyQVMv5UN6StxRROO3hO3d3/R0HcAB4w2V8KyAfEcGAWz+MAsg=", 
+                "server": "AmazonS3", 
+                "x-amz-request-id": "E2ACC88230E0D094", 
+                "location": "/custodian-inventory-test", 
+                "date": "Tue, 14 Nov 2017 19:35:59 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.DeleteBucket_1.json b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.DeleteBucket_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.DeleteBucket_1.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 204, 
+    "data": {
+        "ResponseMetadata": {
+            "HTTPStatusCode": 204, 
+            "RetryAttempts": 0, 
+            "HostId": "iPNcbBcZbt81tJsOglFYXxn/oa59mPJIo5sLZiNqOXHSNpqfmnF5GG6G6WtwzLsehfW/+KpwhCY=", 
+            "RequestId": "1E168101E6F798E6", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "iPNcbBcZbt81tJsOglFYXxn/oa59mPJIo5sLZiNqOXHSNpqfmnF5GG6G6WtwzLsehfW/+KpwhCY=", 
+                "date": "Tue, 14 Nov 2017 19:36:00 GMT", 
+                "x-amz-request-id": "1E168101E6F798E6", 
+                "server": "AmazonS3"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.ListBucketInventoryConfigurations_1.json b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.ListBucketInventoryConfigurations_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.ListBucketInventoryConfigurations_1.json
@@ -0,0 +1,19 @@
+{
+    "status_code": 200, 
+    "data": {
+        "IsTruncated": false, 
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200, 
+            "RetryAttempts": 0, 
+            "HostId": "5CQgck1RL1vCu/QsJz67GnxET1qH7XkgAYpPcS9MJNJhaPQHSW7BI5mPEdhLUY3oScasEFS5pTI=", 
+            "RequestId": "46884612F4197BCB", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "5CQgck1RL1vCu/QsJz67GnxET1qH7XkgAYpPcS9MJNJhaPQHSW7BI5mPEdhLUY3oScasEFS5pTI=", 
+                "date": "Tue, 14 Nov 2017 19:36:00 GMT", 
+                "content-length": "189", 
+                "x-amz-request-id": "46884612F4197BCB", 
+                "server": "AmazonS3"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.ListBucketInventoryConfigurations_2.json b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.ListBucketInventoryConfigurations_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.ListBucketInventoryConfigurations_2.json
@@ -0,0 +1,43 @@
+{
+    "status_code": 200, 
+    "data": {
+        "InventoryConfigurationList": [
+            {
+                "Schedule": {
+                    "Frequency": "Daily"
+                }, 
+                "IsEnabled": true, 
+                "Destination": {
+                    "S3BucketDestination": {
+                        "Encryption": {
+                            "SSES3": {}
+                        }, 
+                        "Prefix": "Inventories/644160558196", 
+                        "Bucket": "arn:aws:s3:::inv-dest", 
+                        "Format": "CSV"
+                    }
+                }, 
+                "OptionalFields": [
+                    "Size", 
+                    "EncryptionStatus"
+                ], 
+                "IncludedObjectVersions": "Current", 
+                "Id": "inv-name"
+            }
+        ], 
+        "IsTruncated": false, 
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200, 
+            "RetryAttempts": 0, 
+            "HostId": "p6T2z05JAGDYLckeRHYyIvgvt6qT3wROlV7pPjfotFOZ6mRN/SVlEjZbjJ9GypqgujbTEqEzCIc=", 
+            "RequestId": "3BF592B1420F133D", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "p6T2z05JAGDYLckeRHYyIvgvt6qT3wROlV7pPjfotFOZ6mRN/SVlEjZbjJ9GypqgujbTEqEzCIc=", 
+                "date": "Tue, 14 Nov 2017 19:36:00 GMT", 
+                "content-length": "673", 
+                "x-amz-request-id": "3BF592B1420F133D", 
+                "server": "AmazonS3"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.ListBuckets_1.json b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.ListBuckets_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.ListBuckets_1.json
@@ -0,0 +1,38 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Owner": {
+            "DisplayName": "jnelson11", 
+            "ID": "cb8b9d465982cf7cc480d18ccfe6fd8e017a49374af0d4f5e764ab65a3773e8f"
+        }, 
+        "Buckets": [
+            {
+                "CreationDate": {
+                    "hour": 19, 
+                    "__class__": "datetime", 
+                    "month": 11, 
+                    "second": 59, 
+                    "microsecond": 0, 
+                    "year": 2017, 
+                    "day": 14, 
+                    "minute": 35
+                }, 
+                "Name": "custodian-inventory-test"
+            }
+        ], 
+        "ResponseMetadata": {
+            "HTTPStatusCode": 200, 
+            "RetryAttempts": 0, 
+            "HostId": "x2YzlDTTkg6vVJFBL323/1VhuP+1s/IxyDKVWHrnSKY+SRrGZM0JhM9eWGBOeKar0r0n2h0+KnE=", 
+            "RequestId": "639A263A9744045C", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "x2YzlDTTkg6vVJFBL323/1VhuP+1s/IxyDKVWHrnSKY+SRrGZM0JhM9eWGBOeKar0r0n2h0+KnE=", 
+                "server": "AmazonS3", 
+                "transfer-encoding": "chunked", 
+                "x-amz-request-id": "639A263A9744045C", 
+                "date": "Tue, 14 Nov 2017 19:35:59 GMT", 
+                "content-type": "application/xml"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.PutBucketInventoryConfiguration_1.json b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.PutBucketInventoryConfiguration_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_s3_set_encrypted_inventory_sses3/s3.PutBucketInventoryConfiguration_1.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 204, 
+    "data": {
+        "ResponseMetadata": {
+            "HTTPStatusCode": 204, 
+            "RetryAttempts": 0, 
+            "HostId": "p1vLR2f7a+J9vk3DCYga4wlhk2D+SM6XW4djEEFWZ1Zayq+QGHJoG/ookGfQBosI8GCShxetZKA=", 
+            "RequestId": "F0D2E08553BC70FB", 
+            "HTTPHeaders": {
+                "x-amz-id-2": "p1vLR2f7a+J9vk3DCYga4wlhk2D+SM6XW4djEEFWZ1Zayq+QGHJoG/ookGfQBosI8GCShxetZKA=", 
+                "date": "Tue, 14 Nov 2017 19:36:00 GMT", 
+                "x-amz-request-id": "F0D2E08553BC70FB", 
+                "server": "AmazonS3"
+            }
+        }
+    }
+}
\ 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
@@ -123,6 +123,113 @@ def test_metrics(self):
 
 class BucketInventory(BaseTest):
 
+    def test_s3_set_encrypted_inventory_sses3(self):
+        bname = 'custodian-inventory-test'
+        self.patch(s3.S3, 'executor_factory', MainThreadExecutor)
+        self.patch(s3, 'S3_AUGMENT_TABLE', [])
+
+        session_factory = self.replay_flight_data('test_s3_set_encrypted_inventory_sses3')
+
+        client = session_factory().client('s3')
+        client.create_bucket(Bucket=bname)
+        self.addCleanup(client.delete_bucket, Bucket=bname)
+
+        p = self.load_policy({
+            'name': 's3-inv',
+            'resource': 's3',
+            'filters': [
+                {'Name': bname}
+            ],
+            'actions': [
+                {
+                    'type': 'set-inventory',
+                    'destination': 'inv-dest',
+                    'name': 'inv-name',
+                    'state': 'enabled',
+                    'encryption': 'SSES3',
+                    'fields': ['Size', 'EncryptionStatus']
+                }
+            ]
+        }, session_factory=session_factory)
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+
+        invs = client.list_bucket_inventory_configurations(
+            Bucket=bname).get('InventoryConfigurationList')
+        self.assertTrue(invs)
+        self.assertTrue('SSES3' in invs[0]['Destination']['S3BucketDestination']['Encryption'])
+        self.assertTrue('EncryptionStatus' in invs[0]['OptionalFields'])
+
+    def test_s3_set_encrypted_inventory_ssekms(self):
+        bname = 'custodian-inventory-test'
+        self.patch(s3.S3, 'executor_factory', MainThreadExecutor)
+        self.patch(s3, 'S3_AUGMENT_TABLE', [])
+
+        session_factory = self.replay_flight_data('test_s3_set_encrypted_inventory_ssekms')
+
+        client = session_factory().client('s3')
+        client.create_bucket(Bucket=bname)
+        self.addCleanup(client.delete_bucket, Bucket=bname)
+
+        p = self.load_policy({
+            'name': 's3-inv',
+            'resource': 's3',
+            'filters': [
+                {'Name': bname}
+            ],
+            'actions': [
+                {
+                    'type': 'set-inventory',
+                    'destination': 'inv-dest',
+                    'name': 'inv-name',
+                    'state': 'enabled',
+                    'encryption': 'SSEKMS',
+                    'key_id': 'arn:valid:kms',
+                    'fields': ['Size', 'EncryptionStatus']
+                }
+            ]
+        }, session_factory=session_factory)
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+
+        invs = client.list_bucket_inventory_configurations(
+            Bucket=bname).get('InventoryConfigurationList')
+        self.assertTrue(invs)
+        self.assertTrue('SSEKMS' in invs[0]['Destination']['S3BucketDestination']['Encryption'])
+        self.assertTrue('EncryptionStatus' in invs[0]['OptionalFields'])
+
+    def test_s3_delete_inventory_inventory_not_set(self):
+        bname = 'delete_inventory'
+        self.patch(s3.S3, 'executor_factory', MainThreadExecutor)
+        self.patch(s3, 'S3_AUGMENT_TABLE', [])
+
+        session_factory = self.replay_flight_data('test_s3_delete_inventory_inventory_not_set')
+
+        client = session_factory().client('s3')
+        client.create_bucket(Bucket=bname)
+        self.addCleanup(client.delete_bucket, Bucket=bname)
+
+        p = self.load_policy({
+            'name': 's3-inv',
+            'resource': 's3',
+            'filters': [
+                {'Name': bname}
+            ],
+            'actions': [
+                {
+                    'type': 'set-inventory',
+                    'destination': 'inv-dest',
+                    'name': 'inv-name',
+                    'state': 'absent',
+                }
+            ]
+        }, session_factory=session_factory)
+
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        inventoryConfigList = client.list_bucket_inventory_configurations(Bucket=bname).get('InventoryConfigurationList')
+        self.assertFalse(inventoryConfigList)
+
     @functional
     def test_inventory(self):
         bname = 'custodian-test-data'