prometheus 添加 login 登录认证界面(nginx + flask 实现)

网友投稿 599 2022-10-01

prometheus 添加 login 登录认证界面(nginx + flask 实现)

前言

prometheus是现在一个比较主流的监控软件,随着容器的普及,prometheus的应用越来越广泛,前面我也有专门讲到prometheus的相关文章。但是跟传统老牌的zabbix监控不一样,prometheus的web UI是没有登录认证的,有时候显得没有安全性,本文就主要讲解一下如何为prometheus添加一个登录认证界面。其实像elasticsearch、consul等一些服务的web UI也是没有登录认证的,都可以使用本文的方式进行实现。

1. 实现思路

主要是通过nginx代理转发进行实现,我们可以在nginx转发到prometheus之前添加一层认证的过程,从而进行实现。当然,如果有实力的朋友也可以修改prometheus的源码来添加认证机制。

1.1 nginx auth_basic 方式

nignx的ngx_web页面必须输入用户名和密码,经过认证后才能进行访问,我们可以利用这个特性来为prometheus设置代理。    该实现方式比较简单,只需要在nginx配置文件里面添加上auth_basic相关的参数即可,网上也有很多资料,这里就不在赘述了。

1.2 nginx auth_request 方式

有时候我们需要自定义一个 web 登录网页作为我们的监控系统的登录入口,这就可以结合 auth_request 模块来实现。 auth_request原理:(1)当auth_request对应的路由返回401或者403时,nginx会拦截请求,直接返回前端401或者403信息;(2)当auth_request对应的路由返回2xx状态码时,nginx不会拦截请求,而是构建一个subrequest请求,再去请求真实受保护资源的接口; 登录认证实现思路:(1)通过nginx代理prometheus访问,初次访问首页时,auth_request返回401,让其强制跳转到我们自定义的login 登录界面;(2)在login登录认证界面,如果用户名密码认证正确,返回一个token,并且重定向到nginx首页;(3)此时再次访问首页时,是带着token来进行访问,验证token正确,auth_request返回200,就成功转发 prometheus监控页面;(4)如果token过期,登录首页时就返回到login页面,再次进行用户名密码认证。

2.实现代码

2.1 nginx配置文件

将如下配置添加到nginx的配置文件的 部分里面

server { listen 0.0.0.0:9190; # 访问首页入口 location / { proxy_pass # prometheus服务监听端口 auth_request /auth; error_page 401 = @error401; } location @error401 { # 401就转发到登录页面 add_header Set-Cookie "ORIGINURL=$scheme://$http_host;Path=/"; return 302 /login; } location /auth { # internal; proxy_pass # 后端token认证 auth_request off; } location /login { proxy_pass # 后端用户名密码认证 auth_request off; } location /static/rainbowhhy { # 此处很重要,需要自定义一个静态文件目录,本文为rainbowhhy,否则会与prometheus的静态文件冲突,导致prometheus的页面加载不完全 proxy_pass http://localhost:5000/static/rainbowhhy; auth_request off; } }

2.2 登录认证

登录认证部分是通过 flask 实现代码目录结构如下

├── profiles.json ├── readme.md ├── requirements.txt ├── run.py ├── static │   └── rainbowhhy │   ├── css │   │   └── style.css │   └── js │   └── jquery-1.8.2.min.js └── templates └── login.html

安装包准备

pip3 install flask==1.1.1 pip3 install flask-login==0.4.1 pip3 install werkzeug==0.16.0

2.2.1 密码加密文件

profiles.json,采用json格式保存加密后的用户名和密码

cat profiles.json {"admin": ["pbkdf2:sha256:150000$8J65mjTc$db116dd4d5de7eff899d126bd57b4f73910afb1e57982a9ded6878c547b584c5"]}

生成密码的方式:

>>> from werkzeug.security import generate_password_hash >>> generate_password_hash("12345678") 'pbkdf2:sha256:150000$8J65mjTc$db116dd4d5de7eff899d126bd57b4f73910afb1e57982a9ded6878c547b584c5'

2.2.2 后端认证服务

run.py,实现了登录认证过程

from flask import Flask, request, render_template from flask_login import UserMixin from werkzeug.security import check_password_hash import json import os app = Flask(__name__) app.config["SECRET_KEY"] = "123456" app.secret_key = '123456' # 存放用户名和密码的json文件 PROFILE_PATH = os.path.dirname(os.path.abspath(__file__)) PROFILE_FILE = os.path.join(PROFILE_PATH, "profiles.json") # 用户名密码加密认证 class User(UserMixin): def __init__(self, username, password): self.username = username self.password_hash = self.get_password_hash() def verify_password(self, password): if self.password_hash is None: return False return check_password_hash(self.password_hash, password) def get_password_hash(self): # 从文件中获取密码 try: with open(PROFILE_FILE) as f: user_profiles = json.load(f) user_info = user_profiles.get(self.username, None) if user_info is not None: return user_info[0] except: print("get password error!") @app.route("/auth", methods=["GET", "POST"]) def auth(): url = request.cookies.get('ORIGINURL') token = request.cookies.get('token') if token == "ABCDE": return ("success", 200) else: return ("go to login", 401) @app.route("/login", methods=["GET", "POST"]) def login(): if request.method == "POST": username = request.form["username"] password = request.form["password"] user = User(username, password) if user.verify_password(password): token = "ABCDE" return (token, 200) else: error = "用户名或密码错误..." return (error, 403) else: return render_template("login.html") if __name__ == '__main__': app.config['JSON_AS_ASCII'] = False app.run(host="localhost", port=5000)

2.2.3 前端登录页面

login.html,简单实现了登录认证的前端web```html/xml

监控系统

账号:
密码:

  style.css,为了体现出自定义一个静态文件目录的重要性,这里特地写了一个简单的自定义css ```html/xml .head { width: 500px; height: 200px; margin: 0 auto; } .error { color:red; font-size: 18px; margin: 0 auto; }

3.启动服务

启动nginx服务

systemctl start nginx

启动flask认证服务

python3 run.py 生产上可以做成systemd或者supervisor的方式启动

参考文档

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java使用JWT的方法
下一篇:爱数私有云盘 AnyShare 部署(一)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~