前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于k8s Ingress Nginx+OAuth2+Gitlab无代码侵入实现自定义服务的外部验证

基于k8s Ingress Nginx+OAuth2+Gitlab无代码侵入实现自定义服务的外部验证

作者头像
仙人技术
发布2021-01-27 15:36:06
3.6K0
发布2021-01-27 15:36:06
举报
文章被收录于专栏:山山仙人的专栏

1、OAuth和OAuth2.0介绍

OAuth是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌token,用来代替密码,供第三方应用使用。

OAuth 2.0是用于授权的行业标准协议。OAuth 2.0致力于简化客户端开发人员的工作,同时为Web应用程序,桌面应用程序,移动电话和客厅设备提供特定的授权流程。

OAuth 2.0是目前最流行的授权机制,用来授权第三方应用,获取用户数据。

2、应用场景

很多情况下,许多应用程序不提供内置的身份验证或开箱即用的访问控制。由于这些应用程序处理的敏感数据,这可能是一个主要问题,通常有必要提供某种类型的安全性。基于k8s部署的一些服务,并没有自身的访问认证控制机制。例如我们部署一个用于公司内部使用的web应用,又不想做基于统一账号SSO的认证功能的开发,但是又想在用户访问时加上一层认证功能。这类情况的解决思路一般是在访问入口,例如Ingress上添加一层访问认证,可以借助于basic auth实现此功能,但basic auth存在过于简单、账号权限不好控制、需要手动维护等诸多问题。

于是另外一种相对更为成功的解决办法是使Ingress通过OAuth对接到能够提供支持oauth认证的外部服务,例如githubgitlab。这种方式没有对应用程序的代码侵入,仅仅在应用入口添加了配置。

除了上述我描述的这个应用场景,还有很多可以利用oauth轻松实现认证的场景。

3、oauth2 proxy介绍

oauth2 proxy是一个反向代理和静态文件服务器,使用提供程序(GoogleGitHub和其他提供商)提供身份验证,以通过电子邮件,域或组验证帐户。

项目地址:https://github.com/oauth2-proxy/oauth2-proxy

认证过程的流程如下

4、具体实现

实验环境:

  • k8s 1.15.0
  • Ingress nginx 0.25.0
  • gitlab 13.7.4

4.1 在Gitlab配置OpenID应用

登录到Gitlab—>管理中心—>应用,创建一个应用

参数:

  • 回调URL:指GitLab在用户通过身份验证后应将其发送到的端点,对于oauth2-proxy应该是https://<应用域名>/oauth2/callback
  • 范围:应用程序对GitLab用户配置文件的访问级别。对于大多数应用程序,选择openidprofileemail即可。

创建完应用后,会生成一对ID和密钥,这个在后面会用到。

4.2 生成Cookie密钥

生成Cookie密钥。该Cookie密钥作为种子字符串以产生安全的cookie

参考官方说明,使用base64编码,可利用以下的python脚本生成字符串。

代码语言:javascript
复制
import secrets
import base64

print(base64.b64encode(base64.b64encode(secrets.token_bytes(16))))

4.3 部署oauth2-proxy

k8s中部署oauth-proxy,资源清单oauth2-gitlab.yaml和相关参数说明如下。更多的配置参数,可以参考官方文档

代码语言:javascript
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: oauth2-proxy
  name: oauth2-proxy
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: oauth2-proxy
  template:
    metadata:
      labels:
        k8s-app: oauth2-proxy
    spec:
      containers:
      - name: oauth2-proxy
        image: quay.io/oauth2-proxy/oauth2-proxy:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 4180
          protocol: TCP
        args:
        # OAuth提供者
        - --provider=gitlab
        # 上游端点的http网址
        - --upstream=file:///dev/null
        # 对具有指定域的电子邮件进行身份验证,可以多次给出,使用*验证任何电子邮件
        - --email-domain=*
        # 监听的地址
        - --http-address=0.0.0.0:4180
        # 设置安全(仅HTTPS)cookie标志
        - --cookie-secure=false
        # OAuth重定向URL
        - --redirect-url=https://nginx-test.ssgeek.com/oauth2/callback
        # 跳过登录页面直接进入下一步
        - --skip-provider-button=false
        # 设置X-Auth-Request-User,X-Auth-Request-Email和X-Auth-Request-Preferred-Username响应头(在Nginx auth_request模式下有用)。与结合使用时--pass-access-token,会将X-Auth-Request-Access-Token添加到响应标头中
        - --set-xauthrequest=true
        # 跳过OPTIONS请求的身份验证
        - --skip-auth-preflight=false
        # 绕过OIDC端点发现
        - --skip-oidc-discovery
        # OpenID Connect发行者url,这里是gitlab的url
        - --oidc-issuer-url=https://gitlab.ssgeek.com
        # 认证url
        - --login-url=https://gitlab.ssgeek.com/oauth/authorize
        # token url
        - --redeem-url=https://gitlab.ssgeek.com/oauth/token
        # 用于令牌验证的url
        - --oidc-jwks-url=https://gitlab.ssgeek.com/oauth/discovery/keys
        env:
        - name: OAUTH2_PROXY_CLIENT_ID
          value: '85945b7195ab109377183837b9221bd299bc64b31fe272304a1c777e8e241d83'
        - name: OAUTH2_PROXY_CLIENT_SECRET
          value: '2f9782928b493686f387d18db9138e92607448cef045c81319967cc3e5ce4ba1'
         # 安全cookie的种子字符串,可通过python脚本生成
        - name: OAUTH2_PROXY_COOKIE_SECRET
          value: 'VGlYNVBVOGw4UFgyRURzbERxVTRiZz09'

---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: oauth2-proxy
  name: oauth2-proxy
  namespace: kube-system
spec:
  type: NodePort
  ports:
  - name: http
    port: 4180
    protocol: TCP
    targetPort: 4180
    nodePort: 30020
  selector:
    k8s-app: oauth2-proxy

应用上面的资源清单,创建deploymentservice

代码语言:javascript
复制
$ kubectl apply -f oauth2-gitlab.yaml
$ kubectl -n kube-system get pods -l k8s-app=oauth2-proxy 
NAME                           READY   STATUS    RESTARTS   AGE
oauth2-proxy-884695869-bkwns   1/1     Running   0          113s

上面通过nodeport单独暴露了oauth2-proxy应用,可以访问检查以确保浏览器可以正常打开

4.4 创建测试应用并配置Ingress

资源清单文件nginx.yaml如下,其中为该nginx应用配置了https证书

代码语言:javascript
复制
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.15
        imagePullPolicy: IfNotPresent
        name: nginx

---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: kube-system
spec:
  selector:
    app: nginx
  ports:
  - name: nginx
    port: 80
    targetPort: 80

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx
  namespace: kube-system
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /
    # 指定外部认证url
    nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
    # 指定外部认证重定向的地址
    nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/secure-backends: "true"
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - nginx-test.ssgeek.com
    secretName: nginx-test
  rules:
    - host: nginx-test.ssgeek.com
      http:
        paths:
        - path: /
          backend:
            serviceName: nginx
            servicePort: 80

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    # 将nginx应用的访问请求跳转到oauth2-proxy组件url
    nginx.ingress.kubernetes.io/rewrite-target: "/oauth2"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/secure-backends: "true"
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  name: nginx-oauth2
  namespace: kube-system
spec:
  tls:
  - hosts:
    - nginx-test.ssgeek.com
    secretName: nginx-test
  rules:
  - host: nginx-test.ssgeek.com
    http:
      paths:
      - path: /oauth2
        backend:
          serviceName: oauth2-proxy
          servicePort: 4180

应用上面的资源清单,创建相应资源

代码语言:javascript
复制
$ kubectl apply -f other/nginx.yaml
deployment.extensions/nginx unchanged
service/nginx unchanged
ingress.extensions/nginx unchanged
ingress.extensions/nginx-oauth2 unchanged
$ kubectl -n kube-system get po,svc,ing |grep nginx                        
pod/nginx-5ddcc6cb74-rnjlx                    1/1     Running   0          3m

service/nginx                     ClusterIP   10.68.199.62    <none>        80/TCP                      3m

ingress.extensions/nginx               nginx-test.ssgeek.com             80, 443   3m
ingress.extensions/nginx-oauth2        nginx-test.ssgeek.com             80, 443   3m

4.5 测试外部认证

通过访问上面部署的nginx应用,在浏览器中进行测试,会被重定向到Gitlab登录页面;

输入账号,正确登录后,会被重定向回nginx应用。

4.6 流程分析

在请求登录外部认证的过程中查看oauth2-proxy的日志如下

代码语言:javascript
复制
172.16.1.110:49976 - - [2021/01/23 17:28:23] nginx-test.ssgeek.com GET - "/oauth2/auth" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15" 401 21 0.000
172.16.1.110:9991 - - [2021/01/23 17:28:23] nginx-test.ssgeek.com GET - "/oauth2/start?rd=%2F" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15" 302 341 0.000
172.16.1.110:9991 - admin@example.com [2021/01/23 17:28:32] [AuthSuccess] Authenticated via OAuth2: Session{email:admin@example.com user:root PreferredUsername: token:true id_token:true created:2021-01-23 17:28:32.440915913 +0000 UTC m=+2248.944621207 expires:2021-01-23 17:30:32 +0000 UTC refresh_token:true}
172.16.1.110:9991 - - [2021/01/23 17:28:32] nginx-test.ssgeek.com GET - "/oauth2/callback?code=9b7f5425d48a41f213065a4ff5b3d20d76e6d241ba753c5cd63d1a405f48818e&state=5d868b96b1f539a28da2291404152b7c%3A%2F" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15" 302 24 0.381
172.16.1.110:5610 - admin@example.com [2021/01/23 17:28:32] nginx-test.ssgeek.com GET - "/oauth2/auth" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15" 202 0 0.000
  • 访问nginx应用的时候,Ingress nginx controller会向定义的auth-url发起认证,该认证由Ingress nginx controller发起,所以Ingress nginx controller对应的pod必须能够访问auth-url
  • 如果认证没有通过,Ingress nginx controller将客户端重定向到auth-signinauth-signin是目标应用的 oauth2登录页面即oauth2-proxy
  • 客户端被重定向到oauth2登录页面后,自动进入Gitlab的登录页面, 用户登录Gitlab后,Gitlab再将客户端重定向到在Gitlab中配置的应用回调地址。
  • 客户端访问回调地址后,oauth2_proxy在客户端设置cookie,并将客户端重定向到最初的访问地址。
  • 带有cookie的客户端再次访问目标应用时,通过了auth-url的认证,成功访问到目标服务即nginx应用。

5、总结

本文以基于k8s部署的nginx服务为例,记录如何通过ingressoauth2 proxy对接gitlab实现对应用没有代码侵入的外部认证。

最后,还要提到的一点是,我这里一开始使用的Gitlab是已有的10.8.4版本,调试了关于Oauth2-proxy的很多参数一直不成功,也没有找到解决办法,但是按照官方的配置与github对接时却没有报任何异常。最终通过提交issue得到了可能原因,即GitlabAPI版本可能不兼容,oauth2-proxy的开发测试成功版本的Gitlab12.x版本以上。详情可参考我提交的issue

See you ~

参考文档:

https://oauth.net/2/ https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/ https://oauth2-proxy.github.io/oauth2-proxy/docs/

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-01-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、OAuth和OAuth2.0介绍
  • 2、应用场景
  • 3、oauth2 proxy介绍
  • 4、具体实现
    • 4.1 在Gitlab配置OpenID应用
      • 4.2 生成Cookie密钥
        • 4.3 部署oauth2-proxy
          • 4.4 创建测试应用并配置Ingress
            • 4.5 测试外部认证
              • 4.6 流程分析
              • 5、总结
              相关产品与服务
              多因子身份认证
              多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档