我们曾多次撰文介绍在当前勒索软件和僵尸网络驱动型攻击频发的环境下,保护应用和API安全的重要性。除了Web应用防火墙(WAF)等机制外,验证用户身份和实施授权控制也是保护业务应用的重要方式。
实现身份验证和授权最直接的方式,是在应用本身中实现。用户规模较小且应用不需要频繁更新时,这种方式或许可行,但随着规模扩大,很快就会难以为继。例如,如果用户必须记住多个应用各自不同的账户名和密码,登录时往往会遇到令人沮丧的“用户名或密码不正确”提示,进而采用不安全的做法,比如使用容易被猜到的“abc123”作为密码。我们也都见过显示器周围贴满写有密码提示的Post-it®便笺!
单点登录(SSO)技术使用一组凭据取代各自独立的用户名和密码,可以在一定程度上解决这些问题。用户只需通过身份提供商(IdP)登录一次,即可访问多个应用。但开发人员仍必须在应用中加入与SSO系统对接的代码。随着应用日益复杂,这项工作可能极具挑战性。
随着组织规模扩大,并需要满足快速增长的用户群体的需求,将身份验证和授权等并非应用功能特有的要求从应用层卸载变得至关重要。在Kubernetes中,集中处理身份验证和授权的理想位置是Ingress控制器。它可以检查进入集群的所有流量,并将流量路由到相应的服务。这样,开发人员无需再构建、维护和复制身份验证逻辑,并可使用原生Kubernetes API在入口层轻松利用SSO技术。
本文将介绍如何实现一套功能完备的SSO解决方案,其中基于NGINX Plus的NGINX Ingress Controller充当中继方,并支持OIDC授权码流程,预配置的身份提供商(IdP)为Okta。
注意:基于NGINX Open Source的NGINX Ingress Controller不提供此功能。
先决条件
本文假定您具备 Kubernetes 环境运维经验。此外,还需要满足以下条件:
- Kubernetes环境:NGINX Ingress Controller支持原生Kubernetes以及多种Kubernetes平台,包括Amazon Elastic Kubernetes(EKS)、裸机、Google Kubernetes Engine(GKE)、Microsoft Azure Kubernetes Service(AKS)、Rancher Kubernetes Engine和Red Hat OpenShift。
- 基于NGINX Plus的NGINX Ingress Controller:必须持有基于NGINX Plus的NGINX Ingress Controller版本的有效许可证。立即申请30天免费试用,即可开始使用许可证。有关更多信息,请参阅文档。
- Okta开发者账户:要将Okta配置为身份提供商(IdP),请先注册开发者账户。也可以下载Okta Command Line Interface(CLI),然后运行
oktaregister命令注册新账户。截至本文撰写时,Okta CLI仍处于测试阶段,不建议用于生产环境。
预配置IdP
云服务必须知道从何处检索和验证用户身份,因此需要使用身份提供商(IdP)。IdP可安全地管理和存储数字身份,并确保攻击者无法窃取身份来冒充用户。
本节使用Okta CLI将Okta预配置为IdP,并创建Okta所称的“应用集成”。
- 运行“
oktalogin”命令,使用Okta Developer Account对Okta CLI进行身份验证。根据提示输入Okta域名和API令牌。
$ okta login Okta Org URL: https://your-okta-domain
Okta API token: your-api-token- 创建应用集成:
$ okta apps create --app-name=mywebapp --redirect-uri=http[s]://ingress-controller-hostname/_codexch- 其中
--app-name定义应用程序名称(此处为“mywebapp”)--redirect-uri定义登录重定向到的URI(此处为ingress-controller-hostname/_codexch)
- 根据提示指定应用类型,先输入1(表示Web应用),然后输入5(表示使用所列框架之外的其他框架)。
Type of Application
(The Okta CLI only supports a subset of application types and properties):
> 1: Web
> 2: Single Page App
> 3: Native App (mobile)
> 4: Service (Machine-to-Machine)
Enter your choice [Web]: 1
Type of Application
> 1: Okta Spring Boot Starter
> 2: Spring Boot
> 3: JHipster
> 4: Quarkus
> 5: Other
Enter your choice [Other]: 5
Configuring a new OIDC Application, almost done:
Created OIDC application, client-id: 0oa1mi...OrfQAg5d7配置NGINX Ingress Controller
将基于NGINX Plus的NGINX Ingress Controller版本配置为对用户进行身份验证的中继方。
定义客户端凭据Secret
出于安全考虑,不支持在OIDC策略对象中硬编码客户端密钥。应改为创建一个Kubernetes Secret,其data字段包含经base64编码的客户端密钥值。
apiVersion: v1
kind: Secret
metadata:
name: oidc-secret
type: nginx.org/oidc
data:
client-secret: base64-encoded-value-of-client-secret 然后应用包含Secret的YAML文件(此处为client-secret.yaml):
$ kubectl apply –f client-secret.yaml获取身份验证端点
使用OAuth 2.0和OpenID Connect API获取Okta在其授权服务器上公开的端点信息。
在本地计算机上运行以下命令,输出Okta端点的相关信息。记下示例输出中显示的authorization_endpoint、token_endpoint和jwks_uri的值。下一节将使用这些值。next section.
$ curl -i https://your-okta-domain/.well-known/openid-configuration
{
"authorization_endpoint": "https://your-okta-domain/oauth2/v1/authorize",
...
"jwks_uri": "https://your-okta-domain/oauth2/v1/keys",
...
"token_endpoint": "https://your-okta-domain/oauth2/v1/token",
...
}定义NGINX Ingress OIDC策略
NGINX Ingress Controller 1.10.0新增了对基于OIDC的身份验证的支持。有关详细信息,请阅读博客文章《使用OpenID Connect和NGINX Ingress Controller轻松实现可靠的单点登录》。
NGINX Ingress Controller的OIDC身份验证实现使用一个Policy对象。该对象是Kubernetes自定义资源,用于在NGINX Ingress Controller中定义OIDC策略。
- 将在上一节中获取的信息填入
authEndpoint、tokenEndpoint和jwksURI字段,这些字段位于Policy对象中。
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: oidc-policy
spec:
oidc:
clientID: client-id
clientSecret: oidc-secret
authEndpoint: https://your-okta-domain/oauth2/v1/authorize
tokenEndpoint: https://your-okta-domain/oauth2/v1/token
jwksURI: https://your-okta-domain/oauth2/v1/keys- 应用策略(此处定义于oidc.yaml):
$ kubectl apply -f oidc.yaml- (可选)检查策略的有效性:
$ kubectl get policy
NAME STATE AGE
oidc-policy Valid 2m定义VirtualServer对象
VirtualServer和VirtualServerRoute是NGINX Ingress资源,用于配置将传入流量路由到Kubernetes集群中后端应用的规则。要使OIDC策略生效,必须在VirtualServer或VirtualServerRoute资源中引用该策略。
- 在/路径前缀下引用OIDC策略,以便在将请求代理到
app-server-payload服务之前,对请求与该前缀匹配的路径的用户进行身份验证。
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: app-ingress
spec:
host: unit-demo.linkpc.net
upstreams:
- name: app-server-payload
service: app-server-svc
port: 80
routes:
- path: /
policies:
- name: oidc-policy
action:
proxy:
upstream: app-server-payload- 应用VirtualServer资源(此处定义于app-virtual-server.yaml):
$ kubectl apply -f app-virtual-server.yaml- (可选)验证资源的有效性:
$ kubectl get vs
NAME STATE HOST IP PORTS AGE
app-ingress Valid unit-demo.linkpc.net 2m测试环境
要测试OIDC与Okta的集成是否正常运行,请在浏览器地址栏中输入NGINX Ingress Controller的主机名。系统会将您重定向到Okta登录门户,您可以在其中输入Okta开发者账户的凭据,以访问后端应用。

身份验证成功后,即可访问上游服务app-server-payload。
向应用程序添加用户
大多数情况下,贵组织中的多位用户需要访问您的应用。请在Okta管理控制台的人员页面(位于目录类别下)中逐一添加用户。

为多个应用创建SSO集成
通过将Okta配置为IdP,并将NGINX Ingress Controller配置为中继方,我们已将一个应用的身份验证流程卸载出去。在实际使用中,您可能希望用户使用一组凭据访问多个应用,也可能希望能够灵活控制每位用户可访问的应用。为此,可以对每个应用重复执行上述各节中的说明:
- 预配置IdP,以将其他应用与Okta集成
- 定义NGINX Ingress OIDC策略,以定义其他OIDC策略
- 定义VirtualServer对象,以引用其他策略
在下图所示的示例中,有两个子域:unit-demo.marketing.net和unit-demo.engineering.net。这两个子域均解析到NGINX Ingress Controller的外部IP地址。NGINX Ingress Controller根据子域将请求路由到Marketing应用或Engineering应用。要向用户授予访问权限,请在Okta GUI的Assignments选项卡中,将该用户与每个相应的应用关联。随后,Okta会向通过身份验证的用户授予一个短期会话Cookie,用于访问这些应用。

总结
在Kubernetes中实施基于OIDC的SSO,并使用NGINX Ingress Controller作为中继方、Okta作为身份提供商(IdP),可让开发人员不再承担身份验证和授权工作,从而专注于优化应用中的业务逻辑。要开始使用基于NGINX Plus的NGINX Ingress Controller,请立即申请30天免费试用,或联系我们,讨论您的用例。
关于作者
相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。

