如何在 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'
});
}
我现在的 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'
});
}