Amazon S3 is widely used as a repository for backups. Backups are an important aspect of a resilient system, but they are also a potential security vulnerability. Unauthorized access to a database backup is still a PCI or HIPAA violation. The permissions on Amazon S3 should be configured to minimize access to critical backups. My strategy is to use IAM to create a backup user with no password (cannot log in to AWS) and a single access key. The backup user’s access key is used to put backup files into S3. The S3 bucket policy is configured to allow “write-only” access for the backup user. The backups cannot be obtained, even if the backup user’s credentials are compromised.
It is fairly difficult to figure out how to create a “write only” bucket policy. The policy shown below is the “write only” policy that I use. It consists of two statements: BucketPermissions gives a user ability to locate the bucket (necessary to do anything in the bucket) and list its contents (to verify that a backup was written). You may remove the s3:ListBucket action if true write-only access is desired. The statement called ObjectPermissions allows the user to create objects in the specified bucket.
{ "Version": "2012-10-17", "Id": "YOUR_POLICY_ID_NUMBER", "Statement": [ { "Sid": "BucketPermissions", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::YOUR_ACCOUNT_ID:user/USERNAME" }, "Action": [ "s3:ListBucket", "s3:GetBucketLocation" ], "Resource": "arn:aws:s3:::BUCKET_NAME" }, { "Sid": "ObjectPermissions", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::YOUR_ACCOUNT_ID:user/USERNAME" }, "Action": [ "s3:PutObjectAcl", "s3:PutObject" ], "Resource": "arn:aws:s3:::BUCKET_NAME/*" } ] }
S3 does one odd thing: this policy allows the user to verify that a particular object exists in S3, even if they don’t have permission to GET the object. For example, running the command:
s3cmd get s3://BUCKET_NAME/PATH/BACKUP_FILE_NAME.tgz
Produces the output:
s3://BUCKET_NAME/PATH/BACKUP_FILE_NAME.tgz -> ./BACKUP_FILE_NAME.tgz ERROR: S3 error: Unknown error
It appears that the file is being downloaded, but in fact only an empty file is created! While it is generally a bad idea to allow unauthorized users to guess file names, it is not a real problem in this case, because the backup user’s credentials would have to be compromised even to confirm the existence of a file stored in S3.