在 PostgreSQL RDS/Amazon Aurora 中签署 s3 URL

问题描述 投票:0回答:2

数据库(PostgreSQL RDS/Amazon Aurora)返回大量图像文件。我们需要对 URL 进行签名。目前,用户定义的函数或视图返回记录。

我正在寻找一种直接在 SQL 中将 S3 URL 签名为用户定义函数的方法。不幸的是,除了在用户定义的函数中使用 Python 语言之外,似乎没有其他方法,并且 PostgreSQL/Aurora 不支持 python 作为过程语言。

有人知道我们可以直接对 URL 进行签名作为 PostgreSQL RDS/Amazon Aurora 中 SQL 查询的一部分吗?

postgresql amazon-web-services amazon-s3 amazon-rds amazon-aurora
2个回答
0
投票

是的,这是可能的,我已经做到了。

首先,让我们看看AWS SDK是如何做到的。在 JavaScript AWS SDK 中,我们调用

getSignedUrlPromise
来获取签名的 url。

import AWS from 'aws-sdk';
const s3 = new AWS.S3();
s3.getSignedUrlPromise('getObject', { Bucket, Key, Expires: 60 * 60});

getSignedUrlPromise 开始,到 getSignedUrlrequest.presignAWS.Signers.Presign().sign,我们可以看到

  sign: function sign(request, expireTime, callback) {
    request.on('build', signedUrlBuilder);
    request.on('sign', signedUrlSigner);
// ...
      return AWS.util.urlFormat(request.httpRequest.endpoint);
  }

签名发生在 V3 的 signedUrlSigner

function signedUrlSigner(request) {
  var auth = request.httpRequest.headers['Authorization'].split(' ');
  if (auth[0] === 'AWS') {
    auth = auth[1].split(':');
    queryParams['Signature'] = auth.pop();
    queryParams['AWSAccessKeyId'] = auth.join(':');
  }

  endpoint.search = AWS.util.queryParamsToString(queryParams);
}

Signature
来自
headers['Authorization']
,但是
Authorization
集在哪里?

它在 AWS.Signers.S3.addAuthorization

中设置
  addAuthorization: function addAuthorization(credentials, date) {
    var signature = this.sign(credentials.secretAccessKey, this.stringToSign());
    var auth = 'AWS ' + credentials.accessKeyId + ':' + signature;

    this.request.headers['Authorization'] = auth;
  },

sign
函数使用sha1和base64摘要

  sign: function sign(secret, string) {
    return AWS.util.crypto.hmac(secret, string, 'base64', 'sha1');
  }

并且

stringToSign
有点令人困惑,但在我的实验中结果是

const stringToSign = `GET\n\n\n${EXPIRES}\n/${BUCKET}/${KEY}`;

有了以上信息,我们就可以轻松编写一个postgres函数了

CREATE OR REPLACE FUNCTION image_s3_signed_url(image_row "Image")
RETURNS TEXT AS $$
DECLARE
    newline text := E'\n';
    method text := 'GET';
    bucket text := 'my_bucket';
    access_key text := 'my_access_key';
    access_secret text := 'my_access_secret';
    filepath text;
    expires bigint;
    tosign text;
    raw_signature text;
    encoded_signatre text;
    result text;
BEGIN

  filepath := image_row.filepath;
  expires = EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) + 60 * 60;
  
  tosign := method || newline || newline || newline || expires || newline || '/' || bucket || filepath;
  raw_signature := encode(hmac(tosign, access_secret, 'sha1'), 'base64');
  encoded_signatre := REPLACE(REPLACE(REPLACE(raw_signature, '+', '%2B'), '/', '%2F'), '=', '%3D');

  result = filepath || '?AWSAccessKeyId=' || access_key || '&Expires=' || expires || '&Signature=' || encoded_signatre;

  RETURN result;

END;
$$ LANGUAGE plpgsql STABLE;

-1
投票

数据库不是执行此类操作的地方。 您应该考虑将签名 URL 放入数据库中,或者重新考虑您的应用程序(如果不应该重新构建它)。

© www.soinside.com 2019 - 2024. All rights reserved.