This article is an answer to my bug report here: https://github.com/minio/minio/issues/21735
Context
S3 buckets ca be configured to keep old versions of objects when overwriting/deleting them. This is called a versioned bucket
Calling DeleteObject on an object in a versioned bucket will not really delete it, but mark it as so with a delete marker. The object will appear deleted, but can still be viewed/deleted by specifying its versionId.
This behaviour is really useful, for example for backups, where you want a client to upload its backups, but not be able to delete them all instantly. In this case, you would allow the client to do DeleteObject calls, but not DeleteObjectVersion, and clean up old versions periodically.
MinIO-specific behaviour
Unfortunately, MinIO policies don’t behave the same way as in other platforms. On CEPH & AWS (The 2 other providers implementing policies that I know of), the s3:DeleteObject permission does not grant s3:DeleteObjectVersion.
But on MinIO, allowing s3:DeleteObject to an user will implicitely grant it s3:DeleteObjectVersion. As shown here and in my exchange with the devs, this is a known and expected behaviour of MinIO, which cannot be fixed because it would produce a breaking change.
The solution to block object version deletions is to explicitely deny DeleteObjectVersion, like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"s3:DeleteObjectVersion"
],
"Resource": "arn:aws:s3:::test/*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::test/*"
}
]
}
Conclusion
The above policy will block DeleteObjectVersion calls but allow DeleteObject, allowing you to have the same behaviour with MinIO as you have with other S3 providers.
⚠️ Not applying these changes might expose you to malicious code deleting all backups using the backup client’s S3 user. This affects MinIO, and maybe also AIStor.
Note: another change is that s3:ListBucket seems to grant s3:ListBucketVersions implicitely, with no way to disable it (even by Deny-ing it).