如何用脚本批量添加LDAP用户?

wen 实用脚本 5

如何用脚本批量添加LDAP用户?

目录导读

  1. 为什么需要批量添加LDAP用户?

    如何用脚本批量添加LDAP用户?

    • LDAP在企业中的核心作用
    • 手动添加的痛点与脚本优势
  2. 批量添加LDAP用户的前置准备

    • 环境要求(OpenLDAP / 389 DS / AD)
    • LDIF文件结构解析
    • 脚本语言选择(Bash / Python / PowerShell)
  3. 三种主流脚本实现方案

    • Bash + ldapadd命令(Linux环境)
    • Python + python-ldap库(跨平台)
    • PowerShell + AD模块(Windows AD环境)
  4. 常见问题与脚本优化技巧

    • 密码加密处理(SSHA / MD5)
    • 错误重试与日志记录
    • 批量修改、删除的扩展思路
  5. 问答精选

    • Q1:批量添加时如何避免重复用户?
    • Q2:脚本中密码明文传输安全吗?
    • Q3:LDIF文件格式错误如何排查?

为什么需要批量添加LDAP用户?

在现代企业IT架构中,LDAP(轻量级目录访问协议)是集中管理用户身份的核心服务,无论是内部OA系统、VPN接入还是服务器认证,LDAP都承担着统一账号池的角色。

手动添加的三大痛点:

  • 效率低下:单个用户添加需多次输入DN、CN、ou等属性,100人操作耗时数小时
  • 易出错:拼写错误、属性缺失(如缺少objectClass)导致认证失败
  • 批量场景缺失:新员工入职100人、部门迁移等场景,无法快速同步

脚本化优势:

  • 一次编写,无限复用
  • 支持CSV/Excel数据源导入
  • 可嵌入CI/CD流水线或定时任务

批量添加LDAP用户的前置准备

1 环境确认

  • OpenLDAP:需安装ldap-utils(Debian/Ubuntu)或openldap-clients(CentOS/RHEL)
  • 389 Directory Server:自带dsidm工具
  • Windows AD:需安装Active Directory PowerShell模块(RSAT工具)

2 LDIF文件结构模板

dn: uid=johndoe,ou=users,dc=example,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
cn: John Doe
sn: Doe
uid: johndoe
uidNumber: 1001
gidNumber: 1001
homeDirectory: /home/johndoe
loginShell: /bin/bash
userPassword: {SSHA}加密后的密码

3 脚本语言选择建议

  • Bash:适合Linux原生环境,命令简单,但字符串处理需依赖awk/sed
  • Python:跨平台能力强,支持LDAP库(python-ldap),推荐大型项目
  • PowerShell:Windows AD管理员首选,可直接调用New-ADUser命令

三种主流脚本实现方案

Bash + ldapadd命令(Linux)

#!/bin/bash
# 批量从CSV文件生成LDIF并导入
INPUT_CSV="users.csv"
LDIF_FILE="/tmp/add_users.ldif"
BIND_DN="cn=admin,dc=example,dc=com"
BIND_PW="admin_password"
# 清空临时LDIF
> "$LDIF_FILE"
while IFS=',' read -r uid cn sn password
do
    # 生成SSHA密码(需安装slappasswd)
    ENCRYPTED_PW=$(slappasswd -s "$password" -h {SSHA})
    cat >> "$LDIF_FILE" << EOF
dn: uid=$uid,ou=users,dc=example,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
cn: $cn
sn: $sn
uid: $uid
uidNumber: $(shuf -i 1000-9999 -n 1)  # 自动分配UID
gidNumber: 1001
homeDirectory: /home/$uid
userPassword: $ENCRYPTED_PW
EOF
done < "$INPUT_CSV"
# 导入LDAP
ldapadd -x -D "$BIND_DN" -w "$BIND_PW" -f "$LDIF_FILE" 2>&1 | tee -a add_log.txt

优点:无需额外安装Python库
缺点:密码生成需slappasswd,Windows不原生支持

Python + python-ldap(跨平台)

import ldap
import ldap.modlist as modlist
import hashlib, base64
# LDAP连接配置
LDAP_SERVER = "ldap://192.168.1.100"
BIND_DN = "cn=admin,dc=example,dc=com"
BIND_PW = "admin123"
# 用户数据(可从CSV/json读取)
users = [
    {"uid": "alice", "cn": "Alice Wang", "sn": "Wang", "password": "pass1"},
    {"uid": "bob", "cn": "Bob Li", "sn": "Li", "password": "pass2"}
]
def add_ldap_user(user):
    # 独立连接避免竞态
    conn = ldap.initialize(LDAP_SERVER)
    conn.simple_bind_s(BIND_DN, BIND_PW)
    dn = f"uid={user['uid']},ou=users,dc=example,dc=com"
    # 生成SSHA密码
    salt = base64.b64encode(b'salt_for_' + user['uid'].encode())
    pwd_hash = hashlib.sha1(user['password'].encode() + salt).digest()
    encoded_pwd = "{SSHA}" + base64.b64encode(pwd_hash + salt).decode()
    attrs = {
        'objectClass': [b'top', b'inetOrgPerson', b'posixAccount'],
        'cn': [user['cn'].encode()],
        'sn': [user['sn'].encode()],
        'uid': [user['uid'].encode()],
        'uidNumber': [b'2001'],
        'gidNumber': [b'2001'],
        'homeDirectory': [f'/home/{user["uid"]}'.encode()],
        'userPassword': [encoded_pwd.encode()]
    }
    ldif = modlist.addModlist(attrs)
    conn.add_s(dn, ldif)
    conn.unbind_s()
# 批量执行
for user in users:
    try:
        add_ldap_user(user)
        print(f"成功添加用户: {user['uid']}")
    except ldap.ALREADY_EXISTS:
        print(f"用户已存在,跳过: {user['uid']}")
    except Exception as e:
        print(f"添加失败 {user['uid']}: {str(e)}")

优点:可处理复杂逻辑(如属性映射、错误回滚)
缺点:需安装python-ldapldap3

PowerShell(Windows AD)

# 导入AD模块
Import-Module ActiveDirectory
# 从CSV读取用户列表
$users = Import-Csv -Path "C:\users.csv"
foreach ($user in $users) {
    $securePwd = ConvertTo-SecureString $user.password -AsPlainText -Force
    New-ADUser -Name $user.name `
               -SamAccountName $user.sam `
               -UserPrincipalName "$($user.sam)@domain.com" `
               -GivenName $user.firstName `
               -Surname $user.lastName `
               -Path "OU=Users,DC=domain,DC=com" `
               -AccountPassword $securePwd `
               -Enabled $true `
               -PassThru | Out-Null
    Write-Host "已添加: $($user.sam)"
}

注意:Windows AD建议使用Set-ADAccountPassword单独设置密码


常见问题与脚本优化技巧

问题1:密码加密处理

  • 推荐算法:SSHA(SHA-1加盐),OpenLDAP原生支持
  • PowerShell AD:自动处理Kerberos加密,无需手动加密

问题2:错误处理与日志

# Bash示例:重试逻辑
for i in {1..3}; do
    ldapadd ... && break || sleep 2
done

问题3:从Excel/CSV读取的通用建议

  • 使用xlsx格式时,Bash请配合ssconvertcsvtool
  • Python推荐pandas库:pd.read_csv()pd.read_excel()

问答精选

Q1:批量添加时如何避免重复用户?

A
方案一:添加前查询是否存在

ldapsearch -x -b "ou=users,dc=example,dc=com" "uid=$uid" 2>/dev/null | grep -q "dn:" && echo "已存在" || { echo "新增"; }

在LDIF中使用changetype: delete先清理旧记录(需谨慎操作)

Q2:脚本中密码明文传输安全吗?

A:不安全!

  • 生产环境:应将密码存储于加密配置文件或Vault(如HashiCorp Vault)
  • 临时方案:使用-w参数时,设置文件权限为600
  • 最佳实践:使用-y从文件读取密码,且该文件由管理员手动创建

Q3:LDIF文件格式错误如何排查?

A

  • 执行:ldapadd -x -D "cn=admin,dc=example,dc=com" -W -f bad.ldif 2>&1
  • 常见错误:
    • ldap_add: Invalid syntax (21):属性值含非法字符(如中文未编码)
    • ldap_add: Object class violation (65):缺少必要属性(如uidNumber

扩展:高级脚本模板

批量修改脚本(Python)

# 将所有用户的主目录改为/home2/
update_filter = "(objectClass=posixAccount)"
attrs = {'homeDirectory': b'/home2'}
ldap_modify_with_filter(filter_str, attrs)

批量删除(谨慎使用)

# 基于搜索结果删除
ldapsearch -x -LLL "(&(objectClass=posixAccount)(uid=guest*))" dn | ldapdelete -x -D ... -f /dev/stdin

通过以上三种方案,你可以根据实际环境选择最合适的脚本化方法,建议初次使用时,先在测试LDAP实例中执行,并始终备份现有数据,批量自动化是提升LDAP运维效率的关键,而脚本的灵活性可满足从几十人到数万用户的扩展需求。

抱歉,评论功能暂时关闭!