×

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

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

作为 ABI 规范,Proxy-WASM 定义了名为主机的软件与名为模块程序扩展的另一个软件之间的交互。主机公开模块用来执行任务的一组服务,在本例中,用于处理代理请求。

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

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

兼容性

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

作为独立模块使用

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

配置 threescale-wasm-auth 模块

OpenShift Dedicated 上的集群管理员可以通过应用程序二进制接口 (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 服务网格中通过应用外部ServiceEntry对象和相应的DestinationRule对象(用于 TLS 配置以使用 HTTPS 协议)来实现。

自定义资源 (CR) 为从服务网格内部安全访问 3scale 托管 (SaaS) 的后端和系统组件(服务管理 API 和帐户管理 API)设置服务条目和目标规则。服务管理 API 接收有关每个请求的授权状态的查询。帐户管理 API 提供服务的 API 管理配置设置。

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

    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. 将以下外部ServiceEntry CR 和相关的DestinationRule CR 应用于您的集群的 3scale 托管**系统**

    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

字符串数组,每个字符串都代表要匹配的URLAuthority。这些字符串接受支持星号(*)、加号(+)和问号(?)匹配器的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密钥。

可选

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模块查找查询

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

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

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

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 模块源对象

对象存在于任何凭据对象字段内的源数组中。对象字段名称,称为类型,可以是以下任何一种:

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

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

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

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

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

keys

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

ops

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

可选

filter字段名称需要一个path条目来显示您用于查找数据的元数据中的路径。

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

操作提供了一种方法来指定在第一阶段查找之后拥有的输入的某些条件和转换。当您需要转换、解码和断言属性时,可以使用操作,但是它们并没有提供一种成熟的语言来处理所有需求,并且缺乏图灵完备性。

一个堆栈存储操作的输出。评估时,查找查询通过分配堆栈底部的值(取决于凭据消耗多少值)来完成。

3scale WebAssembly 模块操作对象

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

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

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

有几种不同的操作类别:

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

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

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

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

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

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

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

其他资源

3scale WebAssembly 模块映射规则对象

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

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

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

3scale WebAssembly 模块mapping_rule对象

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 模块凭据用例示例

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

以下是您可以修改以适应特定用例的凭据示例。

您可以将它们全部组合起来,但是当您指定多个具有自身查找查询的源对象时,将按顺序评估它们,直到其中一个成功解析。

查询字符串参数中的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. 运行test: 检查堆栈中是否有两个值,这意味着获取了app_key

    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>