Keycloak使用群晖Synology Directory Server作为AD/LDAP用户数据源

这又是keycloak的另外一个大坑。keycloak并不会自动创建一系列SSL证书相关的配置,都要自己手撸。

如果还没安装keycloak,可以参考前一篇文章『Docker Compose安装Keycloak

然后,你的群晖要先把AD配置好,这里就不重复了。

1、获得群晖AD对应的SSL证书

首先,要把群晖为AD所生产的自签名SSL证书下载回来,后面需要用。

位置:群晖DSM管理后台-控制面板-安全性-证书。如果不太确定是哪张证书,可以点击『设置』,找到『Synology Directory Server』对应的证书下拉。

在对应的证书上点击右键,选择『导出证书』

导出的证书解压后有两个文件,一个是证书本身cert.pem,另外一个是证书的私钥privkey.pem,我们需要用到的是cert.pem

💡
UPDATE

另外一个使用OpenSSL来获取证书的方法(方便不支持导出的LDAP服务器)

openssl s_client -showcerts -verify 5 -connect <AD/LDAP服务器IP或者域名>:636  < /dev/null | awk '/BEGIN/,/END/{ if(/BEGIN/)    {a++}; out="ad-cert-"a".pem"; print >out}' 

上面命令运行后,当前目录下会生成多个ad-cert-x.pem的证书文件,找到对应的证书即可。

OK,基础数据准备好,我们开始干活。

2、为keycloak生成Java所需要用的keystore文件

这里有个大坑。虽然新版本的Java建议出于更高的安全性考虑,keystore应该使用PKCS12格式,keytool也是默认创建PKCS12格式的keystore。但,keycloak不认。

所以,我们还是需要创建JKS格式的keystore文件。

别问我怎么知道的,晚上10点搞到凌晨3点。

我们进入到放置docker-compose.yml的目录,创建一个存放证书的目录certs,并且把前面群晖导出的cert.pem也拷贝进去,一会需要用来导入

mkdir certs
# 下面的cert.pem改为自己实际存放的路径
cp ~/archive/cert.pem certs
# 创建keystore文件
keytool -genkeypair -storepass password -storetype JKS -keyalg RSA -keysize 2048 -validity 3650 -dname "CN=KeyCloak" -alias KeyCloak -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore certs/server.jks
# 把群晖的证书导入keystore
keytool -storepass password -noprompt -trustcacerts -alias nas.synology -import -file certs/cert.pem -keystore certs/server.jks

如果系统提示没有keytool,那么安装一下

apt install openjdk-11-jre-headless

3、把keystore映射到docker

正常情况下,docker-compose的up和down会删掉镜像里面的内容重新创建,所以刚才创建的证书如果直接放入到容器里,会丢失。我们有两个方法解决这个问题,一个是自己通过dockerfile创建docker镜像,另外一个是把文件夹映射到容器。我们就不整那么麻烦的事情了,直接映射文件夹是最方便的。

我们需要在docker-compose.yml里面增加下面两段

    volumes:
      - ./certs:/opt/keycloak/certs

这样就把当前certs文件夹映射到容器的/opt/keycloak/certs了

4、为KeyCloak指定使用自己创建的keystore文件

同样,在docker-compose.yml里面,environment段增加下面的内容

      KC_SPI_TRUSTSTORE_FILE_FILE: /opt/keycloak/certs/server.jks
      KC_SPI_TRUSTSTORE_FILE_PASSWORD: password
      KC_SPI_TRUSTSTORE_FILE_HOSTNAME_VERIFICATION_POLICY: ANY
      KC_HTTPS_TRUST_STORE_FILE: /opt/keycloak/certs/server.jks
      KC_HTTPS_TRUST_STORE_PASSWORD: password

修改过的docker-compose.yml,看起来大概是这样(注意缩进,注意缩进,注意缩进)

修改后的docker-compose.yml

然后,我们重启一下容器

docker-compose down
docker-compose up -d

这样,KeyCloak应该就可以正确识别SSL证书了。

5、KeyCloak中增加User Federation

我们进入KeyCloak的管理后台,左侧导航点击『User federation』,选择添加一个LDAP的源。

接着就看图说话。基本上只要改前面的内容,后面的内容就保持默认好了。

关于DN的问题,可以参考文章『Gitlab整合群晖Synology Active Directory

提供上面的一些字符串,方便复制修改

CN=Administrator,CN=Users,DC=NAIZHAO,DC=COM
CN=Administrator,CN=Users,DC=BRA,DC=DO

保存完,我们就可以开始测试了。

6、测试用户数据是否正常

点击左侧导航Clients,然后点击account右边的URL,会进入到一个登陆页面(新开个浏览器,或者浏览器开个无痕窗口,不然当前浏览器有cookie,默认就登录了)。点击页面右上角的『Sign in』,新页面里面输入AD里面的用户名和密码,正常的话就登录成功了。

然后我们回到管理页面,点击左侧的Users,Search Users的输入框里面输入一个星号*,点击搜索,你会发现AD里面的用户都出来了

OK,搞定。后面可以继续创建realm,创建openid client。

7、关于DN,多说一嘴

很多朋友搞不清什么是DN。其实简单理解,DN和文件夹、DNS都很像,也有一定的关联。

比如有个用户叫Bra,组织架构是在集团Com,事业群Naizhao,研发部Dev的运维Ops下面,那么找到Bra,有几种方法:

文件夹(目录)方式

COM\NAIZHAO\DEV\OPS\BRA

域名方式

bra.ops.dev.naizhao.com

Active Directory/LDAP的DN方式

CN=Bra,CN=Ops,CN=Dev,DC=NAIZHAO,DC=COM

8、关于从Windows Active Directory同步的其他一些补充

从Windows AD同步的时候,cn属性值是用户的全名。Windows AD用户全名默认是用户的姓+名的组合,所以并不一定是登陆的用户名,特别是姓名是中文的时候。所以,如果使用Windows AD作为用户数据源,我们需要把设置中『LDAP searching and updating』-『Username LDAP attribute』从cn改为sAMAccountName,同时把『Mappers』-『username』-『LDAP Attribute』也从cn改为sAMAccountName,保存即可。