Nginx使用auth_request模块做外部认证集成Kibana
概述
业务需要使用Kibana提供报表。为了增加Kibana分享链接的鉴权认证,就考虑使用Nginx代理并使用auth_request模块做认证。
环境
- 操作系统 Centos 7.9
- Kibana 8.19.5
- Nginx 1.28.0
架构
Nginx反向代理Kibana,在配置接收URL: /Kibana/ 时,启用auth_request模块,预先将URL请求送至后端验证接口(需要开发)鉴权。流程如下:
- 用户请求kibana地址,例如http://www.test.com/kibana/app/home…
- 请求送至nginx代理服务器
- nginx代理服务器预先将请求转发至后端验证接口(需要开发)
- 后端验证接口鉴权并返回状态码(200允许,非200阻止)
- nginx根据得到的状态码决定,200放行,非200返回对应错误
安装
Nginx编译安装auth_request模块
nginx默认没有auth_request模块,需要编译 –with-http_auth_request_module ,安装详见 Nginx的安装
Kibana安装配置
详见 Kibana安装配置
配置auth_request模块
- 创建一个tmpfs文件(内存)用作缓存,为了应对高并发
# 定义 auth_cache 缓存区域
mkdir -p /var/cache/nginx/car_cache
# 手动挂载缓存文件系统
mount -t tmpfs -o size=100m tmpfs /var/cache/nginx/car_cache
# 添加启动挂载 echo "tmpfs /var/cache/nginx/car_cache tmpfs defaults,size=100m 0 0" | sudo tee -a /etc/fstab
chown -R nginx:nginx /var/cache/nginx
- 配置 nginx.conf
proxy_cache_path /var/cache/nginx/auth_cache # 内存缓存文件路径levels=1:2 # 设置缓存目录的层级结构,避免单个目录文件过多,提升文件系统性能keys_zone=car_cache:50m # 定义用于存储缓存键和元数据的共享内存区域max_size=100m # 设置缓存目录的最大磁盘使用量inactive=60m # 定义缓存文件的"闲置"生存时间use_temp_path=off; # 临时文件直接写入缓存目录upstream proxy_kol-kibana {# server指令指定后端服务器的IP地址和端口server 192.168.15.15:5601 max_fails=5 fail_timeout=30s; #当检查后端服务5次失败(每1秒一次),判定后端服务不可用,然后30秒内不再检查。server 192.168.15.95:5601 max_fails=5 fail_timeout=30s; #当检查后端服务5次失败(每1秒一次),判定后端服务不可用,然后30秒内不再检查。}# HTTP Serverserver {# 监听了两个端口,一个用作防火墙映射端口,一个用作内部服务访问端口(有些内部服务特殊,需要使用默认的443端口)listen 8443 ssl;listen 443 ssl;server_name kol-test.xk.com;# 证书路径及名称为示例ssl_certificate /usr/local/nginx/conf/xk/xk.com.pem;ssl_certificate_key /usr/local/nginx/conf/xk/xk.com.key;ssl_session_cache shared:SSL:30m;ssl_session_timeout 5m;ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!3DES;ssl_protocols TLSv1.2 TLSv1.3;ssl_prefer_server_ciphers on;gzip on; #开启gzip压缩输出gzip_min_length 1k; #最小压缩文件大小gzip_buffers 4 16k; #压缩文件缓冲区gzip_comp_level 2; #压缩等级gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png image/x-icon;try_files $uri $uri/ /index.html;root /opt/application/kol-share-frontend/sourcecode/;charset utf-8; location ~ .*\.(js|css)?${expires 15d;}proxy_connect_timeout 300;proxy_send_timeout 300;proxy_read_timeout 300;proxy_set_header Host $host;proxy_set_header X-Forwarder-For $remote_addr;add_header Referrer-Policy "no-referrer" always;# 保留 server root,这个 location 可以处理其他静态资源或根请求。当前未使用。location / {root /opt/application/kol-share-frontend/sourcecode/;try_files $uri $uri/ =404;} # 后端验证接口,为/kibana/鉴权location /kol/kibana/verify {internal; # 关键!声明此位置仅允许Nginx内部请求,防止外部直接访问# 后端验证接口proxy_pass http://127.0.0.1:18084/kol/backend/api/data/checker/check-kibana;# 以下配置通常用于不传递请求体到认证服务,以提升效率proxy_pass_request_body off;proxy_set_header Content-Length ""; # 传递原始请求的重要信息给认证服务proxy_set_header X-Original-URI $request_uri;proxy_set_header X-Real-IP $remote_addr;# 可以根据需要传递更多头部,如Cookie、Authorization等 (本例中,后端验证接口从Authorization 获取令牌进行验证)proxy_set_header Cookie $http_cookie;proxy_set_header Authorization $http_authorization; # 以下配置与本示例内容无关client_max_body_size 1000m;proxy_set_header Host $host;#proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;add_header X-Content-Type-Options nosniff;add_header X-Xss-header "1;mode=block";add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'";add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";add_header 'Referrer-Policy' 'origin';add_header X-Permitted-Cross-Domain-Policies "master-only";add_header X-Download-Options "noopen" always;add_header X-Frame-Options SAMEORIGIN;add_header X-XSS-Protection "1; mode=block";#添加以下跨域头add_header 'Access-Control-Allow-Origin' '*' always;add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization' always;add_header 'Access-Control-Allow-Credentials' 'true' always;#预检请求(OPTIONS)if ($request_method = OPTIONS ) {add_header 'Access-Control-Max-Age' 1728000;add_header 'Content-Type' 'text/plain charset=UTF-8';add_header 'Content-Length' 0;return 204;}}# 后端kibanalocation /kibana/ {# 启用认证,并指定认证子请求的URIauth_request /kol/kibana/verify;# 基础认证(另外一种验证方式配和httpd-tools工具使用,单独使用账号和密码验证,不在本例演示范围内)#auth_basic "Kibana - Restricted Access";#auth_basic_user_file /usr/local/nginx/conf/conf.d/kibana.htpasswd;# 可选: 将认证结果或返回的头部信息保存到变量中(无特殊用途可不开启)# auth_request_set $auth_status $upstream_status;# auth_request_set $auth_user $upstream_http_x_user; # 例如获取认证服务返回的用户名# 可选: 自定义错误页面,提升用户体验error_page 401 = /error/401.html;error_page 403 = /error/403.html;error_page 500 502 503 504 = /error/500.html;;proxy_pass http://proxy_kol-kibana;#proxy_intercept_errors on;# rewrite 规则,用于处理路径重写,配合kibana.yml的server.basePath设置rewrite ^/kibana/(.*)$ /$1 break;# 这里写死kibana登录的账号和密码# 可使用 echo -n 'elastic:www*123456.' | base64 生成proxy_set_header Authorization "Basic ZWxhc3RpYzp3d3cqMTIzNDU2Lg==";# 启用缓存proxy_cache auth_cache;proxy_cache_key "$request_uri$http_authorization$http_cookie"; # 建议根据关键信息构建缓存键,例如URI和认证头,以及COOKIEproxy_cache_valid 200 15m; # 缓存200响应15分钟proxy_cache_bypass $http_cache_control; # 尊重客户端的缓存绕过指令#proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; # 认证服务故障时使用过期缓存client_max_body_size 1000m;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;proxy_set_header X-Forwarded-Host $host;# WebSocket支持( kibana 需求)proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";add_header X-Content-Type-Options nosniff;add_header X-Xss-header "1;mode=block";# kibana 需要关闭,或者调整Content-Security-Policy#add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'";add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";add_header 'Referrer-Policy' 'origin';add_header X-Permitted-Cross-Domain-Policies "master-only";add_header X-Download-Options "noopen" always;add_header X-Frame-Options SAMEORIGIN;add_header X-XSS-Protection "1; mode=block";#添加以下跨域头add_header 'Access-Control-Allow-Origin' '*' always;add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization' always;add_header 'Access-Control-Allow-Credentials' 'true' always;#预检请求(OPTIONS)if ($request_method = OPTIONS ) {add_header 'Access-Control-Max-Age' 1728000;add_header 'Content-Type' 'text/plain charset=UTF-8';add_header 'Content-Length' 0;return 204;}}
生效
- 检验配置文件
# 检查配置文件的命令
sudo -u nginx /usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
# 输出结果
nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /usr/local/nginx/conf/nginx.conf:2
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
- 重新加载配置
systemctl reload nginx
验证
开发http://127.0.0.1:18084/kol/backend/api/data/checker/check-kibana 验证接口,分别返回200状态码及非200状态码,验证auth_request模块是否生效,是否能够管控登录Kibana系统
