1. 目的

Keycloak 和 Crowd 是企业内部常用的两种单点登录系统,二者都支持使用 Active Directory 作为用户、组的存储,以及作为背后真正的认证系统。本文使用 Samba 4 替代 Active Directory,并配置 Keycloak 和 Crowd 使用 Samba 4 ,整个过程使用了 macOS 以及 VMWare Fusion 虚拟机,这些步骤也可以照搬到真实物理机上。

2. 搭建 Samba DC

Samba 4 增加了 Microsoft Active Directory 的 Domain Controller 功能,包含 DNS server, Kerberos server, LDAP server,实际对于 Keycloak 和 Crowd 来说只需要用 AD 里头 LDAP server 功能。 以下步骤参考 Matei Cezar 的 Samba 系列文章:

2.1 在 VMware Fusion 里安装 Ubuntu 20.04 server edition

这个没啥好说的,具体步骤省略。

2.2 安装 Samba DC

这里假定 Ubuntu 主机名为 ad,域为 example.me

  1. apt install samba winbind krb5-user

  2. 确保 samba 服务是停止状态:

    systemctl stop samba-ad-dc.service smbd.service nmbd.service winbind.service
    systemctl disable samba-ad-dc.service smbd.service nmbd.service winbind.service
    
  3. 备份 /etc/samba/smb.conf

    mv /etc/samba/smb.conf /etc/samba/smb.conf.initial
    
  4. 初始化 AD domain

    samba-tool domain provision --use-rfc2307 --interactive
    
    # Realm 填写:EXAMPLE.ME
    # 后面都选默认值,除了 DNS forwarder IP address 填写非本机 IP,因为 Ubuntu
    # 默认启动了 systemd-resolved 监听本机 53 端口,会跟 winbindd 冲突
    
  5. 设置默认 /etc/krb5.conf 配置:

    mv /etc/krb5.conf /etc/krb5.conf.initial
    ln -s /var/lib/samba/private/krb5.conf /etc/
    
  6. 禁用 systemd-resolved,避免跟 winbindd 冲突

    systemctl stop systemd-resolved
    systemctl disable systemd-resolved
    
    # 修改 /etc/resolv.conf,内容如下:
    nameserver 127.0.0.1
    options edns0
    search example.me
    
  7. 启动 Samba Active Directory Domain Controller 服务:

    systemctl unmask samba-ad-dc.service  # Samba 安装后默认是 standalone 模式,这个 service 被自动 mask 掉了
    systemctl start samba-ad-dc.service
    systemctl status samba-ad-dc.service
    systemctl enable samba-ad-dc.service
    
  8. 检查 Samba 是否运行正常

    samba-tool domain level show
    # 应该输出: Domain and forest function level for domain 'DC=example,DC=me'
    
    host -t A example.me
    host -t A ad.example.me
    host -t SRV _kerberos._udp.example.me        # UDP Kerberos SRV record
    host -t SRV _ldap._tcp.example.me            # TCP LDAP SRV record
    # 应该都能成功解析
    
    kinit administrator@EXAMPLE.ME
    klist
    # 应该能成功申请到 ticket
    
  9. 增加测试用户和组

    samba-tool user add test --given-name=test-given --surname=test-sur \
      --mail-address=test@example.me --login-shell=/bin/bash
    
    samba-tool user list
    
    samba-tool group add test-group
    samba-tool group list
    
    samba-tool group addmembers test-group test
    samba-tool group listmembers test-group
    
    samba-tool domain passwordsettings show
    wbinfo -g                # 显示组列表
    wbinfo -u                # 显示用户列表
    wbinfo -i test           # 显示用户信息
    

3. 配置 Crowd

  1. 配置 JDK 的 cacerts 文件,信任 samba server 的 CA 证书

    # 复制 /var/lib/samba/private/tls/ca.pem 到 Crowd 所在机器(本文使用本地的 macOS 系统)
    
    # 导入到 cacerts,cacerts keystore 的默认密码是 changeit
    sudo keytool -import -alias ad.example.me-ca -file ca.pem \
      -keystore /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/security/cacerts
    
  2. 修改 /etc/hosts 加入 172.16.56.137 ad.example.me,这里的 IP 是 Samba 服务所在机器的 IP,请自行修正。

  3. 启动 Crowd

    # JDK >= 11 默认使用 TLS 1.3,但实现有个问题,会导致 Crowd 连接 Samba 时报错:
    # javax.net.ssl.SSLHandshakeException: extension (5) should not be presented in certificate_request
    # 解决办法是使用 JDK < 11,或者使用 java 选项 -Djdk.tls.client.protocols=TLSv1.2
    # 参考: https://mongodb.github.io/mongo-java-driver/4.1/driver/tutorials/ssl/
    
    export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
    atlassian-crowd-4.1.0/start_crowd.sh
    
  4. 在 Crowd 里增加 Directory,在 Connector 标签页里设置如下字段:

    • URL: ldaps://ad.example.me:636/
    • SSL: LDAPS
    • Base DN: CN=Users,DC=example,DC=me
    • Username: administrator@EXAMPLE
  5. 在 Crowd 里配置对应目录的对应组可以登录 Crowd web console:

    • Applications 标签页,选择 “Crowd”
    • Directories & groups 标签页,添加刚配置的 Active Directory,并拖动调整优先级到第一位,然后此目录条目右边的 Action,选择 “Configure authentication”,把 test-group 加入允许列表里。

4. 配置 Keycloak

  1. 配置 JDK 的 cacerts 文件,同上

  2. 修改 /etc/hosts,同上

  3. 启动 Keycloak

    export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
    keycloak-11.0.3/bin/standalone.sh
    
  4. 在 Keycloak 里增加 LDAP 类型的 User Federation,在 Settings 标签页里设置如下字段:

    • Import Users: ON
    • Edit Mode: WRITABLE
    • Sync Registrations: ON
    • Vendor: Active Directory
    • Username LDAP attribute: sAMAccountName
    • Connection URL: ldaps://ad.example.me:636
    • Users DN: CN=Users,DC=example,DC=me
    • Bind DN: administrator@EXAMPLE

5. 使用 Apache Directory Studio 访问 Samba DC

在新建连接对话框里设置如下:

  • Hostname: ad.example.me
  • Port: 636
  • Encryption method: Use SSL encryption (ldaps://)
  • Bind DN or user: administrator@EXAMPLE