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

调用GuardDuty创建Threat Intel Set时遇AttributeError错误求助

问题排查与修复方案

1. 核心错误:异常属性访问错误

报错'BadRequestException' object has no attribute 'message'是因为boto3客户端抛出的异常并不提供message属性。你需要替换错误信息的获取方式,有两种可靠方案:

  • 将异常对象转为字符串:str(error)
  • 从异常的response属性提取标准错误信息:error.response['Error']['Message']

修改异常判断代码:

except Exception as error:
    # 转字符串判断错误内容
    if "name already exists" in str(error):
        # 原有更新逻辑...

2. S3 Location格式错误

GuardDuty要求create_threat_intel_set的Location参数对于S3文件必须是s3://bucket/key的原生格式,你当前写的https://s3://...是非法格式,需要移除https://前缀:

location = "s3://awssaflitetifeeds-security/GDfeeds/compromised-ips.csv"

3. 其他未定义变量与逻辑问题

  • environ['DAYS_REQUESTED']:代码中未导入os模块,且该变量与当前业务无关,建议删除该引用,替换为符合实际场景的提示信息。
  • responseStatus、responseData:需提前初始化,避免finally块中出现未定义错误。
  • send_response函数:代码中调用了该函数但未实现,若用于CloudFormation自定义资源,需补充函数逻辑;若不需要则可移除相关代码。

修复后的完整代码示例

import boto3
import logging
from datetime import datetime
import requests.packages.urllib3 as urllib3

# 若为CloudFormation自定义资源,保留该函数;否则可删除
def send_response(event, context, responseStatus, responseData, physicalResourceId=None, reason=None):
    import json
    from urllib3.exceptions import ProtocolError
    http = urllib3.PoolManager()
    responseBody = json.dumps({
        'Status': responseStatus,
        'Reason': reason or "详情查看CloudWatch日志流: " + context.log_stream_name,
        'PhysicalResourceId': physicalResourceId or context.log_stream_name,
        'StackId': event['StackId'],
        'RequestId': event['RequestId'],
        'LogicalResourceId': event['LogicalResourceId'],
        'Data': responseData
    })

    headers = {'Content-Type': '', 'Content-Length': str(len(responseBody))}
    try:
        response = http.request('PUT', event['ResponseURL'], body=responseBody, headers=headers)
        print("响应状态码:", response.status)
    except ProtocolError as e:
        logging.error("发送响应失败: %s", e)

def lambda_handler(event, context):
    url = 'https://rules.emergingthreats.net/blockrules/compromised-ips.txt'
    bucket = 'awssaflitetifeeds-security'
    key = 'GDfeeds/compromised-ips.csv'

    s3 = boto3.client('s3')
    http = urllib3.PoolManager()
    s3.upload_fileobj(http.request('GET', url, preload_content=False), bucket, key)
    
    # Guard Duty 逻辑
    location = "s3://awssaflitetifeeds-security/GDfeeds/compromised-ips.csv"
    timeStamp = datetime.now()
    name = "TF-%s" % timeStamp.strftime("%Y%m%d")
    guardduty = boto3.client('guardduty')
    response = guardduty.list_detectors()

    if len(response['DetectorIds']) == 0:
        raise Exception('GuardDuty未激活,请先启用该服务')

    detectorId = response['DetectorIds'][0]
    responseStatus = 'SUCCESS'
    responseData = {}
    reason = None

    try:
        guardduty.create_threat_intel_set(
            Activate=True,
            DetectorId=detectorId,
            Format='FIRE_EYE',
            Location=location,
            Name=name
        )
        responseData['message'] = f"成功创建威胁情报集: {name}"

    except Exception as error:
        error_msg = str(error)
        if "name already exists" in error_msg:
            found = False
            ti_sets = guardduty.list_threat_intel_sets(DetectorId=detectorId)
            for setId in ti_sets['ThreatIntelSetIds']:
                ti_set = guardduty.get_threat_intel_set(DetectorId=detectorId, ThreatIntelSetId=setId)
                if name == ti_set['Name']:
                    found = True
                    guardduty.update_threat_intel_set(
                        Activate=True,
                        DetectorId=detectorId,
                        Location=location,
                        Name=name,
                        ThreatIntelSetId=setId
                    )
                    responseData['message'] = f"成功更新威胁情报集: {name}"
                    break

            if not found:
                raise
        else:
            logging.error(f"操作失败: {error_msg}")
            responseStatus = 'FAILED'
            reason = error_msg
            responseData['message'] = f"操作失败: {error_msg}"

    finally:
        if 'ResponseURL' in event:
            send_response(event, context, responseStatus, responseData, event['LogicalResourceId'], reason)
    
    return {
        'statusCode': 200 if responseStatus == 'SUCCESS' else 500,
        'body': responseData
    }

额外注意事项

  • 确保Lambda角色拥有S3上传权限,以及GuardDuty的CreateThreatIntelSet、ListDetectors、ListThreatIntelSets、GetThreatIntelSet、UpdateThreatIntelSet权限。
  • 确认S3中文件格式符合GuardDuty的FIRE_EYE要求(Emerging Threats的compromised-ips.txt为纯IP列表,符合格式)。

内容的提问来源于stack exchange,提问作者Ishwar Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:50:23