【运维开发】PHP写一个LDAP账号检测&删除脚本

公司多数内部系统账号接入了LDAP,账号由IT维护,人员离职由IT接收流程通知后,手动进入LAM操作删除账号,操作较为繁琐,且有时候会有错删、漏删除等情况,于是写一个账号自动检测删除脚本,进一步提升自动化管理能力,解放IT运维双手,增加摸鱼时间😂。
开发思路,个人浅见,如有巧合,以你为准

一、核心背景与目标

  • 现状: 公司内部系统账号通过 LDAP 管理,IT 人员需手动处理离职账号删除,存在流程繁琐、易漏删 / 错删等问题。
    • 公司内部服务器部署有openldap服务,多数内部系统(如VPN、GIT、跳板机等)接入LDAP,用户可以在多个服务(系统)中使用同一个账号密码。
    • IT管理员使用LAM管理用户账号,离职通过HR系统的流程抄送IT人员,IT按需进行账号删除(锁定)等操作;
    • 随着企业人员流动性增加,系统维护工作耗时多,且时有错删、漏删除等情况,企业内部流程效率低、系统安全得不到保障;
  • 目标: 开发自动化脚本,实现离职账号自动检测与删除,提升管理效率,降低人为操作风险。
    人员离职流程

    二、技术方案与实现

    1. 技术选型

    很多开发语言都有相关扩展库或函数可实现LDAP的管理,如Shell、Python、Go等
    因个人习惯,本文为PHP语言编写方法

  • 语言: PHP(利用php-ldap扩展操作 LDAP)。
  • 工具:
    • OpenLDAP: 开源 LDAP 服务,用于存储和管理账号信息。
    • LAM: Web 界面工具,辅助 LDAP 账号管理(原手动流程使用)。
    • 企业微信机器人: 通过 Webhook 接收自动化操作结果通知。

      2. 关键流程

  1. 数据获取:
    通过 HR 系统接口获取员工状态(如离职标记 “8”),匹配 LDAP 中用户邮箱。
  2. LDAP 操作:
    连接 LDAP 服务器,检索所有用户信息(通过ldap_search)。
    遍历用户,对比 HR 系统状态,对标记为离职的用户执行ldap_delete删除操作。
  3. 通知与日志:
    企业微信机器人实时推送删除结果(成功 / 失败列表)。
    定时任务(Cron)每日 10 点触发脚本,日志记录执行详情。

    3.环境准备

  • Linux

  • PHP(安装php-curl,php-ldap扩展)

    1
    2
    3
    4
    #安装运行环境软件
    yum install php php-common php-ldap -y
    #创建一个php文件
    touch ldap_user_check.php
  • 一个获取HR系统人员信息的接口

  • 一个webhook地址(用于接收通知,如企微群机器人)

  • 服务器软件安装(CentOS7)

    4.代码结构

  • 配置参数: LDAP 服务器地址、管理员账号、Base DN、HR 接口 URL 等。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
    // 人员信息较多的时候有可能会超时,在脚本最开头添加执行时间限制(0表示无限制)
    set_time_limit(0);
    // LDAP 配置
    $ldapServer = "ldap://192.168.1.100:389";
    $ldapAdmin = "cn=admin,dc=example,dc=net";
    $ldapPassword = "adminpassword";
    $ldapBaseDn = "ou=demo,dc=example,dc=net";
    $ldapFilter = "(sn=*)";
    //获取人员信息接口(通过邮箱号查找人员)
    $hr_api = "https://api.example.com/user/get?token=token&email=youremail";
    // webhook 配置(企业微信群聊机器人)
    $webhookUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=yourkey";
  • 自定义函数:

    • getBsUserInfo:调用 HR 接口获取员工状态。
    • sendWechatGroupRobotMessage:发送企业微信通知。
    • checkLdapUsers:核心逻辑,执行 LDAP 用户检测与删除。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      //getBsUserInfo:调用 HR 接口获取员工状态等信息
      function getBsUserInfo($hr_api,$email) {
      $hr_url = $hr_api.$email;
      //获取用户信息
      $ch = curl_init($hr_url);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
      // 新增超时设置
      // curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // 连接超时10秒
      // curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 总超时30秒

      $get_user_info = curl_exec($ch);
      // 检查 cURL 请求是否成功
      if ($get_user_info === false) {
      $error = curl_error($ch);
      curl_close($ch);
      // 处理错误,这里简单返回 null 表示获取信息失败
      return null;
      }
      curl_close($ch);
      $hr_data = json_decode($get_user_info, true);
      // 检查 JSON 解码是否成功
      if ($hr_data === null) {
      // 处理错误,这里简单返回 null 表示解码失败
      return null;
      }
      $hr_empStatus = $hr_data['empStatus'] ?? null; //获取用户状态

      // 根据用户状态返回信息(8=离职)
      if ($hr_empStatus ==='8') {
      return 1;
      } else {
      return 0;
      }
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      // sendWechatGroupRobotMessage:发送企业微信通知
      function sendWechatGroupRobotMessage($webhookUrl, $message) {
      $data = [
      "msgtype" => "text",
      "text" => [
      "content" => $message
      ]
      ];
      $options = [
      'http' => [
      'method' => 'POST',
      'header' => "Content-Type: application/json\r\n",
      'content' => json_encode($data)
      ]
      ];
      $context = stream_context_create($options);
      $response = file_get_contents($webhookUrl, false, $context);
      return $response;
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      // checkLdapUsers:核心逻辑,执行 LDAP 用户检测与删除
      function checkLdapUsers($ldapServer, $ldapAdmin, $ldapPassword, $ldapBaseDn, $ldapFilter, $webhookUrl) {
      echo "[" . date('Y-m-d H:i:s') . "] 开始执行LDAP用户离职检查...\n";

      $ldapconn = ldap_connect($ldapServer) or die("Could not connect to LDAP server.");
      ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
      $ldapbind = ldap_bind($ldapconn, $ldapAdmin, $ldapPassword) or die("Error trying to bind: ".ldap_error($ldapconn));

      $ldapSearch = ldap_search($ldapconn, $ldapBaseDn, $ldapFilter, array("cn", "uid","mail","givenname"));
      $ldapEntries = ldap_get_entries($ldapconn, $ldapSearch);
      echo "发现待检查用户数:" . $ldapEntries['count'] . "\n";

      $usernames = [];
      for ($i = 0; $i < $ldapEntries['count']; $i++) {
      $email = $ldapEntries[$i]['mail'][0] ?? null;
      $dn = $ldapEntries[$i]['dn']; // 获取用户DN
      echo "正在处理用户:" . ($email ?? '无邮箱用户:'.$ldapEntries[$i]['uid'][0]) . "\n";

      if ($email) {
      global $hr_api;
      $isLeft = getBsUserInfo($hr_api, $email);
      if ($isLeft === 1) { // 只处理明确标记为离职的情况
      echo "发现离职用户:" . $ldapEntries[$i]['givenname'][0] . "\n";
      // 执行LDAP删除操作
      if (@ldap_delete($ldapconn, $dn)) {
      echo "成功删除用户:" . $ldapEntries[$i]['givenname'][0] . "\n";
      $usernames[] = $ldapEntries[$i]['givenname'][0];
      } else {
      echo "删除失败:".ldap_error($ldapconn)."\n";
      }
      }
      }
      }
      if (!empty($usernames)) {
      $usernameList = implode(', ', $usernames);
      $message = "LDAP离职用户汇总:{$usernameList},已自动删除账号。";
      echo "准备发送通知:" . $message . "\n";
      sendWechatGroupRobotMessage($webhookUrl, $message);
      } else {
      echo "未发现离职用户\n";
      }
      ldap_close($ldapconn);
      echo "[" . date('Y-m-d H:i:s') . "] 检查完成\n";
      }
      1
      2
      //执行检测
      checkldapAdmins($ldapServer, $ldapAdmin, $ldapPassword, $ldapBaseDn, $ldapFilter, $webhookUrl);
  • 脚本执行: Shell 脚本封装 PHP 执行过程,重定向输出到日志文件(ldap_check_daily.sh)

    1
    2
    3
    4
    #!/bin/bash
    LOG_FILE="/var/log/ldap_check_$(date +\%Y\%m\%d).log"
    echo "===== 任务触发时间: $(date +'%Y-%m-%d %H:%M:%S') =====" >> $LOG_FILE
    php /home/check_ldap_users.php >> $LOG_FILE 2>&1

    5.定时任务

    创建定时任务,每天10点执行检测

    1
    2
    crontab -e
    0 10 * * * /home/ldap_check_daily.sh

    6.查看执行结果

    通知样例

    7.查询执行日志

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #cat /var/log/ldap/ldap_check_xxxxxxx.log
    ===== 任务触发时间: 2025-05-20 10:00:01 =====
    [2025-05-20 10:00:01] 开始执行LDAP用户离职检查...
    发现待检查用户数:212

    正在处理用户:demo1@example.com
    正在处理用户:demo2@example.com
    正在处理用户:demo3@example.com
    正在处理用户:demo4@example.com
    正在处理用户:demo5@example.com
    正在处理用户:无邮箱用户:demo6
    ...
    准备发送通知:LDAP离职用户汇总:狼人1、狼人2、狼人3,已自动删除账号。
    [2025-05-20 10:28:59] 检查完成

    三、效果与优势

  1. 效率提升: 从手动逐个处理转为自动化批量操作,减少 IT 运维耗时。
  2. 准确性增强: 避免人为漏删 / 错删,通过系统数据比对提升操作可靠性。
  3. 可追溯性: 日志记录与通知机制便于审计和问题排查。

    四、注意事项与扩展建议

  4. 权限安全:
    LDAP 管理员账号需严格管控,避免脚本代码泄露。
    离职用户删除前可增加 “预冻结” 机制(如禁用账号而非立即删除)。
  5. 异常处理:
    补充网络请求超时、HR 接口异常等容错逻辑(当前代码已添加部分超时设置)。
    对无邮箱用户(通过uid标识)增加额外处理方式(如人工复核)。
  6. 扩展场景:
    支持多 LDAP 服务器集群管理。
    集成更多系统(如跳板机、GIT)的账号联动删除。

    五、总结

    该脚本通过技术手段解决了企业 LDAP 账号管理中的痛点,实现了离职账号处理的自动化、标准化。后续可进一步优化容错机制和功能扩展性,推动 IT 运维向智能化方向发展,释放人力用于更复杂的系统优化工作。

源码地址:https://github.com/WannaCryZ/ldap-user-check.git