There are a lot of things that can go wrong with signed URLs. There might be problems with permissions, with the configuration of the S3 service object, or with the bucket or the object itself. Even for the slightest misconfiguration, AWS returns an error.
And all errors with signed URLs surface when the URL is used and not when it's signed. As these are visible to the users they are deliberately vague and cryptic. This makes debugging harder as it's not readily apparent what went wrong.
This chapter is a collection of the error I've encountered with a brief description of the root cause in each case.
AccessDenied is the most common form of error you'll see and it can have a variety of causes. When there is no
<Message> to provide any details, it means the signer entity has no permission to read the object.
This can be for a variety of reasons, but some of the common ones are:
The signer entity has no
s3:GetObject permission for the bucket
Check the policy that is in use. Also double check that the bucket is the same for the signing and for the permission.
A policy has an explicit deny
If any applicable policy has an explicit deny then it will prevent access even if there is an allow. Check the bucket policy, and the identity policy.
No access to the KMS key
If the object is encrypted with a Customer Managed CMK then the signer entity needs access to the key in addition to the object. Check that the signer role has the
kms:Decrypt permission for the CMK's ARN.
The object does not exist and there is no
getObject operation for an object that does not exist can result an Access Denied error if there is no
s3:ListBucket permission for the bucket. To debug this, you can add the
s3:ListBucket permission to see if the error changes to
NoSuchKey. If it does, then it indicates that the problem is a nonexistent object.