使用Serverless部署后AWS Access Key无效问题求助
我是Serverless和Lambda新手,应用中需要用到S3服务。用自己AWS账户手动创建的凭证能正常访问S3,但通过Serverless部署后,无论是线上还是本地运行,都报错:InvalidAccessKeyId: The AWS Access Key Id you provided does not exist in our records.
serverless.yaml
org: juan app: knot service: knot-be provider: environment: APP_ENV: staging ...... env variables..... name: aws runtime: nodejs18.x region: us-east-1 apiGateway: binaryMediaTypes: - "*/*" iamRoleStatements: - Effect: "Allow" Action: - "s3:*" Resource: "arn:aws:s3:::knot-be/*" - Effect: "Allow" Action: - "ses:SendEmail" - "ses:SendRawEmail" Resource: "*" - Effect: "Allow" Action: - "rds:*" Resource: "*" ecr: images: appimage: path: ./ functions: api: image: name: appimage command: - dist/lambda.handler entryPoint: - '/lambda-entrypoint.sh' timeout: 30 events: - http: path: /{proxy+} method: any - http: path: / method: any resources: Resources: Bloodknot3Bucket: Type: AWS::S3::Bucket Properties: BucketName: knot-be plugins: - serverless-offline
s3.config.ts
const s3Config = { bucketName: process.env.AWS_S3_BUCKET_NAME || 'bloodknot-storage-dev', region: (process.env.AWS_REGION || 'us-east-2') as BucketLocationConstraint, credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID || '', secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || '', }, } const s3Client = new S3Client(s3Config) export { s3Config, GetObjectCommand, PutObjectCommand, DeleteObjectCommand, ListObjectsV2Command, S3Client, getSignedUrl, } export default s3Client
我创建了端点检查环境变量,部署后返回的结果显示变量存在:
{ "bucketName": "knot-be", "region": "us-east-1", "credentials": { "accessKeyId": "ASIA.....", "secretAccessKey": "qG....." } }
但无论线上还是本地运行,都会触发以下错误:
[Nest] 5538 - 05/07/2024, 1:00:21 AM ERROR [S3StorageProvider] InvalidAccessKeyId: The AWS Access Key Id you provided does not exist in our records. [Nest] 5538 - 05/07/2024, 1:00:21 AM ERROR [ExceptionsHandler] Error uploading file at 6b613615-af7b-4408-8566-89e9a5f08872 Error: Error uploading file at 6b613615-af7b-4408-8566-89e9a5f08872 at S3StorageProvider.uploadFile (/home/seb/Desktop/knotblood/bloodknot-backend/src/commons/providers/file-storage/s3/s3-storage.provider.ts:125:13) at processTicksAndRejections (node:internal/process/task_queues:95:5) at async Promise.all (index 0)
为什么本地用自己的AWS凭证能正常工作,但用Serverless提供的变量时,无论线上还是本地都报错?是serverless.yaml配置有误,还是需要在AWS后台做额外配置?
移除硬编码凭证,让AWS SDK自动使用IAM角色
Lambda运行时会自动获取执行角色的临时凭证,不需要在代码里显式传入credentials参数。你已经在serverless.yaml中配置了iamRoleStatements,给Lambda赋予了S3访问权限,直接修改s3.config.ts:const s3Config = { bucketName: process.env.AWS_S3_BUCKET_NAME || 'bloodknot-storage-dev', region: (process.env.AWS_REGION || 'us-east-2') as BucketLocationConstraint, // 移除credentials配置,SDK会自动使用Lambda执行角色 }你看到的
ASIA开头的是临时会话凭证,这类凭证需要搭配sessionToken才能生效,但你只传入了accessKeyId和secretAccessKey,导致验证失败。检查serverless.yaml的环境变量配置
确认environment字段中是否误写入了临时凭证。Serverless部署Lambda时不需要手动注入AWS凭证,Lambda会通过IAM角色获取权限,所以要确保AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY没有被错误设置。本地运行serverless-offline的配置
本地运行时,serverless-offline会读取你本地的AWS配置(~/.aws/credentials或本地环境变量),不需要在代码里硬编码。确保本地的AWS凭证有对应S3桶的访问权限,同时代码不传入credentials,让SDK自动读取本地配置。修正S3权限的Resource范围
当前IAM权限只允许访问桶内对象(arn:aws:s3:::knot-be/*),如果代码涉及桶级操作(比如获取桶信息),需要补充桶本身的权限:- Effect: "Allow" Action: - "s3:*" Resource: - "arn:aws:s3:::knot-be" - "arn:aws:s3:::knot-be/*"
内容的提问来源于stack exchange,提问作者Sebastian Rodriguez

