如何通过Python ldap3实现计算机加入Active Directory时发送HTTP请求?
事件ID 4741 含义及实现方案
事件ID 4741 是什么?
Windows域控制器的安全日志中,事件ID 4741对应的是计算机账户被创建的操作记录——这正是你要监控的“计算机被添加至AD”的触发事件。每次有新计算机加入域(或管理员手动创建计算机账户),域控制器都会生成这条日志,里面包含关键信息:新计算机的账户名、创建该账户的用户、域信息等。
如何借助它实现需求?
核心思路是:监控域控制器的安全日志,捕获4741事件,提取关键信息后触发HTTP请求。ldap3主要用于AD数据查询/操作,监控事件日志需要结合Windows日志读取工具,以下是具体步骤和代码示例:
1. 确保域控制器记录4741事件
先确认域控制器的审核策略已开启:
- 打开组策略编辑器,定位到
计算机配置 > Windows设置 > 安全设置 > 本地策略 > 审核策略 > 审核账户管理 - 勾选“成功”审核,保存后刷新组策略,这样域控制器才会生成4741事件日志
2. Python监控事件日志并发送HTTP请求
使用pywin32读取Windows事件日志,requests发送HTTP请求,先安装依赖:
pip install pywin32 requests
示例代码:
import win32evtlog import win32evtlogutil import requests import time def monitor_new_computers(): # 替换为你的域控制器主机名/IP dc_server = "dc.yourdomain.com" # 目标HTTP接口地址 webhook_url = "https://your-webhook-endpoint.com/notify" # 连接域控制器的安全日志 log_handle = win32evtlog.OpenEventLog(dc_server, "Security") read_flags = win32evtlog.EVENTLOG_FORWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ print("开始监控AD新增计算机事件...") while True: events = win32evtlog.ReadEventLog(log_handle, read_flags, 0) if events: for event in events: # 只处理计算机账户创建事件(ID4741) if event.EventID == 4741: # 提取事件中的关键信息(StringInserts的索引对应固定字段) computer_account = event.StringInserts[0] # 计算机账户名(带$后缀) creator_user = event.StringInserts[5] # 创建该账户的用户 domain_name = event.StringInserts[6] # 域名 # 构造HTTP请求数据 payload = { "event_type": "AD计算机账户创建", "computer_name": computer_account.rstrip("$"), # 去掉默认的$后缀 "creator": creator_user, "domain": domain_name, "timestamp": event.TimeGenerated.Format() } # 发送POST请求 try: resp = requests.post(webhook_url, json=payload, timeout=10) resp.raise_for_status() print(f"已通知:新增计算机{computer_account},HTTP响应码{resp.status_code}") except Exception as e: print(f"通知失败:{str(e)}") # 每5秒轮询一次日志,可根据需求调整 time.sleep(5) if __name__ == "__main__": monitor_new_computers()
3. 用ldap3补充查询计算机详细信息(可选)
如果需要获取新计算机的更多AD属性(如主机名、操作系统、所属OU),可以在捕获事件后调用ldap3查询:
from ldap3 import Server, Connection, ALL def get_ad_computer_details(computer_name, domain, username, password): # 初始化AD连接 server = Server(f"dc.{domain}", get_info=ALL) conn = Connection(server, f"{username}@{domain}", password, auto_bind=True) # 构造查询路径(需根据你的AD组织结构调整OU) search_base = f"DC={domain.replace('.', ',DC=')}" # 查询计算机账户 conn.search( search_base, f"(sAMAccountName={computer_name}$)", # 计算机账户名默认带$后缀 attributes=["dNSHostName", "operatingSystem", "distinguishedName"] ) if conn.entries: return conn.entries[0].entry_attributes_as_dict return None # 在监控代码中调用示例: # details = get_ad_computer_details(computer_account.rstrip("$"), domain_name, "admin@yourdomain.com", "yourpassword") # if details: # payload.update(details)
注意事项
- 运行脚本的账户需要读取域控制器安全日志的权限,以及AD查询权限(如果用到ldap3)
- 若在非Windows机器上监控,可通过WMI远程连接域控制器读取日志,或在域控制器上部署脚本
- 可优化日志读取逻辑,记录最后处理的事件ID,避免重复发送通知
内容的提问来源于stack exchange,提问作者Syrenthia
相关产品推荐
相关产品推荐

