简介
如果企业内部有使用LDAP进行用户身份验证,则可以通过配置Rancher与OpenLDAP服务器通信以对用户进行身份验证。
本文将介绍如何通过docker快速搭建OpenLDAP环境,并对接Rancher认证功能
主要用到两个镜像:
osixia/openldap:1.5.0
:LDAP服务端
osixia/phpldapadmin:0.9.0
:LDAP web管理工具
步骤
安装OpenLDAP服务
基于osixia/openldap:1.5.0
镜像,创建OpenLDAP服务
1
| docker run -p 389:389 -p 636:636 --name openldap -itd --env LDAP_ORGANISATION="rancher" --env LDAP_DOMAIN="rancherldap.com" --env LDAP_ADMIN_PASSWORD="Rancher123" osixia/openldap:1.5.0
|
参数说明:
缺省ldap使用389端口,加密使用636端口
LDAP_ORGANISATION
:Organisation名称,默认是Example Inc.
LDAP_DOMAIN
:LDAP domain,例如默认是example.org
,则domain为dc=example,dc=org
LDAP_ADMIN_PASSWORD
:admin用户密码
创建osixia/phpldapadmin:0.9.0
镜像,创建Web服务
phpldapadmin是一个基于Web的管理LDAP的工具,可以更加直观的查看和管理LDAP信息
1
| docker run -p 6443:443 --env PHPLDAPADMIN_LDAP_HOSTS=172.16.21.12 -itd --name phpldapadmin osixia/phpldapadmin:0.9.0
|
参数说明:
PHPLDAPADMIN_LDAP_HOSTS
:LDAP服务地址,这里如果是将openLDAP容器启动在相同主机上则填写本机的IP地址即可
docker-compose(可选)
也可以通过docker-compose去创建OpenLDAP环境
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
| version: '2.3' services: openldap: image: osixia/openldap:1.5.0 container_name: openldap restart: always environment: - LDAP_ORGANISATION=rancher - LDAP_DOMAIN=rancherldap.com - LDAP_ADMIN_PASSWORD=Rancher123 ports: - 389:389 - 636:636 volumes: - ./slapd:/etc/ldap/slapd.d - ./data:/var/lib/ldap phpldapadmin: image: osixia/phpldapadmin:0.9.0 container_name: phpldapadmin restart: always environment: - PHPLDAPADMIN_LDAP_HOSTS=openldap links: - openldap:openldap depends_on: - openldap ports: - 6443:443 volumes: - ./phpldapadmin-certs:/container/service/phpldapadmin/assets/apache2/certs
|
将上诉文件保存到docker-compose.yml
中,然后执行docker-compose up -d
命令即可
运行成功后,会在跟docker-compose.yml
文件相同的目录下创建三个目录slapd
、data
、phpldapadmin-certs
默认admin domain账号为:cn=admin,dc=rancherldap,dc=com
,密码为:Rancher123
进入openldap容器中,执行ldapsearch
命令尝试搜索
1
| docker exec openldap ldapsearch -x -H ldap://localhost -b dc=rancherldap,dc=com -D "cn=admin,dc=rancherldap,dc=com" -w Rancher123
|
可以得到如下输出结果,则说明部署成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
dn: dc=rancherldap,dc=com objectClass: top objectClass: dcObject objectClass: organization o: rancher dc: rancherldap
search: 2 result: 0 Success
|
基于phpldapadmin的web工具创建用户
浏览器访问:https://<IP>:6443
,点击左侧login登录

其中账号密码如下:
1 2
| cn=admin,dc=rancherldap,dc=com Rancher123
|

登录进去后,可以看到domain相关信息
创建Organisational Unit
点击dc=rancherldap,dc=com
,在其目录下点击Create a child entry
创建子条目

点击 Generic: Organisational Unit

填写OU名称,例如这里填写rancher,填好之后点击Create Object
创建该对象

点击Commit二次确认

创建成功后,就可以在左侧中看到我们创建的OU对象

创建Group
在ou=rancher
下,点击Create a child entry
创建子条目,点击 Generic: Posix Group
创建Group对象

填写Group名称,例如这里填写group
,

填好之后点击Create Object
创建该对象,点击Commit二次确认,创建成功后,就可以在左侧中看到我们创建的Group对象

创建User
在cn=group
下,点击Create a child entry
创建子条目,点击 Generic: User Account
创建User对象

填写对应的user信息,填写First name和Last name,会自动生成Common Name和User ID,其中UserID为后续Rancher登录的用户名
填写Password,后续登录Rancher使用该密码
选择刚刚创建的group

填好之后点击Create Object
创建该对象,点击Commit二次确认,创建成功后,就可以在左侧中看到我们创建的USer对象

同理,我们用相同的方法再创建一个test用户

对接Rancher认证
对接OpenLDAP
在Rancher UI中,点击 全局-安全-认证,选择OpenLDAP

参数说明:
主机名或 IP 地址
:OpenLDAP服务器的IP地址
端口
:默认端口是389
服务帐户专有名称
:cn=admin,dc=rancherldap,dc=com
,这里填写admin用户的domain
服务账号密码
:admin用户的密码
用户搜索起点
:例如刚刚创建的OU为rancher,则这里的搜索起点为ou=rancher,dc=rancherldap,dc=com
用户名
:这个用户会成为管理员,用户名需要基于User Name
填写,例如我们刚刚创建的adminuser,则这里填写auser
密码
:该用户的密码
参数填写完之后,点击启用OpenLDAP认证,开启OpenLDAP认证

测试LDAP用户登录

登录成功,默认该用户没有权限

OpenLDAP启用TLS
上述情况下,对接LDAP使用389端口,我们可以使用此端口进行LDAP连接。 但是该端口是非安全和未加密的连接,容易造成安全问题,暴露用户相关信息,一般建议是389仅用在内网或者测试环境。
针对这个情况,我们可以使用LDAP的另一个tls加密端口:636端口,来对接LDAP。
创建自签名证书
在docker-compose.yml
同级目录下,新建一个目录,命名为certs
新建一个文件create-cert.sh
,复制如下脚本至该文件中
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
| #!/bin/bash -e
help () { echo ' ================================================================ ' echo ' --ssl-domain: 生成ssl证书需要的主域名,如不指定则默认为www.rancher.local,如果是ip访问服务,则可忽略;' echo ' --ssl-trusted-ip: 一般ssl证书只信任域名的访问请求,有时候需要使用ip去访问server,那么需要给ssl证书添加扩展IP,多个IP用逗号隔开;' echo ' --ssl-trusted-domain: 如果想多个域名访问,则添加扩展域名(SSL_TRUSTED_DOMAIN),多个扩展域名用逗号隔开;' echo ' --ssl-size: ssl加密位数,默认2048;' echo ' --ssl-cn: 国家代码(2个字母的代号),默认CN;' echo ' 使用示例:' echo ' ./create_self-signed-cert.sh --ssl-domain=www.test.com --ssl-trusted-domain=www.test2.com \ ' echo ' --ssl-trusted-ip=1.1.1.1,2.2.2.2,3.3.3.3 --ssl-size=2048 --ssl-date=3650' echo ' ================================================================' }
case "$1" in -h|--help) help; exit;; esac
if [[ $1 == '' ]];then help; exit; fi
CMDOPTS="$*" for OPTS in $CMDOPTS; do key=$(echo ${OPTS} | awk -F"=" '{print $1}' ) value=$(echo ${OPTS} | awk -F"=" '{print $2}' ) case "$key" in --ssl-domain) SSL_DOMAIN=$value ;; --ssl-trusted-ip) SSL_TRUSTED_IP=$value ;; --ssl-trusted-domain) SSL_TRUSTED_DOMAIN=$value ;; --ssl-size) SSL_SIZE=$value ;; --ssl-date) SSL_DATE=$value ;; --ca-date) CA_DATE=$value ;; --ssl-cn) CN=$value ;; esac done
CA_DATE=${CA_DATE:-3650} CA_KEY=${CA_KEY:-cakey.pem} CA_CERT=${CA_CERT:-cacerts.pem} CA_DOMAIN=cattle-ca
SSL_CONFIG=${SSL_CONFIG:-$PWD/openssl.cnf} SSL_DOMAIN=${SSL_DOMAIN:-'www.rancher.local'} SSL_DATE=${SSL_DATE:-3650} SSL_SIZE=${SSL_SIZE:-2048}
CN=${CN:-CN}
SSL_KEY=$SSL_DOMAIN.key SSL_CSR=$SSL_DOMAIN.csr SSL_CERT=$SSL_DOMAIN.crt
echo -e "\033[32m ---------------------------- \033[0m" echo -e "\033[32m | 生成 SSL Cert | \033[0m" echo -e "\033[32m ---------------------------- \033[0m"
if [[ -e ./${CA_KEY} ]]; then echo -e "\033[32m ====> 1. 发现已存在CA私钥,备份"${CA_KEY}"为"${CA_KEY}"-bak,然后重新创建 \033[0m" mv ${CA_KEY} "${CA_KEY}"-bak openssl genrsa -out ${CA_KEY} ${SSL_SIZE} else echo -e "\033[32m ====> 1. 生成新的CA私钥 ${CA_KEY} \033[0m" openssl genrsa -out ${CA_KEY} ${SSL_SIZE} fi
if [[ -e ./${CA_CERT} ]]; then echo -e "\033[32m ====> 2. 发现已存在CA证书,先备份"${CA_CERT}"为"${CA_CERT}"-bak,然后重新创建 \033[0m" mv ${CA_CERT} "${CA_CERT}"-bak openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN}/CN=${CA_DOMAIN}" else echo -e "\033[32m ====> 2. 生成新的CA证书 ${CA_CERT} \033[0m" openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN}/CN=${CA_DOMAIN}" fi
echo -e "\033[32m ====> 3. 生成Openssl配置文件 ${SSL_CONFIG} \033[0m" cat > ${SSL_CONFIG} <<EOM [req] req_extensions = v3_req distinguished_name = req_distinguished_name [req_distinguished_name] [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, serverAuth EOM
if [[ -n ${SSL_TRUSTED_IP} || -n ${SSL_TRUSTED_DOMAIN} || -n ${SSL_DOMAIN} ]]; then cat >> ${SSL_CONFIG} <<EOM subjectAltName = @alt_names [alt_names] EOM IFS="," dns=(${SSL_TRUSTED_DOMAIN}) dns+=(${SSL_DOMAIN}) for i in "${!dns[@]}"; do echo DNS.$((i+1)) = ${dns[$i]} >> ${SSL_CONFIG} done
if [[ -n ${SSL_TRUSTED_IP} ]]; then ip=(${SSL_TRUSTED_IP}) for i in "${!ip[@]}"; do echo IP.$((i+1)) = ${ip[$i]} >> ${SSL_CONFIG} done fi fi
echo -e "\033[32m ====> 4. 生成服务SSL KEY ${SSL_KEY} \033[0m" openssl genrsa -out ${SSL_KEY} ${SSL_SIZE}
echo -e "\033[32m ====> 5. 生成服务SSL CSR ${SSL_CSR} \033[0m" openssl req -sha256 -new -key ${SSL_KEY} -out ${SSL_CSR} -subj "/C=${CN}/CN=${SSL_DOMAIN}" -config ${SSL_CONFIG}
echo -e "\033[32m ====> 6. 生成服务SSL CERT ${SSL_CERT} \033[0m" openssl x509 -sha256 -req -in ${SSL_CSR} -CA ${CA_CERT} \ -CAkey ${CA_KEY} -CAcreateserial -out ${SSL_CERT} \ -days ${SSL_DATE} -extensions v3_req \ -extfile ${SSL_CONFIG}
echo -e "\033[32m ====> 7. 证书制作完成 \033[0m" echo echo -e "\033[32m ====> 8. 以YAML格式输出结果 \033[0m" echo "----------------------------------------------------------" echo "ca_key: |" cat $CA_KEY | sed 's/^/ /' echo echo "ca_cert: |" cat $CA_CERT | sed 's/^/ /' echo echo "ssl_key: |" cat $SSL_KEY | sed 's/^/ /' echo echo "ssl_csr: |" cat $SSL_CSR | sed 's/^/ /' echo echo "ssl_cert: |" cat $SSL_CERT | sed 's/^/ /' echo
echo -e "\033[32m ====> 9. 附加CA证书到Cert文件 \033[0m" cat ${CA_CERT} >> ${SSL_CERT} echo "ssl_cert: |" cat $SSL_CERT | sed 's/^/ /' echo
echo -e "\033[32m ====> 10. 重命名服务证书 \033[0m" echo "cp ${SSL_DOMAIN}.key tls.key" cp ${SSL_DOMAIN}.key tls.key echo "cp ${SSL_DOMAIN}.crt tls.crt" cp ${SSL_DOMAIN}.crt tls.crt
|
使用示例如下,详细参数说明请参考Rancher一键生成自签名证书脚本:
1 2
| chmod +x create-cert.sh ./create-cert.sh --ssl-domain=ldap.zerchin.xyz --ssl-trusted-ip=172.16.21.12 --ssl-size=2048 --ssl-date=3650
|
LDAP 添加相关 TLS 配置参数
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
| version: '2.3' services: openldap: image: osixia/openldap:1.5.0 container_name: openldap restart: always environment: - LDAP_ORGANISATION=rancher - LDAP_DOMAIN=rancherldap.com - LDAP_ADMIN_PASSWORD=Rancher123 - LDAP_TLS_CRT_FILENAME=tls.crt - LDAP_TLS_KEY_FILENAME=tls.key - LDAP_TLS_CA_CRT_FILENAME=cacerts.pem - LDAP_TLS_VERIFY_CLIENT=try ports: - 389:389 - 636:636 volumes: - ./slapd:/etc/ldap/slapd.d - ./data:/var/lib/ldap - ./certs:/container/service/slapd/assets/certs phpldapadmin: image: osixia/phpldapadmin:0.9.0 container_name: phpldapadmin restart: always environment: - PHPLDAPADMIN_LDAP_HOSTS=openldap links: - openldap:openldap depends_on: - openldap ports: - 6443:443 volumes: - ./phpldapadmin-certs:/container/service/phpldapadmin/assets/apache2/certs
|
参数说明:
LDAP_TLS_CRT_FILENAME
:ldap证书文件名
LDAP_TLS_KEY_FILENAME
:ldap证书key文件名
LDAP_TLS_CA_CRT_FILENAME
:CA证书文件名
LDAP_TLS_VERIFY_CLIENT
:默认是demand
,会对传入的 TLS 会话中的客户端证书强制执行检查,在对接的过程中会报证书相关错误,这里设置为try
,没有证书也可以正常会话保持。可参考此文档。
然后重新运行docker-compose命令即可:
1 2
| docker-compose down -v docker-compose up -d
|
Rancher对接TLS OpenLDAP

其中端口要改为636 tls端口,并将加密类型设置为TLS,其中CA证书去certs目录下查看cacerts.pem
文件拷贝过来即可,对接成功如下:
