Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

aws - s3 - adding bucket_key_enabled to bucket-encryption filter #8868

Merged
merged 8 commits into from
Sep 1, 2023
27 changes: 26 additions & 1 deletion c7n/resources/s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -3402,15 +3402,28 @@
filters:
- type: bucket-encryption
state: False
- name: s3-bucket-test-bucket-key-enabled
resource: s3
region: us-east-1
filters:
- type: bucket-encryption
bucket_key_enabled: True
"""
schema = type_schema('bucket-encryption',
state={'type': 'boolean'},
crypto={'type': 'string', 'enum': ['AES256', 'aws:kms']},
key={'type': 'string'})
key={'type': 'string'},
bucket_key_enabled={'type': 'boolean'})
kapilt marked this conversation as resolved.
Show resolved Hide resolved

permissions = ('s3:GetEncryptionConfiguration', 'kms:DescribeKey', 'kms:ListAliases')
annotation_key = 'c7n:bucket-encryption'

def validate(self):
if self.data.get('bucket_key_enabled') is not None and self.data.get('key') is not None:
raise PolicyValidationError(
f'key and bucket_key_enabled attributes cannot both be set: {self.data}'
)

def process(self, buckets, event=None):
self.resolve_keys(buckets)
results = []
Expand Down Expand Up @@ -3445,6 +3458,13 @@
rules = be.get('ServerSideEncryptionConfiguration', {}).get('Rules', [])
# default `state` to True as previous impl assumed state == True
# to preserve backwards compatibility
if self.data.get('bucket_key_enabled'):
for rule in rules:
return self.filter_bucket_key_enabled(rule)
elif self.data.get('bucket_key_enabled') is False:
for rule in rules:
return not self.filter_bucket_key_enabled(rule)

if self.data.get('state', True):
for sse in rules:
return self.filter_bucket(b, sse)
Expand Down Expand Up @@ -3490,6 +3510,11 @@
key_ids = {key.get('Arn'), key.get('KeyId'), *key['Aliases']}
return rule.get('KMSMasterKeyID', 'alias/aws/s3') in key_ids

def filter_bucket_key_enabled(self, rule) -> bool:
if not rule:
return False

Check warning on line 3515 in c7n/resources/s3.py

View check run for this annotation

Codecov / codecov/patch

c7n/resources/s3.py#L3515

Added line #L3515 was not covered by tests
return rule.get('BucketKeyEnabled')


@actions.register('set-bucket-encryption')
class SetBucketEncryption(KMSKeyResolverMixin, BucketActionBase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"status_code": 200,
"data": {
"ResponseMetadata": {},
"ServerSideEncryptionConfiguration": {
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
},
"BucketKeyEnabled": false
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"status_code": 200,
"data": {
"ResponseMetadata": {},
"ServerSideEncryptionConfiguration": {
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:us-east-1:644160558196:key/845ab6f1-744c-4edc-b702-efae6836818a"
},
"BucketKeyEnabled": true
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"status_code": 200,
"data": {
"ResponseMetadata": {},
"Buckets": [
{
"Name": "c7n-test-s3-bucket",
"CreationDate": {
"__class__": "datetime",
"year": 2023,
"month": 8,
"day": 22,
"hour": 13,
"minute": 27,
"second": 29,
"microsecond": 0
}
},
{
"Name": "c7n-test-s3-bucket-bucket-key-disabled",
"CreationDate": {
"__class__": "datetime",
"year": 2023,
"month": 8,
"day": 22,
"hour": 13,
"minute": 29,
"second": 11,
"microsecond": 0
}
}
],
"Owner": {
"DisplayName": "mandeep.bal",
"ID": "e7c8bb65a5fc49cf906715eae09de9e4bb7861a96361ba79b833aa45f6833b15"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"status_code": 200,
"data": {
"ResponseMetadata": {},
"ServerSideEncryptionConfiguration": {
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
},
"BucketKeyEnabled": false
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"status_code": 200,
"data": {
"ResponseMetadata": {},
"ServerSideEncryptionConfiguration": {
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:us-east-1:644160558196:key/845ab6f1-744c-4edc-b702-efae6836818a"
},
"BucketKeyEnabled": true
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"status_code": 200,
"data": {
"ResponseMetadata": {},
"Buckets": [
{
"Name": "c7n-test-s3-bucket",
"CreationDate": {
"__class__": "datetime",
"year": 2023,
"month": 8,
"day": 22,
"hour": 13,
"minute": 27,
"second": 29,
"microsecond": 0
}
},
{
"Name": "c7n-test-s3-bucket-bucket-key-disabled",
"CreationDate": {
"__class__": "datetime",
"year": 2023,
"month": 8,
"day": 22,
"hour": 13,
"minute": 29,
"second": 11,
"microsecond": 0
}
}
],
"Owner": {
"DisplayName": "mandeep.bal",
"ID": "e7c8bb65a5fc49cf906715eae09de9e4bb7861a96361ba79b833aa45f6833b15"
}
}
}
82 changes: 82 additions & 0 deletions tests/test_s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -4431,3 +4431,85 @@ def test_s3_bucket_no_replication_rule(self):
resources = p.run()
self.assertEqual(len(resources), 1)
self.assertEqual(resources[0]['Name'],'custodian-replication-west')


def test_s3_bucket_key_enabled(self):
self.patch(s3.S3, "executor_factory", MainThreadExecutor)
self.patch(s3.BucketEncryption, "executor_factory", MainThreadExecutor)
self.patch(s3, "S3_AUGMENT_TABLE", [])
factory = self.replay_flight_data('test_s3_bucket_key_enabled')
kapilt marked this conversation as resolved.
Show resolved Hide resolved

p = self.load_policy(
{
'name': 'test-s3-bucket-key-enabled',
'resource': 'aws.s3',
'filters': [
{
'type': 'bucket-encryption',
'bucket_key_enabled': True
},
{
'type': 'value',
'key': 'Name',
'value': 'c7n-test-s3-bucket',
'op': 'contains'
}
]
},
session_factory=factory
)
resources = p.run()
self.assertEqual(len(resources), 1)


def test_s3_bucket_key_disabled(self):
self.patch(s3.S3, "executor_factory", MainThreadExecutor)
self.patch(s3.BucketEncryption, "executor_factory", MainThreadExecutor)
self.patch(s3, "S3_AUGMENT_TABLE", [])
factory = self.replay_flight_data('test_s3_bucket_key_disabled')

p = self.load_policy(
{
'name': 'test-s3-bucket-key-disabled',
'resource': 'aws.s3',
'filters': [
{
'type': 'bucket-encryption',
'bucket_key_enabled': False
},
{
'type': 'value',
'key': 'Name',
'value': 'c7n-test-s3-bucket',
'op': 'contains'
}
]
},
session_factory=factory
)
resources = p.run()
self.assertEqual(len(resources), 1)


def test_bucket_encryption_invalid(self):
self.assertRaises(
PolicyValidationError,
self.load_policy,
{
'name': 'test-s3-bucket-encryption-invalid',
'resource': 'aws.s3',
'filters': [
{
'type': 'bucket-encryption',
'bucket_key_enabled': False,
'key': 'alias/foobar'
},
{
'type': 'value',
'key': 'Name',
'value': 'c7n-test-s3-bucket',
'op': 'contains'
}
]
},
)