putObject 到公共 S3 存储桶

时间:2021-06-30 19:34:35

标签: amazon-web-services amazon-s3 aws-lambda

我有一个 API 调用的 lambda,它生成签名的 getObject 和 putObject URL。我的受限存储桶(包含 zip 文件)上的 GET 和 PUT 工作正常,但我的公共存储桶(包含图像)上的 PUT 返回“SignatureDoesNotMatch”错误。公共存储桶上没有 GET,直接引用该存储桶中的图像。我需要额外的配置来 PUT 到公共存储桶上吗?我已经尝试给予我能想到的最慷慨的权限。

编辑:我最终不得不将特定图像 MIME 类型发送到生成签名 URL 的端点。不幸的是,image/* 没有用。

签名 URL 生成(由 getSignedImgUploadUrl 调用)

let params = {
    Bucket: "public-bucket",
    Key: `${folder}/${key}.jpg`, // Ideally without extension
    Expires: 30,
    ContentType: "image/jpeg", // Ideally image/*
    ACL: "public-read" // Tried with and without this
};
let url = s3.getSignedUrl("putObject", params);
let result = {
    signedUrl: url,
    key: key
};
return result;

使用签名网址

  public uploadImg(folder: string, file: any, key: string): Observable<any> {
    return this._spinnerService.spinObservable(
      new Observable(subscriber => {
        this.getSignedImgUploadUrl(folder, key)
          .subscribe(result => {
            // put to signedUrl fails with 403 SignatureDoesNotMatch
            this._httpClient.put(result["signedUrl"], file, { headers: { "x-amz-acl": "public-read" } })
              .subscribe(() => {
                subscriber.next(result["key"]);
                subscriber.complete();
              }, err => {
                console.log(err);
                subscriber.error(err);
              });
          }, err => {
            console.log(err);
            subscriber.error(err);
          });
      }));
  }

Lambda 角色

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::restricted-bucket/*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": "s3:*", (Ideally just getObject/putObject)
            "Resource": "arn:aws:s3:::public-bucket/*"
        }
    ]
}

公共存储桶政策

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::public-bucket/*"
        },
        // Also tried adding s3:* for the lambda role without luck
        {
            "Sid": "Stmt1624999949645",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::account:role/service-role/lambda-role"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::public-bucket/*"
        }
    ]
}

1 个答案:

答案 0 :(得分:1)

根据 OP 的评论,明确发送 Content-Type HTTP 标头有效。有时需要此标头的原因是 HTTP 客户端无法从 PUT 负载正确推断 MIME 类型。