Kubernetes 身份管理:身份验证

与其他复杂的系统一样,Kubernetes 拥有自己的安全模型来与用户、系统进行交互。在本文中,我将介绍 Kubernetes 的一些身份验证方案,并提供有关管理集群访问权限的示例和建议。 #身份对 Kubernetes 意味着什么 首先,你需要明白在 Kubernetes 中,“什么是身份”?Kubernetes 与大多数其他系统和应用程序截然不同。它是一组 API,没有 “Web 界面”、没有“登录”、“会话”或“超时”等选项框。每个 API 请求都是唯一且不同的,并且它必须包含 Kubernetes 验证和授权请求所需的所有内容。 也就是说,你要牢记这样一个道理:Kubernetes 的用户不会存在于任何持久状态中。你不需要将 Kubernetes 连接到 LDAP 目录或 Active Directory 中,但是每个请求都必须存在一种方法可以对 Kubernetes ASSERT(断言)身份。我将 ASSERT 大写,是因为它将在后文变得十分重要。Kubernetes 不会对用户进行身份验证,它验证的是断言。如果你想和更多 Kubernetes 技术专家交流,可以加我微信liyingjiese,备注『加群』。群里每周都有全球各大公司的最佳实践以及行业最新动态。 ##服务账户 服务帐户正好与我们刚刚提到的规则相反。Kubernetes 不存储有关用户的信息,但它存储服务帐户的信息(该信息为任何非人的事物)。在 Kubernetes 中,与任何内容交互的东西都会被作为服务帐户运行。例如,如果你要提交一个非常基本的 Pod:
1.jpg
在部署后的 Kubernetes 中,你可以通过运行 kubectl get pod myapp-pod -o yaml 来查看它:
2.jpg
你会发现这里存在 serviceAccount 和 serviceAccountName 属性,这两者都是 default。此服务帐户由入口控制器链为使用者注入,你可以在 Pod 上设置自己的服务帐户。 服务帐户易于创建和使用,但它们有一些缺点: * 服务帐户的令牌是一个很长的字符串,需要被记录下来。如果处理不当,它就有可能会被利用; * 授权服务帐户的唯一方法是通过 RBAC 进行绑定; * 在服务帐户还在使用期间时,如果一个人泄露了令牌并且未被发觉。它可能会被一直滥用,直到被处理为止。 在日常工作中,如果你的应用程序在一个 Pod 中运行并且需要与 API 服务器通信,你就可以通过挂载到 Pod 上的一个 secret 来检索 Pod 的服务帐户。 通过上面示例 YAML,你会发现一个挂载的卷被添加到了 /var/run/secrets/kubernetes.io/serviceaccount 中,这其中有一个令牌文件包含 Pod 的服务帐户令牌。你需要注意:不要将服务帐户令牌嵌入到集群中运行的 Pod 的 secret 或配置中!因为这样的做法会使得你使用旋转令牌(rotating token)变得更加困难,并且难以管理。 ##用户账户 Kubernetes 不连接任何类型的用户存储(至少不直接连接)。这意味着在每个请求中,你必须为 Kubernetes 提供足够的信息以验证调用者的身份。Kubernetes 并不关心你如何建立身份,它只关心它如何证明身份是有效的。 #Kubernetes 如何知道你是谁 ##OpenID Connect OpenID Connect 是你用来验证用户身份的选项: * OpenID Connect 令牌具有短暂性。当该类令牌被拦截或泄露时,如果攻击者得知该令牌的字符串,那么令牌就没用了; * 使用 OpenID Connect 的好处是:Kubernetes 永远不会拥有用户的凭据,它不可能泄漏 Kubernetes 没有的东西; * OpenID Connect 提供的用户标识不仅可以提供用户名信息,还可以提供组信息。这使得它们通过 LDAP 目录或外部数据库管理访问变得更容易(你无需为单个用户创建 RBAC 绑定); * 通过在 Kubernetes 和身份层之间添加“代理”,你可以更轻松地添加多种类型的身份验证,例如多因素身份验证; * 大量的开源 OpenID Connect 可以与 Kubernetes 一起使用。 ##OpenID Connect Primer 在深入研究如何使用 OpenID Connect 之前,你需要先了解一下该协议: * OpenID Connect 是一个建立在 OAuth2 之上的断言生成协议; * OAuth2 则是一个用于传输承载令牌授权的协议。 这两点似乎缺少一个词:认证!那是因为 OpenID Connect 不是身份验证协议。它不关心你如何进行身份验证。如果用户使用的是用户名和密码,那么一张智能卡或许看起来真的很值得信赖,但是 OpenID Connect 是一种用于生成、检索和刷新用户断言的协议。用户如何进行身份验证最终取决于 OpenID Connect 的实现。 OAuth2 是一个比较关键的协议,它可以用于传递令牌,但是它没有定义令牌是什么或如何使用。它只是定义了令牌和依赖方之间如何传递令牌。 #Kubernetes 如何使用 OpenID Connect 图 1 显示了 Kubernetes 身份验证页面:
3.jpg
以下为该图的基础知识点: * 用户可以登录到用户身份的提供程序中; * 身份提供者会生成一个 id_token 和一个 refresh_token; * id_token 可以将用户的身份断言为 Kubernetes 的; * 当 id_token 过期时,refresh_token 用于生成新的 id_token。 一个 id_token 是一个 JSON Web Token(JWT),它可以表示: * 用户是谁; * 用户所属的组(可选); * 令牌有效时长; * 它包含一个数字签名,用于验证 JWT 是否未被篡改。 用户的 ID 属性 sub 通常是用户的唯一标识符。用户经常会使用 Active Directory 的登录 ID(也称为 samAccountName),还有一些人更喜欢使用电子邮件地址。一般来说,这不是最佳的做法。用户的 ID 应该是唯一的和不可变的。虽然电子邮件地址也是唯一的,但它并不总是不可变的(例如,有时名称会更改)。 JWT 将在从 kubectl 到 Kubernetes 的每个请求上传递。其中 id_token 被称为 “承载令牌”,因为它会授予承载者访问权限而无需任何额外的检查。这意味着,如果 API 调用流程中的系统泄漏此令牌,攻击者就可以滥用该系统了。 因为这些令牌很容易被滥用,所以它们的寿命极短。我推荐它们的使用寿命在一分钟左右。这样,如果当一个令牌被泄露时,即使攻击者知道它是什么,但是令牌也已经过期。使用此类短期令牌,最重要的是在它过期后,系统会配置一个 refresh_token 去更新你的 id_token。 kubectl 知道如何通过使用 refresh_token 调用标识提供者的授权服务 URL,并更新 id_token 令牌。 refresh_token 是 Kubernetes 的 API 服务器永远不会使用的令牌,用户可以将它视为 secret。该令牌用于获取新的 JWT,此时可以使用 JWT 中新的 refresh_token。如果 id_token 的生命周期非常短,则 refresh_token 超时与非活动超时类似,通常为 15-20 分钟。这样,你的 Kubernetes 实现将符合企业中针对不活动超时的策略。使用一个 refresh_token 获取一个新 id_token 内容比使用更长时间更安全,因为这个 refresh_token 意味着以下内容: * 它只能使用一次。一旦使用,就会生成一个新的令牌; * 它只在用户和身份提供者之间传递,在极少情况下会被泄露; * 如果它自己被泄漏了,就不能被用来识别你。因为它是不透明的,所以如果没有额外的信息,攻击者根本不知道该如何处理它。 Kubernetes 仪表板 仪表板没有自己的登录系统。所有这一切都可以使用代表用户的现有令牌。这意味着在仪表板前面放置了一个反向代理,它将 id_token 在每个请求上注入 ,然后反向代理会根据需求刷新令牌。 #我应该使用哪个身份提供商 在选择身份提供商时,Kubernetes 实际上只有两个要求: * 它必须支持 OpenID Connect 发现; * 它提供了一种生成令牌并将其注入到 〜/.kube/config 的机制中。 只要符合以上两个要求,你就可以使用了。因为这种类型的身份提供商,它使你不必手动告诉 Kubernetes 不同的 URL 在哪里,用于签名的密钥是什么 ...... 将 Kubernetes 指向所有具有这种信息发现的 URL 就容易多了。因为大多数身份提供商都支持开箱即用(通用标准)。 而关于如何从你的登录点(通常是 Web 浏览器)将令牌信息添加到 〜/.kube/config 中,可以有不同的方法。 ##Web 浏览器注入 在此模型中,所有内容都集中在你的 Web 浏览器上。你可以通过浏览器进行身份验证,然后获得正确设置 kubectl 客户机的命令。例如,OpenUnison(我们自己的项目)为你提供了一个命令,该命令可用于身份验证后设置集群的配置(图 2)。
4.png
图 2 浏览器令牌 你可以使用 kubectl 的内置功能从命令行配置配置文件以完成设置。 这种方法有几个优点: * 浏览器具有最多的身份验证选项。除了用户名和密码,你还可以集成 Kerberos、Multi-Factor 等; * 你不需要管理复杂的 Kubernetes 配置; * 这种方法适用于 stock kubectl 命令。 Kubectl 插件 你可以使用插件扩展 kubectl 命令。使用插件,你可以收集用户的凭据,然后生成令牌。我看到过一些插件可以从 CLI 收集到你的凭证,还有一些插件可以启动浏览器提示你登录。从 CLI 角度来看,这种方法很好,因为它可以让你的 CLI 驱动你的用户体验。这种方法的主要缺点是需要在每个工作站上安装插件。 下载配置 使用此方法,身份提供程序(或自定义应用程序)可以为你提供用于下载的完整生成配置文件。但是,如果你没有将某些内容保存到正确的位置上,就可能会产生支持问题。 选择身份提供者后,请按照其说明进行集成,其中关键项是发现 URL、标识符“claim”以及组的“claim”。 ##X509 证书 证书身份验证利用客户端(通常是 kubectl 命令)和 Kubernetes API 服务器之间的 TLS 握手,通过向 API 服务器提供证书来声明身份。除了一个用例之外,这种方法并不是 “最佳实践”: * 证书不能在 Kubernetes 中撤销。你需要等到证书过期或重新生成整个集群后才可以撤销; * 证书的私钥永远不离开生成它的安全介质。通常情况下,你会一起“获得”密钥对和证书; * 使用带证书的组很困难,你需要将它们嵌入到 subject 中。 你可以使用 X509 证书来进行身份验证的情形是:当你在引导集群时,或者在紧急情况下,你的身份提供程序不可用。 大多数发行版都会为每个主服务器部署密钥对。因此,如果你 ssh 进入该主服务器,则可以使用它 kubectl 管理集群。这意味着你需要锁定对主服务器的访问权限。 ##Webhook 此方法允许你通过 Webhook 集成第三方登录或令牌系统。Kubernetes 不会告诉你 Kubernetes 如何验证身份,而是调用 webhook 并询问“这是谁”。 除非你是云提供商并拥有自己的身份解决方案,否则请勿这样做。几乎我见过的每一个实现都变成了一个糟糕的 OpenID Connect。 ##带模拟的反向代理 这里客户端(kubectl 或其他)不直接与 API 服务器通信。它会与反向代理进行通信,然后反向代理会将头部注入请求以表示用户。这通常被当作处理高级身份验证的一种方法,因为从 API 服务器的角度来看,它需要的工作量最少。实施步骤如下: * 创建服务帐户; * 授权服务帐户进行模拟; * 配置反向代理以将服务帐户和模拟标头注入到每个请求中。 这个方案现有的标准可能会更适合用户的需求,因为它易于管理和维护。 #如何将身份整合到 Kubernetes 中 要将身份整合到 Kubernetes 中,请遵循以下基本核对清单: * 仅将服务帐户用于系统,而不是人员; * 建议使用 OpenID Connect。因为它会受到多种系统的审核和支持,包括开源和专有系统; * 仅对“紧急情况”使用证书认证。 遵循这些规则,你会发现团队中的开发人员会很乐意记住身份验证的密码,安防人员也会很高兴地遵守合规性的要求。 参考文献:https://www.linuxjournal.com/content/kubernetes-identity-management-authentication 原文链接:https://mp.weixin.qq.com/s/9_mS5eet8WDSMJcBzQCelg

0 个评论

要回复文章请先登录注册