You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Lambda中从外部文件引用策略字典的问题排查

AWS Lambda中从外部文件引用策略字典的问题排查

我来帮你梳理下问题所在,以及怎么解决这个问题~

你遇到的核心问题

你最后碰到的"'function' object has no attribute 'data_pols'"错误,主要有两个原因:

  1. 变量作用域问题:你把data_pol放到了policies.py的lambda_handler函数内部,这个变量是函数的局部变量,外部模块(index.py)根本无法直接访问它。
  2. 拼写小失误:你在index.py里写的是policies.data_pols,但实际变量名是data_pol,多了个s,不过这只是次要问题,核心还是作用域。

再往前推的两个错误(BUCKETNAME未定义、event未定义),本质也是因为你没处理好动态参数(event)和环境变量的传递/加载逻辑:

  • 一开始policies.py里没加载环境变量,所以找不到BUCKETNAME;
  • 后来环境变量加载了,但data_pol里用到了event(Lambda请求的动态数据),而模块顶层代码在Lambda冷启动时就执行了,这时候还没有event,自然会报错。

正确的解决方案

我们可以把policies.py改成一个提供策略生成函数的模块,通过函数参数把动态的event传进去,同时在模块顶层加载环境变量(因为环境变量是固定的,冷启动时加载没问题)。

第一步:修改policies.py

把策略生成逻辑封装成一个可调用的函数,接收event参数,返回构造好的策略字典:

import os

# 提前加载环境变量(模块加载时执行,只加载一次)
BUCKETNAME = os.environ['bucketname']
PUBLICKEYSBUCKETNAME = os.environ['publickkeysbucketname']

def get_transfer_policy(event):
    """根据Lambda的event参数生成对应的S3访问策略"""
    data_pol = {
        "Version": "2012-10-17",
        "Statement": [{
            "Sid": "AllowListAccessToBucket",
            "Action": ["s3:ListBucket"],
            "Effect": "Allow",
            "Resource": ["arn:aws:s3:::" + BUCKETNAME, "arn:aws:s3:::" + PUBLICKEYSBUCKETNAME],
            "Condition": { "StringLike": { "s3:prefix": [ event["username"] + "/*", event["username"]]}}},
        {"Sid": "GetAccessForPublicKeys",
            "Effect": "Allow",
            "Action": ["s3:GetObject","s3:GetObjectAcl","s3:GetObjectVersion","s3:GetBucketLocation"],
            "Resource": ["arn:aws:s3:::" + PUBLICKEYSBUCKETNAME + "/" + event["username"],
                        "arn:aws:s3:::" + PUBLICKEYSBUCKETNAME + "/" + event["username"] + "/*"]},
        {"Sid": "PublicKeysPubFilePutAccess",
            "Effect": "Allow",
            "Action": ["s3:PutObject","s3:PutObjectAcl"],
            "Resource": ["arn:aws:s3:::" + PUBLICKEYSBUCKETNAME + "/" + event["username"] + "/*.pub"]},
        {"Sid": "TransferDataBucketAccess",
            "Effect": "Allow",
            "Action": ["s3:PutObject","s3:PutObjectAcl","s3:GetObject","s3:GetObjectAcl","s3:GetObjectVersion","s3:GetBucketLocation","s3:DeleteObject","s3:DeleteObjectVersion"],
            "Resource": ["arn:aws:s3:::" + BUCKETNAME + "/" + event["username"],
                        "arn:aws:s3:::" + BUCKETNAME + "/" + event["username"] + "/*"]}]}
    return data_pol

第二步:修改index.py

导入policies模块后,在自己的lambda_handler里调用这个函数,传入event参数获取策略:

import boto3
import json
import os
import policies  # 导入policies模块

# 保留你原来的环境变量加载(如果需要在index.py里用到的话)
BUCKETNAME = os.environ['bucketname']
PUBLICKEYSBUCKETNAME = os.environ['publickkeysbucketname']
TRANSFERACCESSADMINROLE = os.environ['transferaccessadminrole']
TRANSFERACCESSREADROLE  = os.environ['transferaccessreadrole']
TRANSFERACCESSHUBADMINROLE = os.environ['transferaccesshubadminrole']
PRIMARY_REGION = os.environ['AWS_REGION']
SSM_PREFIX = os.environ['transferssmparameter']

def lambda_handler(event, context):
    auth_response = {}
    data_ret = {}
    
    # 调用policies里的函数获取动态生成的策略
    data_pol = policies.get_transfer_policy(event)
    data_ret["Policy"] = json.dumps(data_pol)
    
    data_ret["HomeDirectoryType"] = "PATH"
    #data_ret["HomeDirectoryDetails"] = json.dumps(directorymapping)
    data_ret["HomeDirectory"] = "/" + BUCKETNAME + "/" + event["username"]
    
    return data_ret

为什么这么做能解决问题

  • 环境变量在policies.py的模块顶层加载,冷启动时就完成初始化,不会重复加载,效率高;
  • 策略生成逻辑封装在函数里,通过参数接收动态的event,确保每次请求都能拿到当前用户的username;
  • 函数返回的字典可以直接被index.py使用,不存在作用域访问不到的问题。

备注:内容来源于stack exchange,提问作者Jason Stanley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 14:23:14