以编程方式将成员添加到 Kerberos 域

以编程方式将成员添加到 Kerberos 域

我想让嵌入式设备加入基于 Linux 的 AD/DC 域。嵌入式设备上有 kerberos 库(无可执行文件)。嵌入式设备上有一个应用程序,可以作为客户端成功验证并访问域上的服务。我还想让嵌入式设备作为成员加入域,获取凭据并接受来自域用户的身份验证请求。

我一直在使用 kerberos src/appl/gss-sample 目录中的示例程序 gss-server 作为将服务器功能集成到我的应用程序的模型。

提示:我发布了我的解决方案作为该问题的答案。

我遗漏了一个重要的部分。在嵌入式设备能够提供 kerberos 服务之前,它必须加入域,据我所知,这涉及 a) 为主机创建主体,b) 在设备的密钥表中添加条目,以及 c) 在域控制器密钥表上添加相应的条目。如果我在设备上运行完整的 samba 堆栈,我会使用类似samba-tool domain join或 之类的东西net ads join。我查看了 samba-tool 和 net 的代码,它们似乎比我需要或想要的要多得多。在大多数情况下,我相信我需要做的就是添加允许嵌入式设备通过 DC 进行身份验证的工件。我真的不知道我是否做对了,也不相信我知道所有的步骤。但我认为我正在尝试这样做:

  • 在 DC 上配置一台计算机
  • 从 DC 导出 keytab 条目
  • 在嵌入式设备上导入 keytab 条目。

完成上述三个步骤后,我大概可以成功运行 gss-client/gss-server 了。第一个问题:这样做对吗?这样做对吗?第二个问题:如何导入 keytab 条目?

也许我不需要密钥表,而是使用 gss_acquire_cred,我以某种方式从 DC 导出凭证并安全地将其传达给嵌入式设备,然后使用 gss_import_cred。

有人知道我是否走在正确的轨道上吗?他们知道任何可以做到这一点的示例代码吗?

背景是这样的,我们有一个在 Android 上运行的商业 SMB 客户端/服务器堆栈。我们支持客户端的 NTLM 和 Kerberos 身份验证,以及服务器上的 NTLM。我们正在尝试升级服务器以支持 Kerberos 身份验证。

答案1

它必须加入域,据我了解,这涉及a)为主机创建主体,b)在设备的密钥表中添加条目,以及c)在域控制器密钥表上添加相应的条目。

是的,尽管它不是域控制器端的单个“密钥表”,但它专门设置与主机主体条目相关的密钥。在 AD 中,它意味着设置(计算机或用户)帐户的密码并让它从中派生密钥;然后您在本地使用相同的过程来派生密钥并将其存储在密钥表文件中。

对于 AD,如果您想要接受通常与 AD 中的某个服务关联的 Kerberos 票证,例如host/(SSH) 或cifs/(SMB),则只需要一个真正的“计算机”帐户。然而,在许多其他情况下,创建一个“用户”帐户并为其分配您想要的特定服务主体的“servicePrincipalName”属性就足够了。例如,接受 SPNEGO 的 Web 服务器HTTP/可以很容易地与“用户”帐户绑定。

还请注意,在 Active Directory 的情况下,不可能实际上从 KDC“导出密钥表”,因为这基本上相当于检索帐户的密码哈希。相反,这个过程是相反的:你会将账户的密码设置为随机生成的值,然后使用与哈希算法输入相同的密码在本地生成 keytab。

如果您想使用 Linux 工具完成所有操作,adcli可以使用该工具(realmd 的一部分)在 Active Directory 中配置计算机帐户,作为 samba-tool 的替代方案。它可以在必要时创建一个 keytab 文件,或者您可以为计算机帐户提供一个强大的随机密码,然后使用ktutil它手动为其生成 keytab。

但是,adcli它不使用任何不常见的 RPC 接口,因此您也可以使用通用 LDAP 客户端执行相同操作 - 例如,您可以使用 python-ldap 创建用户或计算机帐户并设置其密码。最后,只需让 AD 管理员预先创建一个帐户并为您生成一个密钥表即可。

第二个问题:如何导入 keytab 条目?

这在很大程度上取决于你所使用的 Kerberos 实现,但在大多数情况下,没有“导入”过程 – keytab 文件停留一个 keytab 文件,您只需将其放在正确的位置(/etc/krb5.keytab 是类 Unix 系统上传统的“系统范围”默认值)。

MIT Krb5 和 Heimdal 的最新版本具有“凭证存储“扩展到 GSS API 接口来从指定路径获取凭据,因此“正确的位置”完全由您决定。

(在旧版本中,它需要通过原始 libkrb5 API 或在环境中设置 KRB5_KTNAME 来完成。)

类似地,其他 Kerberos 或 GS​​SAPI 实现(例如 Java 实现)通常会允许您从指定路径加载服务器密钥。

答案2

解决方案:这就是我为了让事情正常运转所做的事情。

  1. 我的 DC 正在运行 samba-ad-dc。这假设您已经在 DC 上配置了用户。使用 samba-tool 为服务帐户添加服务主体并将其附加到用户:
# samba-tool spn add cifs/myhost.mydomain.com@MYREALM MyUser

其中 cifs 是我的服务的名称,myhost.mydomain.com 是我的计算机的 FQDN,MYREALM 是领域或域名,MyUser 是我想要附加主体的现有用户。

  1. 生成一个包含该服务主体条目的密钥表
# samba-tool domain exportkeytab cifs.keytab --principal cifs/myhost.mydomain.com@MYREALM

其中 cifs.keytab 是包含 keytab 的输出文件的任意名称,而 cifs/myhost.mydomain.com@MYREALM 是我在步骤 1 中刚刚添加的服务主体。

  1. 将该 keytab 文件复制到 FQDN 为 myhost.mydomain.com 的成员计算机。我可以用成员上的此 keytab 文件做三件事。a) 用它替换 /etc/krb5.keytab,b) 使用 ktutil 实用程序将其中的所有内容导入 /etc/krb5.keytab,或 c) 将其指定为 gss-server 的参数。我选择 c。

  2. 以我们在步骤 1 中创建的服务主体所附加的用户身份登录。

# kinit MyUser@MYREALM
  1. 运行 gss-server
# gss-server -keytab cifs.keytab cifs/myhost.mydomain.com@MYREALM

其中 cifs.keytab 是从 DC 导出并复制到成员计算机的 keytab 文件,而 cifs/myhost.mydomain.com@MYREALM 是我们在步骤 1 中创建的主体。

  1. 运行 gss-client
# gss-client myhost.mydomain.com cifs message

其中 myhost.mydomain.com 是我的成员计算机的 FQDN,cifs 是我在步骤 1 中创建的主体的服务名称,message 是我想要传输到我的服务器的任何消息。

很简单,不是吗?不是!但是用户1686的耐心的帮助,我能够渡过难关。谢谢。

相关内容