对于任何一个研发团队,一套内部通用的帐号管理系统都是必不可少的。请注意我的用词:"内部通用"。
公司内部可能有各种系统:
如果没有内部通用帐号,那么每来一个新员工,就需要到上述所有系统中,分别注册一次。想象一下,这是多么让人头疼的事情!
因此,我们建议团队一定要拥有一套"内部通用"的帐号管理系统。
在这里,我们选用了LDAP(Lightweight Directory Access Protocol)。是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息。
在技术型团队中,LDAP可以当作内部帐号管理系统来使用。此外,LDAP可以很轻松地与其他系统对接,我们后面即将构建的代码管理、版本管理,都将通过LDAP帐号接入。
能提供LDAP服务的开源项目有很多,我们选用了较为成熟的开源服务器OpenLDAP。
虽然OpenLDAP并不是微服务,但我们依然放到Kubernetes集群部署,主要原因是:
来看一下部署文件openldap-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: openldap-deployment
spec:
selector:
matchLabels:
app: openldap
replicas: 1
template:
metadata:
labels:
app: openldap
spec:
restartPolicy: OnFailure
nodeSelector:
kubernetes.io/hostname: minikube
containers:
- name: openldap-ct
image: osixia/openldap:1.1.9
ports:
- containerPort: 389
hostPort: 389
- containerPort: 636
hostPort: 636
volumeMounts:
- mountPath: "../../../etc/ldap/slapd.d"
name: volume
subPath: conf
- mountPath: "../../../var/lib/ldap"
name: volume
subPath: data
env:
- name: LDAP_TLS
value: "false"
- name: LDAP_DOMAIN
value: "coder4.com"
- name: LDAP_ADMIN_PASSWORD
value: "admin123"
- name: LDAP_READONLY_USER
value: "true"
- name: LDAP_READONLY_USER_USERNAME
value: "guest"
- name: LDAP_READONLY_USER_PASSWORD
value: "guest123"
volumes:
- name: volume
hostPath:
path: /data/openldap/
这是一个很长的文件,我们来逐条解释下:
在部署前,我们先要保证物理机上的挂载点存在。
minikube ssh
$ cd /data
$ sudo mkdir openldap
然后部署OpenLDAP服务:
kubectl apply -f ./openldap-deployment.yaml
查看下状态,启动成功了:
kubectl get pods
NAME READY STATUS RESTARTS AGE
openldap-deployment-7d6b7875f-hxqxf 1/1 Running 0 14m
获取集群的IP:
minikube ip
192.168.99.100
验证下,端口已经成功暴露给了集群外:
telnet 192.168.99.100 389
Trying 192.168.99.100...
Connected to 192.168.99.100.
Escape character is '^]'.
^]
操作ldap集群,需要安装一些工具,以Ubuntu为例:
sudo apt-get install ldap-utils
有了工具后,两个系统帐号已经创建成功:
ldapwhoami -h 192.168.99.100 -p 389 -D "cn=admin,dc=coder4,dc=com" -w admin123
dn:cn=admin,dc=coder4,dc=com
ldapwhoami -h 192.168.99.100 -p 389 -D "cn=guest,dc=coder4,dc=com" -w guest123
dn:cn=guest,dc=coder4,dc=com
至此,我们已经完成了OpenLDAP的基础配置,并且成功创建了两个系统帐号。
在刚才的配置中,我们创建了两个系统帐号,但在实际工作中,团队成员一般不会使用系统帐号。
对于一个团队成员,它的帐号至少需要有如下属性:
大公司的内部,会细分为多个团队,此时还应当将用户划分到相应的属组。由于篇幅所限,我们在此不讨论属组的问题。
在密码加密方面,我们采用ssha,它需要命令slappasswd,你可以在任何安装了openldap的机器上找到它:
slappasswd -h {ssha} -s pass123
{SSHA}yG3DQj7iol10+fzWoeBAgoZ+D+h9uQre
上述即生成了一个ssha加密过的密码pass123。
我们前面已经提到,LDAP是一个"目录式"的权限管理服务。其本身规则非常复杂到可以单独写一本书:-)
本书不会对其规则进行过多讲解,这里先提供了一个简单的模板,供大家学习。
./users.ldif
version: 1
# users org
dn: ou=users,dc=coder4,dc=com
objectClass: top
objectClass: organizationalUnit
ou: users
# group org
dn: ou=groups,dc=coder4,dc=com
objectClass: top
objectClass: organizationalUnit
ou: groups
# define users here
dn: cn=lihy,ou=users,dc=coder4,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: lihy
sn:: 5p2O6LWr5YWD
mail: lihy@coder4.com
userPassword: {SSHA}yG3DQj7iol10+fzWoeBAgoZ+D+h9uQre
dn: cn=zhangsan,ou=users,dc=coder4,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: zhangsan
sn:: 5byg5LiJ
mail: zhangsan@coder4.com
userPassword: {SSHA}yG3DQj7iol10+fzWoeBAgoZ+D+h9uQre
# should also modify here if insert new user
dn: cn=Users,ou=groups,dc=coder4,dc=com
objectClass: top
objectClass: groupOfUniqueNames
cn: Users
uniqueMember: cn=lihy,ou=users,dc=coder4,dc=com
uniqueMember: cn=zhangsan,ou=users,dc=coder4,dc=com
# define admin here
dn: cn=Admin,ou=groups,dc=coder4,dc=com
objectClass: top
objectClass: groupOfUniqueNames
cn: Admin
uniqueMember: cn=lihy,ou=users,dc=coder4,dc=com
简单解释下:
我们来应用这个模板:
ldapadd -c -h 192.168.99.100 -p 389 -w admin123 -D "cn=admin,dc=coder4,dc=com" -f ./users.ldif
如上,需要用admin帐号,-c选项是忽略所有错误,继续执行。
验证一下新增的内部用户:
ldapwhoami -h 192.168.99.100 -p 389 -D "cn=lihy,ou=users,dc=coder4,dc=com" -w pass123
dn:cn=lihy,ou=users,dc=coder4,dc=com
添加新用户,需要操作三个步骤:
不用我说大家也明白,上述步骤真的是非常繁琐,而且容易出错。
面对这种情况,大家可以选用第三方的工具来管理LDAP帐号,例如phpLDAPadmin,但是这需要额外维护一套系统,不免有些笨重。
为了降低维护成本,我提供了几个简单的小脚本,以满足日常的管理工作。
添加帐号,ldap_add.sh
#!/bin/bash
# const
LDAP_SERVER_IP="192.168.99.100"
LDAP_SERVER_PORT="389"
LDAP_ADMIN_USER="cn=admin,dc=coder4,dc=com"
LDAP_ADMIN_PASS="admin123"
if [ x"$#" != x"3" ];then
echo "Usage: $0 <username> <password> <realname>"
exit -1
fi
# param
USERNAME="$1"
PASSWORD="$2"
ENCRYPT_PASSWORD=$(slappasswd -h {ssha} -s "$PASSWORD")
REALNAME="$3"
REALNAME_BASE64=$(echo -n $REALNAME | base64)
# add count & group
cat <<EOF | ldapmodify -c -h $LDAP_SERVER_IP -p $LDAP_SERVER_PORT -w $LDAP_ADMIN_PASS -D $LDAP_ADMIN_USER
dn: cn=$USERNAME,ou=users,dc=coder4,dc=com
changetype: add
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: $USERNAME
sn:: $REALNAME_BASE64
mail: $USERNAME@coder4.com
userPassword: $ENCRYPT_PASSWORD
dn: cn=Users,ou=groups,dc=coder4,dc=com
changetype: modify
add: uniqueMember
uniqueMember: cn=$USERNAME,ou=users,dc=coder4,dc=com
EOF
上述脚本通过ldapmodify命令,自动完成了我们之前提到的三个步骤。
我们试着添加新用户lisi
./ldap_add.sh lisi pass123 李四
adding new entry "cn=lisi,ou=users,dc=coder4,dc=com"
modifying entry "cn=Users,ou=groups,dc=coder4,dc=com"
验证一下,添加成功
ldapwhoami -h 192.168.99.100 -p 389 -D "cn=lisi,ou=users,dc=coder4,dc=com" -w pass123
dn:cn=lisi,ou=users,dc=coder4,dc=com
第二个常见的情况是,修改密码, ./ldap_modify_password.sh:
#!/bin/bash
# const
LDAP_SERVER_IP="192.168.99.100"
LDAP_SERVER_PORT="389"
LDAP_ADMIN_USER="cn=admin,dc=coder4,dc=com"
LDAP_ADMIN_PASS="admin123"
if [ x"$#" != x"2" ];then
echo "Usage: $0 <username> <newPassword>"
exit -1
fi
# param
USERNAME="$1"
PASSWORD="$2"
ENCRYPT_PASSWORD=$(slappasswd -h {ssha} -s "$PASSWORD")
# modify
cat <<EOF | ldapmodify -c -h $LDAP_SERVER_IP -p $LDAP_SERVER_PORT -w $LDAP_ADMIN_PASS -D $LDAP_ADMIN_USER
dn: cn=$USERNAME,ou=users,dc=coder4,dc=com
changetype: modify
replace: userPassword
userPassword: $ENCRYPT_PASSWORD
EOF
我们尝试修改lisi的密码:
./ldap_modify_password.sh lisi hahaha
modifying entry "cn=lisi,ou=users,dc=coder4,dc=com"
验证一下,新密码已经修改成功:
ldapwhoami -h 192.168.99.100 -p 389 -D "cn=lisi,ou=users,dc=coder4,dc=com" -w hahaha
dn:cn=lisi,ou=users,dc=coder4,dc=com
最后一个场景是删除用户,这里我们只删除用户,不删除其加入的属组
#!/bin/bash
# const
LDAP_SERVER_IP="192.168.99.100"
LDAP_SERVER_PORT="389"
LDAP_ADMIN_USER="cn=admin,dc=coder4,dc=com"
LDAP_ADMIN_PASS="admin123"
if [ x"$#" != x"1" ];then
echo "Usage: $0 <username>"
exit -1
fi
# param
USERNAME="$1"
# delete user
ldapdelete -c -h $LDAP_SERVER_IP -p $LDAP_SERVER_PORT -w $LDAP_ADMIN_PASS -D $LDAP_ADMIN_USER "cn=$USERNAME,ou=users,dc=coder4,dc=com"
尝试删除一下:
./ldap_delete.sh zhangsan
然后验证下,确实无法登录了
ldapwhoami -h 192.168.99.100 -p 389 -D "cn=zhangsan,ou=users,dc=coder4,dc=com" -w pass123
ldap_bind: Invalid credentials (49)
至此,我们完成了LDAP服务的构建,并可以通过简单的脚本完成帐号的添删改操作。
如果你十分看中帐号服务对外通信的安全性,建议还是开启,具体可以参考docker-openldap)
↩