Ingress-Nginx 外部身份验证的自定义响应
Custom response for Ingress-Nginx External Authentication
我已经在 EKS 上部署了我的 Kubernetes 集群。我有一个 ingress-nginx,它通过负载均衡器公开以将流量路由到不同的服务。在 ingress-nginx 中,第一个请求转到 auth 服务进行身份验证,如果它是一个有效请求,那么我允许它继续前进。这是使用 ingress-nginx 注释 nginx.ingress.kubernetes.io/auth-url 完成的。
Auth 服务是使用 FastAPI 开发的。如果来自 fastAPI 的 401 响应如下所示
FASTAPI
但是当我使用 ingress-nginx 时,响应看起来像这样
INGRESS_NGINX
有没有办法从 Ingress-nginx 获得 JSON 响应?
入口文件
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: 'nginx'
nginx.ingress.kubernetes.io/use-regex: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/auth-response-headers: item_id
nginx.ingress.kubernetes.io/auth-method: POST
nginx.ingress.kubernetes.io/auth-url: http://pth-auth.default.svc.cluster.local:8000/item/1
# UPDATE THIS LINE ABOVE
spec:
rules:
- http:
paths:
- path: /?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: client-cluster-ip-service
servicePort: 3000
- path: /api/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: server-cluster-ip-service
servicePort: 5000
- path: /pth-auth/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: pth-auth
servicePort: 8000
这对我有用,参考了这里
https://github.com/kubernetes/ingress-nginx/issues/2292
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: 'nginx'
nginx.ingress.kubernetes.io/use-regex: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/auth-response-headers: item_id
nginx.ingress.kubernetes.io/auth-method: POST
nginx.ingress.kubernetes.io/auth-url: http://pth-auth.default.svc.cluster.local:8000/items/1
nginx.ingress.kubernetes.io/server-snippet: |
location = /error/401 {
proxy_method POST;
proxy_pass http://pth-auth.default.svc.cluster.local:8000/error/401;
}
location = /error/403 {
proxy_method POST;
proxy_pass http://pth-auth.default.svc.cluster.local:8000/error/403;
}
nginx.ingress.kubernetes.io/configuration-snippet: |
error_page 401 /error/401;
error_page 403 /error/403;
# UPDATE THIS LINE ABOVE
spec:
rules:
- http:
paths:
- path: /?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: client-cluster-ip-service
servicePort: 3000
- path: /api/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: server-cluster-ip-service
servicePort: 5000
- path: /pth-auth/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: pth-auth
servicePort: 8000
你只需要告诉 nginx 万一错误路由流量到这个位置,他们的函数将处理特定的错误。在我的例子中,函数是 error/{error_code}.
这是一个对我有用的解决方案。它允许身份验证服务 return 每个请求的自定义错误消息。
需要注意的是,由于nginx无法访问auth响应body,pth-auth
服务需要将数据放在Pth-Auth-Error
header(base64编码).
此示例处理 401、500 和 pth-auth
服务不可用时的特殊情况。
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: 'nginx'
nginx.ingress.kubernetes.io/use-regex: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/auth-response-headers: item_id
nginx.ingress.kubernetes.io/auth-method: POST
nginx.ingress.kubernetes.io/auth-url: http://pth-auth.default.svc.cluster.local:8000/item/1
# UPDATE THIS LINE ABOVE
nginx.ingress.kubernetes.io/configuration-snippet: |
# Redirect auth errors to custom named locations
error_page 401 = @ingress_service_custom_error_401;
error_page 500 = @ingress_service_custom_error_500;
# Grab data from auth error response
auth_request_set $pth_auth_error $upstream_http_pth_auth_error;
auth_request_set $pth_auth_error_content_type $upstream_http_content_type;
auth_request_set $pth_auth_status $upstream_status;
nginx.ingress.kubernetes.io/server-snippet: |
location @ingress_service_custom_error_401 {
internal;
# Decode auth response header
set_decode_base64 $pth_auth_error_decoded $pth_auth_error;
# Return the error from pth-auth service if any
if ($pth_auth_error_decoded != ""){
add_header Content-Type $pth_auth_error_content_type always;
return 401 $pth_auth_error_decoded;
}
# Fall back to default nginx response
return 401;
}
location @ingress_service_custom_error_500 {
internal;
# Decode auth response header
set_decode_base64 $pth_auth_error_decoded $pth_auth_error;
# Return the error from pth-auth service if any
if ($pth_auth_error_decoded != ""){
add_header Content-Type $pth_auth_error_content_type always;
return 500 $pth_auth_error_decoded;
}
# Return a hardcoded error in case no pth-auth pods are available
if ($pth_auth_status = 503){
add_header Content-Type application/json always;
return 503 "{\"msg\":\"pth-auth service is unavailable\"}";
}
# Fall back to default nginx response
return 500;
}
spec:
rules:
- http:
paths:
- path: /?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: client-cluster-ip-service
servicePort: 3000
- path: /api/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: server-cluster-ip-service
servicePort: 5000
- path: /pth-auth/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: pth-auth
servicePort: 8000
灵感来自:https://whosebug.com/a/31485557/99237
疑难解答提示:
- Here's the template nginx ingress uses when transforming the ingress annotations into nginx config file.
- 连接到入口控制器 pod 并查看
/etc/nginx/nginx.conf
以查看生成的 nginx 配置。
我已经在 EKS 上部署了我的 Kubernetes 集群。我有一个 ingress-nginx,它通过负载均衡器公开以将流量路由到不同的服务。在 ingress-nginx 中,第一个请求转到 auth 服务进行身份验证,如果它是一个有效请求,那么我允许它继续前进。这是使用 ingress-nginx 注释 nginx.ingress.kubernetes.io/auth-url 完成的。 Auth 服务是使用 FastAPI 开发的。如果来自 fastAPI 的 401 响应如下所示 FASTAPI
但是当我使用 ingress-nginx 时,响应看起来像这样 INGRESS_NGINX
有没有办法从 Ingress-nginx 获得 JSON 响应? 入口文件
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: 'nginx'
nginx.ingress.kubernetes.io/use-regex: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/auth-response-headers: item_id
nginx.ingress.kubernetes.io/auth-method: POST
nginx.ingress.kubernetes.io/auth-url: http://pth-auth.default.svc.cluster.local:8000/item/1
# UPDATE THIS LINE ABOVE
spec:
rules:
- http:
paths:
- path: /?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: client-cluster-ip-service
servicePort: 3000
- path: /api/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: server-cluster-ip-service
servicePort: 5000
- path: /pth-auth/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: pth-auth
servicePort: 8000
这对我有用,参考了这里 https://github.com/kubernetes/ingress-nginx/issues/2292
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: 'nginx'
nginx.ingress.kubernetes.io/use-regex: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/auth-response-headers: item_id
nginx.ingress.kubernetes.io/auth-method: POST
nginx.ingress.kubernetes.io/auth-url: http://pth-auth.default.svc.cluster.local:8000/items/1
nginx.ingress.kubernetes.io/server-snippet: |
location = /error/401 {
proxy_method POST;
proxy_pass http://pth-auth.default.svc.cluster.local:8000/error/401;
}
location = /error/403 {
proxy_method POST;
proxy_pass http://pth-auth.default.svc.cluster.local:8000/error/403;
}
nginx.ingress.kubernetes.io/configuration-snippet: |
error_page 401 /error/401;
error_page 403 /error/403;
# UPDATE THIS LINE ABOVE
spec:
rules:
- http:
paths:
- path: /?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: client-cluster-ip-service
servicePort: 3000
- path: /api/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: server-cluster-ip-service
servicePort: 5000
- path: /pth-auth/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: pth-auth
servicePort: 8000
你只需要告诉 nginx 万一错误路由流量到这个位置,他们的函数将处理特定的错误。在我的例子中,函数是 error/{error_code}.
这是一个对我有用的解决方案。它允许身份验证服务 return 每个请求的自定义错误消息。
需要注意的是,由于nginx无法访问auth响应body,pth-auth
服务需要将数据放在Pth-Auth-Error
header(base64编码).
此示例处理 401、500 和 pth-auth
服务不可用时的特殊情况。
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: 'nginx'
nginx.ingress.kubernetes.io/use-regex: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/auth-response-headers: item_id
nginx.ingress.kubernetes.io/auth-method: POST
nginx.ingress.kubernetes.io/auth-url: http://pth-auth.default.svc.cluster.local:8000/item/1
# UPDATE THIS LINE ABOVE
nginx.ingress.kubernetes.io/configuration-snippet: |
# Redirect auth errors to custom named locations
error_page 401 = @ingress_service_custom_error_401;
error_page 500 = @ingress_service_custom_error_500;
# Grab data from auth error response
auth_request_set $pth_auth_error $upstream_http_pth_auth_error;
auth_request_set $pth_auth_error_content_type $upstream_http_content_type;
auth_request_set $pth_auth_status $upstream_status;
nginx.ingress.kubernetes.io/server-snippet: |
location @ingress_service_custom_error_401 {
internal;
# Decode auth response header
set_decode_base64 $pth_auth_error_decoded $pth_auth_error;
# Return the error from pth-auth service if any
if ($pth_auth_error_decoded != ""){
add_header Content-Type $pth_auth_error_content_type always;
return 401 $pth_auth_error_decoded;
}
# Fall back to default nginx response
return 401;
}
location @ingress_service_custom_error_500 {
internal;
# Decode auth response header
set_decode_base64 $pth_auth_error_decoded $pth_auth_error;
# Return the error from pth-auth service if any
if ($pth_auth_error_decoded != ""){
add_header Content-Type $pth_auth_error_content_type always;
return 500 $pth_auth_error_decoded;
}
# Return a hardcoded error in case no pth-auth pods are available
if ($pth_auth_status = 503){
add_header Content-Type application/json always;
return 503 "{\"msg\":\"pth-auth service is unavailable\"}";
}
# Fall back to default nginx response
return 500;
}
spec:
rules:
- http:
paths:
- path: /?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: client-cluster-ip-service
servicePort: 3000
- path: /api/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: server-cluster-ip-service
servicePort: 5000
- path: /pth-auth/?(.*)
# UPDATE THIS LINE ABOVE
backend:
serviceName: pth-auth
servicePort: 8000
灵感来自:https://whosebug.com/a/31485557/99237
疑难解答提示:
- Here's the template nginx ingress uses when transforming the ingress annotations into nginx config file.
- 连接到入口控制器 pod 并查看
/etc/nginx/nginx.conf
以查看生成的 nginx 配置。