集中认证 说明 我们常说的认证平台或4A认证是指: 认证(Authentication)、授权(Authorization)、账号(Account)、审计(Audit)
认证: 是否允许你通过
授权: 通过后你拥有哪些权限
账号: 用以标记你是谁, 可以是人、设备、服务等
审计: 都做了什么, 留痕
这里集中认证实现的是账号+认证
, 不同于单点登录(SSO, Single Sign On).
授权一般是业务自身来处理, 比如基于账号ID、账号某属性
审计一般是基于日志分析用户做了什么, 有什么安全风险
简单的需求分析 本质需求: 公司的IT系统、业务系统使用同一套用户/密码体系进行登录认证
这时候需进一步对需要登录的系统进行简单罗列:
按照需要支持的协议拆分:
是不是会有点懵…
不急, 框架定好, 一步一步搭建测试环境, 逐步满足需求
TODO: 各种选型的对比、认证原理
技术方案 基于简单的需求分析
, 私下肯定会做一定的功课, 这里我们先做如下决策
OpenLDAP 用作账号管理
Kerberos 用作认证
测试环境, 一定要记住下面都是测试环境的产物
, 只是为了快速验证方案
Ubuntu 18.04.5 LTS
slapd 2.4.45+dfsg-1ubuntu1.10
krb5-kdc 1.16-2ubuntu0.2
OpenLDAP 安装 一些概念不再敖述, 可自行官网通读手册或搜索
安装
1 2 apt install slapd apt install ldap-utils
slapd OpenLDAP Server, ldap服务的守护进程
ldap-utils OpenLDAP utilites, ldap的客户端工具集, 比如ldapsearch
slapd改为使用slapd.conf
配置文件, 而不是官网建议的slapd.d目录
尝试过基于slapd.d目录配置, 可读性、可维护性个人感觉太差了
1 2 3 cd /etc/ldap mv slapd.d slapd.d.bak cp /usr/share/slapd/slapd.conf .
结合配置示例, 剥离出一个最简配置如下slapd.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 include /etc/ldap/schema/core.schema include /etc/ldap/schema/cosine.schema include /etc/ldap/schema/inetorgperson.schema include /etc/ldap/schema/misc.schema include /etc/ldap/schema/nis.schema include /etc/ldap/schema/kerberos.schema pidfile /var/run/slapd/slapd.pid argsfile /var/run/slapd/slapd.args loglevel stats idletimeout 30 writetimeout 5 modulepath /usr/lib/ldap moduleload back_hdb database hdb directory /var/lib/ldap/ dbconfig set_cachesize 0 1048576 0 dbconfig set_lg_ bsize 2097152 suffix "dc=intra,dc=wafcloud,dc=cn" rootdn "cn=root,ou=Control,dc=intra,dc=wafcloud,dc=cn" rootpw "{SSHA}bjVQ5hStFSeqHyc/thFM4HX1HJ8AF6HA"
rootpw
字段对应的值是通过slappasswd
命令生成, 例如slappasswd -s virE8jUt
养成好习惯, 测试环境也避免使用弱密码
kerberos.schema
来源于krb5-kdc-ldap
软件包中的kerberos.schema.gz
其它参数具体意义可man slapd.conf
测试
1 ldapsearch -D 'cn=root,ou=Control,dc=intra,dc=wafcloud,dc=cn' -b 'dc=intra,dc=wafcloud,dc=cn' -h 127.0.0.1 -x -W
-x 简单认证
-W 交互输入密码; 也可以-w virE8jUt
测试命令建议都保存到某个test.sh
文件用作测试样例, 后期配置调试会经常用到类似查询
数据初始化
ldapadd -x -D ‘cn=root,ou=Control,dc=intra,dc=wafcloud,dc=cn’ -h 127.0.0.1 -W -f init_ldap.ldif
init_ldap.ldif 内容如下
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 dn: dc=intra,dc=wafcloud,dc=cn dc: intra objectClass: domain objectClass: dcObject dn: ou=Group,dc=intra,dc=wafcloud,dc=cn ou: Group objectClass: organizationalUnit dn: ou=People,dc=intra,dc=wafcloud,dc=cn ou: People objectClass: organizationalUnit dn: ou=Control,dc=intra,dc=wafcloud,dc=cn ou: Control objectClass: organizationalUnit dn: cn=root,ou=Control,dc=intra,dc=wafcloud,dc=cn cn: root userPassword:: e1NTSEF9cU9kVnZqMzFCcy8xUVFBYXRKcXNxbFZSWWx1ZFhzbm8K objectClass: simpleSecurityObject objectClass: organizationalRole dn: uid=test1,ou=People,dc=intra,dc=wafcloud,dc=cn uid: test uidNumber: 10001 gidNumber: 20000 sn: Test cn: Test User1 userPassword:: e1NTSEF9cWxVcS9EdWx2b0syWExPMThWUU5NbzJlSmFjb1J2RWcK loginShell: /bin/bash homeDirectory: /home/test1 objectClass: person objectClass: posixAccount objectClass: inetOrgPerson objectClass: organizationalPerson dn: uid=test2,ou=People,dc=intra,dc=wafcloud,dc=cn uid: test2 uidNumber: 10002 gidNumber: 20000 sn: Test cn: Test User2 userPassword:: e1NTSEF9cWxVcS9EdWx2b0syWExPMThWUU5NbzJlSmFjb1J2RWcK loginShell: /bin/bash homeDirectory: /home/test2 objectClass: person objectClass: posixAccount objectClass: inetOrgPerson objectClass: organizationalPerson
userPassword
字段对应的值是通过slappasswd -s xxx | base64
命令生成, 例如slappasswd -s 6WykeemU | base64
测试
1 2 ldapsearch -D 'uid=test1,ou=People,dc=intra,dc=wafcloud,dc=cn' -b 'dc=intra,dc=wafcloud,dc=cn' -h 127.0.0.1 -x -W ldapsearch -D 'uid=test2,ou=People,dc=intra,dc=wafcloud,dc=cn' -b 'dc=intra,dc=wafcloud,dc=cn' -h 127.0.0.1 -x -W
注意这里是uid=
了
ACL
细心的话肯定发现了安全问题: 普通账号可以遍历整个LDAP库的任何字段, 包括userPassword
slapd.conf增加如下配置并重启服务
1 2 3 4 5 6 7 8 9 10 11 12 access to attrs=userPassword,shadowLastChange by dn="cn=root,ou=Control,dc=intra,dc=wafcloud,dc=cn" write by anonymous auth by self write by * none access to dn.base="" by * read access to * by dn="cn=root,ou=Control,dc=intra,dc=wafcloud,dc=cn" write by users read
通过ldapsearch进行查询条件、限定条件组合测试; 线上环境ACL会是重点!
安利下Apache Directory Studio
这个客户端软件, 效果如下
Kerberos 安装 关于Kerberos认证流程, 推荐这篇文章https://www.cnblogs.com/artech/archive/2007/07/05/807492.html
安装
1 apt install krb5-kdc krb5-admin-server
krb5-kdc Kerberos key server
krb5-admin-server Kerberos master server (kadmind)
乍一看这安装包的描述信息确实很懵逼, 这种情况下一般先把包下载到本地并并解压
krb5-kdc主要包含kdb5_util, kproplog, krb5kdc
几个命令, 其中krb5kdc
是守护进程(服务)
krb5-admin-server主要包含kadmind, kadmin.local, kprop, krb5_newrealm
几个命令, 其中kadmind
是守护进程(服务)
dpkg-reconfigure krb5-config
交互式进行初步配置, 也可以直接复用下面的配置
/etc/krb5.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 [libdefaults] debug = true default_realm = INTRA.WAFCLOUD.CN [realms] INTRA.WAFCLOUD.CN = { kdc = 127.0.0.1 #admin_server = 127.0.0.1 default_domain = intra.wafcloud.cn key_stash_file = /etc/krb5.keyfile max_life = 1d 0h 0m 0s max_renewable_life = 90d 0h 0m 0s dict_file = /usr/share/dict/words } [domain_realm] .intra.wafcloud.cn = INTRA.WAFCLOUD.CN intra.wafcloud.cn = INTRA.WAFCLOUD.CN [logging] default = SYSLOG:DEBUG kdc = FILE=/var/tmp/kdc.log admin_server = FILE=/var/tmp/kadmin.log
/etc/krb5kdc/kdc.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [kdcdefaults] kdc_ports = 750,88 [realms] INTRA.WAFCLOUD.CN = { database_name = /var/lib/krb5kdc/principal admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab acl_file = /etc/krb5kdc/kadm5.acl key_stash_file = /etc/krb5kdc/stash kdc_ports = 750,88 max_life = 10h 0m 0s max_renewable_life = 7d 0h 0m 0s master_key_type = des3-hmac-sha1 #supported_enctypes = aes256-cts:normal aes128-cts:normal default_principal_flags = +preauth }
/etc/krb5kdc/kadm5.acl
1 */admin@INTRA.WAFCLOUD.CN *
初始化数据库并启动服务
1 2 kdb5_util create -s -r INTRA.WAFCLOUD.CN /etc/init.d/krb5-kdc start
kadmin.local
和kadmin
都kerberos数据库的管理程序,区别是kadmin.local
直接操作数据库, kadmin
是通过连接kadmind
kadmin
读取krb5.conf中的配置找到admin_server
添加一个test/admin
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 root@dev:~# kadmin.local Authenticating as principal test/admin@INTRA.WAFCLOUD.CN with password. kadmin.local: list_principals K/M@INTRA.WAFCLOUD.CN kadmin/admin@INTRA.WAFCLOUD.CN kadmin/changepw@INTRA.WAFCLOUD.CN kadmin/dev@INTRA.WAFCLOUD.CN kiprop/dev@INTRA.WAFCLOUD.CN krbtgt/INTRA.WAFCLOUD.CN@INTRA.WAFCLOUD.CN kadmin.local: add_principal test/admin WARNING: no policy specified for test/admin@INTRA.WAFCLOUD.CN; defaulting to no policy Enter password for principal "test/admin@INTRA.WAFCLOUD.CN": Re-enter password for principal "test/admin@INTRA.WAFCLOUD.CN": Principal "test/admin@INTRA.WAFCLOUD.CN" created. kadmin.local: list_principals K/M@INTRA.WAFCLOUD.CN kadmin/admin@INTRA.WAFCLOUD.CN kadmin/changepw@INTRA.WAFCLOUD.CN kadmin/dev@INTRA.WAFCLOUD.CN kiprop/dev@INTRA.WAFCLOUD.CN krbtgt/INTRA.WAFCLOUD.CN@INTRA.WAFCLOUD.CN test/admin@INTRA.WAFCLOUD.CN kadmin.local: change_password test/admin Enter password for principal "test/admin@INTRA.WAFCLOUD.CN": Re-enter password for principal "test/admin@INTRA.WAFCLOUD.CN": Password for "test/admin@INTRA.WAFCLOUD.CN" changed.
可以下面这种方式添加一个test1
1 kadmin.local -q 'ank -pw 123456 test1'
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 root@dev:~# kinit test/admin Password for test/admin@INTRA.WAFCLOUD.CN: kinit: Password incorrect while getting initial credentials root@dev:~# kinit test/admin Password for test/admin@INTRA.WAFCLOUD.CN: root@dev:~# klist Ticket cache: FILE:/tmp/krb5cc_0 Default principal: test/admin@INTRA.WAFCLOUD.CN Valid starting Expires Service principal 09/08/2021 09:59:52 09/09/2021 09:59:49 krbtgt/INTRA.WAFCLOUD.CN@INTRA.WAFCLOUD.CN
OpenLDAP + Kerberos 前面分别介绍了OpenLDAP
和Kerberos
测试环境下的精简部署方式, 明显认证还没有融合在一起
这时我们进行个简单的怎么融合
的思维发散?
共用某字段, 比如userPassword
有某个起到转发
的桥梁
, 把其中的一个认证服务转发给另一个服务
通过saslauthd
把来自LDAP的认证转发给kerberos
saslauthd
安装不再敖述, 变更其配置文件/etc/default/saslauthd
中的MECHANISMS="kerberos5"
重启服务即可
测试
1 root@dev:~# testsaslauthd -u test1 -p 123456
这时肯定会报错… saslauthd
只是配置了Kerberos, 去哪儿找呢? tcpdump -i any -n -p port 53
也会发现DNS解析请求
建议自建一个DNS服务器, 其次绑定hosts
; 下面是DNS的测试配置
1 2 3 4 5 6 7 8 9 10 11 $ORIGIN _tcp.intra.wafcloud.cn. _kerberos-adm IN SRV 0 0 749 kdc01.intra.wafcloud.cn. $ORIGIN _udp.intra.wafcloud.cn. _kerberos IN SRV 0 0 88 kdc01.intra.wafcloud.cn. _kerberos-master IN SRV 0 0 88 kdc01.intra.wafcloud.cn. _kpasswd IN SRV 0 0 464 kdc01.intra.wafcloud.cn. $ORIGIN intra.wafcloud.cn. kdc01 A 192.168.3.108 kerberos CNAME kdc01
更多详情可参考https://web.mit.edu/kerberos/krb5-1.4/krb5-1.4.1/doc/krb5-admin/Hostnames-for-KDCs.html
继续测试, auth.log
大概率会有如下类似日志
1 2 3 saslauthd[13500]: auth_krb5: krb5_ kt_read_ service_key(): Key table file '/etc/krb5.keytab' not found (2) saslauthd[13503]: auth_krb5: krb5_ kt_read_ service_key(): No key table entry found for host/dev@INTRA.WAFCLOUD.CN (-1765328203) saslauthd[13503]: auth_krb5: krb5_ kt_read_ service_key(): No key table entry found for host/host@INTRA.WAFCLOUD.CN (-1765328203)
解决
1 2 3 4 kadmin.local -q "ank -clearpolicy -randkey host/localhost" kadmin.local -q "ank -clearpolicy -randkey host/dev" ktadd host/localhost ktadd host/dev
直到测试OK, 代表saslauthd
和kerberos
之间打通
1 2 root@dev:~# testsaslauthd -u test2 -p 123456 0: OK "Success."
下一步就是OpenLDAP
和saslauthd
打通
OpenLDAP
主要是改动两个地方
认证改为saslauthd
用户属性中的userPassword改为{SASL}形式
认证改为saslauthd
, /etc/ldap/sasl2/slapd.conf
1 2 pwcheck_method: saslauthd saslauthd_path: /var/run/saslauthd/mux
change_test1_pass.ldif
userPassword生成方式 echo -n "{SASL}test1@INTRA.WAFCLOUD.CN" | base64
1 2 3 4 dn: uid=test1,ou=People,dc=intra,dc=wafcloud,dc=cn changetype: modify replace: userPassword userPassword:: e1NBU0x9dGVzdDFASU5UUkEuV0FGQ0xPVUQuQ04=
更改test1密码为{SASL}验证方式
1 ldapadd -x -D 'cn=root,ou=Control,dc=intra,dc=wafcloud,dc=cn' -h 127.0.0.1 -W -f change_test1_ pass.ldif
通过kadmin.local更改test1密码测试并逐步验证
Kerberos ---> Saslauthd ---> OpenLDAP
1 2 3 kinit test1 testsaslauthd -u test1 -p 112233 ldapwhoami -D 'uid=test1,ou=People,dc=intra,dc=wafcloud,dc=cn' -h 127.0.0.1 -x -w 112233 -vvv
总结概要
OpenLDAP账户管理, Kerberos认证
Saslauthd 起到了中间桥梁
的作用
善于通过日志解决问题, 必要的时候调整日志级别记录更多信息/var/tmp/kdc.log
/var/tmp/kadmin.log
/var/log/syslog
/var/log/auth.log
krb5kdc[10706]: Couldn’t open log file /var/log/krb5/kdc.log: Read-only file system
1 2 3 参考<https: //bugs.launchpad.net /ubuntu /+source /freeipa /+bug /1874915 > 日志文件需在特定目录下, 应该是个Bug
其它 此篇配置远未达到线上环境配置要求! 比如安全、扩展、维护等
后面一步步优化, 比如细心的同学发现slapd.conf
中的include /etc/ldap/schema/kerberos.schema
没用到啊