未硬编码Instance ID时Lambda调用SSM执行失败问题排查
问题
需求是通过EventBridge规则捕获新启动EC2实例的Instance ID,再触发Lambda执行指定SSM文档。目前Lambda能正确提取到实例ID(CloudWatch日志已验证),但直接使用提取的ID时无法执行SSM文档;如果硬编码Instance ID则可以正常执行。相关代码及日志如下:
未硬编码的代码(执行失败)
import boto3 import json def lambda_handler(event, context): # Extract the instance ID from the event (assuming it's already extracted as shown in your previous code) if event.get("detail", {}).get("eventName") == "RunInstances": # Extract the instance ID and event details instance_id = event["detail"]["responseElements"]["instancesSet"]["items"][0]["instanceId"] event_details = json.dumps(event["detail"], indent=2) # You can now process the instance ID and event details as needed print(f"{instance_id}") # print(f"Event Details: {event_details}") return { "statusCode": 200, "body": json.dumps("Event processed successfully") } # Initialize the SSM client ssm_client = boto3.client('ssm') # instance_id = 'i-08be0407d47363235' # hard-code for example # Define the SSM document name and parameters document_name = "prisma-cloud-agent-ssm-doc" # Replace with your SSM document name ssm_parameters = { "InstanceId": [instance_id], # Add more parameters as needed } try: # Send the command using the SSM document and parameters response = ssm_client.send_command( InstanceIds=[instance_id], DocumentName=document_name, Parameters=ssm_parameters, ) # Process the response as needed command_id = response["Command"]["CommandId"] print(f"SSM Command sent with Command ID: {command_id}") return { "statusCode": 200, "body": json.dumps(f"SSM Command sent with Command ID: {command_id}") } except Exception as e: print(f"Error sending SSM command: {str(e)}") return { "statusCode": 500, "body": json.dumps("Error sending SSM command") }
硬编码的代码(执行正常)
import boto3 import json def lambda_handler(event, context): # Extract the instance ID from the event (assuming it's already extracted as shown in your previous code) # if event.get("detail", {}).get("eventName") == "RunInstances": # # Extract the instance ID and event details # instance_id = event["detail"]["responseElements"]["instancesSet"]["items"][0]["instanceId"] # event_details = json.dumps(event["detail"], indent=2) # # You can now process the instance ID and event details as needed # print(f"{instance_id}") # # print(f"Event Details: {event_details}") # return { # "statusCode": 200, # "body": json.dumps("Event processed successfully") # } # Initialize the SSM client ssm_client = boto3.client('ssm') instance_id = 'i-08be0407d47363235' # hard-code for example # Define the SSM document name and parameters document_name = "xyz-doc" # Replace with your SSM document name ssm_parameters = { "InstanceId": [instance_id], # Add more parameters as needed } try: # Send the command using the SSM document and parameters response = ssm_client.send_command( InstanceIds=[instance_id], DocumentName=document_name, Parameters=ssm_parameters, ) # Process the response as needed command_id = response["Command"]["CommandId"] print(f"SSM Command sent with Command ID: {command_id}") return { "statusCode": 200, "body": json.dumps(f"SSM Command sent with Command ID: {command_id}") } except Exception as e: print(f"Error sending SSM command: {str(e)}") return { "statusCode": 500, "body": json.dumps("Error sending SSM command") }
CloudWatch日志输出
Instance ID: i-006aba8d1200a8bce
原因与解决方法
核心原因
未硬编码的代码中,提取完Instance ID后直接执行了return语句,导致后续的SSM客户端初始化、发送命令等代码完全没有被执行。Lambda函数在遇到return时会立即终止,所以虽然能打印出Instance ID,但永远走不到发送SSM命令的逻辑。
修正后的代码
把提前返回的return块删除或移到SSM命令执行逻辑之后,确保提取ID后能继续执行SSM相关代码:
import boto3 import json def lambda_handler(event, context): instance_id = None # 提取Instance ID if event.get("detail", {}).get("eventName") == "RunInstances": instance_id = event["detail"]["responseElements"]["instancesSet"]["items"][0]["instanceId"] print(f"{instance_id}") if not instance_id: return { "statusCode": 400, "body": json.dumps("No valid instance ID found in event") } # 初始化SSM客户端并发送命令 ssm_client = boto3.client('ssm') document_name = "prisma-cloud-agent-ssm-doc" ssm_parameters = { "InstanceId": [instance_id], } try: response = ssm_client.send_command( InstanceIds=[instance_id], DocumentName=document_name, Parameters=ssm_parameters, ) command_id = response["Command"]["CommandId"] print(f"SSM Command sent with Command ID: {command_id}") return { "statusCode": 200, "body": json.dumps(f"SSM Command sent with Command ID: {command_id}") } except Exception as e: print(f"Error sending SSM command: {str(e)}") return { "statusCode": 500, "body": json.dumps("Error sending SSM command") }
额外注意事项
- 确保Lambda角色拥有
ssm:SendCommand权限,以及目标EC2实例已安装SSM Agent并能正常连接到SSM服务 - 添加对
instance_id的非空校验,避免因事件格式异常导致后续报错
内容的提问来源于stack exchange,提问作者code userit
相关产品推荐
相关产品推荐

