当前位置:首页 > 技术文章 > 正文内容

使用 OAuth2-Proxy 和 Keycloak 为系统添加 OAuth2 身份验证

arlanguage3个月前 (01-31)技术文章28

背景

在平常工作,相信大家都会使用到一些常用的开源软件,像 prometheus , rabbitmq , kibanba 等。这些软件很多在权限设计这块就比较简单,或者是没有,如Prometheus 自带的查询面板,早期的 rocketmq dashboard,kibana 等,相信小伙伴有不少基于这块的安全整改,整改措施一般只是配置简单的 http basic 认证,或者 IP 白名单访问。下面介绍基于 Keycloak 和 OAuth2-Proxy 为系统添加 OAuth2 身份验证的方案。

keycloak 简单介绍

KeyCloak 是一种开源身份和访问管理解决方案,以最少的工作量为应用程序添加身份验证和保护服务。Keycloak 提供用户联合、强身份验证、用户管理、精细授权等。目前支持挺多开源软件单点登录,如 jenkins, redash, grafana 等。

OAuth2-Proxy 简单介绍

oauth2-proxy 是一个反向代理和静态文件服务器,它使用提供程序(Google、Keycloak、GitHub 等)提供身份验证,以通过电子邮件、域或组验证帐户。

方案介绍

我们可以使用 OAuth2-ProxyKeycloak 为应用程序中添加 OAuth2 身份验证,特别是那些没有身份验证的系统,下面以 Prometheus 为例,在我的一台服务器上,有 nginx , keycloak , oauth2_proxy 以及 prometheus 4 个服务,其中 keycloak, oauth2_proxy, prometheus 都是通过 nginx vhost 反向代理访问,域名如下图:

配置 Prometheus 基于 OAuth2-ProxyKeycloak 身份验证的请求过程可以参考下图:

nginx , keycloak , oauth2_proxy 以及 prometheus 4 个服务这次全部使用 docker 部署。

keycloak docker 部署

keycloak docker-compose.yml

services:
  keycloak:
    image: quay.io/keycloak/keycloak:25.0.4
    ports:
      - "8080:8080"
 #   restart: always
    environment:
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: ftLVBgGK9SP
      KC_HTTP_ENABLED: true
      KC_PROXY_HEADERS: xforwarded  # keycloak 访问通过 nginx 反向代理,proxy headers 支持 forwarded, xforwarded
      KC_HEALTH_ENABLED: true
      KC_HOSTNAME: keycloak.zwade.top
      #KC_HOSTNAME_STRICT: false
      KC_DB: mysql
      KC_DB_URL: jdbc:mysql://mysql:3306/keycloak
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: Pp123456
    command: 
      - start 
    networks:
      - access-mysql
        
networks:
  access-mysql:
    external: true

默认情况下,服务器使用 dev-file 数据库。这是服务器将用于持久数据的默认数据库,并且仅存在用于开发用例的数据库。 dev-file 数据库不适合生产用例,必须在部署到生产之前替换。keycloak 内置支持不同的数据库,具体可以参考官档。

oauth2-proxy docker 部署

Oauth2-proxy 的配置项可以参考 oauth2-proxy 官档,每个命令行参数都可以指定为环境变量,方法是将其前缀 OAUTH2_PROXY_ ,将其大写,并将连字符 ( - ) 替换为下划线 ( _ )。如果可以多次指定参数,则环境变量应为复数(尾随 S )。注意,环境配置项的值千万不要加引号

生成强 Cookie 密钥,对应环境变量 OAUTH2_PROXY_COOKIE_SECRET

dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | tr -d -- '\n' | tr -- '+/' '-_' ; echo

REDIRECT_URL 需要与 keycloak 配置的 client 的 Valid redirect URIs 配置项要对应上,下面是 oauth2-proxydocker-compose.yml

services:
   server:
     image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0
     ports:
       - "4180:4180"
     environment:
       - OAUTH2_PROXY_PROVIDER=keycloak-oidc
       - OAUTH2_PROXY_CLIENT_ID=prometheus
       - OAUTH2_PROXY_CLIENT_SECRET=z6rqgRPAZ3QsOIbx02Zq60llHeDGpZnAuo
       - OAUTH2_PROXY_REDIRECT_URL=https://prometheus.zwade.top/oauth2/callback
       - OAUTH2_PROXY_OIDC_ISSUER_URL=https://keycloak.zwade.top/realms/master
       - OAUTH2_PROXY_COOKIE_SECRET=ofonr_QLDW5EaKaVp09P2b46Pycn8pps7bHNpjDEUEk=
       - OAUTH2_PROXY_EMAIL_DOMAINS=*
       - OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL=true
       - OAUTH2_PROXY_CODE_CHALLENGE_METHOD=S256
       - OAUTH2_PROXY_REVERSE_PROXY=true
       - OAUTH2_PROXY_HTTP_ADDRESS=0.0.0.0:4180

Nginx 和 Prometheus docker 部署

部署过程略

Keycloak 创建新的 OIDC

Keycloak新版控制台按照以下步骤创建:
a. 在 Keycloak realm 下创建新的 OIDC client
Clients -> Create client
Client Type 选择 OpenID Connect,填写 Client ID,* 必填项,其他项也可以进行填写, Next

Client authentication 'On',
Authentication flow ,勾选 Standard flow,取消勾选 Direct access grants, Next

填写Valid redirect URIs,需要与 oauth2_proxyOAUTH2_PROXY_REDIRECT_URL 对应上,Save

b. client 配置专用的 audience mapper
Clients -> <your client's id> -> Client scopes
点击
Configure a new mapper 然后选择 Audience

Name 一般以aud-mapper-<your client's id>格式,Included Client Audience 下拉框选择你对应的 client's id,Add to ID token 'On',Add to access token 'On',其他保持默认就可以,然后 Save

更多请参考:https://oauth2-proxy.github.io/oauth2-proxy/configuration/providers/keycloak_oidc/

配置 Nginx 反向代理

创建关于 prometheus 域名 nginx vhost 配置,使用 Nginx auth_request 指令,该指令允许 Nginx 通过 oauth2-proxy 的/auth endpoint 对请求进行身份验证,该 endpoint 仅返回 202 Accepted 响应或 401 Unauthorized 响应,而不通过代理请求。

upstream prometheus {
    server localhost:9090;
    keepalive 1;
}


server {
    listen 80;
    listen 443 ssl http2;
    server_name prometheus.zwade.top;

    ssl_certificate /etc/nginx/conf.d/ssl/zwade.top/zwade.top.cer;
    ssl_certificate_key /etc/nginx/conf.d/ssl/zwade.top/zwade.top.key;

    proxy_buffer_size 32k;
    proxy_buffers 4 32k;

    location /oauth2/ {
        proxy_pass       http://127.0.0.1:4180;
        proxy_set_header Host                    $host;
        proxy_set_header X-Real-IP               $remote_addr;
        proxy_set_header X-Auth-Request-Redirect $request_uri;
        # or, if you are handling multiple domains:
        proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
    }

    location = /oauth2/auth {
        proxy_pass       http://127.0.0.1:4180;
        proxy_set_header Host             $host;
        proxy_set_header X-Real-IP        $remote_addr;
        proxy_set_header X-Forwarded-Uri  $request_uri;
        # nginx auth_request includes headers but not body
        proxy_set_header Content-Length   "";
        proxy_pass_request_body           off;
    }

    location / {
        auth_request /oauth2/auth;
        error_page 401 =403 /oauth2/sign_in;

        # pass information via X-User and X-Email headers to backend,
        # requires running with --set-xauthrequest flag
        auth_request_set $user   $upstream_http_x_auth_request_user;
        auth_request_set $email  $upstream_http_x_auth_request_email;
        proxy_set_header X-User  $user;
        proxy_set_header X-Email $email;

        # if you enabled --pass-access-token, this will pass the token to the backend
        auth_request_set $token  $upstream_http_x_auth_request_access_token;
        proxy_set_header X-Access-Token $token;

        # if you enabled --cookie-refresh, this is needed for it to work with auth_request
        auth_request_set $auth_cookie $upstream_http_set_cookie;
        add_header Set-Cookie $auth_cookie;

        # When using the --set-authorization-header flag, some provider's cookies can exceed the 4kb
        # limit and so the OAuth2 Proxy splits these into multiple parts.
        # Nginx normally only copies the first `Set-Cookie` header from the auth_request to the response,
        # so if your cookies are larger than 4kb, you will need to extract additional cookies manually.
        auth_request_set $auth_cookie_name_upstream_1 $upstream_cookie_auth_cookie_name_1;

        # Extract the Cookie attributes from the first Set-Cookie header and append them
        # to the second part ($upstream_cookie_* variables only contain the raw cookie content)
        if ($auth_cookie ~* "(; .*)") {
            set $auth_cookie_name_0 $auth_cookie;
            set $auth_cookie_name_1 "auth_cookie_name_1=$auth_cookie_name_upstream_1$1";
        }

        # Send both Set-Cookie headers now if there was a second part
        if ($auth_cookie_name_upstream_1) {
            add_header Set-Cookie $auth_cookie_name_0;
            add_header Set-Cookie $auth_cookie_name_1;
        }

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass  http://prometheus/;

    }

}
  

测试验证


打开浏览器开发者模式,可以看到请求Prometheus 是带有 ouath2_proxy cookies 认证。

最后

keycloak + oauth2_proxy 真的基本上可以开箱即用,无需额外开发,我们可以使用 keycloak 做统一用户管理,当然 keycloak 还不止上面这些功能,有兴趣的朋友可以自行查看官档。

扫描二维码推送至手机访问。

版权声明:本文由AR编程网发布,如需转载请注明出处。

本文链接:http://www.arlanguage.com/post/1567.html

分享给朋友:

“使用 OAuth2-Proxy 和 Keycloak 为系统添加 OAuth2 身份验证” 的相关文章

NGINX 路由配置与参数详解(https配置、跨域配置、socket配置)

一、概述Nginx 是一个高性能的开源Web服务器,也可以用作反向代理服务器、负载均衡器和HTTP缓存。它的设计目标是提供高并发、低内存消耗和高度可伸缩性,使其成为处理大量并发连接的理想选择。NGINX 基础部分可以参考我这篇文章:NGINX - 高级负载均衡器、Web服务器、反向代理二、https...

PHP日志记录

背景在生产环境中日志的重要性显而易见,能快速定位问题和程序的调优。在LNMP架构中怎么记录好程序中的错误日志。设置error_log记录PHP日志信息#将会向PHP报告发生的每个错误 error_reporting = E_ALL #关闭页面显示才能将错误回写到日志文件 display_err...

基于 consul + nginx 的Spring boot微服务集群部署

consul + nginx 负载均衡最近做的基于consul的微服务项目,仅仅在单机上部署了一套,压测的时候扛不住(并发太高的时候linux文件连接数超过上限),于是想办法搞个集群部署。最终在我们的服务器的三台机器(mirage05-mirage07)上完成部署。一. 背景介绍以及项目现状1. c...

Nginx安全相关配置常用教程 nginx安全策略

1. 限制请求速度设置 Nginx、Nginx Plus 的连接请求在一个真实用户请求的合理范围内。比如,如果你觉得一个正常用户每两秒可以请求一次登录页面,你就可以设置 Nginx 每两秒钟接收一个客户端 IP 的请求(大约等同于每分钟30个请求)。limit_req_zone $binary_re...

nginx反向代理配置去除前缀

使用Nginx做代理的时候,可以简单的直接把请求原封不动的转发给下一个服务。比如,访问abc.com/appv2/a/b.html, 要求转发到localhost:8088/appv2/a/b.html简单配置如下:upstream one { server localhost:8088 wei...

Vue3项目没有独立域名靠路径分发的痛苦部署方式

Vue3项目部署注意事项,特别是如果有路径分发,没有独立域名的情况,会遇到各种刷新404页面的问题,那怎么解决呢?root和alias的区别nginx配置文件中,指定静态资源路径时,root和alias的区别路径拼接方式: 使用root时,location块中指定的URI将会直接拼接到root路径后...