diff --git a/controlpanel/api/aws.py b/controlpanel/api/aws.py index 4a8e6f284..367872e30 100644 --- a/controlpanel/api/aws.py +++ b/controlpanel/api/aws.py @@ -198,18 +198,46 @@ def delete_role(name): def create_bucket(bucket_name, is_data_warehouse=False): + s3_resource = boto3.resource("s3") + s3_client = boto3.client('s3') try: - bucket = boto3.resource('s3').create_bucket( + bucket = s3_resource.create_bucket( Bucket=bucket_name, ACL='private', CreateBucketConfiguration={ 'LocationConstraint': settings.BUCKET_REGION, }, ) + # Enable versioning by default. + # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html?highlight=s3#S3.BucketVersioning + versioning = bucket.Versioning() + versioning.enable() + # Set bucket lifecycle. Send non-current versions of files to glacier + # storage after 30 days. + # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.put_bucket_lifecycle_configuration + lifecycle_id = f"{bucket_name}_lifecycle_configuration" + lifecycle_conf = s3_client.put_bucket_lifecycle_configuration( + Bucket=bucket_name, + LifecycleConfiguration={ + "Rules": [ + { + "ID": lifecycle_id, + "Status": "Enabled", + "Prefix": "", + "NoncurrentVersionTransitions": [ + { + 'NoncurrentDays': 30, + 'StorageClass': 'GLACIER', + }, + ] + }, + ] + } + ) if is_data_warehouse: _tag_bucket(bucket, {"buckettype": "datawarehouse"}) - except bucket.meta.client.exceptions.BucketAlreadyOwnedByYou: + except s3_resource.meta.client.exceptions.BucketAlreadyOwnedByYou: log.warning(f'Skipping creating Bucket {bucket_name}: Already exists') return diff --git a/tests/api/test_aws.py b/tests/api/test_aws.py index 697bacfbf..c93b6259f 100644 --- a/tests/api/test_aws.py +++ b/tests/api/test_aws.py @@ -253,6 +253,17 @@ def test_create_bucket(logs_bucket, s3): aws.create_bucket(bucket_name, is_data_warehouse=True) + # Check versioning. + assert bucket.Versioning().status == "Enabled" + + # Check lifecycle. + versioning = bucket.LifecycleConfiguration() + rule = versioning.rules[0] + assert rule["ID"].endswith("_lifecycle_configuration") + assert rule["Status"] == "Enabled" + assert rule["NoncurrentVersionTransitions"][0]["NoncurrentDays"] == 30 + assert rule["NoncurrentVersionTransitions"][0]["StorageClass"] == "GLACIER" + # Check logging assert bucket.Logging().logging_enabled['TargetBucket'] == settings.LOGS_BUCKET_NAME # Check tagging