注意

本文档适用于 Ceph 的开发版本。

关于如何设置 Ceph Kerberos 身份验证的详细文档

本文档提供了 Kerberos 授权协议的详细信息。这是第一个草稿,我们将努力随着可能发生的代码更改而保持更新。

此协议有几种免费实现可用(MIT、Heimdal、MS...),涵盖了广泛的操作系统。麻省理工学院(MIT)是 Kerberos 最初的开发地,它继续开发他们的 Kerberos 软件包,这也是我们选择合作的实现。MIT Kerberos

请向 Daniel Oliveira (doliveira@suse.com) 提供反馈

上次更新:2018 年 12 月 3 日


背景

在深入了解 Kerberos 细节之前,让我们定义一些术语,以便我们理解它能做什么和不能做什么

目录服务

目录服务是一个可自定义的信息存储,作为一个单点,用户可以从其中找到分布在整个网络中的资源和服务。这个可自定义的信息存储还为管理员提供了一个单点来管理其对象及其属性。虽然这个信息存储在网络用户看来是一个单点,但它实际上最常以分布式形式存储。目录服务至少包括一个 目录服务器和目录客户端,并根据 X.500 标准实施。

OpenLDAP、389 Directory Server、MS Active Directory、NetIQ eDirectory 是很好的例子。

目录服务通常被描述为一种 写入一次、读取多次的服务,这意味着通常存储在目录服务中的数据不会期望在每次访问时都发生变化。

构成目录服务的数据库 不是为事务数据设计的


LDAP(轻量级目录访问协议 v3)

LDAP 是一组 LDAP 协议交换 (不是服务器的实现),它定义了访问数据的方法。LDAPv3 是 IETF 在 RFC 2251 中定义的标准,描述了数据如何在目录服务中表示(数据模型或 DIT)。

最后,它定义了如何将数据加载到(导入)和保存自(导出)目录服务(使用 LDIF)。LDAP 没有定义数据如何存储或操作。就标准而言,数据存储是一个“自动”过程,通常由后端模块处理。

没有一个目录服务实现完全实现了 LDAP v3 协议的所有功能。所有目录服务器实现都有其不同的问题和/或异常,以及可能不会像另一个目录服务器实现那样返回结果的功能。


身份验证

身份验证是关于验证凭证(如用户名/ID 和密码)以验证身份。系统使用凭证确定一个人是否如其所声称。

通常,身份验证是通过用户名和密码完成的,有时结合 (单、双或多)因素身份验证,这指的是进行身份验证的各种方式。


授权

授权在身份被系统成功验证后发生,最终赋予访问资源(如信息、文件、数据库等,几乎任何东西)的完全权限。它决定了访问系统的能力以及访问的程度(授予了什么权限/权利以及授予给哪里/什么)。


审计

审计获取 身份验证和授权 的结果,并将它们记录到审计日志中。审计日志记录了在身份验证和授权期间采取的所有操作,供管理员以后审查。虽然身份验证和授权是预防性系统(防止未经授权的访问),但审计是反应性系统(提供某人如何/何时/何地访问环境的详细日志)。


Kerberos (KRB v5)

Kerberos 是一种网络 身份验证协议。它旨在通过使用秘密密钥加密(对称密钥)为客户端/服务器应用程序提供强大的身份验证。MIT 提供了一个免费的此协议实现。然而,Kerberos 也存在于许多商业产品中。

它旨在为不安全网络上的服务提供安全身份验证。Kerberos 使用票证来验证用户或服务应用程序,并且从不在网络上明文传输密码。因此,客户端和服务器都可以在不通过网络发送任何未加密秘密的情况下证明其身份。

Kerberos 可用于单点登录 (SSO)。SSO 背后的想法很简单,我们希望只登录一次,就能够使用我们有权使用的任何服务,而无需在每个服务上都登录。


简单身份验证和安全层 (SASL)

SASL (RFC 4422) 是一个框架,帮助开发人员实现不同的身份验证机制(实现一系列挑战和响应),允许客户端和服务器为每个连接协商一个双方都接受的机制,而不是硬编码它们。

SASL 机制示例

  • ANONYMOUS (RFC 4505)

    • 用于访客访问,意味着 未经身份验证

  • CRAM-MD5 (RFC 2195)

    • 基于 HMAC-MD5 的简单挑战-响应方案。它不建立任何安全层。 不如 DIGEST-MD5 和 GSSAPI 安全。

  • DIGEST-MD5 (RFC 2831)

    • HTTP Digest 兼容 (部分) 基于 MD5 的挑战-响应方案,提供 数据安全层。它优于 PLAIN 文本密码,可防止明文攻击。它是 LDAPv3 服务器的强制身份验证方法。

  • EXTERNAL (RFCs 4422, 5246, 4301, 2119)

    • 其中 身份验证在上下文中是隐式的(即; 对于已经使用 IPsec 或 TLS [TLS/SSL 进行基于证书的身份验证] 的协议)。此方法使用公共密钥进行强身份验证。

  • GS2 (RFC 5801)

    • 机制系列支持 SASL 中的任意 GSS-API 机制

  • NTLM (MS 专有)

    • MS Windows NT LAN Manager 身份验证机制

  • OAuth 1.0/2.0 (RFCs 5849, 6749, 7628)

    • 委托资源访问的身份验证协议

  • OTP (RFC 2444)

    • 一次性密码机制 (取代 SKEY 机制)

  • PLAIN (RFC 4616)

    • 简单的明文密码机制 (RFC 4616)。由于其相对缺乏强度,这不是大多数应用程序的首选机制。

  • SCRAM (RFCs 5802, 7677)

    • 支持通道绑定的现代挑战-响应方案机制


通用安全服务应用编程接口 (GSSAPI)

GSSAPI (RFCs 2078, 2743, 2744, 4121, 4752) 被协议实现者广泛用作在他们的应用程序中实现 Kerberos v5 支持的一种方式。它提供了一个通用的接口和消息格式,可以封装来自任何具有 GSSAPI 兼容库的身份验证方法的身份验证交换。

它本身不定义协议、身份验证或安全机制;相反,它通过提供统一、通用的 API 来实现安全服务,使应用程序员更容易支持多种身份验证机制。它是一组函数,包括 API 和处理身份验证的方法论,旨在尽可能地将应用程序协议与安全协议的细节隔离开来。

Microsoft Windows Kerberos 实现不包括 GSSAPI 支持,而是包括 Microsoft 特定的 API,即 安全支持提供程序接口 (SSPI)。在 Windows 中,SSPI 客户端可以与 GSSAPI 服务器 通信。

大多数支持 GSSAPI 的应用程序也支持 Kerberos v5。


简单且受保护的 GSSAPI 协商机制 (SPNEGO)

如我们所见,GSSAPI 解决了为不同身份验证机制提供单个 API 的问题。然而,它没有解决协商使用哪种机制的问题。事实上,要使 GSSAPI 工作,相互通信的两个应用程序必须事先知道他们计划使用哪种身份验证机制,如果只支持一种机制(意味着 Kerberos v5),这通常不是问题。

然而,如果R有多种机制可供选择,则需要一种方法来安全地协商客户端和服务器都支持的身份验证机制;这就是 SPNEGO (RFC 2478, 4178) 发挥作用的地方。

SPNEGO 提供了一个框架,供参与身份验证的双方从一组可能的身份验证机制中进行选择,同时保留安全协议对使用它的应用程序协议的不透明性。

它是一种安全协议,使用 GSSAPI 身份验证机制,并在实现中协商几种可用的身份验证机制,选择一种用于满足应用程序协议的身份验证需求。

它是一个 元协议,完全在其他应用程序协议中传输;它从不直接在没有应用程序协议的情况下使用。


为什么这很重要,我们为什么要关心?

有了这些背景信息,我们可以轻松地描述如下事情:

1. Ceph Kerberos 身份验证 完全基于使用 GSSAPI 的 MIT Kerberos 实现。

2. 目前我们仍在使用 Kerberos 默认后端数据库,但我们计划添加 LDAP 作为后端,这将通过 SASL 机制 为我们提供 GSSAPI (KRB5) 身份验证LDAP (LDAPv3) 授权


开始之前

我们假设环境已经有一些外部服务正常运行

  • Kerberos 需要正确配置,这也意味着(对于所有服务器和 KDC)

    • 时间同步(使用 NTPchrony)。

      • Kerberos 不仅依赖时间同步,Ceph 也依赖时间同步。

    • DNS 解析

      • 包括 (正向和反向) 区域,以及 完全限定域名 (fqdn) (hostname + domain.name)

      • KDC 发现可以设置为使用 DNS (srv resources) 作为服务位置协议 (RFCs 2052, 2782),以及将 host 或 domain 映射到 适当的 realm (txt record)

      • 尽管运行 Kerberos realm 并不需要这些 DNS 条目/设置,但它们确实有助于消除在所有客户端上手动配置的需要。

      • 这极其重要,因为大多数 Kerberos 问题通常与名称解析有关。Kerberos 在检查系统名称和主机查找时非常挑剔。

  • 只要有可能,为了避免 单点故障,为基础设施中的每个部分设置 备份、辅助或从属 (ntp, dns, and kdc servers)

此外,以下 Kerberos 术语 很重要

  • 票证

    • 票证或凭证是一组可用于验证客户端身份的信息。Kerberos 票证可以存储在文件中,也可以仅存在于内存中。

    • 获得的第一张票证是票证授予票证 (TGT),它允许客户端获取额外的票证。这些额外的票证授予客户端对特定服务的权限。这些额外票证的请求和授予是透明发生的。

      • TGT 会在指定时间过期,它允许客户端获取额外的票证,这些票证授予对特定服务的权限。这些额外票证的请求和授予对用户是透明的。

  • 密钥分发中心 (KDC)。

    • KDC 为客户端创建一个票证授予票证 (TGT),使用客户端的密码作为密钥对其进行加密,并将加密的 TGT 发送回客户端。然后,客户端尝试使用其密码解密 TGT。如果客户端成功解密 TGT(即,如果客户端提供了正确的密码),它会保留解密的 TGT,这表明客户端身份的证明。

    • KDC 由三个组件组成

      • Kerberos 数据库,其中存储了有关主体及其所属领域的所有信息,以及其他内容。

      • 身份验证服务 (AS)

      • 票证授予服务 (TGS)

  • 客户端

    • 发送票证请求的 用户、主机或服务

  • 主体

    • 它是一个唯一的身份,Kerberos 可以为其分配票证。主体可以有任意数量的组件。每个组件由组件分隔符(通常为 /)分隔。最后一个组件是 realm,由 realm 分隔符(通常为 @)与主体的其余部分分隔开来。

    • 如果主体中没有 realm 组件,则假定该主体位于正在使用的上下文的默认 realm 中。

    • 通常,一个主体分为三部分

      • the primary, the instance, and the realm

      • 典型的 Kerberos V5 主体格式为 primary/instance@REALM

      • primary 是主体的第一部分。对于用户,它与 username 相同。对于主机,primary 是单词 host。对于 Ceph,我们将使用 ceph 作为 primary 名称,这使得组织和识别 Ceph 相关主体更容易。

      • instance 是一个可选字符串,用于限定 primary。instance 通过斜杠 / 与 primary 分隔。对于用户,instance 通常为 null,但用户也可能有一个额外的名为 admin 的 instance 的主体,用于管理数据库。

        主体 johndoe@MYDOMAIN.COM 与主体 johndoe/admin@MYDOMAIN.COM 完全分开,具有单独的密码和单独的权限。对于主机,instance 是完全限定主机名,即 osd1.MYDOMAIN.COM

      • realm 是 Kerberos realm。通常,Kerberos realm 是域名,采用 大写字母。例如,机器 osd1.MYDOMAIN.COM 将位于 realm MYDOMAIN.COM 中。

  • Keytab

    • keytab 文件存储实际的加密密钥,该密钥可用于代替给定主体的密码挑战。创建 keytab 文件对于非交互式主体非常有用,例如 服务主体名称,这些主体通常与 Ceph daemon 等长时间运行的进程相关联。keytab 文件不必是与单个主体的“1:1 映射”。多个不同的主体密钥可以存储在单个 keytab 文件中

      • keytab 文件允许用户/服务在不知道密码的情况下进行身份验证。因此,keytab 应该受到适当控制的保护,以防止未经授权的用户使用它进行身份验证。

      • 默认客户端 keytab 文件是 /etc/krb5.keytab


Ceph 方面的事项

为了配置(从 Ceph 节点到 KDC 的)连接

  1. 登录到 Kerberos 客户端(Ceph 服务器节点)并通过检查和正确编辑 /etc/krb5.conf 文件来确认其配置正确

    /etc/krb5.conf
    [libdefaults]
        dns_canonicalize_hostname = false
        rdns = false
        forwardable = true
        dns_lookup_realm = true
        dns_lookup_kdc = true
        allow_weak_crypto = false
        default_realm = MYDOMAIN.COM
        default_ccache_name = KEYRING:persistent:%{uid}
    [realms]
        MYDOMAIN.COM = {
            kdc = kerberos.mydomain.com
            admin_server = kerberos.mydomain.com
            ...
        }
    ...
    
  2. 登录到 KDC 服务器 并确认其配置正确,可以对相关的 Kerberos realm 进行身份验证

    1. Kerberos 相关的 DNS RR

      /var/lib/named/master/mydomain.com
      kerberos                IN A        192.168.10.21
      kerberos-slave          IN A        192.168.10.22
      _kerberos               IN TXT      "MYDOMAIN.COM"
      _kerberos._udp          IN SRV      1 0 88 kerberos
      _kerberos._tcp          IN SRV      1 0 88 kerberos
      _kerberos._udp          IN SRV      20 0 88 kerberos-slave
      _kerberos-master._udp   IN SRV      0 0 88 kerberos
      _kerberos-adm._tcp      IN SRV      0 0 749 kerberos
      _kpasswd._udp           IN SRV      0 0 464 kerberos
      ...
      
    2. KDC 配置文件

      /var/lib/kerberos/krb5kdc/kdc.conf
      [kdcdefaults]
              kdc_ports = 750,88
      [realms]
              MYDOMAIN.COM = {
                  acl_file = /var/lib/kerberos/krb5kdc/kadm5.acl
                  admin_keytab = FILE:/var/lib/kerberos/krb5kdc/kadm5.keytab
                  default_principal_flags = +postdateable +forwardable +renewable +proxiable
                                                          +dup-skey -preauth -hwauth +service
                                                          +tgt-based +allow-tickets -pwchange
                                                          -pwservice
                  dict_file = /var/lib/kerberos/krb5kdc/kadm5.dict
                  key_stash_file = /var/lib/kerberos/krb5kdc/.k5.MYDOMAIN.COM
                  kdc_ports = 750,88
                  max_life = 0d 10h 0m 0s
                  max_renewable_life = 7d 0h 0m 0s
              }
      ...
      
  3. 仍在 KDC 服务器上,运行 Kerberos 管理实用程序;kadmin.local,以便我们可以列出已创建的所有主体。

    kadmin.local:  listprincs
    K/M@MYDOMAIN.COM
    krbtgt/MYDOMAIN.COM@MYDOMAIN.COM
    kadmin/admin@MYDOMAIN.COM
    kadmin/changepw@MYDOMAIN.COM
    kadmin/history@MYDOMAIN.COM
    kadmin/kerberos.mydomain.com@MYDOMAIN.COM
    root/admin@MYDOMAIN.COM
    ...
    
  4. 为我们想要由 Kerberos 身份验证的 每个 Ceph 集群节点添加一个主体

    1. 添加主体

      kadmin.local:  addprinc -randkey ceph/ceph-mon1
      Principal "ceph/ceph-mon1@MYDOMAIN.COM" created.
      kadmin.local:  addprinc -randkey ceph/ceph-osd1
      Principal "ceph/ceph-osd1@MYDOMAIN.COM" created.
      kadmin.local:  addprinc -randkey ceph/ceph-osd2
      Principal "ceph/ceph-osd2@MYDOMAIN.COM" created.
      kadmin.local:  addprinc -randkey ceph/ceph-osd3
      Principal "ceph/ceph-osd3@MYDOMAIN.COM" created.
      kadmin.local:  addprinc -randkey ceph/ceph-osd4
      Principal "ceph/ceph-osd4@MYDOMAIN.COM" created.
      kadmin.local:  listprincs
      K/M@MYDOMAIN.COM
      krbtgt/MYDOMAIN.COM@MYDOMAIN.COM
      kadmin/admin@MYDOMAIN.COM
      kadmin/changepw@MYDOMAIN.COM
      kadmin/history@MYDOMAIN.COM
      kadmin/kerberos.mydomain.com@MYDOMAIN.COM
      root/admin@MYDOMAIN.COM
      ceph/ceph-mon1@MYDOMAIN.COM
      ceph/ceph-osd1@MYDOMAIN.COM
      ceph/ceph-osd2@MYDOMAIN.COM
      ceph/ceph-osd3@MYDOMAIN.COM
      ceph/ceph-osd4@MYDOMAIN.COM
      ...
      
    2. 这与我们创建 用户主体 的思路相同

      kadmin.local:  addprinc johndoe
      WARNING: no policy specified for johndoe@MYDOMAIN.COM; defaulting to no policy
      Enter password for principal "johndoe@MYDOMAIN.COM":
      Re-enter password for principal "johndoe@MYDOMAIN.COM":
      Principal "johndoe@MYDOMAIN.COM" created.
      ...
      
  5. 为每个 Ceph 集群节点创建 keytab 文件

    由于默认客户端 keytab 文件是 /etc/krb5.keytab,我们将希望使用不同的文件名,因此我们指定 要创建的 keytab 文件要从中导出密钥的主体

    kadmin.local:  ktadd -k /etc/gss_client_mon1.ktab ceph/ceph-mon1
    Entry for principal ceph/ceph-mon1 with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/gss_client_mon1.ktab.
    Entry for principal ceph/ceph-mon1 with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/gss_client_mon1.ktab.
    Entry for principal ceph/ceph-mon1 with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/etc/gss_client_mon1.ktab.
    Entry for principal ceph/ceph-mon1 with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/etc/gss_client_mon1.ktab.
    kadmin.local:  ktadd -k /etc/gss_client_osd1.ktab ceph/ceph-osd1
    Entry for principal ceph/ceph-osd1 with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/gss_client_osd1.ktab.
    Entry for principal ceph/ceph-osd1 with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/gss_client_osd1.ktab.
    Entry for principal ceph/ceph-osd1 with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/etc/gss_client_osd1.ktab.
    Entry for principal ceph/ceph-osd1 with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/etc/gss_client_osd1.ktab.
    kadmin.local:  ktadd -k /etc/gss_client_osd2.ktab ceph/ceph-osd2
    Entry for principal ceph/ceph-osd2 with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/gss_client_osd2.ktab.
    Entry for principal ceph/ceph-osd2 with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/gss_client_osd2.ktab.
    Entry for principal ceph/ceph-osd2 with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/etc/gss_client_osd2.ktab.
    Entry for principal ceph/ceph-osd2 with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/etc/gss_client_osd2.ktab.
    kadmin.local:  ktadd -k /etc/gss_client_osd3.ktab ceph/ceph-osd3
    Entry for principal ceph/ceph-osd3 with kvno 3, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/gss_client_osd3.ktab.
    Entry for principal ceph/ceph-osd3 with kvno 3, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/gss_client_osd3.ktab.
    Entry for principal ceph/ceph-osd3 with kvno 3, encryption type des3-cbc-sha1 added to keytab WRFILE:/etc/gss_client_osd3.ktab.
    Entry for principal ceph/ceph-osd3 with kvno 3, encryption type arcfour-hmac added to keytab WRFILE:/etc/gss_client_osd3.ktab.
    kadmin.local:  ktadd -k /etc/gss_client_osd4.ktab ceph/ceph-osd4
    Entry for principal ceph/ceph-osd4 with kvno 4, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/gss_client_osd4.ktab.
    Entry for principal ceph/ceph-osd4 with kvno 4, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/gss_client_osd4.ktab.
    Entry for principal ceph/ceph-osd4 with kvno 4, encryption type des3-cbc-sha1 added to keytab WRFILE:/etc/gss_client_osd4.ktab.
    Entry for principal ceph/ceph-osd4 with kvno 4, encryption type arcfour-hmac added to keytab WRFILE:/etc/gss_client_osd4.ktab.
    
    # ls -1 /etc/gss_client_*
    /etc/gss_client_mon1.ktab
    /etc/gss_client_osd1.ktab
    /etc/gss_client_osd2.ktab
    /etc/gss_client_osd3.ktab
    /etc/gss_client_osd4.ktab
    

    我们还可以通过以下方式检查这些新创建的 keytab 客户端文件

    # klist -kte /etc/gss_client_mon1.ktab
    Keytab name: FILE:/etc/gss_client_mon1.ktab
    KVNO Timestamp           Principal
    ---- ------------------- ------------------------------------------------------
       2 10/8/2018 14:35:30 ceph/ceph-mon1@MYDOMAIN.COM (aes256-cts-hmac-sha1-96)
       2 10/8/2018 14:35:31 ceph/ceph-mon1@MYDOMAIN.COM (aes128-cts-hmac-sha1-96)
       2 10/8/2018 14:35:31 ceph/ceph-mon1@MYDOMAIN.COM (des3-cbc-sha1)
       2 10/8/2018 14:35:31 ceph/ceph-mon1@MYDOMAIN.COM (arcfour-hmac)
    ...
    
  6. Ceph 中添加了一个新的 设置参数gss_ktab_client_file,它指向与相关的 Ceph 节点 (或主体) 相关的 keytab 文件。

    默认情况下,它指向 /var/lib/ceph/$name/gss_client_$name.ktab。因此,对于 Ceph 服务器 osd1.mydomain.com,keytab 文件的位置和名称应为:/var/lib/ceph/osd1/gss_client_osd1.ktab

    因此,我们需要将每个新创建的 keytab 文件从 KDC scp 到它们各自的 Ceph 集群节点(例如):# for node in mon1 osd1 osd2 osd3 osd4; do scp /etc/gss_client_$node*.ktab root@ceph-$node:/var/lib/ceph/$node/; done

    或者任何其他让人感到舒服的方式,只要每个 keytab 客户端文件被复制到正确的位置。

    此时,即使 不使用任何 keytab 客户端文件,我们也应该能够对 用户主体 进行身份验证

    # kdestroy -A && kinit -f johndoe && klist -f
    Password for johndoe@MYDOMAIN.COM:
    Ticket cache: KEYRING:persistent:0:0
    Default principal: johndoe@MYDOMAIN.COM
    
    Valid starting       Expires              Service principal
    10/10/2018 15:32:01  10/11/2018 07:32:01  krbtgt/MYDOMAIN.COM@MYDOMAIN.COM
        renew until 10/11/2018 15:32:01, Flags: FRI
    ...
    

    鉴于 keytab 客户端文件 应该已经复制到 Kerberos 客户端(Ceph 集群节点)并可用,我们应该能够在继续之前使用它进行身份验证

    # kdestroy -A && kinit -k -t /etc/gss_client_mon1.ktab -f 'ceph/ceph-mon1@MYDOMAIN.COM' && klist -f
    Ticket cache: KEYRING:persistent:0:0
    Default principal: ceph/ceph-mon1@MYDOMAIN.COM
    
    Valid starting       Expires              Service principal
    10/10/2018 15:54:25  10/11/2018 07:54:25  krbtgt/MYDOMAIN.COM@MYDOMAIN.COM
        renew until 10/11/2018 15:54:25, Flags: FRI
    ...
    
  7. 如果存在且可读,默认客户端 keytab 将用于自动获取 GSSAPI 客户端应用程序的初始凭证。默认情况下,获取初始凭证时使用客户端 keytab 中第一个条目的主体名称

    1. the KRB5_CLIENT_KTNAME environment variable.

    2. the default_client_keytab_name profile variable in [libdefaults].

    3. The hardcoded default, DEFCKTNAME.

    所以,我们所做的是在内部将环境变量 KRB5_CLIENT_KTNAME 设置为与 gss_ktab_client_file 相同的位置,即 /var/lib/ceph/osd1/gss_client_osd1.ktab,并更改 ceph.conf 文件以添加新的身份验证方法。

    /etc/ceph/ceph.conf
    [global]
        ...
        auth_cluster_required = gss
        auth_service_required = gss
        auth_client_required = gss
        gss_ktab_client_file = /{$my_new_location}/{$my_new_ktab_client_file.keytab}
        ...
    
  8. 这样 GSSAPI 将能够读取 keytab 文件,并通过名称和服务解析过程 (由 DNS 提供),能够按如下方式请求 TGT

    1. 用户/客户端向 KDC 服务器发送主体身份和凭证(TGT 请求)。

    2. KDC 在其内部数据库中检查相关主体。

    3. KDC 创建 TGT,并使用主体的密钥对其进行包装(TGT + Key)。

    4. 新创建的 TGT 被解密并存储在凭证缓存中。

    5. 此时,Kerberos/GSSAPI 感知的应用程序(和/或服务)能够检查 keytab 文件中活动的 TGT 列表。



** 仅供 Ceph 开发人员参考 **

我们当然可以使用直观的原生 KRB5 APIs(而不是 GSSAPIs),但我们想要一个在网络安全方面更具可移植性的选项,这是 GSS (通用安全标准) -API 的标志。它本身并不真正提供安全服务。

相反,它是一个以通用方式向调用者提供安全服务的框架。

GSS-API 主要做两件事

  1. 它创建一个安全上下文,数据可以在应用程序之间传递。上下文可以被认为是两个应用程序之间的 “信任状态”

    共享上下文的应用程序彼此了解对方是谁,因此只要上下文持续存在,就可以允许它们之间进行数据传输。

  2. 它对要传输的数据应用一种或多种类型的保护,称为 “安全服务”

GSS-API 为应用程序提供了多种可移植性

  1. 机制独立性。 GSS-API 为已实现的机制提供了通用接口。通过指定默认安全机制,应用程序不需要知道它正在使用哪种机制(例如,Kerberos v5),甚至不需要知道它使用哪种机制类型。例如,当应用程序将用户的凭证转发到服务器时,它不需要知道该凭证是 Kerberos 格式还是其他机制使用的格式,也不需要知道凭证如何由机制存储以及如何由应用程序访问。(如有必要,应用程序可以指定要使用的特定机制)

  2. 协议独立性。 GSS-API 独立于任何通信协议或协议套件。它可以与使用套接字、RCP 或 TCP/IP 等的应用程序一起使用。RPCSEC_GSS “RPCSEC_GSS Layer” 是一个额外的层,它将 GSS-API 与 RPC 平滑集成。

  3. 平台独立性。 GSS-API 完全不了解应用程序正在运行的操作系统类型。

  4. 保护质量独立性。 保护质量 (QOP) 是用于加密数据或生成加密标签的算法类型的名称;GSS-API 允许程序员忽略 QOP,使用 GSS-API 提供的默认值。(另一方面,如果需要,应用程序可以指定 QOP。)

GSS-API 提供的基本安全性是身份验证。身份验证是身份的验证:如果通过身份验证,则意味着您被确认为您声称的身份。

如果底层机制支持,GSS-API 提供两种额外的安全服务

  1. 完整性: 仅仅知道向您发送数据的应用程序是它声称的身份并不总是足够的。数据本身可能已损坏或受到威胁。

    GSS-API 提供了一种伴随数据的加密标签,称为 Message Integrity Code (MIC),以证明到达您家门口的数据与发送方传输的数据相同。这种对数据有效性的验证被称为 “完整性”

  2. 保密性: 然而,身份验证和完整性都使数据本身保持不变,因此如果数据被拦截,其他人可以读取它。

    因此,如果底层机制支持,GSS-API 允许加密数据。这种数据加密被称为 “保密性”


GSS-API 可用的机制

GSS-API 的当前实现仅适用于 Kerberos v5 安全机制。

Mechanism Name          Object Identifier       Shared Library  Kernel Module
----------------------  ----------------------  --------------  --------------
diffie_hellman_640_0    1.3.6.4.1.42.2.26.2.4   dh640-0.so.1
diffie_hellman_1024_0   1.3.6.4.1.42.2.26.2.5   dh1024-0.so.1
SPNEGO                  1.3.6.1.5.5.2
iakerb                  1.3.6.1.5.2.5
SCRAM-SHA-1             1.3.6.1.5.5.14
SCRAM-SHA-256           1.3.6.1.5.5.18
GSS-EAP (arc)           1.3.6.1.5.5.15.1.1.*
kerberos_v5             1.2.840.113554.1.2.2    gl/mech_krb5.so gl_kmech_krb5

Therefore:
    Kerberos Version 5 GSS-API Mechanism
    OID {1.2.840.113554.1.2.2}

    Kerberos Version 5 GSS-API Mechanism
    Simple and Protected GSS-API Negotiation Mechanism
    OID {1.3.6.1.5.5.2}

有两种不同的格式

  1. 第一种格式 { 1 2 3 4 },由 GSS-API 规范正式规定。gss_str_to_oid() 期望第一种格式。

  2. 第二种格式 1.2.3.4,使用更广泛,但不是官方标准格式。

尽管 GSS-API 使数据保护变得简单,但为了最大限度地提高其通用性,它不执行某些操作。其中包括

  1. 为用户或应用程序提供安全凭证。这些必须由底层安全机制提供。GSS-API 确实允许应用程序获取凭证,无论是自动还是显式。

  2. 在应用程序之间传输数据。应用程序有责任处理所有数据在对等方之间的传输,无论它是安全相关数据还是“普通”数据。

  3. 区分不同类型的传输数据(例如,知道或确定数据包是普通数据而不是 GSS-API 相关数据)。

  4. 指示由于远程(异步)错误导致的状态。

  5. 自动保护多进程程序的进程之间发送的信息。

  6. 分配字符串缓冲区(“Strings and Similar Data”)以传递给 GSS-API 函数。

  7. 解除分配 GSS-API 数据空间。这些必须使用 gss_release_buffer()gss_delete_name() 等函数显式解除分配。


以下是使用 GSS-API 的基本步骤

  1. 每个应用程序(发送方和接收方)显式获取凭证,如果凭证尚未自动获取。

  2. 发送方启动安全上下文,接收方接受它。

  3. 发送方将安全保护应用于要传输的消息(数据)。这意味着它要么加密消息,要么用识别标签标记消息。发送方传输受保护的消息。(发送方可以选择不应用任何安全保护,在这种情况下,消息只有与之关联的默认 GSS-API 安全服务。即身份验证,其中接收方知道发送方是其声称的身份。)

  4. 接收方解密消息(如果需要)并验证它(如果合适)。

  5. (可选)接收方将识别标签返回给发送方以进行确认。

  6. 两个应用程序都销毁共享安全上下文。如有必要,它们还可以解除分配任何 “剩余” GSS-API 数据。

使用 GSS-API 的应用程序应包括文件 gssapi.h

好的参考资料

** Kerberos 服务器设置 **

首先,这不是生产环境的推荐。我们不涉及 Master/Slave replication cluster 或任何与生产环境相关的内容(ntp/chrony、dns、pam/nss、sssd 等)。

此外,在服务器端可能需要不同的依赖项和/或配置步骤,具体取决于将使用哪个后端数据库。LDAP 作为后端数据库 就是一个很好的例子。

在客户端方面,根据将使用的客户端后端配置,有不同的步骤。例如 PAM/NSSSSSD(以及用于身份服务的 LDAP,[和用于身份验证服务的 Kerberos]),这是加入 MS Active Directory domains 和进行 User Logon Management 的最佳选择。

我们绝不打算在此处涵盖所有可能的场景/组合。这些步骤旨在简单地 启动并运行一个 (MIT) Kerberos 服务器

请注意,rpm 包的名称可能略有不同,二进制文件和/或配置文件的位置也可能不同,具体取决于我们指的是哪个 Linux 发行版。

最后,请记住,某些 Linux 发行版将有自己的 向导,可以执行所需的基本配置

SUSE:
    Kerberos server:
        yast2 auth-server

    Kerberos client:
        pam/nss: yast2 ldapkrb
        sssd: yast2 auth-client

但是,我们将采用 手动配置

为了让新的 MIT KDC 服务器运行起来

  1. 通过以下方式安装 KDC 服务器

    1. 安装所需的包

      SUSE: zypper install krb5 krb5-server krb5-client
          Additionally:
              for development: krb5-devel
              if using 'sssd': sssd-krb5 sssd-krb5-common
      
      REDHAT: yum install krb5-server krb5-libs krb5-workstation
          Additionally: 'Needs to be checked'
      
    2. 编辑 KDC 服务器配置文件

      /var/lib/kerberos/krb5kdc/kdc.conf
      [kdcdefaults]
              kdc_ports = 750,88
      [realms]
              MYDOMAIN.COM = {
                  acl_file = /var/lib/kerberos/krb5kdc/kadm5.acl
                  admin_keytab = FILE:/var/lib/kerberos/krb5kdc/kadm5.keytab
                  default_principal_flags = +postdateable +forwardable +renewable +proxiable
                                                          +dup-skey -preauth -hwauth +service
                                                          +tgt-based +allow-tickets -pwchange
                                                          -pwservice
                  dict_file = /var/lib/kerberos/krb5kdc/kadm5.dict
                  key_stash_file = /var/lib/kerberos/krb5kdc/.k5.MYDOMAIN.COM
                  kdc_ports = 750,88
                  max_life = 0d 10h 0m 0s
                  max_renewable_life = 7d 0h 0m 0s
              }
      ...
      
    3. 编辑 Kerberos 客户端配置文件

      /etc/krb5.conf
      [libdefaults]
          dns_canonicalize_hostname = false
          rdns = false
          forwardable = true
          dns_lookup_realm = true     //--> if using DNS/DNSMasq
          dns_lookup_kdc = true       //--> if using DNS/DNSMasq
          allow_weak_crypto = false
          default_realm = MYDOMAIN.COM
          default_ccache_name = KEYRING:persistent:%{uid}
      
      [realms]
          MYDOMAIN.COM = {
              kdc = kerberos.mydomain.com
              admin_server = kerberos.mydomain.com
              ...
          }
      ...
      
  2. 创建 Kerberos 数据库

    SUSE: kdb5_util create -s
    
    REDHAT: kdb5_util create -s
    
  3. 启用并启动 'KDC 和 KDC admin' 服务器

    SUSE: systemctl enable/start krb5kdc
          systemctl enable/start kadmind
    
    REDHAT: systemctl enable/start krb5kdc
            systemctl enable/start kadmin
    
  4. 创建 Kerberos 管理员

    Kerberos 主体可以在 KDC 服务器本地创建,也可以通过网络使用 'admin principal' 创建。在 KDC 服务器上,使用 kadmin.local

    1. 列出现有的主体

      kadmin.local:  listprincs
      K/M@MYDOMAIN.COM
      krbtgt/MYDOMAIN.COM@MYDOMAIN.COM
      kadmin/admin@MYDOMAIN.COM
      kadmin/changepw@MYDOMAIN.COM
      kadmin/history@MYDOMAIN.COM
      kadmin/kerberos.mydomain.com@MYDOMAIN.COM
      root/admin@MYDOMAIN.COM
      ...
      

    b. 如果我们没有内置的 'admin principal',那么我们创建一个(无论 principal name 是什么,我们使用 root,因为默认情况下 kinit 尝试使用相同的系统登录用户名进行身份验证,除非将 principal 作为参数传递 kinit principal

    # kadmin.local -q "addprinc root/admin"
    Authenticating as principal root/admin@MYDOMAIN.COM with password.
    WARNING: no policy specified for root/admin@MYDOMAIN.COM; defaulting to no policy
    Enter password for principal "root/admin@MYDOMAIN.COM":
    
    1. 确认新创建的 'admin principal' 在 KDC ACL 中具有所需的权限(如果 ACL 更改,则需要重新启动 kadmind

      SUSE: /var/lib/kerberos/krb5kdc/kadm5.acl
      REDHAT: /var/kerberos/krb5kdc/kadm5.acl
      
      ###############################################################################
      #Kerberos_principal      permissions     [target_principal]      [restrictions]
      ###############################################################################
      #
      */admin@MYDOMAIN.COM     *
      
    2. 创建简单的 'user principal'(步骤与 Ceph 方面的事项; 4a 相同)

      kadmin.local:  addprinc johndoe
      WARNING: no policy specified for johndoe@MYDOMAIN.COM; defaulting to no policy
      Enter password for principal "johndoe@MYDOMAIN.COM":
      Re-enter password for principal "johndoe@MYDOMAIN.COM":
      Principal "johndoe@MYDOMAIN.COM" created.
      
    3. 确认新创建的 'user principal' 能够进行身份验证(步骤与 Ceph 方面的事项; 6 相同)

      # kdestroy -A && kinit -f johndoe && klist -f
      Password for johndoe@MYDOMAIN.COM:
      Ticket cache: KEYRING:persistent:0:0
      Default principal: johndoe@MYDOMAIN.COM
      
      Valid starting       Expires              Service principal
      11/16/2018 13:11:16  11/16/2018 23:11:16  krbtgt/MYDOMAIN.COM@MYDOMAIN.COM
              renew until 11/17/2018 13:11:16, Flags: FRI
      ...
      
  5. 此时,我们应该拥有一个 简单的 (MIT) Kerberos 服务器并运行

    1. 考虑到我们将希望使用 keytab 文件,用于 'user and service' 主体,请参考 Ceph 方面的事项,从步骤 4 开始。

    2. 确保您熟悉以下内容及其 manpages

      krb5.conf       -> Krb client config file
      kdc.conf        -> KDC server config file
      
      krb5kdc         -> KDC server daemon
      kadmind         -> KDC administration daemon
      
      kadmin          -> Krb administration tool
      kdb5_util       -> Krb low-level database administration tool
      
      kinit           -> Obtain and cache Kerberos ticket-granting ticket tool
      klist           -> List cached Kerberos tickets tool
      kdestroy        -> Destroy Kerberos tickets tool
      
  6. 名称解析

    如前所述,Kerberos 严重依赖名称解析。大多数 Kerberos 问题通常与名称解析有关,因为 Kerberos 对 系统名称主机查找非常挑剔

    1. Ceph 方面的事项; 步骤 2a 所述,DNS RR 通过分别使用 (srv resources)(txt record)(根据 开始之前; DNS 解析)极大地改善了服务位置和主机/域解析。

      /var/lib/named/master/mydomain.com
      kerberos                IN A        192.168.10.21
      kerberos-slave          IN A        192.168.10.22
      _kerberos               IN TXT      "MYDOMAIN.COM"
      _kerberos._udp          IN SRV      1 0 88 kerberos
      _kerberos._tcp          IN SRV      1 0 88 kerberos
      _kerberos._udp          IN SRV      20 0 88 kerberos-slave
      _kerberos-master._udp   IN SRV      0 0 88 kerberos
      _kerberos-adm._tcp      IN SRV      0 0 749 kerberos
      _kpasswd._udp           IN SRV      0 0 464 kerberos
      ...
      
    2. 对于没有 DNS 服务器 的小型网络或开发环境,我们可以选择使用 DNSMasq,这是一个易于配置的轻量级 DNS 服务器(以及其他一些功能)。

      这些记录可以添加到 /etc/dnsmasq.conf(除了所需的 'host records' 之外)

      /etc/dnsmasq.conf
      ...
      txt-record=_kerberos.mydomain.com,"MYDOMAIN.COM"
      srv-host=_kerberos._udp.mydomain.com,kerberos.mydomain.com,88,1
      srv-host=_kerberos._udp.mydomain.com,kerberos-2.mydomain.com,88,20
      srv-host=_kerberos-master._udp.mydomain.com,kerberos.mydomain.com,88,0
      srv-host=_kerberos-adm._tcp.mydomain.com,kerberos.mydomain.com,749,0
      srv-host=_kpasswd._udp.mydomain.com,kerberos.mydomain.com,464,0
      srv-host=_kerberos._tcp.mydomain.com,kerberos.mydomain.com,88,1
      ...
      
    3. 在 'b)' 全部设置好并且 dnsmasq 服务启动并运行后,我们可以使用以下方式进行测试

      # nslookup kerberos
      Server:     192.168.10.1
      Address:    192.168.10.1#53
      
      Name:   kerberos.mydomain.com
      Address: 192.168.10.21
      
      # host -t SRV _kerberos._tcp.mydomain.com
      _kerberos._tcp.mydomain.com has SRV record 1 0 88 kerberos.mydomain.com.
      
      # host -t SRV {each srv-host record}
      # host -t TXT _kerberos.mydomain.com
      _kerberos.mydomain.com descriptive text "MYDOMAIN.COM"
      ...
      
    1. 只要 name resolution 正常工作,无论是 dnsmasq 还是 named,Kerberos 都应该能够找到所需的服务记录。

由 Ceph 基金会为您呈现

Ceph 文档是由非营利性 Ceph 基金会 资助和托管的社区资源。如果您希望支持这项工作和我们的其他努力,请考虑 立即加入