检查 header 有效令牌的 Istio EnvoyFilter
Istio EnvoyFilter that checks header for a valid token
我需要验证是否为自定义 header 提供了正确的值。如果没有,我想拒绝访问该服务并产生一个带有消息的 401。
我已经能够为此创建一个 Istio AuthorizationPolicy,但它给了我 403,这并不是完全错误的,但我想正确并给 401。
这是我迄今为止尝试过的方法,不幸的是它对我发送的请求没有任何影响(我不是 envoy 也不是 lua 专家请和我一起):
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: custom-filter
namespace: dev
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: NETWORK_FILTER # http connection manager is a filter in Envoy
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
patch:
operation: MERGE
value: # lua filter specification
name: envoy.lua
typed_config:
"@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
inlineCode: |
function envoy_on_request(request_handle)
if request_handle:headers():get("auth_token") != "xxx" then
request_handle:respond({[":status"] = "401"}, "nope")
end
end
产生 403 的工作 AuthorizationPolicy,我想将其替换为上面的内容:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-method-get
namespace: dev
spec:
selector:
matchLabels:
app: myapp
action: DENY
rules:
- when:
- key: request.headers[auth_token]
notValues: ["xxx"]
根据我的理解,istio 的响应是正确的:
来自 RFC 标准:
The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource...The user agent MAY repeat the request with a new or replaced Authorization header field.
The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it...If authentication credentials were provided in the request, the server considers them insufficient to grant access.
所以你的带有令牌的请求被理解但被禁止(403)但是没有令牌的请求根本不提供凭据,所以它是未经授权的。
关于您的过滤器:
将过滤器应用于 HTTP_FILTER
而不是 NETWORK_FILTER
。它应该在任何其他过滤器之前应用,因此将选项设置为 INSERT_BEFORE
.
更新
要将过滤器应用于单个广告连播而不是所有 pods,请将上下文从 GATEWAY
更改为 SIDECAR_INBOUND
并设置 workloadSelector
:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: custom-filter
namespace: dev
spec:
workloadSelector:
labels:
app: my-app
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
subFilter:
name: "envoy.router"
patch:
operation: INSERT_BEFORE
value: # lua filter specification
name: envoy.lua
typed_config:
"@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
inlineCode: |
function envoy_on_request(request_handle)
if request_handle:headers():get("auth_token") ~= "my_secret_token" then
request_handle:respond({[":status"] = "401"}, "nope")
end
end
我需要验证是否为自定义 header 提供了正确的值。如果没有,我想拒绝访问该服务并产生一个带有消息的 401。
我已经能够为此创建一个 Istio AuthorizationPolicy,但它给了我 403,这并不是完全错误的,但我想正确并给 401。
这是我迄今为止尝试过的方法,不幸的是它对我发送的请求没有任何影响(我不是 envoy 也不是 lua 专家请和我一起):
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: custom-filter
namespace: dev
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: NETWORK_FILTER # http connection manager is a filter in Envoy
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
patch:
operation: MERGE
value: # lua filter specification
name: envoy.lua
typed_config:
"@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
inlineCode: |
function envoy_on_request(request_handle)
if request_handle:headers():get("auth_token") != "xxx" then
request_handle:respond({[":status"] = "401"}, "nope")
end
end
产生 403 的工作 AuthorizationPolicy,我想将其替换为上面的内容:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-method-get
namespace: dev
spec:
selector:
matchLabels:
app: myapp
action: DENY
rules:
- when:
- key: request.headers[auth_token]
notValues: ["xxx"]
根据我的理解,istio 的响应是正确的:
来自 RFC 标准:
The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource...The user agent MAY repeat the request with a new or replaced Authorization header field.
The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it...If authentication credentials were provided in the request, the server considers them insufficient to grant access.
所以你的带有令牌的请求被理解但被禁止(403)但是没有令牌的请求根本不提供凭据,所以它是未经授权的。
关于您的过滤器:
将过滤器应用于 HTTP_FILTER
而不是 NETWORK_FILTER
。它应该在任何其他过滤器之前应用,因此将选项设置为 INSERT_BEFORE
.
更新
要将过滤器应用于单个广告连播而不是所有 pods,请将上下文从 GATEWAY
更改为 SIDECAR_INBOUND
并设置 workloadSelector
:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: custom-filter
namespace: dev
spec:
workloadSelector:
labels:
app: my-app
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
subFilter:
name: "envoy.router"
patch:
operation: INSERT_BEFORE
value: # lua filter specification
name: envoy.lua
typed_config:
"@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
inlineCode: |
function envoy_on_request(request_handle)
if request_handle:headers():get("auth_token") ~= "my_secret_token" then
request_handle:respond({[":status"] = "401"}, "nope")
end
end