原创:Marc Boorshtein
编译:小君君(才云)
当你完成 Kubernetes 部署时,你应该如何安全地将它交到开发人员和管理人员手中呢?
与其他复杂的系统一样,Kubernetes 拥有自己的安全模型来与用户、系统进行交互。在本文中,我将介绍 Kubernetes 的一些身份验证方案,并提供有关管理集群访问权限的示例和建议。
身份对 Kubernetes 意味着什么
首先,你需要明白在 Kubernetes 中,“什么是身份”?Kubernetes 与大多数其他系统和应用程序截然不同。它是一组 API,没有 “Web 界面”、没有“登录”、“会话”或“超时”等选项框。每个 API 请求都是唯一且不同的,并且它必须包含 Kubernetes 验证和授权请求所需的所有内容。
也就是说,你要牢记这样一个道理:Kubernetes 的用户不会存在于任何持久状态中。你不需要将 Kubernetes 连接到 LDAP 目录或 Active Directory 中,但是每个请求都必须存在一种方法可以对 Kubernetes ASSERT(断言)身份。我将 ASSERT 大写,是因为它将在后文变得十分重要。Kubernetes 不会对用户进行身份验证,它验证的是断言。
服务账户
服务帐户正好与我们刚刚提到的规则相反。Kubernetes 不存储有关用户的信息,但它存储服务帐户的信息(该信息为任何非人的事物)。在 Kubernetes 中,与任何内容交互的东西都会被作为服务帐户运行。例如,如果你要提交一个非常基本的 Pod:
在部署后的 Kubernetes 中,你可以通过运行 kubectl get pod myapp-pod -o yaml
来查看它:
你会发现这里存在 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 身份验证页面:
图 1 Kubernetes OpenID Connect 流程
以下为该图的基础知识点:
-
用户可以登录到用户身份的提供程序中;
-
身份提供者会生成一个
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)。
图 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。因为它会受到多种系统的审核和支持,包括开源和专有系统;
-
仅对“紧急情况”使用证书认证。
遵循这些规则,你会发现团队中的开发人员会很乐意记住身份验证的密码,安防人员也会很高兴地遵守合规性的要求。
--
参考文献:
1.https://www.linuxjournal.com/content/kubernetes-identity-management-authentication
推荐阅读:
在看点一下
写留言
以上所述就是小编给大家介绍的《Kubernetes 身份管理:身份验证》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Kubernetes身份验证机制演示
- Mongodb常用的身份验证方式
- 使用装饰器完成用户身份验证
- HTTP身份验证渗透测试指南
- 通过足迹进行身份识别 AI 将身份验证技术发挥到了极致
- 技术分享 | 多种测试HTTP身份验证的方法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。