From 90c3c1755a93b3e1a94e85126dd3138e7ae3f9cd Mon Sep 17 00:00:00 2001 From: Chirag Choudha Date: Tue, 14 Jun 2022 19:15:38 +0530 Subject: [PATCH] adding bucket key --- plugins/modules/s3_bucket.py | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/plugins/modules/s3_bucket.py b/plugins/modules/s3_bucket.py index c49d7409905..0797126220b 100644 --- a/plugins/modules/s3_bucket.py +++ b/plugins/modules/s3_bucket.py @@ -84,6 +84,14 @@ description: KMS master key ID to use for the default encryption. This parameter is allowed if I(encryption) is C(aws:kms). If not specified then it will default to the AWS provided KMS key. type: str + encryption_bucket_key: + description: State of Bucket Key for SSE-KMS on new objects. This parameter is allowed if I(encryption) is C(aws:kms). If + not specified then it will default to absent. + required: false + default: absent + choices: [ 'present', 'absent' ] + type: str + public_access: description: - Configure public access block for S3 bucket. @@ -214,6 +222,11 @@ encryption: "aws:kms" encryption_key_id: "arn:aws:kms:us-east-1:1234/5678example" +# Create a bucket with aws:kms encryption, Bucket key +- amazon.aws.s3_bucket: + name: mys3bucket + encryption_bucket_key: present + # Create a bucket with aws:kms encryption, default key - amazon.aws.s3_bucket: name: mys3bucket @@ -359,6 +372,7 @@ def create_or_update_bucket(s3_client, module, location): versioning = module.params.get("versioning") encryption = module.params.get("encryption") encryption_key_id = module.params.get("encryption_key_id") + encryption_bucket_key = module.params.get("encryption_bucket_key") public_access = module.params.get("public_access") delete_public_access = module.params.get("delete_public_access") delete_object_ownership = module.params.get("delete_object_ownership") @@ -535,6 +549,20 @@ def create_or_update_bucket(s3_client, module, location): current_encryption = put_bucket_encryption_with_retry(module, s3_client, name, expected_encryption) changed = True + if encryption_bucket_key is not None: + if current_encryption_algorithm == 'aws:kms': +# current_bucket_key = current_encryption['ServerSideEncryptionConfiguration']['Rules'][0]['BucketKeyEnabled'] if current_encryption else None + current_bucket_key = get_bucket_key(s3_client, name) + if encryption_bucket_key: + expected_encryption = {'BucketKeyEnabled': True} + else: + expected_encryption = {'BucketKeyEnabled': False} + current_bucket_key = put_bucket_key_with_retry(module, s3_client, name, expected_encryption) + changed = True + # if current_bucket_key supplied param from ansible + + + result['encryption'] = current_encryption # Public access clock configuration @@ -700,6 +728,17 @@ def get_bucket_encryption(s3_client, bucket_name): except (IndexError, KeyError): return None +@AWSRetry.exponential_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) +def get_bucket_key(s3_client, bucket_name): + try: + result = s3_client.get_bucket_encryption(Bucket=bucket_name) + return result.get('ServerSideEncryptionConfiguration', {}).get('Rules', [])[0].get('BucketKeyEnabled') + except is_boto3_error_code('ServerSideEncryptionConfigurationNotFoundError'): + return None + except (IndexError, KeyError): + return None + + def put_bucket_encryption_with_retry(module, s3_client, name, expected_encryption): max_retries = 3 @@ -725,6 +764,29 @@ def put_bucket_encryption(s3_client, bucket_name, encryption): server_side_encryption_configuration = {'Rules': [{'ApplyServerSideEncryptionByDefault': encryption}]} s3_client.put_bucket_encryption(Bucket=bucket_name, ServerSideEncryptionConfiguration=server_side_encryption_configuration) +def put_bucket_key_with_retry(module, s3_client, name, expected_encryption): + max_retries = 3 + for retries in range(1, max_retries + 1): + try: + put_bucket_key(s3_client, name, expected_encryption) + except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: # pylint: disable=duplicate-except + module.fail_json_aws(e, msg="Failed to set bucket Key") + current_encryption = wait_encryption_is_applied(module, s3_client, name, expected_encryption, + should_fail=(retries == max_retries), retries=5) + if current_encryption == expected_encryption: + return current_encryption + + # We shouldn't get here, the only time this should happen is if + # current_encryption != expected_encryption and retries == max_retries + # Which should use module.fail_json and fail out first. + module.fail_json(msg='Failed to set bucket key', + current=current_encryption, expected=expected_encryption, retries=retries) + +@AWSRetry.exponential_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) +def put_bucket_key(s3_client, bucket_name, encryption): + server_side_encryption_configuration = {'Rules': [{'BucketKeyEnabled': encryption}]} + s3_client.put_bucket_encryption(Bucket=bucket_name, ServerSideEncryptionConfiguration=server_side_encryption_configuration) + @AWSRetry.exponential_backoff(max_delay=120, catch_extra_error_codes=['NoSuchBucket', 'OperationAborted']) def delete_bucket_tagging(s3_client, bucket_name): @@ -1009,6 +1071,7 @@ def main(): ceph=dict(default=False, type='bool'), encryption=dict(choices=['none', 'AES256', 'aws:kms']), encryption_key_id=dict(), + encryption_bucket_key=dict(type='bool', default=False), public_access=dict(type='dict', options=dict( block_public_acls=dict(type='bool', default=False), ignore_public_acls=dict(type='bool', default=False), @@ -1070,6 +1133,7 @@ def main(): state = module.params.get("state") encryption = module.params.get("encryption") encryption_key_id = module.params.get("encryption_key_id") + encryption_bucket_key = module.params.get("encryption_bucket_key") delete_object_ownership = module.params.get('delete_object_ownership') object_ownership = module.params.get('object_ownership')