I have a versioned S3 bucket named protected-bucket and I want to programmatically delete objects or versions (sometimes just some versions). Bucket has the following policy attached that enforces the MFA to be present when Delete* actions are about to be executed:
{
"Sid": "RequireMFAForDelete",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:Delete*",
"Resource": "arn:aws:s3:::protected-bucket/*",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "false"
}
}
}
I also tried to use the "Condition": { "Null": { "aws:MultiFactorAuthAge": true }} in bucket policy, as suggested on the https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html#example-bucket-policies-use-case-7 page. Got the same problem from below...
Here is a minimal Python3 code that is supposed to delete object version in the bucket I mentioned above:
#!/usr/bin/env python3
import boto3
from datetime import datetime
mfa_totp = input("Enter the MFA code: ")
session_name='my-test-session-' + str(int(datetime.utcnow().timestamp()))
client=boto3.client('sts', 'us-east-1')
ar_res = client.assume_role(
RoleArn='arn:aws:iam::123456789102:role/test-role',
RoleSessionName=session_name,
DurationSeconds=900,
SerialNumber='arn:aws:iam::987654321098:mfa/my_user_name',
TokenCode=mfa_totp,
)
print(ar_res)
tmp_creds = ar_res["Credentials"]
s3_client = boto3.client("s3", "us-east-1",
aws_access_key_id=tmp_creds["AccessKeyId"],
aws_secret_access_key=tmp_creds["SecretAccessKey"],
aws_session_token=tmp_creds["SessionToken"])
s3_bucket = "protected-bucket"
s3_key = "test/test4.txt"
s3_version = "XYZXbHbi3lpCNlOM8peIim6gi.IZQJqM"
# If I put code here that lists objects in
if s3_version:
response = s3_client.delete_object(Bucket=s3_bucket,
Key=s3_key,
VersionId=s3_version)
else:
response = s3_client.delete_object(Bucket=s3_bucket,Key=s3_key)
print(response)
The error I am getting follows:
Traceback (most recent call last):
File "./del_test.py", line 37, in <module>
response = s3_client.delete_object(Bucket=s3_bucket,
File "/home/dejan/py/myproj/lib64/python3.8/site-packages/botocore/client.py", line 386, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/home/dejan/py/myproj/lib64/python3.8/site-packages/botocore/client.py", line 705, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the DeleteObject operation: Access Denied
Few things to note:
- Role I am assuming is a different account (some people may have noticed different account numbers in the Python code.
- That Role has Delete* actions allowed in a policy attached to the role. When I remove the MFA protection in the bucket policy, the Python 3 code above works - it can delete objects and versions.