跳转到主要内容

热门内容

今日:


总体:


最近浏览:


Chinese, Simplified

category

在本文的第一部分中,我们将Key斗篷安装到我们的Kubernetes集群中,并对其进行配置,使其可以从Internet访问。现在我们需要使用它。


Keycloak solution
 

强制身份验证


在本文中,我们将使用上一篇文章中使用的测试服务作为我们的微服务。目前应该可以通过APISIX的APISIX API网关访问该服务<CUSTOM DOMAIN>/worlds,因为这就是我们配置NGINX入口网关和APISIX的方式。

我们在本文中要做的是保护此服务的安全,以便您必须登录并验证自己,然后才能访问它。

此强制执行是在APISIX数据层内完成的,要求我们配置APISIX以检查经过身份验证的用户。


这将是流程:

  1. 用户尝试在没有有效令牌的情况下访问服务,并收到302重定向以登录
  2. 用户进入Keycloft并登录并接收加密cookie形式的令牌
  3. 用户现在再次访问该服务,这次使用令牌
  4. APISIX验证令牌是否有效
  5. APISIX提供对服务的访问


从API网关返回401


在针对API网关开发API的过程中,我很早就意识到了对302HTTP重定向状态的依赖。许多API网关被设计为在用户尚未登录的情况下返回302,从而将用户重定向到登录页面。

这突出了用户正在使用浏览器访问API并且浏览器能够理解302并重定向到登录的广泛假设。

但是,如果我们的客户端不是浏览器,而是系统呢?如果用户界面的设计者想在重定向发生之前做些什么呢?

虽然浏览器很容易理解302响应,但它可能不适合API的使用。在这些情况下,如果没有认证,则需要返回401以表明请求没有附加认证,如果用户被认证但未被授权,则返回403。

很高兴看到APISIX实际上有一个在两者之间切换的配置选项。在本文中,我们将使用302响应,就像使用浏览器一样,但您可以切换标志以获得401响应。

我是否已通过身份验证?


为了保护服务,我们需要检查用户是否已登录。我们将使用开放ID连接(OIDC)协议来实现这一点。你可以在我的另一篇文章中阅读有关OIDC的内容。

使用此协议(特别是隐式Fow 【Implicit Fow】),我们将只允许拥有有效JSON Web令牌(JWT——发音为“jot”)的用户访问服务。我们将使用Keycloak创建APISIX将验证的有效JWT。

要做到这一点,我们需要使用我们的用户信息来设置Keycloak,但稍后会有更多信息。

这是一个非常简单的用例,但为构建单一登录和基于角色的访问控制(RBAC)提供了基础。

APISIX检查身份验证


我们将首先配置APISIX来检查用户是否已通过身份验证,并在用户未通过身份验证时重定向到登录屏幕。

APISIX支持插件的概念,可以处理所有相关的请求。在这种情况下,我们将使用openid-connect插件。

这个插件需要四条我们还没有的信息:

  1. 存在此服务的领域
  2. 向Keycloft注册的客户端ID
  3. 与该客户端ID关联的密钥
  4. Kong可以从Keycloak加载所需配置的URL


配置Keycloak


APISIX需要作为Keycloak客户端安全访问Keycloak。这是通过在Keycloak中创建客户端配置来完成的。

使用本文第一部分中的管理员用户名和密码使用Key斗篷管理UI,登录到管理控制台。

多租户技术


多租户是指应用程序的单个实例(或集群)支持多个客户。每个客户都被称为租户。

在多租户应用程序中,每个租户都认为自己是该应用程序的唯一客户。他们既看不到也无法访问其他租户、他们的帐户或数据。


多租户应用程序
在某些情况下,租户可以在其租赁中创建多个用户,如下所示:


一个租赁中有多个用户
存在更复杂的结构,现有用户可以被邀请进入另一个租赁,因此可能存在于多个租赁中。我们不会在本文中讨论这个案例。

创造Realm


Keycloak支持多租户。这意味着Keycloak的单个实例可以支持多个租户,并且,如上所示,每个租户可以有多个用户。

Keycloak在提到租赁时使用了“Realm ”一词。

在我们开始配置任何东西之前,我们需要为我们的服务创建一个Realm。

登录到管理UI,单击主领域下拉菜单,然后单击创建领域。


创建Realm 


在出现的屏幕中,您只需要给Realm一个名称。让我们称之为“我们的Realm ”。确保Realm已启用,然后单击“创建”。

现在应该向您问候:


钥匙斗篷欢迎页面进入新境界
现在我们可以访问我们的新Realm,是时候开始配置它了。我们现在不会使用任何特定于OAuth的功能,而是专注于OIDC。

对于那些善于观察的人来说,是的,OIDC是建立在OAuth之上的,但Key斗篷将仅身份验证的应用程序配置为OIDC应用程序,而将需要授权的应用程序则配置为OAuth应用程序。

创建客户端


现在我们有了一个境界,我们需要在这个境界中创建一个客户端。Key斗篷客户端是将使用Key斗篷作为其OIDC提供程序(或IdP)的应用程序或服务。在我们的案例中,APISIX和我们的微服务都是Key斗篷的潜在客户,但在这个解决方案中,我们只将APISIX连接到Key斗篷,因此只需要一个客户。

在主菜单上,确保选择了“我们的世界王国”,然后单击“客户端”。


为了简洁起见,我不会向您展示如何做到这一点的所有屏幕截图,而是会告诉您整个过程。这也将使我能够帮助您了解我们正在做什么,而不是专注于我们是如何做的。

您将看到Key斗篷自动注册一组客户端,用于其自身的内部目的。我们可以忽略这些。

我们将通过点击创建客户端来创建我们自己的客户端。现在输入以下信息:

  • 客户端类型【Client type】——OpenID Connect…这允许APISIX使用Keycapture作为基于OAuth的用户身份验证(OIDC)流的一部分。
  • 客户端ID【Client ID】-apisix…这个命令告诉Keycapture如何识别这个客户端。它可以是任何东西。在这种情况下,我们只是将其命名为与我们的APISIX API网关相同
  • 名字【Name】——apisix……对于我们的客户来说,这是一个很好的、可读的名字。


描述是可选的。

单击“下一步”。

现在有三种选择:

  • 客户端身份验证【Client authentication】——打开……通过打开此选项,我们表示我们的客户端(APISIX)能够安全地保存其身份验证机密。
  • 授权【Authorization】--关闭。。这意味着我们不会授权客户使用细粒度访问控制(即:我们只使用OIDC功能)。
  • 身份验证流【Authentication flow】——仅限标准流和隐式流…我们将使用隐式流。


单击“下一步”。

在此页面上,我们配置了有关URL使用方式的约束:

  • Root URL--https://apisix.<CUSTOM DOMAIN>设置它很有用,因为这意味着你不必一直键入根URL,并且可以将其他所有内容都保留为相对路径。
  • Home URL --/worlds…这是“如果有疑问,请返回主页”URL。每当OAuth流失败、用户最终出现在不该出现的位置或注销后,都会使用它。
  • Valid redirect URIs -/*…当应用程序请求时,这个列表告诉Keycapture它可以重定向到哪里。它旨在防止恶意行为者在您不知情的情况下插入自己的重定向。如果Key斗篷重定向到其他地方,它将拒绝该请求。
  • Valid post logout redirect URIs -/*…与重定向URI一样,此列表告诉Keycapture在用户注销后可以重定向到哪里。
  • Web origins -+…这告诉跨来源资源共享(CORS)客户可能来自哪里。输入+表示来自任何重定向URI位置。


单击“保存”。

保存后,您现在可以获得更多的配置选项!

由于这不是一个钥匙斗篷教程,我们将做足够的事情来让我们开始。

单击凭据选项卡。找到客户端机密,然后单击眼睛以揭示机密。你以后需要这个秘密。

著名的API


还有一条信息,我们需要从Keycapture,众所周知的API URL。

是客户端需要从IdP获得的大量信息,包括API端点、用于签署JWT的证书等。这些信息可通过称为.已知端点的标准端点获得。

要查找此端点的地址,请转到主菜单上的Realm settings选项。在“常规”选项卡上,滚动到底部以找到“端点”部分。

单击OpenID端点配置。出现的页面的URL就是您需要的URL。

您可以浏览页面以查看客户端可用的信息类型。

所以现在你应该有:

  • The client ID (apisix)
  • The client secret
  • The .well-known URL

 

配置APISIX


有了所需的信息,我们现在可以安装APISIX的OIDC插件。我们在每一条我们想要保护的路线上都这样做。如果您遵循了我的APISIX安装文章,您将获得以下文件,我们将用粗体标记的行对其进行扩展(用您自己的值替换<>字段):

apisix-hw-route.yml

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: hellow-world-route
  namespace: default
spec:
  http:
  - name: hello-world
    match:
      hosts:
      - apisix.requillion-solutions.cloud
      paths:
      - /*     
    backends:
    - serviceName: hello-world-1-svc
      servicePort: 80
      weight: 70
    - serviceName: hello-world-2-svc
      servicePort: 80
      weight: 30
    plugins:
    - name: proxy-rewrite
      enable: true
      config:
        uri: "/"
    - name: openid-connect
      enable: true
      config:
        client_id: apisix
        client_secret: <CLIENT SECRET>
        discovery: http://my-kc-service.kc:8080/realms/Our%20World/.well-known/openid-configuration
        scope: openid profile
        bearer_only: false
        realm: Our World
        introspection_endpoint_auth_method: client_secret_post
        redirect_uri: /redirect_url 


您可以看到,我们只在文件的底部添加了openid连接插件。然后,我们启用并配置如下:

  • client_id…这被设置为我们在设置Key斗篷客户端时使用的客户端id,apisix
  • client_secret…这是为我们生成的客户端机密密钥斗篷
  • 发现…这是我们较早发现的众所周知的端点,但您会注意到我们正在使用主机的内部DNS名称,而不是外部名称
  • scope…这定义了我们所要求的范围,在这种情况下,我们必须包括openid才能使用OIDC,并添加了概要文件以获取有关用户的更多信息(即:用户名)
  • bear_only…这是一个标志,当为false时,当用户未经身份验证时,返回302重定向到登录(true返回401)
  • 领域…我们正在使用的领域(我们的世界)
  • 内省endpoint_auth_method…定义APISIX将如何从Key斗篷中检索访问令牌(使用前面定义的客户端机密的POST)
  • redirect_url…用户在经过身份验证后(即:登录后)将返回的位置——必须由Key斗篷客户端配置允许


当您的OIDC或OAuth配置出现问题时,很可能是重定向url的定义。在我们的案例中,我们重定向到https://apisix.<CUSTOM DOMAIN>/redirect_url,由于我们定义路由(/*)的方式,它将只提供我们的hello-word测试服务。由于我们现在已通过身份验证,它将按预期提供服务。

现在,我们将更改应用于现有路线(如果是新路线,则创建一个新路线):

kubectl apply -f apisix-hw-route.yml
 

最终配置


还有一个配置更改必须进行。当返回加密的令牌时,NGINX代理模块在传递数据之前会耗尽容纳数据的空间。这可能导致NGINX网关返回500状态。

为了防止这种情况发生,我们需要修改代理设置。以root用户身份登录到gw服务器,然后通过添加粗体行来修改以下文件:

/etc/nginx/proxy_params

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_busy_buffers_size   32k;
proxy_buffers   4 32k;
proxy_buffer_size  16k;


使用以下内容测试配置并重新加载新设置:

nginx -t
systemctl restart nginx


测试配置


现在我们已经配置了Key斗篷和APISIX,现在我们可以测试设置了。

在浏览器中输入以下内容:

apisix.<CUSTOM DOMAIN>/worlds


而不是看Hello World 1!!响应,您现在将直接进入Keycloft登录屏幕。你无法通过这一点,因为你没有登录。你唯一的登录名是管理员用户,但他们属于主领域,无法登录我们的世界领域。

要解决此问题,请登录Key斗篷管理UI并转到我们的世界王国。从左侧的主菜单中选择“用户”。

  1. 单击“添加用户”
  2. 添加用户名(例如:Bob)
  3. 单击电子邮件验证,使其打开(即:无需验证,因为我们尚未设置传出电子邮件)
  4. 单击“创建”


此时,您将看到更多选项。选择凭据选项卡。

  1. 单击“设置密码”
  2. 输入密码并确认
  3. 取消选中临时(除非您希望用户在登录后被迫更改它)
  4. 单击“保存”


现在,刷新您的https://apisix.<CUSTOM DOMAIN>/worlds页面并使用您刚刚创建的用户登录。

登录后,您将看到Hello World 1!!(如果您正在使用我的测试服务)。如果你刷新,你将不会被要求登录。如果你刷新足够的次数,你将看到Hello World 2!!10次中有3次响应。

祝贺您,您已经使用APISIX和Keycloft获得了对服务的访问权限。如果你保护任何其他服务,你现在会意识到,如果它们在同一领域,你可以在所有服务中使用单一登录(SSO)。

那么发生了什么


在这个解决方案中,我们使用的是隐式流。当应用程序无法存储机密时,将使用此流。浏览器就是这样一个应用程序,这就是我们使用隐式流的原因。

流程如下:

Request: /worlds
Response: redirect (302) to /auth ? scope=xxx & state=xxx & client_id=xxx & response_type=xxx & redirect_uri
Request: .../auth ? (params)
Response: login page
Request: .../authenticate ? (params)
Response: redirect to (redirect_url) ? (params)
Request: (redirect_url) ? (params)
Response: redirect to /worlds setting session cookie
Request: /worlds with session cookie
Response: Hellow world response


第一个请求导致重定向,因为没有cookie。

重定向到Key斗篷/auth包含一些参数,这些参数定义了访问服务所需的身份验证,包括身份验证后要遵循的重定向URL。

/auth端点在/authenticate处返回一个登录页面。登录的结果是重定向回重定向URL。该重定向被APISIX拦截,并导致APISIX根据重定向中的参数从Keycloft获取令牌。

然后对令牌进行加密,并将其作为原始域的cookie添加回响应中。响应是重定向到原始/世界URL。

在重定向之后,浏览器现在发送会话cookie。这将由APISIX进行验证,然后将请求直接传递给服务。

如果您再次调用/worlds,会话cookie将被传递,您将立即收到响应。

如果您转到/注销,APISIX会截获请求,并使用会话cookie将您重定向到Keycloft上的/注销。在确认您要注销后,它会清除会话cookie并将您发送回/worlds。

由于此URL受到保护,您将立即返回登录页面!

总结


在这篇文章中,我们…

  • 研究了使用OIDC保护我们服务的方法
  • 讨论了从API网关返回302或401之间的区别
  • 创建了一个密钥斗篷领域创建并配置了APISIX作为密钥斗篷客户端
  • 从Keycloft获得我们需要的信息
  • 修改了APISIX路由以保护我们的测试服务
  • 更新了NGINX配置
  • 已测试配置
  • 看看发生了什么


如果你发现这篇文章感兴趣,请给我一个掌声,因为这有助于我确定人们认为什么是有用的,以及我未来应该写什么文章。如果您有任何建议,请在评论部分添加。

本文地址
最后修改
星期三, June 5, 2024 - 15:47
Article