如何在 NodeJS 中创建预签名 url 以从 AWS-s3 存储桶下载文件 36 小时?

How can I create a pre-signed url to download a file from an AWS-s3 Bucket for 36 hours in NodeJS?

我现在的 aws-lambda 代码是:


    'use strict';
    
    const AWS = require('aws-sdk');
    
    class AwsS3Repository {
      constructor() {
        this.s3 = new AWS.S3();
      }
    
      async getSignedUrl ({ bucketName, Key, Expires }) {
        const params = { 
          Bucket: "bucket_name", 
          Key: "key_name",
          Expires: 60 * 60 * 36,
        }
    
        return this.s3.getSignedUrl('getObject', params);
      }
    } 
    
    module.exports = AwsS3Repository;

虽然有效,但过期时间忽略参数“expires”,而是在似乎不到一小时后过期。

我在 AWS docs 中读到您需要使用 STS 创建有效期为 36 小时的链接,因此我在 AWS 中创建了一个对我的 lambda 函数具有可信策略的 STS,所以我可以使用 STS.assume 正如你在这个例子中看到的那样:


    const AWS = require('aws-sdk');
    // Set the region 
    AWS.config.update({region: 'REGION'});
    
    var roleToAssume = {RoleArn: 'my_role',
                        RoleSessionName: 'session1',
                        DurationSeconds: 900,};
    var roleCreds;
    
    // Create the STS service object    
    var sts = new AWS.STS({apiVersion: '2011-06-15'});
    
    //Assume Role
    sts.assumeRole(roleToAssume, function(err, data) {
        if (err) console.log(err, err.stack);
        else{
            roleCreds = {accessKeyId: data.Credentials.AccessKeyId,
                         secretAccessKey: data.Credentials.SecretAccessKey,
                         sessionToken: data.Credentials.SessionToken};
            stsGetCallerIdentity(roleCreds);
        }
    });
    
    //Get Arn of current identity
    function stsGetCallerIdentity(creds) {
        var stsParams = {credentials: creds };
        // Create STS service object
        var sts = new AWS.STS(stsParams);
            
        sts.getCallerIdentity({}, function(err, data) {
            if (err) {
                console.log(err, err.stack);
            }
            else {
                console.log(data.Arn);
            }
        });    
    }

 

但是,我还是不明白我将如何使用STS来创建预签名url。

如果您阅读 getSignedUrl 的文档,您会看到过期时间是以秒为单位指定的,而不是以小时为单位:

Expires (Integer) — default: 900 — the number of seconds to expire the pre-signed URL operation in. Defaults to 15 minutes.

我通过创建一个 IAM 角色来解决这个问题,该角色有权在我的 S3 存储桶中创建签名 url 并将其设置为通过 AWS 中的信任策略选项信任我的 lambda,然后更新 AWS-SDK配置以使用 sts.assumeRole 方法返回的 IAM 凭据。


    async assumeRole() {
    const roleToAssume = {
      RoleArn: 'my-sts-role-in-aws',
      RoleSessionName: 'session1',
      DurationSeconds: 900,
    };

    const sts = new AWS.STS({ apiVersion: '2011-06-15' });

    const roleCreds = await sts.assumeRole(roleToAssume).promise()

    AWS.config.update({ 
      accessKeyId: roleCreds.accessKeyId,
      secretAccessKey: roleCreds.secretAccessKey,
      sessionToken: roleCreds.sessionToken,
      region: 'us-east-1',
      signatureVersion: 'v4'
    });
  }