通过IAM策略管控S3对象访问异常:修改策略后仍可上传文件
问题排查与解决方法
看起来你遇到的核心问题是Lambda执行时没有使用Cognito用户的身份权限,而是默认使用了Lambda自身的执行角色权限,导致你修改Cognito关联的IAM策略后,权限管控没有生效。下面分点分析原因和解决步骤:
一、核心原因:Lambda使用自身执行角色而非用户Cognito身份
你的代码中直接调用s3.putObject时,默认会使用Lambda的执行角色(不是Cognito认证角色)去访问S3。如果这个Lambda执行角色本身就拥有S3的上传权限(比如AmazonS3FullAccess或者针对性的PutObject权限),那么不管你怎么修改Cognito关联的IAM策略,用户都能成功上传文件——因为实际生效的是Lambda执行角色的权限。
二、解决步骤
1. 改用用户的Cognito身份获取临时凭证调用S3
你需要通过用户的AccessToken,从Cognito Identity Pool获取该用户对应的临时AWS凭证,然后用这些凭证初始化S3客户端,再执行上传操作。修改后的代码示例如下:
const AWS = require('aws-sdk'); const cognitoidentity = new AWS.CognitoIdentity(); app.post("/api/upload/add", upload.single('uploadedFile'), async(req, res) => { try { const token = getAccessToken(req.headers.authorization); const decodedToken = jwt_decode(token); const sub = decodedToken.sub; // 注意:如果解码的token里没有identityId,需先调用GetId API获取 const identityId = decodedToken.identity_id; // 1. 获取用户的临时AWS凭证 const credParams = { IdentityId: identityId, Logins: { 'cognito-idp.eu-west-1.amazonaws.com/<你的用户池ID>': token // 替换为你的用户池ID } }; const creds = await cognitoidentity.getCredentialsForIdentity(credParams).promise(); // 2. 使用临时凭证初始化S3客户端 const s3 = new AWS.S3({ accessKeyId: creds.Credentials.AccessKeyId, secretAccessKey: creds.Credentials.SecretKey, sessionToken: creds.Credentials.SessionToken }); // 3. 执行上传操作 const params = { Bucket: '<Bucket name>', Key: `${sub}/${req.body.propertyId}/${req.file.originalname}`, Body: req.file.buffer, ACL: 'private' }; const data = await s3.putObject(params).promise(); res.status(200).send(data); } catch (err) { console.log("error====", err); res.status(500).send(err.message); } });
2. 确保Lambda执行角色拥有获取凭证的权限
需要给Lambda的执行角色添加允许调用cognito-identity:GetCredentialsForIdentity的权限,否则Lambda无法获取用户的临时凭证。可以在IAM控制台给Lambda角色添加如下内联策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "cognito-identity:GetCredentialsForIdentity", "Resource": "*" } ] }
3. 验证IAM策略的正确性(可选)
确认你的Cognito认证角色策略中的路径匹配正确:
- 你的上传路径是
${sub}/xxx/xxx,策略中的Resourcearn:aws:s3:::<Bucket name>/${cognito-identity.amazonaws.com:sub}/*正好匹配该路径,这部分是没问题的。 - 策略中的
cognito-identity.amazonaws.com:sub变量会在Cognito角色策略中自动替换为用户的sub值,无需手动修改。
4. 处理IAM策略缓存(可选)
IAM策略修改后可能会有5分钟左右的缓存,如果修改后立即测试可能没生效,可以等待几分钟后再验证。
三、额外建议
- 遵循最小权限原则:Lambda执行角色只保留必要的权限(比如获取Cognito凭证的权限),不要给它S3的直接操作权限,确保所有S3操作都通过用户的Cognito身份权限管控。
- 可以使用AWS IAM Access Analyzer来检查策略的有效性,确认权限是否符合预期。
内容的提问来源于stack exchange,提问作者tjhack
相关产品推荐
相关产品推荐

