繁体   English   中英

当我的 Lambda 可以访问 S3 存储桶时,为什么我的 GetObjectRequest 返回 403 Access Denied 错误?

[英]Why does my GetObjectRequest return a 403 Access Denied error when my Lambda has access to the S3 bucket?

我有一个 Lambda 函数,它向 S3 存储桶发出GetObject请求。

但是,我收到以下错误:

AccessDenied: Access Denied
    at deserializeAws_restXmlGetObjectCommandError (/node_modules/@aws-sdk/client-s3/dist-cjs/protocols/Aws_restXml.js:6284:41)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at /node_modules/@aws-sdk/middleware-serde/dist-cjs/deserializerMiddleware.js:6:20
    at /node_modules/@aws-sdk/middleware-signing/dist-cjs/middleware.js:11:20
    at StandardRetryStrategy.retry (/node_modules/@aws-sdk/middleware-retry/dist-cjs/StandardRetryStrategy.js:51:46)
    at /node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:6:22
    at GetS3Data (/src/input.ts:21:26)
    at Main (/src/main.ts:8:34)
    at Runtime.run [as handler] (/handler.ts:6:9) {
  Code: 'AccessDenied',
  RequestId: '3K61PMQGW4825D3W',
  HostId: '5PpmWpu2I4WZPx37Y0pRfDAcdCmjX8fchuE+HLpUzy7uqoJirtb9Os0g96kWfluM/ctkn/mEC5o=',
  '$fault': 'client',
  '$metadata': {
    httpStatusCode: 403,
    requestId: undefined,
    extendedRequestId: '5PpmWpu2I4WZPx37Y0pRfDAcdCmjX8fchuE+HLpUzy7uqoJirtb9Os0g96kWfluM/ctkn/mEC5o=',
    cfId: undefined,
    attempts: 1,
    totalRetryDelay: 0
  }
}

我已授予访问 Lambda 函数的权限以发出此请求。

问题是什么?

serverless.ts

import type { AWS } from "@serverless/typescript";

const serverlessConfiguration: AWS = {
    service: "affiliations",
    frameworkVersion: "2",
    custom: {
        esbuild: {
            bundle: true,
            minify: false,
            sourcemap: true,
            exclude: ["aws-sdk"],
            target: "node14",
            define: { "require.resolve": undefined },
            platform: "node",
        },
    },
    plugins: ["serverless-esbuild"],
    provider: {
        name: "aws",
        region: "us-east-2",
        runtime: "nodejs14.x",
        apiGateway: {
            minimumCompressionSize: 1024,
            shouldStartNameWithService: true,
        },
        environment: {
            AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1",
            NODE_OPTIONS: "--enable-source-maps --stack-trace-limit=1000",
        },
        lambdaHashingVersion: "20201221",
        vpc: {
            securityGroupIds: ["<redacted>"],
            subnetIds: ["redacted>"],
        },
        iam: {
            role: {
                statements: [
                    {
                        Effect: "Allow",
                        Action: ["s3:GetObject"],
                        Resource: "<redacted>",
                    },
                ],
            },
        },
    },
    useDotenv: true,
    // import the function via paths
    functions: {
        run: {
            handler: "handler.run",
            timeout: 300,
            events: [
                {
                    sns: {
                        arn: "<redacted>",
                    },
                },
            ],
        },
    },
};

module.exports = serverlessConfiguration;

s3.ts

export const GetS3Data = async (payload: GetObjectRequest) => {
    try {
        const response = await S3Service.getObject(payload);

        const result = await new Promise((resolve, reject) => {
            const data = [];
            response.Body.on("data", (chunk) => data.push(chunk));
            response.Body.on("err", reject);
            response.Body.once("end", () => resolve(data.join("")));
        });

        return [result, null];
    } catch (err) {
        Logger.error({
            method: "GetS3Data",
            error: err.stack,
        });

        return [null, err];
    }
};

package.json

"@aws-sdk/client-s3": "^3.36.0",

忘记在资源末尾添加/*

Resource: "<redacted>/*",

您的403 Access Denied错误掩盖了404 Not Found错误,因为您的代码和无服务器配置看起来非常好,只要您正确指定了资源,就应该可以按预期工作。


如果您没有正确的s3:ListBucket权限,并且指定键的对象不存在,则 S3 端点将不会返回404 Not Found错误。

GetObjectAPI 参考强调了这个细微差别:

如果您对存储桶拥有 s3:ListBucket 权限,Amazon S3 将返回 HTTP 状态代码 404(“无此类密钥”)错误。

如果您没有 s3:ListBucket 权限,Amazon S3 将返回 HTTP 状态代码 403(“访问被拒绝”)错误。

这是为了防止攻击者枚举公共存储桶并了解存储桶中实际存在哪些对象。

在这种情况下,如果没有 404,就不允许信息泄露(就像登录页面上的Invalid Credentials消息而不是Invalid Password ,它表明用户提供的用户名存在) .


为 Lambda 提供执行s3:ListBucket操作的权限,以取消s3:ListBucket 404 错误和/或最终仔细检查您的GetObjectRequest以确保为确实存在的对象正确指定了密钥:

iam: {
    role: {
        statements: [
            {
                Effect: "Allow",
                Action: ["s3:GetObject", "s3:ListBucket"],
                Resource: "<redacted>",
            },
        ],
    },
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM