Helm部署OAuth2-Proxy
介绍
-
是一款对k8s应用做身份验证的反向代理。工作模式有两种:

在我们的示例中,使用的是右边的middleware模式,作用于ingress-nginx。
-
github:oauth2-proxy/oauth2-proxy
-
releases page: OAuth2 Proxy Manifests Releases
-
artifact hub: oauth2-proxy helm chart
下载
helm repo add --force-update oauth2-proxy https://oauth2-proxy.github.io/manifests
helm repo update oauth2-proxy
helm pull oauth2-proxy/oauth2-proxy --version 7.7.1配置oauth2proxy
创建redis password
oauth的sessionStorage选择使用redis,oauth helm chart会安装redis subchart。这里需要一个redis密码,保存到secret里。
export REDIS_PASSWD=$( openssl rand -base64 32 | head -c 32 | base64 )
kubectl -n oauth2-proxy create secret generic oauth2-proxy-redis --from-literal=redis-password=$REDIS_PASSWD
# 需要打上标签,后续安装helm的时候会被纳入到helm管理
kubectl label secrets oauth2-proxy-redis -n oauth2-proxy "app.kubernetes.io/managed-by"="Helm"
kubectl annotate secrets oauth2-proxy-redis -n oauth2-proxy "meta.helm.sh/release-name"="oauth2-proxy"
kubectl annotate secrets oauth2-proxy-redis -n oauth2-proxy "meta.helm.sh/release-namespace"="oauth2-proxy"sessionStorage负责认证状态维护
sessionStorage: type: redis # 使用 Redis 存储用户会话状态 redis: enabled: true # 启用内置 Redis这样的架构使得:
- Nginx 负责流量路由和认证检查
- OAuth2 Proxy 负责具体的 OAuth 认证流程
- Redis 负责会话状态存储
- 所有受保护的服务都能自动获得统一的身份认证
集成github认证
-
先去github生成一个OauthAPP:(Developer applications),复制
client id和client secret。-
application name:
oauth2proxy-local -
Homepage URL:https://oauth2proxy.hanxux.local/
-
Authorization callback URL:https://oauth2proxy.hanxux.local/oauth2/callback
-
-
创建一个cookie secret
export COOKIE_SECRET=$( openssl rand -base64 32 | head -c 32 | base64 )-
oauth2proxy的values.yaml里面添加github认证相关参数
config: existingSecret: oauth2-proxy-creds extraArgs: provider: github whitelist-domain: .hanxux.local cookie-domain: .hanxux.local -
传入gitub oauth app的client id和secret
方法1-创建secret保存
-
创建k8s secret
export CLIENT_ID="Ov23liF0QvSRG51yPKq1" export CLIENT_SECRET="xxx" kubectl create namespace oauth2-proxy kubectl -n oauth2-proxy create secret generic oauth2-proxy-creds --from-literal=cookie-secret=$COOKIE_SECRET --from-literal=client-id=$CLIENT_ID --from-literal=client-secret=$CLIENT_SECRET
方法2-直接写入values
-
注:上面创建secret的方式oauth2proxy没有读取到。遂采取直接把cookie_secret、client_id和client_secret三个参数直接写到values.yaml里面的方式
config: # Add config annotations annotations: {} # OAuth client ID clientID: "Ov23liF0QvSRG51yPKq1" # OAuth client secret clientSecret: "xxx" # Create a new secret with the following command # openssl rand -base64 32 | head -c 32 | base64 # Use an existing secret for OAuth2 credentials (see secret.yaml for required fields) # Example: #existingSecret: oauth2-proxy-creds cookieSecret: "xxx" # The name of the cookie that oauth2-proxy will create # If left empty, it will default to the release name cookieName: ""
方法3-github secrets
-
上述方式不安全,会直接暴露secret。后续修改了secret加载方式,先存到github repository secrets里面,再从workflow中读取
export helmChartVersion=${{env.oauth2proxyVersion}} export helmRepoName='oauth2-proxy' export helmChartName='oauth2-proxy' export REDIS_PASSWORD=$(kubectl get secret --namespace "oauth2-proxy" oauth2-proxy-redis --kubeconfig $KUBECONFIG -o jsonpath="{.data.redis-password}" | base64 -d) helm upgrade -i oauth2-proxy -n oauth2-proxy \ oci://${{ env.harborURL }}/${{ env.harborProjectName }}/$helmRepoName/$helmChartName \ --version $helmChartVersion \ --history-max 5 \ -f ./base/external/oauth2-proxy/values.yaml \ --set config.clientID='${{ secrets.OAUTH2PROXY_CLIENT_ID}}' \ --set config.clientSecret='${{ secrets.OAUTH2PROXY_CLIENT_SECRET}}' \ --set config.cookieSecret='${{ secrets.OAUTH2PROXY_COOKIE_SECRET}}' \ --set global.redis.password=$REDIS_PASSWORD \ --insecure-skip-tls-verify \ --kubeconfig $KUBECONFIG
配置Https
-
首先部署出certmanager ⇒ 创建clusterissuer ⇒ 创建给oauth2proxy ingress https的secret ⇒ helm values.yaml的ingress.tls部分配置secret、host
-
创建oauth2proxy的tls secret
tee certificate-oauth2proxy.yaml <<'EOF'
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: cert-oauth2proxy
namespace: oauth2-proxy
spec:
secretName: oauth2proxy-tls-cert-secret
privateKey:
rotationPolicy: Always
commonName: oauth2proxy.hanxux.local
dnsNames:
- oauth2proxy.hanxux.local
usages:
- digital signature
- key encipherment
- server auth
issuerRef:
name: selfsigned
kind: ClusterIssuer
EOF- oauth2proxy的values配置ingress tls
ingress:
enabled: true
ingressClassName: nginx-default
hosts:
- oauth2proxy.hanxux.local
tls:
- secretName: oauth2proxy-tls-cert-secret
hosts:
- oauth2proxy.hanxux.local
path: /
# Only used if API capabilities (networking.k8s.io/v1) allow it
pathType: ImplementationSpecific安装
helm upgrade -i oauth2-proxy -n oauth2-proxy --create-namespace . -f values.yaml- 验证安装:
oauth2proxy.hanxux.local也要加到本机hosts文件中,https访问hostname即可看到oauthproxy的主页,有用github登录的提示。由于lab用的是自签证书,所以浏览器会报连接不安全。
回调URL
回调 URL 是 OAuth2 授权流程中,授权服务器(GitHub)在用户完成授权后,将用户重定向回去的目标地址。
使用回调URL的优点:
- 安全验证
- GitHub 只会将授权码发送到预先注册的回调 URL
- 防止恶意应用窃取授权码
- 完成授权流程
- OAuth2 Proxy 通过这个 URL 接收 GitHub 返回的授权码
- 没有这个回调,授权流程无法完成
- 状态管理
- 回调中包含
state参数,用于防止 CSRF 攻击 - OAuth2 Proxy 验证 state 确保请求的合法性
实际示例
使用的是 ingress-nginx 的外部认证功能来集成 OAuth2 Proxy。以访问jenkins
sequenceDiagram participant User as 用户浏览器 participant IngressNginx as Ingress-Nginx Controller participant OAuth2 as OAuth2 Proxy participant GitHub as GitHub OAuth participant Jenkins as Jenkins Pod Note over User,Jenkins: 1. 初始访问 User->>IngressNginx: GET https://jenkins.hanxux.local Note over IngressNginx,OAuth2: 2. Nginx 外部认证检查 IngressNginx->>OAuth2: auth_request to https://oauth2proxy.hanxux.local/oauth2/auth OAuth2->>IngressNginx: 401 Unauthorized (no valid session) Note over IngressNginx,User: 3. 重定向到认证 IngressNginx->>User: 302 Redirect to https://oauth2proxy.hanxux.local/oauth2/start?rd=https://jenkins.hanxux.local Note over User,GitHub: 4. OAuth2 授权流程开始 User->>OAuth2: GET /oauth2/start?rd=... OAuth2->>User: 302 Redirect to GitHub OAuth User->>GitHub: GET /login/oauth/authorize?client_id=...&redirect_uri=https://oauth2proxy.hanxux.local/oauth2/callback Note over User,GitHub: 5. 用户在 GitHub 授权 GitHub->>User: 显示授权页面 User->>GitHub: 用户点击"授权" Note over GitHub,OAuth2: 6. GitHub 回调 GitHub->>User: 302 Redirect to https://oauth2proxy.hanxux.local/oauth2/callback?code=...&state=... User->>OAuth2: GET /oauth2/callback?code=... Note over OAuth2,GitHub: 7. 交换访问令牌 OAuth2->>GitHub: POST /login/oauth/access_token (exchange code for token) GitHub->>OAuth2: 返回 access_token OAuth2->>GitHub: GET /user (获取用户信息) GitHub->>OAuth2: 返回用户信息 Note over OAuth2,User: 8. 设置认证会话 OAuth2->>User: 设置认证 cookie + 302 Redirect to https://jenkins.hanxux.local Note over User,Jenkins: 9. 重新访问原始资源 User->>IngressNginx: GET https://jenkins.hanxux.local (with auth cookie) Note over IngressNginx,OAuth2: 10. 再次进行外部认证 IngressNginx->>OAuth2: auth_request to https://oauth2proxy.hanxux.local/oauth2/auth (with cookie) OAuth2->>IngressNginx: 200 OK + X-Auth-Request-User headers Note over IngressNginx,Jenkins: 11. 转发到后端服务 IngressNginx->>Jenkins: GET / (with user headers) Jenkins->>IngressNginx: 返回 Jenkins 页面 IngressNginx->>User: 返回 Jenkins 页面
OAuth2 Proxy 的作用:
从流程可以看出,OAuth2 Proxy 在这里扮演两个关键角色:
-
认证端点 (
/oauth2/auth):- Nginx 每次请求都会调用这个端点检查用户是否已认证
- 返回 200 表示已认证,401 表示未认证
-
认证流程处理器:
/oauth2/start: 开始 OAuth 流程/oauth2/callback: 处理 GitHub 回调
使用oauth2proxy保护其他app
- 在其他应用的ingress中添加annotations,详细说明参考ingress官网:OAuth External Auth
- 这两个annotations会将请求redirect到oauth2proxy,由oauth2proxy将请求转发到配置的3rd party认证endpoint (github)
annotations:
nginx.ingress.kubernetes.io/auth-url: "http://oauth2-proxy.oauth2-proxy.svc.cluster.local/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://oauth2proxy.hanxux.local/oauth2/start?rd=https%3A%2F%2F<host>.hanxux.local"