Istio:RequestAuthentication jwksUri 不解析内部服务名称
Istio: RequestAuthentication jwksUri does not resolve internal services names
通知
其根本原因与Istio: Health check / sidecar fails when I enable the JWT RequestAuthentication相同,但经过进一步诊断后,我改写为简单(试图获得帮助)
问题
我正在尝试在 Istio 网格中配置 RequestAuthentication(和 AuthorizationPolicy)。我的 JWK 令牌由内部 OAUTH 服务器(基于 CloudFoundry)提供,该服务器可以很好地用于其他服务。
当我配置 uri 以获取签名密钥并链接到内部 pod 时,我的问题就来了。此时,Istio 没有解析内部 pod 的名称。我感到困惑,因为微服务能够连接到我所有的内部 pods(mongodb、mysql、rabbitmq),包括 uaa。为什么 RequestAuthentication 不能做同样的事情?
UAA 服务配置(注意:我也在为外部访问创建一个虚拟服务,这工作正常)
apiVersion: apps/v1
kind: Deployment
metadata:
name: uaa
spec:
replicas: 1
selector:
matchLabels:
app: uaa
template:
metadata:
labels:
app: uaa
spec:
containers:
- name: uaa
image: example/uaa
imagePullPolicy: Never
env:
- name: LOGGING_LEVEL_ROOT
value: DEBUG
ports:
- containerPort: 8090
resources:
limits:
memory: 350Mi
---
apiVersion: v1
kind: Service
metadata:
name: uaa
spec:
selector:
app: uaa
ports:
- port: 8090
name: http
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: vs-auth
spec:
hosts:
- "kubernetes.example.com"
gateways:
- gw-ingress
http:
- match:
- uri:
prefix: /oauth
rewrite:
uri: "/uaa/oauth"
route:
- destination:
port:
number: 8090
host: uaa
- match:
- uri:
prefix: /uaa
rewrite:
uri: "/uaa"
route:
- destination:
port:
number: 8090
host: uaa
RequestAuthentication:注意参数 jwksUri,寻找 uaa
主机名。
apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
name: "ra-product-composite"
spec:
selector:
matchLabels:
app: "product-composite"
jwtRules:
- issuer: "http://uaa:8090/uaa/oauth/token"
jwksUri: "http://uaa:8090/uaa/token_keys"
forwardOriginalToken: true
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: "ap-product-composite"
spec:
selector:
matchLabels:
app: "product-composite"
action: ALLOW
rules:
- to:
- operation:
methods: ["GET","POST","DELETE","HEAD","PUT"]
paths: ["*"]
错误日志(在 istiod pod 中)
2021-03-17T09:56:18.833731Z error Failed to fetch jwt public key from "http://uaa:8090/uaa/token_keys": Get "http://uaa:8090/uaa/token_keys": dial tcp: lookup uaa on 10.96.0.10:53: no such host
2021-03-17T09:56:18.838233Z info ads LDS: PUSH for node:product-composite-5cbf8498c7-nhxtj.chp18 resources:29 size:134.8kB
2021-03-17T09:56:18.856277Z warn ads ADS:LDS: ACK ERROR sidecar~10.1.4.2~product-composite-5cbf8498c7-nhxtj.chp18~chp18.svc.cluster.local-8 Internal:Error adding/updating listener(s) virtualInbound: Provider 'origins-0' in jwt_authn config has invalid local jwks: Jwks RSA [n] or [e] field is missing or has a parse error
解决方法
目前,我已将 OAUTH 服务器声明为外部服务器,并重定向了请求,但这完全没有效率。
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: se-auth
spec:
hosts:
- "host.docker.internal"
ports:
- number: 8090
name: http
protocol: HTTP
resolution: DNS
location: MESH_EXTERNAL
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-auth
spec:
hosts:
- "kubernetes.example.com"
gateways:
- gw-ingress
http:
- match:
- uri:
prefix: /oauth
rewrite:
uri: "/uaa/oauth"
route:
- destination:
port:
number: 8090
host: "host.docker.internal"
- match:
- uri:
prefix: /uaa
rewrite:
uri: "/uaa"
route:
- destination:
port:
number: 8090
host: "host.docker.internal"
---
apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
name: "ra-product-composite"
spec:
selector:
matchLabels:
app: "product-composite"
jwtRules:
- issuer: "http://uaa:8090/uaa/oauth/token"
jwksUri: "http://host.docker.internal:8090/uaa/token_keys"
forwardOriginalToken: true
解决方法 2:
我已经使用主机名中的 FQDN(完全限定名称)解决了这个问题。但这并没有解决我的问题,因为将配置文件链接到命名空间(我使用多个命名空间,我只需要一个配置文件)
无论如何,我当前的行是:
jwksUri: "http://uaa.mynamespace.svc.cluster.local:8090/uaa/token_keys"
我完全确定这是一个愚蠢的配置参数,但我找不到它!提前致谢
jwksUri: "http://uaa:8090/uaa/token_keys"
在 istiod 中不起作用,因为 http://uaa
将被解释为 http://uaa.istio-system.svc.cluster.local
。这就是您的变通办法解决问题的原因。
我不明白为什么您的解决方法 2 不是充分的解决方案。假设您的 uaa 服务在命名空间 auth
中运行。如果您将 jwksUri
配置为 uaa.auth.svc.cluster.local
,则每个 kubernetes pod 都可以调用它,而不管它的命名空间如何。
我有一个非常相似的问题,它是由 PeerAuthentication
为所有 pods 设置 mtls.mode = STRICT
引起的。这导致 istiod
pod 无法检索密钥(因为 istiod
在 jwksUri
上执行 HTTP GET 时似乎不使用 MTLS)。
解决方案是在托管 jwksUri
的 Pod 上设置 PeerAuthentication
和 mtls.mode = PERMISSIVE
(在我的例子中是 dex)。
一些 YAML 示例:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default-mtls
namespace: my-namespace
spec:
mtls:
## the empty `selector` applies STRICT to all Pods in `my-namespace`
mode: STRICT
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: dex-mtls
namespace: my-namespace
spec:
selector:
matchLabels:
my_label: dex
mtls:
## the dex pods must allow incoming non-MTLS traffic because istiod reads the JWKS keys from:
## http://dex.my-namespace.svc.cluster.local:5556/dex/keys
mode: PERMISSIVE
通知
其根本原因与Istio: Health check / sidecar fails when I enable the JWT RequestAuthentication相同,但经过进一步诊断后,我改写为简单(试图获得帮助)
问题
我正在尝试在 Istio 网格中配置 RequestAuthentication(和 AuthorizationPolicy)。我的 JWK 令牌由内部 OAUTH 服务器(基于 CloudFoundry)提供,该服务器可以很好地用于其他服务。 当我配置 uri 以获取签名密钥并链接到内部 pod 时,我的问题就来了。此时,Istio 没有解析内部 pod 的名称。我感到困惑,因为微服务能够连接到我所有的内部 pods(mongodb、mysql、rabbitmq),包括 uaa。为什么 RequestAuthentication 不能做同样的事情?
UAA 服务配置(注意:我也在为外部访问创建一个虚拟服务,这工作正常)
apiVersion: apps/v1
kind: Deployment
metadata:
name: uaa
spec:
replicas: 1
selector:
matchLabels:
app: uaa
template:
metadata:
labels:
app: uaa
spec:
containers:
- name: uaa
image: example/uaa
imagePullPolicy: Never
env:
- name: LOGGING_LEVEL_ROOT
value: DEBUG
ports:
- containerPort: 8090
resources:
limits:
memory: 350Mi
---
apiVersion: v1
kind: Service
metadata:
name: uaa
spec:
selector:
app: uaa
ports:
- port: 8090
name: http
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: vs-auth
spec:
hosts:
- "kubernetes.example.com"
gateways:
- gw-ingress
http:
- match:
- uri:
prefix: /oauth
rewrite:
uri: "/uaa/oauth"
route:
- destination:
port:
number: 8090
host: uaa
- match:
- uri:
prefix: /uaa
rewrite:
uri: "/uaa"
route:
- destination:
port:
number: 8090
host: uaa
RequestAuthentication:注意参数 jwksUri,寻找 uaa
主机名。
apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
name: "ra-product-composite"
spec:
selector:
matchLabels:
app: "product-composite"
jwtRules:
- issuer: "http://uaa:8090/uaa/oauth/token"
jwksUri: "http://uaa:8090/uaa/token_keys"
forwardOriginalToken: true
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: "ap-product-composite"
spec:
selector:
matchLabels:
app: "product-composite"
action: ALLOW
rules:
- to:
- operation:
methods: ["GET","POST","DELETE","HEAD","PUT"]
paths: ["*"]
错误日志(在 istiod pod 中)
2021-03-17T09:56:18.833731Z error Failed to fetch jwt public key from "http://uaa:8090/uaa/token_keys": Get "http://uaa:8090/uaa/token_keys": dial tcp: lookup uaa on 10.96.0.10:53: no such host
2021-03-17T09:56:18.838233Z info ads LDS: PUSH for node:product-composite-5cbf8498c7-nhxtj.chp18 resources:29 size:134.8kB
2021-03-17T09:56:18.856277Z warn ads ADS:LDS: ACK ERROR sidecar~10.1.4.2~product-composite-5cbf8498c7-nhxtj.chp18~chp18.svc.cluster.local-8 Internal:Error adding/updating listener(s) virtualInbound: Provider 'origins-0' in jwt_authn config has invalid local jwks: Jwks RSA [n] or [e] field is missing or has a parse error
解决方法
目前,我已将 OAUTH 服务器声明为外部服务器,并重定向了请求,但这完全没有效率。
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: se-auth
spec:
hosts:
- "host.docker.internal"
ports:
- number: 8090
name: http
protocol: HTTP
resolution: DNS
location: MESH_EXTERNAL
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-auth
spec:
hosts:
- "kubernetes.example.com"
gateways:
- gw-ingress
http:
- match:
- uri:
prefix: /oauth
rewrite:
uri: "/uaa/oauth"
route:
- destination:
port:
number: 8090
host: "host.docker.internal"
- match:
- uri:
prefix: /uaa
rewrite:
uri: "/uaa"
route:
- destination:
port:
number: 8090
host: "host.docker.internal"
---
apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
name: "ra-product-composite"
spec:
selector:
matchLabels:
app: "product-composite"
jwtRules:
- issuer: "http://uaa:8090/uaa/oauth/token"
jwksUri: "http://host.docker.internal:8090/uaa/token_keys"
forwardOriginalToken: true
解决方法 2:
我已经使用主机名中的 FQDN(完全限定名称)解决了这个问题。但这并没有解决我的问题,因为将配置文件链接到命名空间(我使用多个命名空间,我只需要一个配置文件) 无论如何,我当前的行是:
jwksUri: "http://uaa.mynamespace.svc.cluster.local:8090/uaa/token_keys"
我完全确定这是一个愚蠢的配置参数,但我找不到它!提前致谢
jwksUri: "http://uaa:8090/uaa/token_keys"
在 istiod 中不起作用,因为 http://uaa
将被解释为 http://uaa.istio-system.svc.cluster.local
。这就是您的变通办法解决问题的原因。
我不明白为什么您的解决方法 2 不是充分的解决方案。假设您的 uaa 服务在命名空间 auth
中运行。如果您将 jwksUri
配置为 uaa.auth.svc.cluster.local
,则每个 kubernetes pod 都可以调用它,而不管它的命名空间如何。
我有一个非常相似的问题,它是由 PeerAuthentication
为所有 pods 设置 mtls.mode = STRICT
引起的。这导致 istiod
pod 无法检索密钥(因为 istiod
在 jwksUri
上执行 HTTP GET 时似乎不使用 MTLS)。
解决方案是在托管 jwksUri
的 Pod 上设置 PeerAuthentication
和 mtls.mode = PERMISSIVE
(在我的例子中是 dex)。
一些 YAML 示例:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default-mtls
namespace: my-namespace
spec:
mtls:
## the empty `selector` applies STRICT to all Pods in `my-namespace`
mode: STRICT
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: dex-mtls
namespace: my-namespace
spec:
selector:
matchLabels:
my_label: dex
mtls:
## the dex pods must allow incoming non-MTLS traffic because istiod reads the JWKS keys from:
## http://dex.my-namespace.svc.cluster.local:5556/dex/keys
mode: PERMISSIVE