×

threescale-wasm-auth 模块运行在 3scale API Management 2.11 或更高版本与 Red Hat OpenShift Service Mesh 2.1.0 或更高版本的集成上。

threescale-wasm-auth 模块是一个使用一组接口(称为应用程序二进制接口 ( *ABI* ))的 WebAssembly 模块。这由 *Proxy-WASM* 规范定义,用于驱动任何实现 ABI 的软件,以便它可以针对 3scale 授权 HTTP 请求。

作为 ABI 规范,Proxy-WASM 定义了名为 *host* 的软件与名为 *module*、*program* 或 *extension* 的其他软件之间的交互。主机公开模块用于执行任务的一组服务,在本例中,用于处理代理请求。

主机环境由与软件(在本例中为 HTTP 代理)交互的 WebAssembly 虚拟机组成。

模块本身与外部世界隔离运行,除了它在虚拟机上运行的指令和 Proxy-WASM 指定的 ABI 之外。这是为软件提供扩展点的一种安全方式:扩展只能以定义明确的方式与虚拟机和主机交互。这种交互提供了计算模型和代理应该具有的外部世界连接。

兼容性

threescale-wasm-auth 模块旨在完全兼容 *Proxy-WASM ABI* 规范的所有实现。但是,目前它只经过彻底测试才能与 Envoy 反向代理一起使用。

作为独立模块的使用

由于其自包含的设计,可以将此模块配置为与 Proxy-WASM 代理独立于服务网格以及 3scale Istio 适配器部署一起工作。

配置 threescale-wasm-auth 模块

Red Hat OpenShift Service on AWS 上的集群管理员可以通过应用程序二进制接口 (ABI) 配置 threescale-wasm-auth 模块以授权对 3scale API Management 的 HTTP 请求。ABI 定义了主机和模块之间的交互,公开了主机的服务,并允许您使用模块处理代理请求。

WasmPlugin API 扩展

服务网格提供自定义资源定义,以将 Proxy-WASM 扩展指定并应用于 sidecar 代理,称为 WasmPlugin。服务网格将此自定义资源应用于需要使用 3scale 进行 HTTP API 管理的工作负载集。

目前,配置 WebAssembly 扩展是一个手动过程。从 3scale 系统获取服务配置的支持将在未来的版本中提供。

先决条件
  • 在您的服务网格部署中确定要应用此模块的 Kubernetes 工作负载和命名空间。

  • 您必须拥有 3scale 租户帐户。请参阅 SaaS3scale 2.11 本地部署,并定义匹配的服务以及相关的应用程序和指标。

    • 以下示例是 threescale-wasm-auth 模块的自定义资源的 YAML 格式。此示例引用服务网格的 Maistra 版本,WasmPlugin API。您必须声明部署 threescale-wasm-auth 模块的命名空间,以及一个 selector 来标识模块将应用到的应用程序集。

      apiVersion: extensions.istio.io/v1alpha1
      kind: WasmPlugin
      metadata:
        name: <threescale_wasm_plugin_name>
        namespace: <bookinfo> (1)
      spec:
        selector: (2)
          labels:
            app: <product_page>
        pluginConfig: <yaml_configuration>
        url: oci://registry.redhat.io/3scale-amp2/3scale-auth-wasm-rhel8:0.0.3
        phase: AUTHZ
        priority: 100
      1 namespace
      2 selector
  • spec.pluginConfig 字段取决于模块配置,在上一个示例中未填充。相反,该示例使用 <yaml_configuration> 占位符值。您可以使用此自定义资源示例的格式。

    • spec.pluginConfig 字段因应用程序而异。所有其他字段在该自定义资源的多个实例中保持不变。例如:

      • url:仅在部署较新版本的模块时才会更改。

      • phase:保持不变,因为此模块需要在代理完成任何本地授权(例如验证 OpenID Connect (OIDC) 令牌)后调用。

  • 在您拥有 spec.pluginConfig 中的模块配置以及其余自定义资源后,请使用 oc apply 命令应用它。

    $ oc apply -f threescale-wasm-auth-bookinfo.yaml

应用 3scale 外部 ServiceEntry 对象

为了使 threescale-wasm-auth 模块针对 3scale 授权请求,该模块必须能够访问 3scale 服务。您可以在 Red Hat OpenShift Service Mesh 中通过应用外部 ServiceEntry 对象和相应的 DestinationRule 对象(用于 TLS 配置以使用 HTTPS 协议)来实现这一点。

自定义资源 (CR) 设置服务条目和目标规则,以便服务网格安全地访问 3scale 托管 (SaaS) 服务,用于服务管理 API 和账户管理 API 的后端和系统组件。服务管理 API 接收每个请求的授权状态查询。账户管理 API 提供服务的 API 管理配置设置。

步骤
  1. 将以下针对 3scale 托管**后端**的外部ServiceEntry CR 和相关的DestinationRule CR 应用到您的集群

    1. ServiceEntry CR 添加到名为service-entry-threescale-saas-backend.yml的文件中

      ServiceEntry CR
      apiVersion: networking.istio.io/v1beta1
      kind: ServiceEntry
      metadata:
        name: service-entry-threescale-saas-backend
      spec:
        hosts:
        - su1.3scale.net
        ports:
        - number: 443
          name: https
          protocol: HTTPS
        location: MESH_EXTERNAL
        resolution: DNS
    2. DestinationRule CR 添加到名为destination-rule-threescale-saas-backend.yml的文件中

      DestinationRule CR
      apiVersion: networking.istio.io/v1beta1
      kind: DestinationRule
      metadata:
        name: destination-rule-threescale-saas-backend
      spec:
        host: su1.3scale.net
        trafficPolicy:
          tls:
            mode: SIMPLE
            sni: su1.3scale.net
    3. 通过运行以下命令,将针对 3scale 托管后端的外部ServiceEntry CR 应用并保存到您的集群

      $ oc apply -f service-entry-threescale-saas-backend.yml
    4. 通过运行以下命令,将针对 3scale 托管后端的外部DestinationRule CR 应用并保存到您的集群

      $ oc apply -f destination-rule-threescale-saas-backend.yml
  2. 将以下针对 3scale 托管**系统**的外部ServiceEntry CR 和相关的DestinationRule CR 应用到您的集群

    1. ServiceEntry CR 添加到名为service-entry-threescale-saas-system.yml的文件中

      ServiceEntry CR
      apiVersion: networking.istio.io/v1beta1
      kind: ServiceEntry
      metadata:
        name: service-entry-threescale-saas-system
      spec:
        hosts:
        - multitenant.3scale.net
        ports:
        - number: 443
          name: https
          protocol: HTTPS
        location: MESH_EXTERNAL
        resolution: DNS
    2. DestinationRule CR 添加到名为destination-rule-threescale-saas-system.yml的文件中

      DestinationRule CR
      apiVersion: networking.istio.io/v1beta1
      kind: DestinationRule
      metadata:
        name: destination-rule-threescale-saas-system
      spec:
        host: multitenant.3scale.net
        trafficPolicy:
          tls:
            mode: SIMPLE
            sni: multitenant.3scale.net
    3. 通过运行以下命令,将针对 3scale 托管系统的外部ServiceEntry CR 应用并保存到您的集群

      $ oc apply -f service-entry-threescale-saas-system.yml
    4. 通过运行以下命令,将针对 3scale 托管系统的外部DestinationRule CR 应用并保存到您的集群

      $ oc apply -f <destination-rule-threescale-saas-system.yml>

或者,您可以部署一个网内 3scale 服务。要部署网内 3scale 服务,请通过部署 3scale 并链接到部署来更改 CR 中服务的 位置。

3scale WebAssembly 模块配置

WasmPlugin 自定义资源规范提供了Proxy-WASM 模块从中读取的配置。

规范嵌入在主机中,并由Proxy-WASM 模块读取。通常,模块解析的配置采用 JSON 文件格式,但是WasmPlugin 资源可以将规范值解释为 YAML 并将其转换为 JSON,以便模块使用。

如果您以独立模式使用Proxy-WASM 模块,则必须使用 JSON 格式编写配置。使用 JSON 格式意味着在主机配置文件(例如Envoy)中需要使用转义和引号。当您将 WebAssembly 模块与WasmPlugin 资源一起使用时,配置采用 YAML 格式。在这种情况下,无效的配置会强制模块根据其 JSON 表示向 sidecar 的日志流显示诊断信息。

EnvoyFilter 自定义资源不是受支持的 API,尽管它可以在某些 3scale Istio 适配器或服务网格版本中使用。不建议使用EnvoyFilter 自定义资源。请使用WasmPlugin API 代替EnvoyFilter 自定义资源。如果您必须使用EnvoyFilter 自定义资源,则必须以 JSON 格式指定规范。

配置 3scale WebAssembly 模块

3scale WebAssembly 模块配置的架构取决于 3scale 帐户和授权服务,以及要处理的服务列表。

先决条件

先决条件是在所有情况下都有一组最小的必填字段

  • 对于 3scale 帐户和授权服务:backend-listener URL。

  • 对于要处理的服务列表:服务 ID 以及至少一种凭据查找方法及其查找位置。

  • 您将找到处理userkey、带有appkeyappid和 OpenID Connect (OIDC) 模式的示例。

  • WebAssembly 模块使用您在静态配置中指定的设置。例如,如果您向模块添加映射规则配置,即使 3scale 管理门户没有此类映射规则,它也会始终应用。其余的WasmPlugin 资源存在于spec.pluginConfig YAML 条目周围。

3scale WebAssembly 模块 api 对象

来自 3scale WebAssembly 模块的api顶级字符串定义了模块将使用的配置版本。

不存在或不受支持的api对象版本会使 3scale WebAssembly 模块无法运行。

api顶级字符串示例
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
  namespace: <bookinfo>
spec:
  pluginConfig:
    api: v1
# ...

api条目定义了配置的其余值。唯一可接受的值是v1。与当前配置不兼容或需要使用v1的模块无法处理的更多逻辑的新设置将需要不同的值。

3scale WebAssembly 模块系统对象

system顶级对象指定如何访问特定帐户的 3scale 账户管理 API。upstream字段是该对象中最重要的部分。system对象是可选的,但建议使用,除非您为 3scale WebAssembly 模块提供完全静态的配置,如果您不想提供对 3scale 的系统组件的连接,则这是一个选项。

当您除了system对象之外还提供静态配置对象时,静态对象始终优先。

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
  pluginConfig:
    system:
      name: <saas_porta>
      upstream: <object>
      token: <my_account_token>
      ttl: 300
# ...
表 1. system 对象字段
名称 描述 必填

name

3scale 服务的标识符,目前在其他地方没有引用。

可选

upstream

关于要联系的网络主机的详细信息。upstream 指的是称为系统的 3scale 帐户管理 API 主机。

token

具有读取权限的 3scale 个人访问令牌。

ttl

在尝试获取新更改之前,将从该主机检索到的配置视为有效的最小秒数。默认为 600 秒(10 分钟)。**注意:**没有最大值,但模块通常会在此 TTL 过期后的合理时间内获取任何配置。

可选

3scale WebAssembly 模块上游对象

upstream对象描述代理可以对其执行调用的外部主机。

apiVersion: maistra.io/v1
upstream:
  name: outbound|443||multitenant.3scale.net
  url: "https://myaccount-admin.3scale.net/"
  timeout: 5000
# ...
表 2. upstream 对象字段
名称 描述 必填

name

name 不是自由格式标识符。它是代理配置中定义的外部主机的标识符。对于独立的 Envoy 配置,它映射到 集群 的名称,在其他代理中也称为 upstream注意:此字段的值,因为服务网格和 3scale Istio 适配器控制平面根据使用竖线 (|) 作为多个字段分隔符的格式配置名称。出于此集成的目的,始终使用以下格式:outbound|<port>||<hostname>

url

访问所描述服务的完整 URL。除非方案中隐含,否则必须包含 TCP 端口。

超时

超时时间(毫秒),响应时间超过此时间的服务连接将被视为错误。默认值为 1000 秒。

可选

3scale WebAssembly 模块后端对象

backend 顶级对象指定如何访问 3scale 服务管理 API 以授权和报告 HTTP 请求。此服务由 3scale 的 *后端* 组件提供。

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
  pluginConfig:
# ...
    backend:
      name: backend
      upstream: <object>
# ...
表 3. backend 对象字段
名称 描述 必填

name

3scale 后端的标识符,目前在其他地方未引用。

可选

upstream

关于要联系的网络主机的详细信息。这必须引用 3scale 帐户管理 API 主机,即已知的系统。

是。最重要且必需的字段。

3scale WebAssembly 模块服务对象

services 顶级对象指定此特定 module 实例处理哪些服务标识符。

由于帐户有多个服务,因此必须指定要处理的服务。其余配置围绕如何配置服务展开。

services 字段是必需的。它是一个数组,必须包含至少一项服务才能有用。

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
  pluginConfig:
# ...
    services:
    - id: "2555417834789"
      token: service_token
      authorities:
        - "*.app"
        - 0.0.0.0
        - "0.0.0.0:8443"
      credentials: <object>
      mapping_rules: <object>
# ...

services 数组中的每个元素都代表一个 3scale 服务。

表 4. services 对象字段
名称 描述 必填

ID

此 3scale 服务的标识符,目前在其他地方未引用。

token

token 可在系统中服务的代理配置中找到,或者您可以使用以下 curl 命令从系统中检索它

curl https://<system_host>/admin/api/services/<service_id>/proxy/configs/production/latest.json?access_token=<access_token>" | jq '.proxy_config.content.backend_authentication_value

可选

授权机构 (authorities)

一个字符串数组,每个字符串代表要匹配的 *URL* 的 *授权机构*。这些字符串接受支持星号(*)、加号(+)和问号(?)匹配器的 glob 模式。

凭据 (credentials)

一个对象,定义要查找哪种凭据以及在哪里查找。

映射规则 (mapping_rules)

一个对象数组,表示映射规则和要命中的 3scale 方法。

可选

3scale WebAssembly 模块凭据对象

credentials 对象是 service 对象的一个组件。credentials 指定要查找哪种凭据以及执行此操作的步骤。

所有字段都是可选的,但必须至少指定一个,user_keyapp_id。指定每个凭据的顺序无关紧要,因为它是由模块预先确定的。每个凭据只指定一个实例。

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
  pluginConfig:
# ...
    services:
    - credentials:
        user_key: <array_of_lookup_queries>
        app_id: <array_of_lookup_queries>
        app_key: <array_of_lookup_queries>
# ...
表 5. credentials 对象字段
名称 描述 必填

用户密钥 (user_key)

这是一个查找查询数组,它定义了一个 3scale 用户密钥。用户密钥通常称为 API 密钥。

可选

应用 ID (app_id)

这是一个查找查询数组,它定义了一个 3scale 应用标识符。应用标识符由 3scale 提供,或者使用身份提供者(如 Red Hat Single Sign-On (RH-SS0))或 OpenID Connect (OIDC) 提供。此处指定的查找查询的解析,无论何时成功并解析为两个值,都会设置 app_idapp_key

可选

应用密钥 (app_key)

这是一个查找查询数组,它定义了一个 3scale 应用密钥。没有解析的 app_id 的应用密钥是无用的,因此只有在指定 app_id 时才指定此字段。

可选

3scale WebAssembly 模块查找查询

查找查询 对象是 credentials 对象中任何字段的一部分。它指定如何查找和处理给定的凭据字段。评估时,成功解析意味着找到一个或多个值。解析失败意味着未找到任何值。

查找查询 数组描述了一个短路或关系:成功解析其中一个查询会停止对任何剩余查询的评估,并将值分配给指定的凭据类型。数组中的每个查询都是相互独立的。

查找查询 由单个字段(源对象)组成,该字段可以是多种源类型之一。请参阅以下示例

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
  pluginConfig:
# ...
    services:
    - credentials:
        user_key:
          - <source_type>: <object>
          - <source_type>: <object>
# ...
        app_id:
          - <source_type>: <object>
# ...
        app_key:
          - <source_type>: <object>
# ...

3scale WebAssembly 模块源对象

source 对象作为 credentials 对象字段内源数组的一部分存在。对象字段名称(称为 source 类型)可以是以下任何一种

  • header:查找查询接收 HTTP 请求标头作为输入。

  • query_string查找查询 接收 URL 查询字符串参数作为输入。

  • filter查找查询 接收过滤器元数据作为输入。

所有 source 类型对象至少具有以下两个字段

表 6. source 类型对象字段
名称 描述 必填

键 (keys)

一个字符串数组,每个字符串都是一个 key,指的是输入数据中找到的条目。

操作 (ops)

一个执行 key 条目匹配的 操作 数组。该数组是一个管道,其中操作接收输入并在下一个操作上生成输出。无法提供输出的 操作 会将 查找查询 解析为失败。操作的管道顺序决定了评估顺序。

可选

filter 字段名称具有必需的 path 条目,用于显示用于查找数据的元数据中的路径。

key 与输入数据匹配时,其余键将不会被评估,并且源解析算法会跳转到执行指定的 操作ops),如果有的话。如果没有指定 ops,则返回匹配的 key 的结果值(如果有)。

操作 (Operations) 提供了一种方式,用于在第一阶段查找键 (key)之后,指定输入的特定条件和转换。当需要转换、解码和断言属性时,可以使用操作 (operations),但是它们并没有提供成熟的语言来处理所有需求,并且缺乏图灵完备性 (Turing-completeness)

一个栈存储了操作 (operations)的输出。当进行评估时,查找查询 (lookup query)通过分配栈底的值(取决于凭证消耗多少个值)来结束。

3scale WebAssembly 模块操作对象

属于特定源类型 (source type)ops数组中的每个元素都是一个操作 (operation)对象,它要么对值应用转换,要么执行测试。此类对象的字段名称是操作 (operation)本身的名称,任何值都是操作 (operation)的参数,例如结构化对象,例如带有字段和值的映射、列表或字符串。

大多数操作 (operations)处理一个或多个输入,并产生一个或多个输出。当它们消耗输入或产生输出时,它们使用一个值栈:每个被操作消耗的值都会从值栈中弹出,并最初填充任何源 (source)匹配项。它们输出的值会被推入栈中。其他操作 (operations)除了断言某些属性之外,不消耗或产生输出,但它们会检查值栈。

当解析完成时,下一步拾取的值(例如,将值分配为app_idapp_keyuser_key)将取自栈底的值。

有几种不同的操作 (operations)类别

  • 解码 (decode):这些通过解码输入值来获得不同的格式。

  • 字符串 (string):这些以字符串值为输入,并对其进行转换和检查。

  • 栈 (stack):这些采用输入中的一组值,并执行多个栈转换以及对栈中特定位置的选择。

  • 检查 (check):这些以无副作用的方式断言关于操作集的属性。

  • 控制 (control):这些执行允许修改评估流程的操作。

  • 格式化 (format):这些解析输入值的特定格式结构并在其中查找值。

所有操作都由作为字符串的名称标识符指定。

其他资源

3scale WebAssembly 模块映射规则对象 (mapping_rules object)

mapping_rules 对象是service对象的一部分。它指定了一组 REST 路径模式以及在模式匹配时使用的相关 3scale 指标和计数增量。

如果在system顶级对象中没有提供动态配置,则需要该值。如果除了system顶级条目之外还提供了该对象,则首先评估mapping_rules对象。

mapping_rules是一个数组对象。该数组的每个元素都是一个mapping_rule对象。对传入请求的已评估匹配映射规则提供一组用于授权和向APIManager报告的 3scale方法 (methods)。当多个匹配规则引用相同的方法 (methods)时,在调用 3scale 时会对增量 (deltas)进行求和。例如,如果两条规则将Hits方法增加两次,增量 (deltas)分别为 1 和 3,则向 3scale 报告的 Hits 的单个方法条目具有 4 的增量 (delta)

3scale WebAssembly 模块映射规则对象 (mapping_rule object)

mapping_rule对象是mapping_rules对象中数组的一部分。

mapping_rule对象的字段指定以下信息:

  • 要匹配的HTTP 请求方法

  • 与路径匹配的模式。

  • 要报告的 3scale 方法以及要报告的数量。指定字段的顺序决定了评估顺序。

表 7. mapping_rule 对象字段
名称 描述 必填

method

指定表示 HTTP 请求方法(也称为动词)的字符串。接受的值与任何一个接受的 HTTP 方法名称匹配,不区分大小写。特殊值 any 匹配任何方法。

pattern

与 HTTP 请求的 URI 路径组件匹配的模式。此模式遵循 3scale 文档中记录的相同语法。它允许使用通配符(使用星号 (*) 字符),在括号之间使用任何字符序列,例如{this}

usages

usage 对象列表。当规则匹配时,所有具有其增量 (deltas)的方法都将添加到发送到 3scale 以进行授权和报告的方法列表中。

使用以下必需字段嵌入usages对象:

  • name:要报告的method系统名称。

  • delta:要增加该method的数量。

last

此规则的成功匹配是否应停止更多映射规则的评估。

可选布尔值。默认值为false

以下示例独立于 3scale 中方法之间的现有层次结构。也就是说,在 3scale 端运行的任何内容都不会影响此项。例如,Hits指标可能是所有指标的父指标,因此它由于授权请求中所有报告方法的总和而存储 4 次点击,并调用 3scale 的Authrep API 端点。

以下示例使用对路径/products/1/soldGET请求,该路径匹配所有规则。

mapping_rules GET 请求示例
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
  pluginConfig:
# ...
    mapping_rules:
      - method: GET
        pattern: /
        usages:
          - name: hits
            delta: 1
      - method: GET
        pattern: /products/
        usages:
          - name: products
            delta: 1
      - method: ANY
        pattern: /products/{id}/sold
        usages:
          - name: sales
            delta: 1
          - name: products
            delta: 1
# ...

所有usages都将添加到模块对 3scale 执行的请求中,使用数据如下:

  • Hits:1

  • products:2

  • sales:1

3scale WebAssembly 模块凭据用例示例

您将花费大部分时间将配置步骤应用于在对服务的请求中获取凭据。

以下是凭据 (credentials)示例,您可以修改它们以适应特定用例。

您可以将它们全部组合起来,但是当您使用各自的查找查询 (lookup queries)指定多个源对象时,它们将按顺序进行评估,直到其中一个成功解析。

查询字符串参数中的 API 密钥 (user_key)

以下示例在同名的查询字符串参数或标头中查找user_key

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
# ...
    services:
# ...
      credentials:
        user_key:
          - query_string:
              keys:
                - <user_key>
          - header:
              keys:
                - <user_key>
# ...

应用程序 ID 和密钥

以下示例在查询或标头中查找app_keyapp_id凭据。

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
# ...
    services:
# ...
      credentials:
        app_id:
          - query_string:
              keys:
                - <app_id>
          - header:
              keys:
                - <app_id>
        app_key:
          - query_string:
              keys:
                - <app_key>
          - header:
              keys:
                - <app_key>
# ...

授权标头

请求在授权 (authorization)标头中包含app_idapp_key。如果最后输出至少一个或两个值,则可以分配app_key

此处的解析如果最后输出一个或两个值,则分配app_key

授权 (authorization)标头指定一个具有授权类型的值,其值以Base64编码。这意味着您可以用空格字符分割该值,取第二个输出,然后再次使用冒号 (:) 作为分隔符进行分割。例如,如果您使用此格式app_id:app_key,则标头看起来像以下凭据 (credential)示例。

aladdin:opensesame:  Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l

必须使用小写标头字段名称,如下例所示。

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
# ...
    services:
# ...
      credentials:
        app_id:
          - header:
              keys:
                - authorization
              ops:
                - split:
                    separator: " "
                    max: 2
                - length:
                    min: 2
                - drop:
                    head: 1
                - base64_urlsafe
                - split:
                    max: 2
        app_key:
          - header:
              keys:
                - app_key
# ...

前面的用例示例查看授权 (authorization)的标头。

  1. 它获取其字符串值并用空格将其分割,检查它是否生成至少两个凭据 (credential)类型的值和凭据 (credential)本身,然后删除凭据 (credential)类型。

  2. 然后,它解码包含所需数据的第二个值,并使用冒号 (:) 字符将其分割,从而得到一个操作栈,其中首先是app_id,然后是app_key(如果存在)。

    1. 如果授权标头中不存在app_key,则会检查其特定来源,例如,在这种情况下,具有键app_key的标头。

  3. 要向credentials添加额外条件,允许Basic授权,其中app_idaladdinadmin,或任何长度至少为 8 个字符的app_id

  4. app_key必须包含一个值,并且至少有 64 个字符,如下例所示

    apiVersion: extensions.istio.io/v1alpha1
    kind: WasmPlugin
    metadata:
      name: <threescale_wasm_plugin_name>
    spec:
    # ...
        services:
    # ...
          credentials:
            app_id:
              - header:
                  keys:
                    - authorization
                  ops:
                    - split:
                        separator: " "
                        max: 2
                    - length:
                        min: 2
                    - reverse
                    - glob:
                      - Basic
                    - drop:
                        tail: 1
                    - base64_urlsafe
                    - split:
                        max: 2
                     - test:
                        if:
                          length:
                            min: 2
                       then:
                          - strlen:
                              max: 63
                          - or:
                              - strlen:
                                  min: 1
                              - drop:
                                  tail: 1
                    - assert:
                      - and:
                        - reverse
                        - or:
                          - strlen:
                              min: 8
                          - glob:
                            - aladdin
                            - admin
    # ...
  5. 获取authorization标头值后,通过反转堆栈获得Basic credential类型,以便将类型放在顶部。

  6. 对其运行全局匹配。验证后,解码并分割凭据,您将在堆栈底部获得app_id,并在顶部获得app_key(如果存在)。

  7. 如果堆栈中有两个值,这意味着获取了app_key,则运行test:

    1. 确保字符串长度在 1 到 63 之间,包括app_idapp_key。如果密钥长度为零,则将其删除并继续执行,就像不存在密钥一样。如果只有app_id而没有app_key,则缺少的else分支表示测试成功,并且评估继续。

最后一个操作assert表示没有副作用进入堆栈。然后您可以修改堆栈。

  1. 反转堆栈,使app_id位于顶部。

    1. 无论是否存在app_key,反转堆栈都能确保app_id位于顶部。

  2. 使用and保留测试中堆栈的内容。

    然后使用以下可能性之一

    • 确保app_id的字符串长度至少为 8。

    • 确保app_id匹配aladdinadmin

OpenID Connect (OIDC) 使用案例

对于服务网格和 3scale Istio 适配器,必须部署RequestAuthentication,如下例所示,填写您自己的工作负载数据和jwtRules

apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
  name: jwt-example
  namespace: bookinfo
spec:
  selector:
    matchLabels:
      app: productpage
  jwtRules:
  - issuer: >-
      http://keycloak-keycloak.34.242.107.254.nip.io/auth/realms/3scale-keycloak
    jwksUri: >-
      http://keycloak-keycloak.34.242.107.254.nip.io/auth/realms/3scale-keycloak/protocol/openid-connect/certs

应用RequestAuthentication后,它会使用原生插件配置Envoy以验证JWT令牌。代理在运行模块之前验证所有内容,因此任何失败的请求都不会到达 3scale WebAssembly 模块。

验证JWT令牌后,代理会将其内容存储在内部元数据对象中,其中一个条目的键取决于插件的特定配置。此用例使您可以查找具有单个条目(包含未知键名)的结构对象。

用于 OIDC 的 3scale app_id与 OAuth client_id匹配。这可以在JWT令牌的azpaud字段中找到。

要从 Envoy 的原生JWT身份验证过滤器获取app_id字段,请参见以下示例

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
# ...
    services:
# ...
      credentials:
        app_id:
          - filter:
              path:
                - envoy.filters.http.jwt_authn
                - "0"
              keys:
                - azp
                - aud
              ops:
                - take:
                    head: 1
# ...

此示例指示模块使用filter源类型从Envoy特定的JWT身份验证原生插件查找对象的过滤器元数据。此插件包含JWT令牌作为具有单个条目和预配置名称的结构对象的一部分。使用0指定您只访问单个条目。

结果值是一个结构,您将解析其中的两个字段

  • azp:找到app_id的值。

  • aud:也可以找到此信息的值。

此操作确保仅保留一个值用于赋值。

从标头中获取 JWT 令牌

某些设置可能具有针对JWT令牌的验证过程,其中已验证的令牌将通过 JSON 格式的标头到达此模块。

要获取app_id,请参见以下示例

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
# ...
    services:
# ...
      credentials:
        app_id:
          - header:
              keys:
                - x-jwt-payload
              ops:
                - base64_urlsafe
                - json:
                  - keys:
                    - azp
                    - aud
                - take:
                    head: 1
# ,,,

3scale WebAssembly 模块最小工作配置

以下是 3scale WebAssembly 模块最小工作配置的示例。您可以复制并粘贴此内容,并对其进行编辑以使其与您自己的配置一起使用。

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: <threescale_wasm_plugin_name>
spec:
  url: oci://registry.redhat.io/3scale-amp2/3scale-auth-wasm-rhel8:0.0.3
  imagePullSecret: <optional_pull_secret_resource>
  phase: AUTHZ
  priority: 100
  selector:
    labels:
      app: <product_page>
  pluginConfig:
    api: v1
    system:
      name: <system_name>
      upstream:
        name: outbound|443||multitenant.3scale.net
        url: https://istiodevel-admin.3scale.net/
        timeout: 5000
      token: <token>
    backend:
      name: <backend_name>
      upstream:
        name: outbound|443||su1.3scale.net
        url: https://su1.3scale.net/
        timeout: 5000
      extensions:
      - no_body
    services:
    - id: '2555417834780'
      authorities:
      - "*"
      credentials:
        user_key:
          - query_string:
              keys:
                - <user_key>
          - header:
              keys:
                - <user_key>
        app_id:
          - query_string:
              keys:
                - <app_id>
          - header:
              keys:
                - <app_id>
        app_key:
          - query_string:
              keys:
                - <app_key>
          - header:
              keys:
                - <app_key>