Kubernetes实现SSO登录(一)

【编者的话】你是否也在为登录各种网站,提交身份信息而烦恼?是否有一种更省时、省事的打开方式?好吧,让我们来看看原文的作者Joel Speed是如何利用SSO,开启Kubernetes的正确方式。原文是连载的方式,以下是第一篇的内容。

无论生活还是工作,我们经常会登录各种各样的网站,对于我来说,要记住每个网站的登录信息简直就像一场噩梦。

每次注册一个新网站,我会找“使用……登录”之类的链接,希望它能直接从Google或Facebook之类的地方获取我的注册信息。我发现SSO能提升用户体验,减少帐户数量的同时,也节省了一天中登录的次数。

作为 Pusher 的云工程师,我每天都会用Kubernetes。有一段时间,用我们的Kubernetes集群进行身份验证的体验和理想中的SSO(Single Sign-On:单点登录)相差甚远。从一开始使用Kubernetes,我们一直在用单个共享证书进行身份验证,但我们希望每位工程师都拥有自己的凭证。为此,我试图将Kubernetes的登录尽可能做的简单易用,就像我登录其他网站时选择“使用……登录”一样。

Kubernetes很棒的一点是它的认证和授权完全分离。身份认证(Authn)是用来识别用户是谁,授权(Authz)是用来确认是否允许执行某项操作。我们可以把两者想象成护照和签证。在边境,有人检查你的护照(Authn),确认你是谁,然后检查你的Visa(Authz),确认你是否有权进入他们的国家。

这篇文章中,我会阐述基于Kubernetes的身份验证,尤其是SSO的方法,但不会深入的介绍具体的配置。我会在 另一篇文章 中介绍我们正在使用的身份验证流程,以及如何配置。

Kubernetes支持的认证方法

Kubernetes有三种主要的身份验证方法,用于和API进行交互。官网的一个 页面 列出了更多的认证方法,但以下三种是用户认证常见的方法。

静态密码

也叫基本身份验证。由于添加新用户,需要更新每个API服务器节点上的文件,然后重启每个API服务器,因此不利于扩展。我们很快就排除了这种方法。

X.509客户端证书

使用这种方法,每个开发人员都有自己的证书,在建立连接时会呈现给API服务器。API服务器通过验证证书和使用证书内的信息来识别该会话的用户。

证书认证有几个问题:
  • 证书在签发时有一个有效期。它们在有效期内进行用户认证。(不使用OCSP)。
  • 证书必须由一些通用证书签发机构(CA)签署。Kubernetes需要CA证书的副本来验证客户端证书。如果允许人们访问这些CA证书进行自签,他们就有权赋予自己任何组证书或身份。这会导致权限升级,所以必须设法集中签发证书。
  • 签发证书并不容易,因为证书通常有很长的使用期限。
  • 在浏览器内(例如为Kubernetes仪表板)进行证书认证比较困难。

虽然这个解决方案可以识别单个用户,但不是用户友好的方式,所以我决定找一个更简单的方案。

OpenID Connect(OIDC)

Kubernetes用OIDC实现SSO,但目前支持OIDC的供应商屈指可数。虽然这个方案乍看令人沮丧,但它确实可以实现SSO,不用为每个人创建帐号。最终,我们团队决定朝着这个方向继续调查。

什么是Open ID Connect

在Pusher内部,我们用Google的G Suite托管我们的电子邮件,如果可以构建由Google支持的单一登录,那么每位工程师都可以使用已有的登录名。Google支持OIDC作为其平台的一部分,所以我们决定调查OIDC以及它的工作原理。

OpenID Connect基于OAuth 2.0协议,在设计时考虑了身份认证。OIDC生成一个ID令牌。

此类ID令牌采用JSON Web令牌或 JWT (发音为jot)的格式,如下所示:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

该字符串由三部分组成,每个都是Base64编码的JSON。第一部分提供令牌的元数据。第二部分提供身份信息,即所谓的有效载荷。第三部分是签名,用于验证令牌是否是由可信方签发。
如果对有效载荷进行解码,它看起来就像这样:
“iss”:“https://auth.pusherplatform.io/dex”,
“sub”:“ChUxMDk0MzA2MjQwNTcwNDc3MDE4MTkSBmdvb2dsZQ”,
“aud”:“kubernetes”,
“exp”:1519123284,
“iat”:1519036884,
“at_hash”:“X2G33w55vEm39VwyOMMjzg”,
“email”:“[email protected]”,
“email_verified”:true,
“name”:“Joel Speed”

有效载荷包含了发起OIDC登录流程的用户身份信息。它通常包含用户的名字和电子邮件,但也可能包含一些额外的信息,例如组别信息。

OIDC生成令牌的流程类似于 OAuth 2.0
  1. 用户点击网站上的登录按钮
  2. 该网站将其重定向到身份提供商
  3. 浏览器加载身份提供商的登录画面
  4. 用户用他们的用户名和密码登录
  5. 身份提供商将其重定向(包含查询字符串中的身份验证码)回原网站
  6. 浏览器用查询字符串中的认证码加载网站
  7. 网站服务器交换ID令牌。

服务器获取该令牌后,不仅可用于该用户的身份验证,还可为该用户登录其它服务提供身份认证,前提是信任该身份提供商。

Kubernetes本身不提供任何类型的OIDC认证登录网站,但你可以把从其他途径得到的令牌传递给它。这难免让人感到困惑,Kubernetes和身份提供商之间的信任关系又是怎么达成的呢?

就像之前提到过的,令牌的第三部分是签名。OIDC提供商生成的每个ID令牌都带有一个加密的密钥(通常是RS256,由提供商定期生成)。Kubernetes通过OIDC提供商的URL,检索到对应的公钥并验证该令牌是由OIDC提供商签发。至此,Kubernetes接受令牌并信任该令牌代表的用户。

OIDC的局限性

虽然OIDC朝着“好”的用户登录体验迈进了一步,但它也有局限性。

一个问题是ID令牌一旦生成就没法撤销。ID令牌和Auth证书一样,有一个有效期。超过有效期,用户就要重新认证。令牌通常签发1小时,但一些提供商支持令牌刷新。令牌刷新(通常无限期地)可用于签发新的ID令牌,从而保证持久使用某项服务。

另一个问题是缺少支持。Kubernetes官方文档仅列出了三个提供商,如果你不使用Salesforce,Azure AD或Google之一,则无法体验没有内置的SSO服务。

Dex介绍

调查OIDC时,我偶然发现了CoreOS的这款开源产品,它着实帮我解决了一些难题。

Dex 在认证过程中充当中间人的角色。它是Kubernetes ID令牌的提供商和颁发者,但它本身并没有身份认证的功能,而是通过配置上游身份提供商的方式,来提供用户身份认证。

Dex和其他OIDC提供商一样,支持从GitHub,GitLab,SAML,LDAP和Microsoft获取用户信息。它的提供商插件大大提高了与客户现有的用户管理系统进行集成的能力。

Dex的另一个优势是能够控制ID令牌的发布,例如指定生命周期。它能强制组织进行重新认证。借助Dex,可以轻松撤消所有令牌,但无法撤销单个令牌。

Dex还为用户提供令牌刷新机制。当用户登录到Dex时,他会被授予一个ID令牌和一个刷新令牌。诸如kubectl之类的程序可以用这些刷新令牌,在ID令牌过期时重新认证用户。由于这些令牌是Dex发布的,因此可以通过撤销其刷新令牌来停止特定用户的刷新。这在笔记本电脑或手机丢失的情况下就非常有用。

此外,对于Dex这样的集中式认证系统,只需配置一次上游提供商即可。我们有一个设置使得上游的身份提供商只知道Dex。然后,Dex利用多个客户端,对使用内部网站和Kubernetes API的用户进行身份验证。

这种设置的一个好处是,任何用户想要往SSO系统里添加新服务,只需要在Dex配置一个PR。该设置还为用户提供基于上游身份提供商的一键式“撤销访问”的功能,用来撤销访问所有内部服务的权限。同样,这在出现安全漏洞或笔记本电脑丢失的情况下,非常有用。

在Pusher内部,通过使用Dex作为身份认证提供商的代理,使我们对用户身份令牌的签发和撤销,变得精准可控,而且,重要的是,用户不再需要用另一个身份来管理。

总结

在重新审视我们的备选项时,我和我的团队认为我们确实应该用OIDC作为Kubernetes的身份验证。我们倾向于用我们的G Suite帐户,这对我们的工程师来说,比让他们去签发证书容易的多。我们也喜欢Dex带给我们的可控力,不仅是可以设置极短的令牌生命周期,而且还可以让我们管理工程师的会话,在必要时,可以让用户退出集群。

OIDC为工程师们提供友好的用户登录体验的同时,还可以通过RBAC的方式限制访问。

下一篇文章 中,我将更加详细地介绍在Pusher是如何配置特定的SSO,并深入说明用户如何生成ID令牌,以及他们在使用命令行和Web浏览器进行身份验证时的用户体验。同时,我也会详细地阐述如何在你的组织中实现SSO登录。

你可能感兴趣的:(Kubernetes实现SSO登录(一))