pipo
pipo

Reputation: 408

Generate an AWS S3 PreSigned URL using my own domain/subdomain

I'm using AWS SDK for .NET and I am currently generating presigned URLs for my S3 bucket.

The URLs I currently get are like https://{bucketname}.s3.amazonaws.com/{FileAndQueryParameters}

What I was looking for was something like https://{MyDomainName}/{FileAndQueryParameters}

I've already tried to replace the first url with my own CNAME pointing to {bucketname}.s3.amazonaws.com but I get an obvious

<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your key and signing method.
</Message>

Any ideas how to accomplish this?


By the way, this is the code I'm using right now:

(...)
AmazonS3 client = AWSClientFactory.CreateAmazonS3Client(AccessKey, SecretKey);

string S3_KEY = Key;
string BUCKET_NAME = Bucket;
string FOLDER = SubFolder;
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest();
request.WithBucketName(BUCKET_NAME);
request.WithKey(FOLDER + "/" + S3_KEY);

if (ssUseHTTPS)
{
    request.WithProtocol(Protocol.HTTPS);
}
else
{
    request.WithProtocol(Protocol.HTTP);
}

if (DownloadFileName != string.Empty)
{
    ResponseHeaderOverrides responseHeaders = new ResponseHeaderOverrides();
    responseHeaders.CacheControl = "No-cache";
    responseHeaders.ContentDisposition = "attachment; filename=" + DownloadFileName.Replace(";", "").Replace(",", "");

    request.ResponseHeaderOverrides = responseHeaders;
}

request.WithExpires(DateTime.Now.AddSeconds(SecondsValidFor));

Url = client.GetPreSignedURL(request);

return Url;

Upvotes: 9

Views: 3505

Answers (2)

Ryan
Ryan

Reputation: 384

Spent days going round in circles trying to setup custom CNAME/host for presigned URLs and it seemed impossible.

All forums said it cannot be done, or you have to recode your whole app to use cloudfront instead.

Changing my DNS to point from MYBUCKET.s3-WEBSITE-eu-west-1.amazonaws.com to MYBUCKET.s3-eu-west-1.amazonaws.com fixed it instantly.

Hope this helps others.

Working code:

function get_objectURL($key) {


        // Instantiate the client.
        $this->s3 = S3Client::factory(array(
            'credentials' => array(
                'key'    => s3_key,
                'secret' => s3_secret,
            ),
            'region'  => 'eu-west-1',
            'version' => 'latest',
            'endpoint' => 'https://example.com',
            'bucket_endpoint' => true,
            'signature_version' => 'v4'
        ));


        $cmd = $this->s3->getCommand('GetObject', [
            'Bucket' => s3_bucket,
            'Key' => $key
        ]);


        try {
        
            $request = $this->s3->createPresignedRequest($cmd, '+5 minutes');

            // Get the actual presigned-url
            $presignedUrl = (string)$request->getUri();

            return $presignedUrl;

        } catch (S3Exception $e) {

            return $e->getMessage() . "\n";

        } 
    }

Upvotes: 4

devnuts
devnuts

Reputation: 137

The bucket name needs to be the same as the domain.

Upvotes: 0

Related Questions