【发布时间】:2020-09-27 19:28:51
【问题描述】:
问题
在尝试通过我的 ELB 路由到 Kubernetes Nginx 入口控制器时,我从 Spring 获得了 403 SSL 要求。
设置
我的设置如下:
- 我的 Kubernetes 集群(由 kops 创建)有一个带有 ACM 的 ELB (AWS),它将所有请求路由到
- Nginx Ingress Controller 依次根据中规定的规则路由所有请求
- 将流量传递到的入口
- 在 中公开端口 80 并路由到端口 8080 的服务
- 使用标签“app=foobar”(在部署中描述)选择的 Pod
- Pod 正在运行 Spring Boot Web App v2.1.3
所以基本上:
https://foo.bar.com(:443) -> ingress -> http://foo.bar.svc.cluster.local:80
这对所有东西都很有用。除了 SprintBoot。
出于某种原因,我不断收到来自 Spring 的 403 - SSL required
这里要记住一点:我的 Spring 应用程序与 SSL 没有任何关系。我不希望它以那种性质做任何事情。出于本示例的目的,这应该是常规 REST API 请求,SSL 终止发生在容器外部。
到目前为止我尝试了什么
- 端口转发到服务本身并请求 - 它工作正常。
- 在
WebSecurityConfigurerAdapter中禁用 CSRF - 输入入口注释
nginx.ingress.kubernetes.io/force-ssl-redirect=true- 当我尝试它时它会给出 TOO_MANY_REDIRECTS 错误(而不是 403) - 输入入口注释
nginx.ingress.kubernetes.io/ssl-redirect=true- 没有任何作用 - 输入入口注释
nginx.ingress.kubernetes.io/enable-cors: "true"- 没有任何作用 - 还有
nginx.ingress.kubernetes.io/ssl-passthrough: "true" - 还有
nginx.ingress.kubernetes.io/secure-backends: "true" - 还有
kubernetes.io/tls-acme: "true" - 我尝试了一大堆其他我现在不记得的东西
它在我的集群中是什么样子的
Nginx 入口控制器注解是这样的(我使用的是官方的 nginx 入口控制器 helm 图,除了这个东西几乎没有修改):
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "aws_acm_certificate_arn"
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
入口如下所示:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: foobar
namespace: api
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: foobar
servicePort: http
path: /
服务如下所示:
apiVersion: v1
kind: Service
metadata:
name: foobar
namespace: api
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
selector:
app: foobar
我认为问题是什么
我的预感是它带有 X-Forwarded 标头,而 Spring 在幕后发挥了它的魔力,试图变得聪明,并决定我需要基于某些标头的 SSL,而无需我明确要求它。但我还没弄明白。
我到处寻找解决方案,但找不到任何可以减轻痛苦的方法...希望您能提供帮助!
编辑
我发现我当前的设置(没有 k8s 和 nginx)工作正常,ELB 通过 X-Forwarded-Port: 443 和 X-Forwarded-Proto: https,它似乎工作,但在我的带有 nginx 的 k8s 集群上,我放入了一个监听器客户端吐出所有标题,我的标题似乎是X-Forwarded-Port: 80和X-Forwarded-Proto: http
【问题讨论】:
-
错误是显示给你的spring boot api(curl、ajax、postman等)的最终客户端还是显示为你的elb/nginx的登录?
-
@JRichardsz "SSL required" 443 在我使用的任何客户端中从 spring boot api 返回。我还得到了更多线索,请注意我刚刚发布的编辑
-
@DorMunis 您应该能够使用属性文件关闭 https 要求。我不确定你为什么在这种情况下强制使用 HTTPS,因为 HTTPS 会被 ELB 终止,而你的 Kubernetes 集群应该只关心端口和服务端点/IP。
-
@sonus21 黑盒方法,这不是我现在正在做的新事物,我想在实际代码中尽可能地改变。不过谢谢你的回复,我也会调查一下
-
您是否有机会在您的 Spring Boot 应用程序(配置或代码)中启用 ssl?
security.require-ssl=true
标签: spring spring-boot ssl nginx kubernetes