无法在通过 RequestAuthentication 的 outputPayloadToHeader 传递的 Istio 自定义 AuthorizationPolicy 中获取 JWT header

Not able to get JWT header in Istio custom AuthorizationPolicy passed via outputPayloadToHeader of RequestAuthentication

我们使用 Istio 1.11.4 在 AWS EKS 上部署了 kubernetese 集群。 我们使用 JWT 进行身份验证并将其传递到 header x-jwt-assertion。 我们使用 Istio RequestAuthentication 来验证 JWT。 这是定义

apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
  name: "graphql-jwt"
  namespace: graphql
spec:
  selector:
    matchLabels:
      app: graphql
  jwtRules:
    - issuer: "https://login.<mycompany>.io/"
      jwksUri: "https://<mycompany>.us.auth0.com/.well-known/jwks.json"
      outputPayloadToHeader: "my-data"
      fromHeaders:
        - name: x-jwt-assertion
          prefix: "Bearer "

我们在集群中部署了另一个服务,它根据请求 headers 和 body 确定是否应该转发请求。为此,我们使用 Istio CUSTOM Authorization Policy。 AuthorizationPolicy 的定义如下

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: ext-auth-my
spec:
    selector:
      matchLabels:
        app: graphql
  action: CUSTOM
  provider:
    name: my-ext-auth
  rules:
    - { }

此 AuthorizationPolicy 的配置在 istio-system 命名空间下的 istio configmap 中定义。具体配置如下

apiVersion: v1
data:
  mesh: |-
    extensionProviders:
    - name: "my-ext-auth"
      envoyExtAuthzHttp:
        service: "my-api-svc.foo.svc.cluster.local"
        port: "8080"
        pathPrefix: "/hasaccess"
        includeRequestHeadersInCheck: ["my-data", "content-type"]
        includeRequestBodyInCheck:
          maxRequestBytes: 1000000

现在在我的服务中 (my-api-svc.foo.svc.cluster.local:8080/hasaccess) 我没有得到 my-data header。如果我更改 includeRequestHeadersInCheck 的值并删除 content-type,我的服务会抛出无效 MIME 类型的错误,如果我将 my-data 替换为 x-jwt-assertion,则请求不会发出它通过我的服务,我得到 Jwt issuer is not configured。因此,这验证了 header 正在被检测到,但出于某种原因,它只是没有通过我的服务。

为我服务的header是

x-request-id
x-b3-parentspanid
x-b3-traceid
x-b3-spanid
x-forwarded-client-cert
x-b3-sampled
X-Forwarded-Proto
X-Forwarded-For
Host
Content-Length
Content-Type

我无法弄清楚为什么 my-dataheader 没有进入我的 api 以授权请求。此 header 确实到达了请求所针对的目标服务,因此它不会丢失。

我能够通过在 Authorization header 而不是 x-jwt-assertion 中添加我的 JWT 令牌并在我的 RequestAuthentication 中使用 forwardOriginalToken 属性 来解决问题。

所以现在 RequestAuthentication 是

apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
  name: "graphql-jwt"
  namespace: graphql
spec:
  selector:
    matchLabels:
      app: graphql
  jwtRules:
    - issuer: "https://login.<mycompany>.io/"
      jwksUri: "https://<mycompany>.us.auth0.com/.well-known/jwks.json"
      outputPayloadToHeader: "my-data"
      forwardOriginalToken: true
      fromHeaders:
        - name: Authorization
          prefix: "Bearer "

我的 istio configmap 是

apiVersion: v1
data:
  mesh: |-
    extensionProviders:
    - name: "my-ext-auth"
      envoyExtAuthzHttp:
        service: "my-api-svc.foo.svc.cluster.local"
        port: "8080"
        pathPrefix: "/hasaccess"
        includeRequestHeadersInCheck: ["Authorization", "content-type"]
        includeRequestBodyInCheck:
          maxRequestBytes: 1000000

有关详细信息,here 是 link 到 github 讨论。