{"value":"### **1. 写作背景**\n写作本系列文章的背景是我们要在大数据平台/企业数据湖场景下给出中心化的用户身份认证方案。此前,我们实现过 Windows AD + Kerberos 的集成方案,由于 Windows AD 是 LDAP 和 Kerberos 的双重实现,这种天然优势使得 Windows AD 可以实现真正意义上的(大数据集群的)Kerberos 账号与企业用户账号的统一管理。当我们想在 OpenLDAP + Kerberos 上实现同样的目标时,发现这一领域的知识与方案琐碎而凌乱,缺少统一连贯,脉络清晰的讲解,在经过大量技术调研和系统梳理后,我们特别撰写了本系列文章,希望可以借此将这一话题全面彻底地阐述清楚。本系列由三篇文章组成,将沿着“如何集成 OpenLDAP 与 Kerberos 实现统一认证管理”这一主线推进,在实现过程中会详细介绍使用到的技术和原理并给出完备的执行脚本用于实际环境的搭建。我们假设读者已经具备 OpenLDAP 和 Kerberos 的基本知识,不再对两者进行单独介绍。\n\n### **2. 既定目标**\n系统安全有两个重要领域:身份认证和权限管理,前者要解决“系统里有没有这个人?”的问题,后者要解决“他有没有权限执行某项操作?”的问题。在大数据领域,权限管理一般由 Apache Ranger 负责,这是一个与众多大数据组件均有集成的权限管理工具(由于众所周知的原因,另一款工具 Sentry 的前景已经非常暗淡),但是在身份认证方面,情况则有一些复杂:一方面,很多企业都建立了以 Windows AD 或 OpenLDAP 为代表的中心化账号管理基础设施,各 IT 系统通常都需要与之对接,以便实现统一的身份认证,大数据平台/数据湖作为企业IT生态的一部分,也不例外。但是,在大数据生态圈里,最被广泛支持的认证机制其实是 Kerberos,虽然有部分组件(如HiverServer2,Hue等)也支持 LDAP,但是普及程度远不如 Kerberos,如果仅针对大数据平台/数据湖建立一套统一认证机制的话,Kerberos 几乎是唯一的选择。于是,一个很直接的问题就摆在了面前:如何将 OpenLDAP 与 Kerberos 对接,把大数据平台/数据湖的身份认证统一到企业的中心化认证服务上?\n\n下图描绘的就是集成 OpenLDAP 与 Kerberos 后,大数据集群/企业数据湖进行用户身份认证和权限控制的全景视图:\n\n![image.png](https://dev-media.amazoncloud.cn/86fedc861ed1434b89b39778d981f919_image.png)\n\n::: hljs-center\n\n图1: 大数据领域的场景下用户身份认证与权限控制全景视图\n\n:::\n\n在这个生态系统架构中,OpenLDAP 作为企业全局的用户认证中心独立于大数据集群存在;Kerberos KDC 作为大数据集群的身份认证中心,既可以是集群专属的,也可以是一个独立于集群的全局 KDC(如果存在的话),管理员会为用户在 Kerberos 和 OpenLDAP 上分别创建账号,然后通过一系列技术将两套认证系统的账号打通;大数据集群的各个节点通过 SSSD 与 OpenLDAP 对接后,用户可以凭借 LDAP 账号(准确地说是账号中的用户名)登录集群的各个节点。在 Kerberos 和 OpenLDAP 账号打通的前提下,用户还可以使用同一账号完成Kerberos认证,进而可以提交作业或访问大数据相关服务;Ranger 负责集群用户的权限管理,其账号数据同样来自于 OpenLDAP。这样,OpenLDAP、Kerberos 和 Ranger 三方的用户数据一致,就可以实现统一的用户认证和权限管理了。\n\n在展开介绍 OpenLDAP 与 Kerberos 的集成方案前,需要读者清楚提前接受这样一个事实:OpenLDAP 与 Kerberos 作为两套独立的认证系统,是无法做到绝对意义上的统一的,这一点随着后续的深入介绍,读者应该会有所体会。但是在实际应用中,由于绝大多数以 OpenLDAP 和 Kerberos 作为用户认证源的外围系统通常只验证或同步两系统账号中的“用户名”部分,即 OpenLDAP 账号中的 uid 部分和 Kerberos 账号中的 Principal Name((@前面的))部分,这为统一两个认证系统的账号创造了可利用的外部条件,只要我们能将两套账号的用户名部分和密码统一在一起,就可以达到“使用效果”上的账号统一,这是目前各类技术方案之所以可行的一个重要支点。\n\n下面就是本系列文章给出的集成 OpenLDAP 与 Kerberos 的整体方案,也是接下来三篇文章的技术路线图:\n\n![image.png](https://dev-media.amazoncloud.cn/fa9600312c434272b472dfa3e1aae845_image.png)\n\n::: hljs-center\n\n图2: OpenLDAP 与 Kerberos 集成方案\n\n:::\n\n这个方案涉及 OpenLDAP 和 Kerberos KDC 两个身份认证源(两台服务器);Linux 主机代表大数据集群的各个节点,由于其需要与 OpenLDAP 和 Kerberos KDC 进行通信,所以每一个 Linux 主机同时也是 OpenLDAP 和 Kerberos KDC 的客户端(客户端的安装会在后续章节中介绍);参与人员有管理员和用户。方案整体的工作机制如下:\n\n①:管理员会为用户创建 Kerberos 和 OpenLDAP 两个配套账号,并保证两个账号中的用户名部分相同。用户并不需要区分和记忆这两个账号,实际上,管理员只需要将两账号中相同的用户名部分和一个密码发送给用户即可,作为用户,只需要知道自己的用户名和密码即可(至于在登录过程中走的是 OpenLDAP 认证还是 Kerberos 认证,对用户来说其实是透明的); ②:将 Kerberos 的后台数据库迁移到 OpenLDAP 上,并将用户在这两个系统上的配套账号统一存储为一条记录(LDAP Entry); ③:配置并启用 SSSD,允许 Linux 主机(大数据集群各个节点)通过 SSSD 连接到 OpenLDAP 进行账号认证; ④:完成上述操作后,用户就可以使用自己的用户名和密码以常规的 SSH 方式登录 Linux 主机(大数据集群各个节点)了,此时,用户的身份认证链路是:用户 -> Linux主机 -> OpenLDAP; ⑤:配置 SASL/GSSAPI,赋予 Kerberos 账号登录 OpenLDAP 的能力; ⑥:配置 OpenLDAP 的账号映射规则,将 Kerberos 账号映射到目标 OpenLDAP 账号上,实现“账号(用户名)统一”; ⑦:配置 saslauthd,让 OpenLDAP 委托 Kerberos 验证密码,实现“密码统一”; ⑧:完成上述操作后,用户就可以使用自己的用户名和密码以 GSSAPI 方式 SSH 登录 Linux 主机(大数据集群各个节点)了,在登录的同时还将自动完成 Kerberos 认证,为提交大数据作业铺平了道路,此时,用户的身份认证链路是:用户 -> Linux主机 -> Kerberos KDC;\n\n我们将在第一篇文章完成第①、②两步操作;在第二篇文章完成第③、④步操作;剩余的第⑤、⑥、⑦、⑧四步操作将在第三篇文章中完成。其他未标记数字的操作均为常规机制,无需额外配置。\n\n### **3. 环境说明**\n为了更好地说明和演示,我们将在一套真实环境上执行各项操作,这套环境将贯穿整个系列文章,以下是实操环境的各项信息:\n\n※ 提示:以下环境信息(主机名,账号等)将会频繁出现在脚本中,如果读者要进行实操,建议将文章拷贝至文本编辑器,然后根据自己的实际环境,统一查找并替换相关的信息项。其中,只有 OpenLDAP 和 Kerberos KDC 的主机名是每次安装必须替换的项,其他项可视需求自行调整。\n\n- 主机信息\n\n![image.png](https://dev-media.amazoncloud.cn/0dffb136ff784f70b6a7756afad97ed0_image.png)\n\n大数据集群通常由多个节点组成,由于后续操作没有需要显示配置或使用节点主机名的地方,所以在此省略。但是读者需要注意的是:后续文章中凡标记需在[ 大数据集群各个节点 ] 上执行的操作,均需逐一登录集群各个节点重复执行相关操作。此外,从 OpenLDAP 和 Kerberos KDC 的视角看,大数据集群的每一个节点同时也是一个 OpenLDAP 和 Kerberos 的客户端。\n\n※ 备注:本系列文章的所有操作均在 Amazon Linux 2上测试通过,原则上同样适用于CentOS/RHEL 7.0+\n\n- OpenLDAP 环境\n\n![image.png](https://dev-media.amazoncloud.cn/68583b4d33b54c5ebf8384092e3948de_image.png)\n\n\n- OpenLDAP 账号\n\n![image.png](https://dev-media.amazoncloud.cn/d5e25eef3a914182a69a5dd3d7a0aa30_image.png)\n\n- OpenLDAP OU 与 Container DN\n\n![image.png](https://dev-media.amazoncloud.cn/d239219344584607b9afec8164173cb3_image.png)\n\n- Kerbersos 环境\n\n![image.png](https://dev-media.amazoncloud.cn/0911031a34be41a0aa9afb6d334fcc3a_image.png)\n\n- Kerberos 账号\n\n![image.png](https://dev-media.amazoncloud.cn/9c503e8e42f342388ea1abbdf2cf68e0_image.png)\n\n### **4. 安装操作**\n※ 提示:本文所有命令均以 root 用户身份执行,不再显式使用 sudo 修饰。\n\n#### **4.1 安装 OpenLDAP**\n##### **4.1.1 安装软件包**\n※ 提示:本节操作在 [ OpenLDAP ] 上执行\n\n登录准备安装 OpenLDAP 的主机,执行如下安装命令:\n\n```\\nyum -y install openldap openldap-clients openldap-servers compat-openldap openldap-devel migrationtools\\n```\n\n##### **4.1.2 启动服务**\n※ 提示:本节操作在 [ OpenLDAP ] 上执行\n\n安装完毕后,需要启动 OpenLDAP,OpenLDAP Server 端的守护进程是“slapd”,使用如下命令启动:\n```\\nsystemctl enable slapd\\nsystemctl start slapd\\nsystemctl status slapd\\n```\n##### **4.1.3 初始化**\n※ 提示:本节操作在 [ OpenLDAP ] 上执行\n\n启动 OpenLDAP 服务后,需要进行必要的初始化工作,包括配置 Base CN、Root DN,导入常用 Schema 等等,命令如下:\n\n```\\n# Base CN、Root DN等基础配置\\ncat << EOF | ldapadd -Y EXTERNAL -H ldapi:///\\ndn: olcDatabase={1}monitor,cn=config\\nchangetype: modify\\nreplace: olcAccess\\nolcAccess: {0}to * by dn.base=\\"gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth\\" read by dn.base=\\"cn=admin,dc=example,dc=com\\" read by * none\\n\\ndn: olcDatabase={2}hdb,cn=config\\nchangetype: modify\\nadd: olcRootPW\\nolcRootPW: \$(slappasswd -s Admin1234!)\\n-\\nreplace: olcRootDN\\nolcRootDN: cn=admin,dc=example,dc=com\\n-\\nreplace: olcSuffix\\nolcSuffix: dc=example,dc=com\\n-\\nadd: olcAccess\\nolcAccess: {0}to attrs=userPassword by self write by dn.base=\\"cn=admin,dc=example,dc=com\\" write by anonymous auth by * none\\nolcAccess: {1}to * by dn.base=\\"cn=admin,dc=example,dc=com\\" write by self write by * read\\nEOF\\n\\n# 导入常用schema\\nldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/core.ldif\\nldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif\\nldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif\\nldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif\\n```\n这是我们初次对 OpenLDAP 进行配置,需要说明一点:目前网络上流传的不少关于 OpenLDAP 的文章都是让读者去修改 slapd.conf 等配置文件,这种做法已不再推荐,自 OpenLDAP 2.4之后,所有的配置都已统一为使用 ldif 文件,也就是我们上面采用的做法。\n\n##### **4.1.4 禁止匿名访问**\n※ 提示:本节操作在 [ OpenLDAP ] 上执行\n\nOpenLDAP 默认是允许匿名访问的,可以使用如下命令禁用:\n\n```\\ncat << EOF | ldapmodify -Y EXTERNAL -H ldapi:///\\ndn: cn=config\\nchangetype: modify\\nadd: olcDisallows\\nolcDisallows: bind_anon\\n\\ndn: cn=config\\nchangetype: modify\\nadd: olcRequires\\nolcRequires: authc\\n\\ndn: olcDatabase={-1}frontend,cn=config\\nchangetype: modify\\nadd: olcRequires\\nolcRequires: authc\\nEOF\\n```\n##### **4.1.5 创建 O 和 OU**\n\n※ 提示:本节操作在 [ OpenLDAP ] 上执行\n\n我们需要先创建example这个organization((简称O),然后在其下面创建两个OU:```ou=users,dc=example,dc=com```用于存放用户账号;```ou=services,dc=example,dc=com```用户存放服务账号,创建命令如下:\n\n```\\ncat << EOF | ldapadd -D \\"cn=admin,dc=example,dc=com\\" -w Admin1234!\\ndn: dc=example,dc=com\\nobjectClass: dcObject\\nobjectClass: organization\\ndc: example\\no: example\\n\\ndn: ou=users,dc=example,dc=com\\nobjectclass: top\\nobjectclass: organizationalUnit\\nou: users\\ndescription: OU for user accounts\\n\\ndn: ou=services,dc=example,dc=com\\nobjectclass: top\\nobjectclass: organizationalUnit\\nou: services\\ndescription: OU for service accounts\\nEOF\\n```\n至于环境介绍中的```cn=kerberos,dc=example,dc=com```这个 Container DN,不需要显式创建,后续操作中将由命令行工具自动创建。\n\n#### **4.2 迁移Kerberos数据库**\n本系列文章的预设场景是:在 Kerberos 集群已存在的前提下,将 KDC 的后台数据库迁移到 OpenLDAP 上。这一预设场景符合绝大多数用户和数据团队面临的现状,因为主流的 Hadoop 发行包(如CDH)以及云平台上的大数据产品(如 Amazon 的EMR)都已内置了 Kerberos 功能,这些产品都能自动安装 Kerberos 并将大数据集群纳入到 Kerberos 的管控中,采用这种方式安装 Kerberos 是比较明智的。所以,本文会跳过Kerberos 的安装环节,直接从迁移现有 Kerberos 数据库开始介绍。\n\n##### **4.2.1 导入 Kerberos Schema**\n※ 提示:本节操作在 [ OpenLDAP ] 上执行\n\n登录 OpenLDAP 服务器,使用如下命令将 Kerberos 的 Schema 文件下载到本地\n\n```\\nwget https://raw.githubusercontent.com/krb5/krb5/master/src/plugins/kdb/ldap/libkdb_ldap/kerberos.openldap.ldif -O /etc/openldap/schema/kerberos.ldif\\n```\n然后,导入该Schema文件:\n\n```\\nldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/kerberos.ldif\\n```\n##### **4.2.2 创建 Kerberos 在 OpenLDAP 上的服务账号**\n\n※ 提示:本节操作在 [ OpenLDAP ] 上执行\n\n在配置/var/kerberos/krb5kdc/kdc.conf时,有这样两个配置项:\n\n- ldap_kdc_dn:给 krb5kdc 服务使用的 LDAP 账号\n- ldap_kadmind_dn :给 kadmin 服务使用的 LDAP 的账号\n\n配置的这两个账号必须要具备一定的读写权限,因为 Kerberos 要使用这两个账号在 LDAP 上对 Principal 数据进行增删查改操作。针对这两个 LDAP 账号,我们有两种选择:\n\n- 新建专职账号\n- 使用 LDAP 的 admin 账号\n\n如果只是单纯的将 OpenLDAP 作为 Kerberos 后台数据库使用,我们推荐使用专职账号,因为默认情况下 Kerberos 的所有账号都会放置在ldap_kerberos_container_dn定义的子树下面,此时使用专职账号可以为其配置精准的权限管控范围。\n\n但是,由于本系列文章的最终目标是要实现 Kerberos 和 OpenLDAP 的账号统一,在后续的第三篇文章中我们会将一个 Kerberos 账号映射为一个普通的 LDAP 账号,那时,大多数的 Kerberos 账号将不在 ldap_kerberos_container_dn 定义的子树下面,两个专职账号的权限范围就会难以定义,因此,我们选择直接以 LDAP 的 admin 账号作为 Kerberos 的服务账号。\n\n##### **4.2.3 添加索引**\n※ 提示:本节操作在 [ OpenLDAP ] 上执行\n\n为了迁移后能在 LDAP 中快速检索到 Kerberos 账号,建议给 krbPrincipalName 和 krbPwdPolicyReference 两个属性添加索引,具体操作如下命令:\n\n```\\ncat << EOF | ldapmodify -Y EXTERNAL -H ldapi:/// \\ndn: olcDatabase={2}hdb,cn=config\\nchangetype: modify\\nadd: olcDbIndex\\nolcDbIndex: krbPrincipalName eq,pres,sub\\n\\ndn: olcDatabase={2}hdb,cn=config\\nchangetype: modify\\nadd: olcDbIndex\\nolcDbIndex: krbPwdPolicyReference eq\\nEOF\\n```\n##### **4.2.4 备份现有Kerberos数据**\n\n※ 提示:本节操作在 [ Kerberos KDC ] 上执行\n\n对 Kerberos 进行配置前,须提前备份好现有 Kerberos 数据,以便在新的 OpenLDAP 数据库创建完成后可以将备份数据恢复到 OpenLDAP 上。备份前,建议先打印一份 Kerberos 账号列表并保存到文件中,以便在后续恢复数据时有一个参照。具体操作为登录 Kerberos KDC,执行命令:\n\n```\\nkadmin.local -q \\"listprincs\\" | tee principals.txt\\n```\n然后,执行正式的备份操作:\n\n```\\nkdb5_util dump kdc-db.dump\\n\\n```\n该命令会在当前目录生成 kdc-db.dump 和 kdc-db.dump.dump_ok 两个文件,后续4.2.10一节将会使用这两个文件恢复数据。\n\n##### **4.2.5 安装 ```krb5-server-ldap```**\n※ 提示:本节操作在 [ Kerberos KDC ] 上执行\n\n由于后续操作需要使用 krb5-server-ldap 这个软件包,需要先行安装:\n\n```\\nyum -y install krb5-server-ldap\\n```\n\n##### **4.2.6 创建密码文件**\n※ 提示:本节操作在 [ Kerberos KDC ] 上执行\n\n继续在 KDC 上使用如下命令生成 admin 的 password 文件,该文件会在配置 kdc.conf 时使用到:\n\n```\\nkdb5_ldap_util stashsrvpw -f /etc/openldap-admin.keyfile \\"cn=admin,dc=example,dc=com\\"\\n```\n\n命令执行后会要求输入账号密码,验证完毕后会在指定位置上生成密码文件。\n\n注意:使用 kdb5_ldap_util 这个命令需要安装 krb5-server-ldap,而 krb5-server-ldap 又依赖 krb5-server,所以: krb5-server-ldap 应安装在 Kerberos KDC 上,这个操作也是在 KDC 上执行的。\n\n##### **4.2.7 修改 KDC 配置**\n※ 提示:本节操作在 [ Kerberos KDC ] 上执行\n\n这是配置 KDC 改用 OpenLDAP 作为后台数据库的关键一步,涉及 OpenLDAP 的各种信息都要配置到 kdc.conf 中。具体操作是打开/var/kerberos/krb5kdc/kdc.conf文件,在 realm 中将原有的文件数据库配置:“database_name = /var/kerberos/krb5kdc/principal”注释掉,同时添加“database_module = openldap_ldapconf”,然后添加“[dbmodules]”模块,提供 OpenLDAP 的若干配置,具体内容如下:\n\n```\\n[realms]\\n CN-NORTH-1.COMPUTE.INTERNAL = {\\n ...\\n # database_name = /var/kerberos/krb5kdc/principal\\n ...\\n database_module = openldap_ldapconf\\n }\\n\\n[dbmodules]\\n openldap_ldapconf = {\\n db_library = kldap\\n ldap_servers = ldap://ip-10-0-0-70.cn-north-1.compute.internal\\n ldap_kerberos_container_dn = cn=kerberos,dc=example,dc=com\\n ldap_kdc_dn = cn=admin,dc=example,dc=com\\n ldap_kadmind_dn = cn=admin,dc=example,dc=com\\n ldap_service_password_file = /etc/openldap-admin.keyfile\\n ldap_conns_per_server = 5\\n }\\n```\n\n关于上述配置,有如下几项需要特别解释一下:\n\n- ldap_kerberos_container_dn: Kerberos 会将账号集中存放该配置项指定的子树下面,这个 DN 不需要提前创建,Kerberos 在初始化数据库时会自动创建它;\n- ldap_kdc_dn: Kerberos KDC的服务账号,如前所述,本文不会创建专职账号而是使用 LDAP 的 admin 账号;\n- ldap_kadmind_dn : Kerberos 的管理员账号,如前所述,本文不会创建专职账号而是使用 LDAP 的 admin 账号;\n- ldap_service_password_file:用于存放 ldap_kdc_dn 和 ldap_kadmind_dn(即LDAP的admin)密码的 stash 文件,已在上一节创建完成\n\n上述配置可以通过以下脚本直接完成:\n\n```\\ncp -f /var/kerberos/krb5kdc/kdc.conf /var/kerberos/krb5kdc/kdc.conf.\$(date +%s)\\n# 找到database_name这一行,将其注释掉;\\n# 并在下一行插入:database_module = openldap_ldapconf\\nsed -i 's/\\\\(^\\\\s*\\\\)database_name\\\\(.*\\\\)/\\\\1#database_name\\\\2\\\\n\\\\1database_module = openldap_ldapconf/g' /var/kerberos/krb5kdc/kdc.conf\\n# 在文件尾部追加[dbmodules]部分\\ntee -a /var/kerberos/krb5kdc/kdc.conf <<EOF\\n\\n[dbmodules]\\n openldap_ldapconf = {\\n db_library = kldap\\n ldap_servers = ldap://ip-10-0-0-70.cn-north-1.compute.internal\\n ldap_kerberos_container_dn = cn=kerberos,dc=example,dc=com\\n ldap_kdc_dn = cn=admin,dc=example,dc=com\\n ldap_kadmind_dn = cn=admin,dc=example,dc=com\\n ldap_service_password_file = /etc/openldap-admin.keyfile\\n ldap_conns_per_server = 5\\n }\\nEOF\\n```\n\n##### **4.2.8 创建数据库**\n※ 提示:本节操作在 [ Kerberos KDC ] 上执行\n\n接下来就要在 OpenLDAP 上创建 Kerberos 数据库了,命令如下:\n\n```\\nkdb5_ldap_util -D cn=admin,dc=example,dc=com -w Admin1234! -H ldap://ip-10-0-0-70.cn-north-1.compute.internal create -r CN-NORTH-1.COMPUTE.INTERNAL -subtrees dc=example,dc=com\\n```\n\n执行时会要求输入“KDC database master key”,统一输入默认密码:```Admin1234!```。该命令和安装Kerberos时执行的建库操作```kdb5_util create -r <YOUR-REALM> -s```在性质上是一样的,只是后者创建的数据库是以文件((/var/kerberos/krb5kdc/principal))形式存储在 KDC 上,而这条命令会将数据库建到OpenLDAP上。执行成功后可登录 OpenLDAP 查看结果,此时```cn=kerberos,dc=example,dc=com```会被自动创建出来,并且下面还会有若干Kerberos的初始账号数据。\n\n对于4.2.7,4.2.8和4.2.9三节的执行顺序要注意一下,本节4.2.8在执行时需要读取/var/kerberos/krb5kdc/kdc.conf中与OpenLDAP相关的配置信息才能在指定的 OpenLDAP 上创建数据库,所以要先完成4.2.7节kdc.conf的配置,然后再执行本节的建库操作,最后重启 Kerberos KDC 让新库配置生效,这个逻辑关系和应用程序迁移数据类似,一般都是:先修改数据库配置文件,然后创建数据库,最后重启应用让配置生效。\n\n##### **4.2.9 重启 Kerberos KDC**\n※ 提示:本节操作在 [ Kerberos KDC ] 上执行\n\n```\\nsystemctl restart krb5kdc kadmin\\nsystemctl status krb5kdc kadmin\\n```\n\n##### **4.2.10 导入原有备份数据**\n※ 提示:本节操作在 [ Kerberos KDC ] 上执行\n\n呼应“4.2.4 备份 Kerberos 数据库”一节,完成数据库迁移后,现在需要将此前备份的 Kerberos 数据恢复到新的 OpenLDAP 数据库上了,命令如下:\n\n```\\nkdb5_util load -update kdc-db.dump\\n```\n\n命令完成后,再次查看一下 OpenLDAP 的```cn=kerberos,dc=example,dc=com```子树,此前大数据集群的若干服务和主机的principal记录应该都已经恢复到 OpenLDAP 上了:\n\n![image.png](https://dev-media.amazoncloud.cn/2b2164d148e7467bb7f039ec7f2a0d89_image.png)\n\n图3: 迁移完成后 OpenLDAP 上的 Kerberos 数据\n\n##### **4.2.11 使用```addprinc -x dn=...```创建账号**\n完成上述操作后,整合 OpenLDAP 作为 Kerberos 后台数据库的配置工作就全部结束了,现在就可以将一个用户的 Kerberos 账号与 OpenLDAP 账号统一存储为一条记录(LDAP Entry))了。以此前提到的用于测试的 OpenLDAP 账号```uid=user1,ou=users,dc=example,dc=com```和 Kerberos 账号```user1@CN-NORTH-1.COMPUTE.INTERNAL```为例,假定它们属于同一用户 user1,管理员可以通过以下方式为 user1 创建这两个账号:\n\n※ 提示:以下操作在 [ OpenLDAP ] 上执行\n\n登录 OpenLDAP 服务器,通过以下命令创建 OpenLDAP 账号 ```uid=user1,ou=users,dc=example,dc=com```\n\n```\\ncat << EOF | ldapadd -D \\"cn=admin,dc=example,dc=com\\" -w Admin1234!\\ndn: uid=user1,ou=users,dc=example,dc=com\\nobjectClass: posixAccount\\nobjectClass: top\\nobjectClass: inetOrgPerson\\nuid: user1\\ndisplayName: user1\\nsn: user1\\nhomeDirectory: /home/user1\\ncn: user1\\nuidNumber: \$((1000+\$RANDOM%9000))\\ngidNumber: 100\\nuserPassword: Admin1234!\\nEOF\\n```\n\n※ 提示:以下操作在 [ Kerberos KDC ] 上执行\n\n然后登录 KDC,通过以下命令创建 Kerberos 账号```user1@CN-NORTH-1.COMPUTE.INTERNAL```(提示输入密码时请使用统一默认密码:```Admin1234!```):\n\n```\\nkadmin.local -q \\"addprinc -x dn=uid=user1,ou=users,dc=example,dc=com user1@CN-NORTH-1.COMPUTE.INTERNAL\\"\\n```\n\n命令执行后,登录 OpenLDAP 查看一下 user1 的用户数据:\n\n![image.png](https://dev-media.amazoncloud.cn/e515e74981e742a8b08898ad3d67ecd2_image.png)\n\n::: hljs-center\n\n图4: user1 的用户数据\n\n:::\n\n\n从显示的账号信息可以清楚地看到:Kerberos 账号的相关属性(如krbPrincipalName等)全部添加到了```uid=user1,ou=users,dc=example,dc=com```这条记录(entry))上,也就是说:LDAP 账号和 Kerberos 账号的信息共同存储在一条记录上。\n\n要特别注意上述 addprinc 命令中的```-x dn=uid=user1,ou=users,dc=example,dc=com```部分,参数-x的作用是显式控制Principal在LDAP上的存放位置,正是通过这个参数,我们才能将```user1@CN-NORTH-1.COMPUTE.INTERNAL```这个Principal创建到```uid=user1,ou=users,dc=example,dc=com```这个 DN 上,也就是将两个系统账号建到一条记录上。\n\n至此,本系列文章的第一阶段目标:“实现 OpenLDAP 与 Kerberos 用户数据统一存储”已全部完成,但是,这离我们最终的集成目标还差得很远,因为,虽然在数据库层面上我们让一个用户的 Kerberos 账号和OpenLDAP 账号存储为了一条记录(一个 LDAP Entry)),但是在 Kerberos 和 OpenLDAP 两个系统中,它们依然是两个独立的账号,彼此没有任何关系,也不可能互相识别出对方。一个更让人沮丧的事实是:整合 OpenLDAP 作为 Kerberos 后台数据库并不是一个“必选项”,即使跳过本文4.2节中的绝大多数操作,也不会影响后续的集成工作。统一存储的主要收益是给统一维护用户数据创造了便利,之于 Kerberos 和 OpenLDAP 的集成,并没有多少实质性的影响,真正的深度集成要到本系列的最后一篇文章才能展开。\n\n### **附录:常见错误**\n在使用```addprinc -x ...```创建 principal 时报错:\n\n```\\nadd_principal: DN is out of the realm subtree while creating \\"xxx\\"\\n```\n\n原因:-x参数配置的 DN 不在创建 realm 时指定的 subtree 下面,也就是不在“kdb5_ldap_util … create … -subtrees xxxx”命令中指定的 subtrees 下面.\n\n解决方法:调整DN到指定的 subtrees 下面,或调整 subtrees 的配置。提示:subtrees 支持以冒号分隔的多个 subtrees 列表。\n\n### **关联阅读:**\n[基于 OpenLDAP 与 Kerberos 的Amazon EMR 身份认证方案(一):整合后台数据库](https://aws.amazon.com/cn/blogs/china/amazon-emr-authentication-scheme-based-on-openldap-and-kerberos-i-integrating-background-databases/)\n\n[基于 OpenLDAP 与 Kerberos 的Amazon EMR 身份认证方案(二):基于 SSSD 同步 LDAP 账号](https://aws.amazon.com/cn/blogs/china/amazon-emr-authentication-scheme-based-on-openldap-and-kerberos-ii-synchronize-ldap-accounts-based-on-sssd/)\n\n[基于 OpenLDAP 与 Kerberos 的Amazon EMR 身份认证方案(三):基于 SASL/GSSAPI 深度集成](https://aws.amazon.com/cn/blogs/china/amazon-emr-authentication-scheme-based-on-openldap-and-kerberos-iii-deep-integration-based-on-sasl-gssapi/)\n\n### **参考资料**\nOpenLDAP 官方文档 [https://www.openldap.org/doc/admin24/](https://www.openldap.org/doc/admin24/)\n\nKerberos官方文档(OpenLDAP部分) [http://web.mit.edu/kerberos/krb5-latest/doc/admin/database.html#operations-on-the-ldap-database](http://web.mit.edu/kerberos/krb5-latest/doc/admin/database.html#operations-on-the-ldap-database)\n\nKerberos使用 OpenLDAP 作为 backend [https://mp.weixin.qq.com/s/6Hk6qwCDCoXQ2e8km5jeXw](https://mp.weixin.qq.com/s/6Hk6qwCDCoXQ2e8km5jeXw)\n\n使用 LDAP + Kerberos 实现集中用户认证及授权系统 [https://blog.csdn.net/cheng_fangang/article/details/40143261](https://blog.csdn.net/cheng_fangang/article/details/40143261)\n\n#### **本篇作者**\n**Laurence**\nAmazon 资深解决方案架构师,多年系统开发与架构经验,对大数据、云计算、企业级应用、SaaS、分布式存储和领域驱动设计有丰富的实践经验,著有 《大数据平台架构与原型实现:数据中台建设实战》一书。","render":"<h3><a id=\\"1__0\\"></a><strong>1. 写作背景</strong></h3>\\n<p>写作本系列文章的背景是我们要在大数据平台/企业数据湖场景下给出中心化的用户身份认证方案。此前,我们实现过 Windows AD + Kerberos 的集成方案,由于 Windows AD 是 LDAP 和 Kerberos 的双重实现,这种天然优势使得 Windows AD 可以实现真正意义上的(大数据集群的)Kerberos 账号与企业用户账号的统一管理。当我们想在 OpenLDAP + Kerberos 上实现同样的目标时,发现这一领域的知识与方案琐碎而凌乱,缺少统一连贯,脉络清晰的讲解,在经过大量技术调研和系统梳理后,我们特别撰写了本系列文章,希望可以借此将这一话题全面彻底地阐述清楚。本系列由三篇文章组成,将沿着“如何集成 OpenLDAP 与 Kerberos 实现统一认证管理”这一主线推进,在实现过程中会详细介绍使用到的技术和原理并给出完备的执行脚本用于实际环境的搭建。我们假设读者已经具备 OpenLDAP 和 Kerberos 的基本知识,不再对两者进行单独介绍。</p>\n<h3><a id=\\"2__3\\"></a><strong>2. 既定目标</strong></h3>\\n<p>系统安全有两个重要领域:身份认证和权限管理,前者要解决“系统里有没有这个人?”的问题,后者要解决“他有没有权限执行某项操作?”的问题。在大数据领域,权限管理一般由 Apache Ranger 负责,这是一个与众多大数据组件均有集成的权限管理工具(由于众所周知的原因,另一款工具 Sentry 的前景已经非常暗淡),但是在身份认证方面,情况则有一些复杂:一方面,很多企业都建立了以 Windows AD 或 OpenLDAP 为代表的中心化账号管理基础设施,各 IT 系统通常都需要与之对接,以便实现统一的身份认证,大数据平台/数据湖作为企业IT生态的一部分,也不例外。但是,在大数据生态圈里,最被广泛支持的认证机制其实是 Kerberos,虽然有部分组件(如HiverServer2,Hue等)也支持 LDAP,但是普及程度远不如 Kerberos,如果仅针对大数据平台/数据湖建立一套统一认证机制的话,Kerberos 几乎是唯一的选择。于是,一个很直接的问题就摆在了面前:如何将 OpenLDAP 与 Kerberos 对接,把大数据平台/数据湖的身份认证统一到企业的中心化认证服务上?</p>\n<p>下图描绘的就是集成 OpenLDAP 与 Kerberos 后,大数据集群/企业数据湖进行用户身份认证和权限控制的全景视图:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/86fedc861ed1434b89b39778d981f919_image.png\\" alt=\\"image.png\\" /></p>\n<div class=\\"hljs-center\\">\\n<p>图1: 大数据领域的场景下用户身份认证与权限控制全景视图</p>\n</div>\\n<p>在这个生态系统架构中,OpenLDAP 作为企业全局的用户认证中心独立于大数据集群存在;Kerberos KDC 作为大数据集群的身份认证中心,既可以是集群专属的,也可以是一个独立于集群的全局 KDC(如果存在的话),管理员会为用户在 Kerberos 和 OpenLDAP 上分别创建账号,然后通过一系列技术将两套认证系统的账号打通;大数据集群的各个节点通过 SSSD 与 OpenLDAP 对接后,用户可以凭借 LDAP 账号(准确地说是账号中的用户名)登录集群的各个节点。在 Kerberos 和 OpenLDAP 账号打通的前提下,用户还可以使用同一账号完成Kerberos认证,进而可以提交作业或访问大数据相关服务;Ranger 负责集群用户的权限管理,其账号数据同样来自于 OpenLDAP。这样,OpenLDAP、Kerberos 和 Ranger 三方的用户数据一致,就可以实现统一的用户认证和权限管理了。</p>\n<p>在展开介绍 OpenLDAP 与 Kerberos 的集成方案前,需要读者清楚提前接受这样一个事实:OpenLDAP 与 Kerberos 作为两套独立的认证系统,是无法做到绝对意义上的统一的,这一点随着后续的深入介绍,读者应该会有所体会。但是在实际应用中,由于绝大多数以 OpenLDAP 和 Kerberos 作为用户认证源的外围系统通常只验证或同步两系统账号中的“用户名”部分,即 OpenLDAP 账号中的 uid 部分和 Kerberos 账号中的 Principal Name((@前面的))部分,这为统一两个认证系统的账号创造了可利用的外部条件,只要我们能将两套账号的用户名部分和密码统一在一起,就可以达到“使用效果”上的账号统一,这是目前各类技术方案之所以可行的一个重要支点。</p>\n<p>下面就是本系列文章给出的集成 OpenLDAP 与 Kerberos 的整体方案,也是接下来三篇文章的技术路线图:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/fa9600312c434272b472dfa3e1aae845_image.png\\" alt=\\"image.png\\" /></p>\n<div class=\\"hljs-center\\">\\n<p>图2: OpenLDAP 与 Kerberos 集成方案</p>\n</div>\\n<p>这个方案涉及 OpenLDAP 和 Kerberos KDC 两个身份认证源(两台服务器);Linux 主机代表大数据集群的各个节点,由于其需要与 OpenLDAP 和 Kerberos KDC 进行通信,所以每一个 Linux 主机同时也是 OpenLDAP 和 Kerberos KDC 的客户端(客户端的安装会在后续章节中介绍);参与人员有管理员和用户。方案整体的工作机制如下:</p>\n<p>①:管理员会为用户创建 Kerberos 和 OpenLDAP 两个配套账号,并保证两个账号中的用户名部分相同。用户并不需要区分和记忆这两个账号,实际上,管理员只需要将两账号中相同的用户名部分和一个密码发送给用户即可,作为用户,只需要知道自己的用户名和密码即可(至于在登录过程中走的是 OpenLDAP 认证还是 Kerberos 认证,对用户来说其实是透明的); ②:将 Kerberos 的后台数据库迁移到 OpenLDAP 上,并将用户在这两个系统上的配套账号统一存储为一条记录(LDAP Entry); ③:配置并启用 SSSD,允许 Linux 主机(大数据集群各个节点)通过 SSSD 连接到 OpenLDAP 进行账号认证; ④:完成上述操作后,用户就可以使用自己的用户名和密码以常规的 SSH 方式登录 Linux 主机(大数据集群各个节点)了,此时,用户的身份认证链路是:用户 -> Linux主机 -> OpenLDAP; ⑤:配置 SASL/GSSAPI,赋予 Kerberos 账号登录 OpenLDAP 的能力; ⑥:配置 OpenLDAP 的账号映射规则,将 Kerberos 账号映射到目标 OpenLDAP 账号上,实现“账号(用户名)统一”; ⑦:配置 saslauthd,让 OpenLDAP 委托 Kerberos 验证密码,实现“密码统一”; ⑧:完成上述操作后,用户就可以使用自己的用户名和密码以 GSSAPI 方式 SSH 登录 Linux 主机(大数据集群各个节点)了,在登录的同时还将自动完成 Kerberos 认证,为提交大数据作业铺平了道路,此时,用户的身份认证链路是:用户 -> Linux主机 -> Kerberos KDC;</p>\n<p>我们将在第一篇文章完成第①、②两步操作;在第二篇文章完成第③、④步操作;剩余的第⑤、⑥、⑦、⑧四步操作将在第三篇文章中完成。其他未标记数字的操作均为常规机制,无需额外配置。</p>\n<h3><a id=\\"3__36\\"></a><strong>3. 环境说明</strong></h3>\\n<p>为了更好地说明和演示,我们将在一套真实环境上执行各项操作,这套环境将贯穿整个系列文章,以下是实操环境的各项信息:</p>\n<p>※ 提示:以下环境信息(主机名,账号等)将会频繁出现在脚本中,如果读者要进行实操,建议将文章拷贝至文本编辑器,然后根据自己的实际环境,统一查找并替换相关的信息项。其中,只有 OpenLDAP 和 Kerberos KDC 的主机名是每次安装必须替换的项,其他项可视需求自行调整。</p>\n<ul>\\n<li>主机信息</li>\n</ul>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/0dffb136ff784f70b6a7756afad97ed0_image.png\\" alt=\\"image.png\\" /></p>\n<p>大数据集群通常由多个节点组成,由于后续操作没有需要显示配置或使用节点主机名的地方,所以在此省略。但是读者需要注意的是:后续文章中凡标记需在[ 大数据集群各个节点 ] 上执行的操作,均需逐一登录集群各个节点重复执行相关操作。此外,从 OpenLDAP 和 Kerberos KDC 的视角看,大数据集群的每一个节点同时也是一个 OpenLDAP 和 Kerberos 的客户端。</p>\n<p>※ 备注:本系列文章的所有操作均在 Amazon Linux 2上测试通过,原则上同样适用于CentOS/RHEL 7.0+</p>\n<ul>\\n<li>OpenLDAP 环境</li>\n</ul>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/68583b4d33b54c5ebf8384092e3948de_image.png\\" alt=\\"image.png\\" /></p>\n<ul>\\n<li>OpenLDAP 账号</li>\n</ul>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/d5e25eef3a914182a69a5dd3d7a0aa30_image.png\\" alt=\\"image.png\\" /></p>\n<ul>\\n<li>OpenLDAP OU 与 Container DN</li>\n</ul>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/d239219344584607b9afec8164173cb3_image.png\\" alt=\\"image.png\\" /></p>\n<ul>\\n<li>Kerbersos 环境</li>\n</ul>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/0911031a34be41a0aa9afb6d334fcc3a_image.png\\" alt=\\"image.png\\" /></p>\n<ul>\\n<li>Kerberos 账号</li>\n</ul>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/9c503e8e42f342388ea1abbdf2cf68e0_image.png\\" alt=\\"image.png\\" /></p>\n<h3><a id=\\"4__70\\"></a><strong>4. 安装操作</strong></h3>\\n<p>※ 提示:本文所有命令均以 root 用户身份执行,不再显式使用 sudo 修饰。</p>\n<h4><a id=\\"41__OpenLDAP_73\\"></a><strong>4.1 安装 OpenLDAP</strong></h4>\\n<h5><a id=\\"411__74\\"></a><strong>4.1.1 安装软件包</strong></h5>\\n<p>※ 提示:本节操作在 [ OpenLDAP ] 上执行</p>\n<p>登录准备安装 OpenLDAP 的主机,执行如下安装命令:</p>\n<pre><code class=\\"lang-\\">yum -y install openldap openldap-clients openldap-servers compat-openldap openldap-devel migrationtools\\n</code></pre>\\n<h5><a id=\\"412__83\\"></a><strong>4.1.2 启动服务</strong></h5>\\n<p>※ 提示:本节操作在 [ OpenLDAP ] 上执行</p>\n<p>安装完毕后,需要启动 OpenLDAP,OpenLDAP Server 端的守护进程是“slapd”,使用如下命令启动:</p>\n<pre><code class=\\"lang-\\">systemctl enable slapd\\nsystemctl start slapd\\nsystemctl status slapd\\n</code></pre>\\n<h5><a id=\\"413__92\\"></a><strong>4.1.3 初始化</strong></h5>\\n<p>※ 提示:本节操作在 [ OpenLDAP ] 上执行</p>\n<p>启动 OpenLDAP 服务后,需要进行必要的初始化工作,包括配置 Base CN、Root DN,导入常用 Schema 等等,命令如下:</p>\n<pre><code class=\\"lang-\\"># Base CN、Root DN等基础配置\\ncat << EOF | ldapadd -Y EXTERNAL -H ldapi:///\\ndn: olcDatabase={1}monitor,cn=config\\nchangetype: modify\\nreplace: olcAccess\\nolcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read by dn.base="cn=admin,dc=example,dc=com" read by * none\\n\\ndn: olcDatabase={2}hdb,cn=config\\nchangetype: modify\\nadd: olcRootPW\\nolcRootPW: \$(slappasswd -s Admin1234!)\\n-\\nreplace: olcRootDN\\nolcRootDN: cn=admin,dc=example,dc=com\\n-\\nreplace: olcSuffix\\nolcSuffix: dc=example,dc=com\\n-\\nadd: olcAccess\\nolcAccess: {0}to attrs=userPassword by self write by dn.base="cn=admin,dc=example,dc=com" write by anonymous auth by * none\\nolcAccess: {1}to * by dn.base="cn=admin,dc=example,dc=com" write by self write by * read\\nEOF\\n\\n# 导入常用schema\\nldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/core.ldif\\nldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif\\nldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif\\nldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif\\n</code></pre>\\n<p>这是我们初次对 OpenLDAP 进行配置,需要说明一点:目前网络上流传的不少关于 OpenLDAP 的文章都是让读者去修改 slapd.conf 等配置文件,这种做法已不再推荐,自 OpenLDAP 2.4之后,所有的配置都已统一为使用 ldif 文件,也就是我们上面采用的做法。</p>\n<h5><a id=\\"414__129\\"></a><strong>4.1.4 禁止匿名访问</strong></h5>\\n<p>※ 提示:本节操作在 [ OpenLDAP ] 上执行</p>\n<p>OpenLDAP 默认是允许匿名访问的,可以使用如下命令禁用:</p>\n<pre><code class=\\"lang-\\">cat << EOF | ldapmodify -Y EXTERNAL -H ldapi:///\\ndn: cn=config\\nchangetype: modify\\nadd: olcDisallows\\nolcDisallows: bind_anon\\n\\ndn: cn=config\\nchangetype: modify\\nadd: olcRequires\\nolcRequires: authc\\n\\ndn: olcDatabase={-1}frontend,cn=config\\nchangetype: modify\\nadd: olcRequires\\nolcRequires: authc\\nEOF\\n</code></pre>\\n<h5><a id=\\"415__O__OU_152\\"></a><strong>4.1.5 创建 O 和 OU</strong></h5>\\n<p>※ 提示:本节操作在 [ OpenLDAP ] 上执行</p>\n<p>我们需要先创建example这个organization((简称O),然后在其下面创建两个OU:<code>ou=users,dc=example,dc=com</code>用于存放用户账号;<code>ou=services,dc=example,dc=com</code>用户存放服务账号,创建命令如下:</p>\\n<pre><code class=\\"lang-\\">cat << EOF | ldapadd -D "cn=admin,dc=example,dc=com" -w Admin1234!\\ndn: dc=example,dc=com\\nobjectClass: dcObject\\nobjectClass: organization\\ndc: example\\no: example\\n\\ndn: ou=users,dc=example,dc=com\\nobjectclass: top\\nobjectclass: organizationalUnit\\nou: users\\ndescription: OU for user accounts\\n\\ndn: ou=services,dc=example,dc=com\\nobjectclass: top\\nobjectclass: organizationalUnit\\nou: services\\ndescription: OU for service accounts\\nEOF\\n</code></pre>\\n<p>至于环境介绍中的<code>cn=kerberos,dc=example,dc=com</code>这个 Container DN,不需要显式创建,后续操作中将由命令行工具自动创建。</p>\\n<h4><a id=\\"42_Kerberos_181\\"></a><strong>4.2 迁移Kerberos数据库</strong></h4>\\n<p>本系列文章的预设场景是:在 Kerberos 集群已存在的前提下,将 KDC 的后台数据库迁移到 OpenLDAP 上。这一预设场景符合绝大多数用户和数据团队面临的现状,因为主流的 Hadoop 发行包(如CDH)以及云平台上的大数据产品(如 Amazon 的EMR)都已内置了 Kerberos 功能,这些产品都能自动安装 Kerberos 并将大数据集群纳入到 Kerberos 的管控中,采用这种方式安装 Kerberos 是比较明智的。所以,本文会跳过Kerberos 的安装环节,直接从迁移现有 Kerberos 数据库开始介绍。</p>\n<h5><a id=\\"421__Kerberos_Schema_184\\"></a><strong>4.2.1 导入 Kerberos Schema</strong></h5>\\n<p>※ 提示:本节操作在 [ OpenLDAP ] 上执行</p>\n<p>登录 OpenLDAP 服务器,使用如下命令将 Kerberos 的 Schema 文件下载到本地</p>\n<pre><code class=\\"lang-\\">wget https://raw.githubusercontent.com/krb5/krb5/master/src/plugins/kdb/ldap/libkdb_ldap/kerberos.openldap.ldif -O /etc/openldap/schema/kerberos.ldif\\n</code></pre>\\n<p>然后,导入该Schema文件:</p>\n<pre><code class=\\"lang-\\">ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/kerberos.ldif\\n</code></pre>\\n<h5><a id=\\"422__Kerberos__OpenLDAP__197\\"></a><strong>4.2.2 创建 Kerberos 在 OpenLDAP 上的服务账号</strong></h5>\\n<p>※ 提示:本节操作在 [ OpenLDAP ] 上执行</p>\n<p>在配置/var/kerberos/krb5kdc/kdc.conf时,有这样两个配置项:</p>\n<ul>\\n<li>ldap_kdc_dn:给 krb5kdc 服务使用的 LDAP 账号</li>\n<li>ldap_kadmind_dn :给 kadmin 服务使用的 LDAP 的账号</li>\n</ul>\\n<p>配置的这两个账号必须要具备一定的读写权限,因为 Kerberos 要使用这两个账号在 LDAP 上对 Principal 数据进行增删查改操作。针对这两个 LDAP 账号,我们有两种选择:</p>\n<ul>\\n<li>新建专职账号</li>\n<li>使用 LDAP 的 admin 账号</li>\n</ul>\\n<p>如果只是单纯的将 OpenLDAP 作为 Kerberos 后台数据库使用,我们推荐使用专职账号,因为默认情况下 Kerberos 的所有账号都会放置在ldap_kerberos_container_dn定义的子树下面,此时使用专职账号可以为其配置精准的权限管控范围。</p>\n<p>但是,由于本系列文章的最终目标是要实现 Kerberos 和 OpenLDAP 的账号统一,在后续的第三篇文章中我们会将一个 Kerberos 账号映射为一个普通的 LDAP 账号,那时,大多数的 Kerberos 账号将不在 ldap_kerberos_container_dn 定义的子树下面,两个专职账号的权限范围就会难以定义,因此,我们选择直接以 LDAP 的 admin 账号作为 Kerberos 的服务账号。</p>\n<h5><a id=\\"423__215\\"></a><strong>4.2.3 添加索引</strong></h5>\\n<p>※ 提示:本节操作在 [ OpenLDAP ] 上执行</p>\n<p>为了迁移后能在 LDAP 中快速检索到 Kerberos 账号,建议给 krbPrincipalName 和 krbPwdPolicyReference 两个属性添加索引,具体操作如下命令:</p>\n<pre><code class=\\"lang-\\">cat << EOF | ldapmodify -Y EXTERNAL -H ldapi:/// \\ndn: olcDatabase={2}hdb,cn=config\\nchangetype: modify\\nadd: olcDbIndex\\nolcDbIndex: krbPrincipalName eq,pres,sub\\n\\ndn: olcDatabase={2}hdb,cn=config\\nchangetype: modify\\nadd: olcDbIndex\\nolcDbIndex: krbPwdPolicyReference eq\\nEOF\\n</code></pre>\\n<h5><a id=\\"424_Kerberos_233\\"></a><strong>4.2.4 备份现有Kerberos数据</strong></h5>\\n<p>※ 提示:本节操作在 [ Kerberos KDC ] 上执行</p>\n<p>对 Kerberos 进行配置前,须提前备份好现有 Kerberos 数据,以便在新的 OpenLDAP 数据库创建完成后可以将备份数据恢复到 OpenLDAP 上。备份前,建议先打印一份 Kerberos 账号列表并保存到文件中,以便在后续恢复数据时有一个参照。具体操作为登录 Kerberos KDC,执行命令:</p>\n<pre><code class=\\"lang-\\">kadmin.local -q "listprincs" | tee principals.txt\\n</code></pre>\\n<p>然后,执行正式的备份操作:</p>\n<pre><code class=\\"lang-\\">kdb5_util dump kdc-db.dump\\n\\n</code></pre>\\n<p>该命令会在当前目录生成 kdc-db.dump 和 kdc-db.dump.dump_ok 两个文件,后续4.2.10一节将会使用这两个文件恢复数据。</p>\n<h5><a id=\\"425__krb5serverldap_250\\"></a><strong>4.2.5 安装 <code>krb5-server-ldap</code></strong></h5>\n<p>※ 提示:本节操作在 [ Kerberos KDC ] 上执行</p>\n<p>由于后续操作需要使用 krb5-server-ldap 这个软件包,需要先行安装:</p>\n<pre><code class=\\"lang-\\">yum -y install krb5-server-ldap\\n</code></pre>\\n<h5><a id=\\"426__259\\"></a><strong>4.2.6 创建密码文件</strong></h5>\\n<p>※ 提示:本节操作在 [ Kerberos KDC ] 上执行</p>\n<p>继续在 KDC 上使用如下命令生成 admin 的 password 文件,该文件会在配置 kdc.conf 时使用到:</p>\n<pre><code class=\\"lang-\\">kdb5_ldap_util stashsrvpw -f /etc/openldap-admin.keyfile "cn=admin,dc=example,dc=com"\\n</code></pre>\\n<p>命令执行后会要求输入账号密码,验证完毕后会在指定位置上生成密码文件。</p>\n<p>注意:使用 kdb5_ldap_util 这个命令需要安装 krb5-server-ldap,而 krb5-server-ldap 又依赖 krb5-server,所以: krb5-server-ldap 应安装在 Kerberos KDC 上,这个操作也是在 KDC 上执行的。</p>\n<h5><a id=\\"427__KDC__272\\"></a><strong>4.2.7 修改 KDC 配置</strong></h5>\\n<p>※ 提示:本节操作在 [ Kerberos KDC ] 上执行</p>\n<p>这是配置 KDC 改用 OpenLDAP 作为后台数据库的关键一步,涉及 OpenLDAP 的各种信息都要配置到 kdc.conf 中。具体操作是打开/var/kerberos/krb5kdc/kdc.conf文件,在 realm 中将原有的文件数据库配置:“database_name = /var/kerberos/krb5kdc/principal”注释掉,同时添加“database_module = openldap_ldapconf”,然后添加“[dbmodules]”模块,提供 OpenLDAP 的若干配置,具体内容如下:</p>\n<pre><code class=\\"lang-\\">[realms]\\n CN-NORTH-1.COMPUTE.INTERNAL = {\\n ...\\n # database_name = /var/kerberos/krb5kdc/principal\\n ...\\n database_module = openldap_ldapconf\\n }\\n\\n[dbmodules]\\n openldap_ldapconf = {\\n db_library = kldap\\n ldap_servers = ldap://ip-10-0-0-70.cn-north-1.compute.internal\\n ldap_kerberos_container_dn = cn=kerberos,dc=example,dc=com\\n ldap_kdc_dn = cn=admin,dc=example,dc=com\\n ldap_kadmind_dn = cn=admin,dc=example,dc=com\\n ldap_service_password_file = /etc/openldap-admin.keyfile\\n ldap_conns_per_server = 5\\n }\\n</code></pre>\\n<p>关于上述配置,有如下几项需要特别解释一下:</p>\n<ul>\\n<li>ldap_kerberos_container_dn: Kerberos 会将账号集中存放该配置项指定的子树下面,这个 DN 不需要提前创建,Kerberos 在初始化数据库时会自动创建它;</li>\n<li>ldap_kdc_dn: Kerberos KDC的服务账号,如前所述,本文不会创建专职账号而是使用 LDAP 的 admin 账号;</li>\n<li>ldap_kadmind_dn : Kerberos 的管理员账号,如前所述,本文不会创建专职账号而是使用 LDAP 的 admin 账号;</li>\n<li>ldap_service_password_file:用于存放 ldap_kdc_dn 和 ldap_kadmind_dn(即LDAP的admin)密码的 stash 文件,已在上一节创建完成</li>\n</ul>\\n<p>上述配置可以通过以下脚本直接完成:</p>\n<pre><code class=\\"lang-\\">cp -f /var/kerberos/krb5kdc/kdc.conf /var/kerberos/krb5kdc/kdc.conf.\$(date +%s)\\n# 找到database_name这一行,将其注释掉;\\n# 并在下一行插入:database_module = openldap_ldapconf\\nsed -i 's/\\\\(^\\\\s*\\\\)database_name\\\\(.*\\\\)/\\\\1#database_name\\\\2\\\\n\\\\1database_module = openldap_ldapconf/g' /var/kerberos/krb5kdc/kdc.conf\\n# 在文件尾部追加[dbmodules]部分\\ntee -a /var/kerberos/krb5kdc/kdc.conf <<EOF\\n\\n[dbmodules]\\n openldap_ldapconf = {\\n db_library = kldap\\n ldap_servers = ldap://ip-10-0-0-70.cn-north-1.compute.internal\\n ldap_kerberos_container_dn = cn=kerberos,dc=example,dc=com\\n ldap_kdc_dn = cn=admin,dc=example,dc=com\\n ldap_kadmind_dn = cn=admin,dc=example,dc=com\\n ldap_service_password_file = /etc/openldap-admin.keyfile\\n ldap_conns_per_server = 5\\n }\\nEOF\\n</code></pre>\\n<h5><a id=\\"428__328\\"></a><strong>4.2.8 创建数据库</strong></h5>\\n<p>※ 提示:本节操作在 [ Kerberos KDC ] 上执行</p>\n<p>接下来就要在 OpenLDAP 上创建 Kerberos 数据库了,命令如下:</p>\n<pre><code class=\\"lang-\\">kdb5_ldap_util -D cn=admin,dc=example,dc=com -w Admin1234! -H ldap://ip-10-0-0-70.cn-north-1.compute.internal create -r CN-NORTH-1.COMPUTE.INTERNAL -subtrees dc=example,dc=com\\n</code></pre>\\n<p>执行时会要求输入“KDC database master key”,统一输入默认密码:<code>Admin1234!</code>。该命令和安装Kerberos时执行的建库操作<code>kdb5_util create -r <YOUR-REALM> -s</code>在性质上是一样的,只是后者创建的数据库是以文件((/var/kerberos/krb5kdc/principal))形式存储在 KDC 上,而这条命令会将数据库建到OpenLDAP上。执行成功后可登录 OpenLDAP 查看结果,此时<code>cn=kerberos,dc=example,dc=com</code>会被自动创建出来,并且下面还会有若干Kerberos的初始账号数据。</p>\\n<p>对于4.2.7,4.2.8和4.2.9三节的执行顺序要注意一下,本节4.2.8在执行时需要读取/var/kerberos/krb5kdc/kdc.conf中与OpenLDAP相关的配置信息才能在指定的 OpenLDAP 上创建数据库,所以要先完成4.2.7节kdc.conf的配置,然后再执行本节的建库操作,最后重启 Kerberos KDC 让新库配置生效,这个逻辑关系和应用程序迁移数据类似,一般都是:先修改数据库配置文件,然后创建数据库,最后重启应用让配置生效。</p>\n<h5><a id=\\"429__Kerberos_KDC_341\\"></a><strong>4.2.9 重启 Kerberos KDC</strong></h5>\\n<p>※ 提示:本节操作在 [ Kerberos KDC ] 上执行</p>\n<pre><code class=\\"lang-\\">systemctl restart krb5kdc kadmin\\nsystemctl status krb5kdc kadmin\\n</code></pre>\\n<h5><a id=\\"4210__349\\"></a><strong>4.2.10 导入原有备份数据</strong></h5>\\n<p>※ 提示:本节操作在 [ Kerberos KDC ] 上执行</p>\n<p>呼应“4.2.4 备份 Kerberos 数据库”一节,完成数据库迁移后,现在需要将此前备份的 Kerberos 数据恢复到新的 OpenLDAP 数据库上了,命令如下:</p>\n<pre><code class=\\"lang-\\">kdb5_util load -update kdc-db.dump\\n</code></pre>\\n<p>命令完成后,再次查看一下 OpenLDAP 的<code>cn=kerberos,dc=example,dc=com</code>子树,此前大数据集群的若干服务和主机的principal记录应该都已经恢复到 OpenLDAP 上了:</p>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/2b2164d148e7467bb7f039ec7f2a0d89_image.png\\" alt=\\"image.png\\" /></p>\n<p>图3: 迁移完成后 OpenLDAP 上的 Kerberos 数据</p>\n<h5><a id=\\"4211_addprinc_x_dn_364\\"></a><strong>4.2.11 使用<code>addprinc -x dn=...</code>创建账号</strong></h5>\n<p>完成上述操作后,整合 OpenLDAP 作为 Kerberos 后台数据库的配置工作就全部结束了,现在就可以将一个用户的 Kerberos 账号与 OpenLDAP 账号统一存储为一条记录(LDAP Entry))了。以此前提到的用于测试的 OpenLDAP 账号<code>uid=user1,ou=users,dc=example,dc=com</code>和 Kerberos 账号<code>user1@CN-NORTH-1.COMPUTE.INTERNAL</code>为例,假定它们属于同一用户 user1,管理员可以通过以下方式为 user1 创建这两个账号:</p>\\n<p>※ 提示:以下操作在 [ OpenLDAP ] 上执行</p>\n<p>登录 OpenLDAP 服务器,通过以下命令创建 OpenLDAP 账号 <code>uid=user1,ou=users,dc=example,dc=com</code></p>\\n<pre><code class=\\"lang-\\">cat << EOF | ldapadd -D "cn=admin,dc=example,dc=com" -w Admin1234!\\ndn: uid=user1,ou=users,dc=example,dc=com\\nobjectClass: posixAccount\\nobjectClass: top\\nobjectClass: inetOrgPerson\\nuid: user1\\ndisplayName: user1\\nsn: user1\\nhomeDirectory: /home/user1\\ncn: user1\\nuidNumber: \$((1000+\$RANDOM%9000))\\ngidNumber: 100\\nuserPassword: Admin1234!\\nEOF\\n</code></pre>\\n<p>※ 提示:以下操作在 [ Kerberos KDC ] 上执行</p>\n<p>然后登录 KDC,通过以下命令创建 Kerberos 账号<code>user1@CN-NORTH-1.COMPUTE.INTERNAL</code>(提示输入密码时请使用统一默认密码:<code>Admin1234!</code>):</p>\\n<pre><code class=\\"lang-\\">kadmin.local -q "addprinc -x dn=uid=user1,ou=users,dc=example,dc=com user1@CN-NORTH-1.COMPUTE.INTERNAL"\\n</code></pre>\\n<p>命令执行后,登录 OpenLDAP 查看一下 user1 的用户数据:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/e515e74981e742a8b08898ad3d67ecd2_image.png\\" alt=\\"image.png\\" /></p>\n<div class=\\"hljs-center\\">\\n<p>图4: user1 的用户数据</p>\n</div>\\n<p>从显示的账号信息可以清楚地看到:Kerberos 账号的相关属性(如krbPrincipalName等)全部添加到了<code>uid=user1,ou=users,dc=example,dc=com</code>这条记录(entry))上,也就是说:LDAP 账号和 Kerberos 账号的信息共同存储在一条记录上。</p>\\n<p>要特别注意上述 addprinc 命令中的<code>-x dn=uid=user1,ou=users,dc=example,dc=com</code>部分,参数-x的作用是显式控制Principal在LDAP上的存放位置,正是通过这个参数,我们才能将<code>user1@CN-NORTH-1.COMPUTE.INTERNAL</code>这个Principal创建到<code>uid=user1,ou=users,dc=example,dc=com</code>这个 DN 上,也就是将两个系统账号建到一条记录上。</p>\\n<p>至此,本系列文章的第一阶段目标:“实现 OpenLDAP 与 Kerberos 用户数据统一存储”已全部完成,但是,这离我们最终的集成目标还差得很远,因为,虽然在数据库层面上我们让一个用户的 Kerberos 账号和OpenLDAP 账号存储为了一条记录(一个 LDAP Entry)),但是在 Kerberos 和 OpenLDAP 两个系统中,它们依然是两个独立的账号,彼此没有任何关系,也不可能互相识别出对方。一个更让人沮丧的事实是:整合 OpenLDAP 作为 Kerberos 后台数据库并不是一个“必选项”,即使跳过本文4.2节中的绝大多数操作,也不会影响后续的集成工作。统一存储的主要收益是给统一维护用户数据创造了便利,之于 Kerberos 和 OpenLDAP 的集成,并没有多少实质性的影响,真正的深度集成要到本系列的最后一篇文章才能展开。</p>\n<h3><a id=\\"_413\\"></a><strong>附录:常见错误</strong></h3>\\n<p>在使用<code>addprinc -x ...</code>创建 principal 时报错:</p>\\n<pre><code class=\\"lang-\\">add_principal: DN is out of the realm subtree while creating "xxx"\\n</code></pre>\\n<p>原因:-x参数配置的 DN 不在创建 realm 时指定的 subtree 下面,也就是不在“kdb5_ldap_util … create … -subtrees xxxx”命令中指定的 subtrees 下面.</p>\n<p>解决方法:调整DN到指定的 subtrees 下面,或调整 subtrees 的配置。提示:subtrees 支持以冒号分隔的多个 subtrees 列表。</p>\n<h3><a id=\\"_424\\"></a><strong>关联阅读:</strong></h3>\\n<p><a href=\\"https://aws.amazon.com/cn/blogs/china/amazon-emr-authentication-scheme-based-on-openldap-and-kerberos-i-integrating-background-databases/\\" target=\\"_blank\\">基于 OpenLDAP 与 Kerberos 的Amazon EMR 身份认证方案(一):整合后台数据库</a></p>\\n<p><a href=\\"https://aws.amazon.com/cn/blogs/china/amazon-emr-authentication-scheme-based-on-openldap-and-kerberos-ii-synchronize-ldap-accounts-based-on-sssd/\\" target=\\"_blank\\">基于 OpenLDAP 与 Kerberos 的Amazon EMR 身份认证方案(二):基于 SSSD 同步 LDAP 账号</a></p>\\n<p><a href=\\"https://aws.amazon.com/cn/blogs/china/amazon-emr-authentication-scheme-based-on-openldap-and-kerberos-iii-deep-integration-based-on-sasl-gssapi/\\" target=\\"_blank\\">基于 OpenLDAP 与 Kerberos 的Amazon EMR 身份认证方案(三):基于 SASL/GSSAPI 深度集成</a></p>\\n<h3><a id=\\"_431\\"></a><strong>参考资料</strong></h3>\\n<p>OpenLDAP 官方文档 <a href=\\"https://www.openldap.org/doc/admin24/\\" target=\\"_blank\\">https://www.openldap.org/doc/admin24/</a></p>\\n<p>Kerberos官方文档(OpenLDAP部分) <a href=\\"http://web.mit.edu/kerberos/krb5-latest/doc/admin/database.html#operations-on-the-ldap-database\\" target=\\"_blank\\">http://web.mit.edu/kerberos/krb5-latest/doc/admin/database.html#operations-on-the-ldap-database</a></p>\\n<p>Kerberos使用 OpenLDAP 作为 backend <a href=\\"https://mp.weixin.qq.com/s/6Hk6qwCDCoXQ2e8km5jeXw\\" target=\\"_blank\\">https://mp.weixin.qq.com/s/6Hk6qwCDCoXQ2e8km5jeXw</a></p>\\n<p>使用 LDAP + Kerberos 实现集中用户认证及授权系统 <a href=\\"https://blog.csdn.net/cheng_fangang/article/details/40143261\\" target=\\"_blank\\">https://blog.csdn.net/cheng_fangang/article/details/40143261</a></p>\\n<h4><a id=\\"_440\\"></a><strong>本篇作者</strong></h4>\\n<p><strong>Laurence</strong><br />\\nAmazon 资深解决方案架构师,多年系统开发与架构经验,对大数据、云计算、企业级应用、SaaS、分布式存储和领域驱动设计有丰富的实践经验,著有 《大数据平台架构与原型实现:数据中台建设实战》一书。</p>\n"}