【问题标题】:External OAuth authentication with Nginx in Kubernetes在 Kubernetes 中使用 Nginx 进行外部 OAuth 身份验证
【发布时间】:2020-10-29 11:32:39
【问题描述】:

无法为 nginx 入口后面的 Web 应用程序设置外部身份验证。当我尝试从外部访问 URL https://site.example.com 时,我没有重定向到 Github 登录,而是直接访问 Web 应用程序。

为我的环境运行 Pod:

NAME                              READY   STATUS   
nginx-ingress-68df4dfc4f-wpj5t    1/1     Running  
oauth2-proxy-6675d4b57c-cspw8     1/1     Running   
web-deployment-7d4bd85b46-blxb8   1/1     Running   
web-deployment-7d4bd85b46-nqjgl   1/1     Running   

活动服务:

NAME            TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)                      
nginx-ingress   LoadBalancer   10.96.156.157    192.168.1.82   80:31613/TCP,443:32437/TCP   
oauth2-proxy    ClusterIP      10.100.101.251   <none>         4180/TCP                     
web-service     ClusterIP      10.108.237.188   <none>         8080/TCP                     

两个 Ingress 资源:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress
  namespace: nginx-ingress
  annotations:
     kubernetes.io/ingress.class: nginx
     nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
     nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$request_uri"
  labels:
    app: webapp
spec:
  rules:
  - host: site.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web-service
          servicePort: 8080
  tls:
  - hosts:
    - site.example.com
    secretName: example-tls

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: oauth2-proxy
  namespace: nginx-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
  labels:
    app: oauth2-proxy
spec:
  rules:
  - host: site.example.com
    http:
      paths:
      - backend:
          serviceName: oauth2-proxy
          servicePort: 4180
        path: /oauth2

  tls:
  - hosts:
    - site.example.com
    secretName: example-tls

入口输出:

NAME           CLASS    HOSTS              ADDRESS        PORTS     
ingress        <none>   site.example.com   192.168.1.82   80, 443   
oauth2-proxy   <none>   site.example.com                  80, 443   

我在 Ingress oauth2-proxy 事件中看到这些错误:

Events:
  Type     Reason    Age   From                      Message
  ----     ------    ----  ----                      -------
  Warning  Rejected  54m   nginx-ingress-controller  All hosts are taken by other resources

根据在我的 Github 帐户中创建的 OAuth 应用,从部署 here 构建的 Oauth2-proxy 具有客户端 ID、客户端密码和 SECRET。

在 oauth2-proxy 日志中找不到日志,我想是因为它没有在进程中调用。

更新

这个问题不完整,我忘了提到使用的 NGINX 图像(来自installation guide 的 NGINX 1.9.0)。

用下面的改变图像:

NGINX Ingress controller
Release: v0.41.2
Build: d8a93551e6e5798fc4af3eb910cef62ecddc8938
Repository: https://github.com/kubernetes/ingress-nginx
nginx version: nginx/1.19.4

错误消失。简而言之,两种 Ingress 配置,我的问题中的一个和答案中的另一个都有效。

【问题讨论】:

  • 基于外部 IP 它是您的本地环境。您使用的是Kubeadm 还是Minikube?它是一台机器,还是您有一些虚拟化软件,如VMVareVirtualBox?您使用的是最新的 k8s 和 nginx-ingress-controller v0.9.0 还是greetr?你没用过Let's encrypt之类的其他应用吗?
  • Kubeadm - Virtualbox - nginx-ingress:1.9.0 和最新的 k8s,我使用的是用 openssl 在本地签名的证书
  • Kubeadm v1.19.3,Master 和 2 worker 集群

标签: nginx kubernetes


【解决方案1】:

在您的配置中,您使用的是 2 Ingress。正如您所描述的oauth2-proxy Ingress,在Event 部分您可以找到信息:

所有主机都被其他资源占用

您在这里遇到的问题称为Host Collisions。它发生在您使用过的Ingress 中:

spec:
  rules:
  - host: site.example.com

在这种情况下,Ingress 使用称为Choosing the Winner 的默认算法。

如果多个资源争夺同一个主机,Ingress Controller 将根据资源的creationTimestamp 选出获胜者:最旧的资源将获胜。

您的问题的快速解决方案是创建一个具有 2 条路径的 Ingress

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress
  namespace: nginx-ingress
  annotations:
     kubernetes.io/ingress.class: nginx
     nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
     nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$request_uri"
spec:
  rules:
  - host: site.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web-service
          servicePort: 8080
      - path: /oauth2
        backend:
          serviceName: oauth2-proxy
          servicePort: 4180      
  tls:
  - hosts:
    - site.example.com
    secretName: example-tls

解决此问题的另一种方法是使用Merging Configuration for the Same Host,但不应该在这种情况下应用它。

最后,您可以关注官方 Nginx Ingress 教程 - External OAUTH Authentication

【讨论】:

  • 感谢您的回复。 Ingress 的结果提供了两个路径:如果我键入 site.example.com,我会直接进入 Web 应用程序而无需身份验证,如果我使用 /oauth2 键入相同的 URL,我会被重定向到 Github 登录页面。我希望在输入 URL site.example.com 时进行身份验证。
  • 要实现这一点,您只需要更改路径,将web-service 路径从/ 更改为/web,对于oauth2-proxy 将路径从/oauth2 更改为/。这样,当您输入site.example.com 时,您将被重定向到登录页面
  • 很好。访问site.example.com 现在重定向到 Github 登录,在输入用户\密码后我得到 500Internal Server Error,检查 oauth2-proxy 日志我可以发现:在 OAuth2 回调期间兑换代码时出错:执行请求时出错:发布“github.com/login/oauth/access_token”:拨号tcp:在 10.96.0.10:53 上查找 github.com:服务器行为异常。将 /bin/sh 放入 oauth2-proxy 并执行 nslookup github.com 无法解决,我认为这是 DNS 问题,因此 oauth2-proxy 无法解析 github.com
  • DNS 问题与工作节点中的 /etc/resolv.conf 有关,使用正确的名称服务器编辑文件现在 OAuth2 成功。身份验证后,浏览器被重定向到site.example.com,找不到 404 页面
  • @Marco_81 这里的主要问题是您没有被重定向到经过身份验证的 pod,问题的根本原因是入口配置。对于 Oauth 问题,根据 StackOverflow 指南,您应该创建新问题。如果您能提供您是如何配置 oauth 并添加 oauth 标签的,那就太好了
猜你喜欢
  • 2020-04-21
  • 2011-11-27
  • 2019-10-08
  • 1970-01-01
  • 2019-05-08
  • 2011-10-20
  • 2014-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多