1

Learning S3 I know how to generate a presigned URL:

const aws = require('aws-sdk')
const s3 = new aws.S3()
aws.config.update({
  accessKeyId: 'id-omitted', 
  secretAccessKey: 'key-omitted'
})

const myBucket = 'foo'
const myKey = 'bar.png'
const signedUrlExpireSeconds = 60 * 5

const url = s3.getSignedUrl('getObject', {
    Bucket: myBucket,
    Key: myKey,
    Expires: signedUrlExpireSeconds
})

console.log(`Presigned URL: ${url}`)

and from reading the documentation I can retrieve what's in the bucket with headObject but I've tested trying to find wether an object already has a presigned URL:

1st attempt:

let signedUrl = await s3.validSignedURL('getObject', params).promise()
console.log(`Signed URL: ${signedUrl}`)

2nd attempt:

await s3.getObject(params, (err, data) => {
  if (err) console.log(err)
  return data.Body.toString('utf-8')
})

3rd attempt:

let test = await s3.headObject(params).promise()
console.log(`${test}`)

and I'm coming up short. I know could create a file or log to a file when a presigned URL is created but I think that would be a hack. Is there a way in Node I can check an object to see if it has a presigned URL created for it? I'm not looking to do this in the dashboard I'm looking for a way to do this solely in the terminal/script. Going through the tags and querying Google I'm not finding any luck

Referenced:

DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
  • What problem are you trying to solve here? – jarmod Jun 21 '19 at 15:13
  • Find if an object has a presigned URL before creating a second one before creating one and sending it to an API. If I can identify if a URL exists and know the time I will know if there is an issue with a 3rd party API. – DᴀʀᴛʜVᴀᴅᴇʀ Jun 21 '19 at 15:13
  • Why? There's no obvious value in doing this. The cost of generating a new pre-signed URL per use is absolutely minimal (it's simply a function call that does some calculation and signing). Simply create a second one. If you really, really want to cache pre-signed URLs then you can do that, of course, in some kind of key/value store but be aware that they have an expiration time. – jarmod Jun 21 '19 at 15:18
  • I get they have an expiration time. The presigned URL goes to an API and will effect the usage of that API. I wouldn't be worried about the URLs but since it affects the API that I'm using instead of bombarding it with URLs to process files. Instead of building a dynamodb solution to solve this I wanted to know if it was even possible before effecting the API and for a analytics aspect. – DᴀʀᴛʜVᴀᴅᴇʀ Jun 21 '19 at 15:21
  • Interesting. OK, I think you'll need to cache them with an appropriate TTL, unless it makes sense for the remote API itself to deconstruct each pre-signed URL, determine that it's related to an S3 object key that it's already seen and then correlate them. – jarmod Jun 21 '19 at 15:37

2 Answers2

3

Is there a way in Node I can check an object to see if it has a presigned URL created for it?

Short answer: No

Long answer: There is no information about the signed urls stored on the object or any list of created urls. You can even create a signed url completely on client side without invoking any service

gusto2
  • 11,210
  • 2
  • 17
  • 36
1

That question is interesting. I'd tried to find whether some place stored the presigned URL, but still not found.

But what gusto2 says is true, you can just create a presigned URL without any aws service, which is exactly what aws-sdk doing.

Check this file: https://github.com/aws/aws-sdk-js/blob/cc29728c1c4178969ebabe3bbe6b6f3159436394/ts/cloudfront.ts

Then you can get how presigned URL is generated:

var getRtmpUrl = function (rtmpUrl) {
    var parsed = url.parse(rtmpUrl);
    return parsed.path.replace(/^\//, '') + (parsed.hash || '');
};

var getResource = function (url) {
    switch (determineScheme(url)) {
        case 'http':
        case 'https':
            return url;
        case 'rtmp':
            return getRtmpUrl(url);
        default:
            throw new Error('Invalid URI scheme. Scheme must be one of'
                + ' http, https, or rtmp');
    }
};


getSignedUrl: function (options, cb) {
        try {
            var resource = getResource(options.url);
        } catch (err) {
            return handleError(err, cb);
        }

        var parsedUrl = url.parse(options.url, true),
            signatureHash = Object.prototype.hasOwnProperty.call(options, 'policy')
                ? signWithCustomPolicy(options.policy, this.keyPairId, this.privateKey)
                : signWithCannedPolicy(resource, options.expires, this.keyPairId, this.privateKey);

        parsedUrl.search = null;
        for (var key in signatureHash) {
            if (Object.prototype.hasOwnProperty.call(signatureHash, key)) {
                parsedUrl.query[key] = signatureHash[key];
            }
        }

        try {
            var signedUrl = determineScheme(options.url) === 'rtmp'
                    ? getRtmpUrl(url.format(parsedUrl))
                    : url.format(parsedUrl);
        } catch (err) {
            return handleError(err, cb);
        }

        return handleSuccess(signedUrl, cb);
    }
Diya Li
  • 1,048
  • 9
  • 21