news 2026/9/17 8:07:31

Fleet + Flask + Plotly/Dash:用 REST API 构建自定义主机状态可视化仪表盘

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Fleet + Flask + Plotly/Dash:用 REST API 构建自定义主机状态可视化仪表盘

Fleet + Flask + Plotly/Dash:用 REST API 构建自定义主机状态可视化仪表盘

【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet

本文介绍如何跳出 Fleet 自带的 Web UI,基于 Fleet REST API 采集主机遥测数据,用 Flask 作为 Web 框架、Dash(Plotly)作为可视化层,搭建一个带交互式在线/离线状态过滤的自定义仪表盘。读完本文,你将掌握 Fleet API 的鉴权方式与主机列表端点的参数用法、从 API 到图表的数据流,以及可复制的本地运行步骤,并了解如何进一步扩展到软件清单等其他端点。

背景:为什么在 Fleet REST API 之上做自定义仪表盘

Fleet 的设计原则之一是:UI 里能做的事情,REST API 里都能做。Fleet 官方文档 REST API 开篇即说明 "Use the Fleet APIs to automate Fleet",并完整列出了各资源的路由、参数与响应示例。这意味着当你想做一些 UI 没有直接提供的展示形态——比如一张面向管理层的主机在线率看板、一份按团队切分的图表页——不需要额外中间件,直接对 REST API 发请求即可拿到结构化 JSON。

Fleet 团队此前已经演示过通过 Tines 工作流调用 REST API 的场景(仓库内对应 Tines 集成文档),也演示过用 Okta Workflows 调用 API 生成每日 OS 报告(参见 Okta Workflows 示例文章)。本文聚焦另一类场景:数据可视化

市场上有不少商业数据可视化工具,但本文刻意不绑定任何特定方案,只用开源组件证明一件事:连接 Fleet API、采集遥测数据并渲染成图表,门槛非常低。

技术栈

整套方案由三个开源组件组成:

组件角色说明
Fleet REST API数据源提供主机、软件等资源的 JSON 接口,文档见 docs/REST API/rest-api.md
FlaskPython Web 框架承载仪表盘页面,Dash 应用本身就跑在 Flask 之上
Plotly / Dash图表与应用框架MIT 许可的开源绘图库;Dash 提供布局组件与回调(callback)机制,适合做交互式看板

选择 Dash 的动机在于:它把 "Flask 服务 + 前端交互" 压缩到纯 Python 里,用声明式布局组件和回调函数就能实现 "改一下下拉框 → 图表联动刷新" 的交互,而不需要单独写前端工程。本文的示例代码与概念源自社区经典的 Python Dash 教程思路(Real Python 的 Python Dash 系列),只需把数据源从示例用的牛油果数据换成 Fleet 的主机数据即可。

前置条件与本地环境准备

示例运行需要一个可访问的 Fleet 实例与本地开发环境:

  • 一台本地 macOS 开发工作站(其他平台同理);
  • 已安装 Python 3(可用 Homebrew 安装);
  • 一个已部署并可登录的 Fleet 服务器,以及一个可获取 API token 的账号;
  • 示例代码仓库(社区维护的fleetdash示例工程,包含fleetdash.py单文件应用)。

开发 Python Web 应用时,建议先创建虚拟环境(venv)再安装依赖,把requestsplotlydash等库隔离在独立环境中。

目标:一个带交互过滤的主机状态仪表盘

示例应用只做三件事,但完整覆盖了 "API → 数据 → 图表 → 交互" 的链路:

  1. 创建一个 Flask 应用,数据来自单个 Fleet REST API 端点(主机列表);
  2. 使用 Dash 的核心组件与 HTML 组件搭建页面布局;
  3. 通过 callback 实现交互:用下拉框按online / offline状态过滤主机,图表即时更新。

动手:安装依赖与启动

克隆示例仓库后,在激活的 venv 中安装依赖:

(venv) % pip install requests json pandas plotly dash datetime numpy

进入仓库目录,直接启动应用:

(venv) % python3 ./fleetdash.py

一切正常时,终端会输出:

(venv) % python3 ./fleetdash.py Dash is running on http://127.0.0.1:8050/ * Serving Flask app ‘fleetdash’ * Debug mode: on

用浏览器打开http://127.0.0.1:8050/,即可看到上面开头那张截图所示的仪表盘:主机状态分布图表,配合状态过滤下拉框。

示例应用的核心代码结构(讲解版)

示例仓库不在本仓库内,这里按原文档描述的功能流程,给出一个简化的核心结构讲解版,帮助你理解fleetdash.py内部在做什么、也方便你把数据源换成自己的 Fleet 实例:

import dash import pandas as pd import plotly.express as px import requests from dash import dcc, html FLEET_URL = "http://localhost:8080" # 换成你的 Fleet 实例地址 API_TOKEN = "<your-token>" # Fleet UI "My account" 页获取 HEADERS = {"Authorization": f"Bearer {API_TOKEN}"} def fetch_hosts(): """调用主机列表端点,把 JSON 展平为 DataFrame。""" resp = requests.get( f"{FLEET_URL}/api/latest/fleet/hosts", headers=HEADERS, params={"page": 0, "per_page": 50}, timeout=30, ) resp.raise_for_status() rows = [ { "hostname": h["hostname"], "platform": h["platform"], "status": h["status"], # online / offline / mia / missing "os_version": h["os_version"], } for h in resp.json()["hosts"] ] return pd.DataFrame(rows) app = dash.Dash(__name__) df = fetch_hosts() app.layout = html.Div([ html.H1("Fleet Host Dashboard"), # 交互式过滤:全部 / 在线 / 离线 dcc.Dropdown( id="status-filter", options=[ {"label": "All", "value": "all"}, {"label": "Online", "value": "online"}, {"label": "Offline", "value": "offline"}, ], value="all", ), html.Div(id="chart-container"), ]) @app.callback( dash.dependencies.Output("chart-container", "children"), dash.dependencies.Input("status-filter", "value"), ) def update_chart(status): view = df if status == "all" else df[df["status"] == status] chart = px.histogram(view, x="status", title="Hosts by status") return dcc.Graph(figure=chart) if __name__ == "__main__": app.run(debug=True)

这个结构与原文档的三项目标一一对应:requests负责打 Fleet API,pandas把 JSON 列表整理成可过滤的表格,px.histogram出图,@app.callback让下拉框的变化驱动图表重算。把FLEET_URL指向你自己的 Fleet 实例、API_TOKEN换成真实 token 后,即可得到与截图同形态的页面。

Fleet REST API 侧的关键细节(以当前仓库文档为准)

鉴权:API Token + Bearer 头

所有 API 请求默认要求 API token 鉴权,token 绑定到你的 Fleet 用户账号。获取方式有两种(见 REST API 文档 的 Authentication 一节):

  • 在 Fleet UI 的 "My account" 页面(/profile)点击 "Get API token";
  • 或调用登录端点POST /api/v1/fleet/login(SSO/MFA 用户不支持走 API 登录,只能从 UI 取 token)。

拿到 token 后,每个请求都要带上:

Authorization: Bearer <your token>

上面示例代码中的HEADERS就是在做这件事。

主机列表端点:GET /api/v1/fleet/hosts

仪表盘的数据源就是主机列表端点。当前仓库文档中该端点支持丰富的查询参数,与做图表最相关的有:

参数类型说明
page/per_pageinteger分页;文档建议配合query搜索或device_mapping=true等昂贵操作时把per_page压到 50,避免压垮 Fleet 服务器
order_key/order_directionstring排序字段(可为 hosts 表任意列)与方向(asc/desc
statusstring按主机状态过滤:newonlineofflinemiamissingenrolled
querystringhostnamehardware_serialuuidipv4、终端用户邮箱等字段搜索
populate_software/populate_policies/populate_users/populate_labelsstring/boolean控制是否附带软件、策略、用户、标签数据;populate_software返回数据量大,需要漏洞明细时可取without_vulnerability_details

一个典型请求形如:

GET /api/v1/fleet/hosts?page=0&per_page=100&order_key=hostname

响应中的每台主机都带有status字段(online/offline等)、hostnameplatformos_versionuuid等信息,正是仪表盘需要展示的列。值得注意的是:由于服务端已经支持status过滤,如果你在 API 侧过滤而不是在 DataFrame 里过滤,还能显著减少传输量——这是从文档参数表可以直接得到的优化方向。

路径版本说明

仓库当前文档以/api/v1/...作为端点路径(如GET /api/v1/fleet/hostsGET /api/v1/fleet/software/titles),同时文档内资源 URL 中仍出现/api/latest/...形式(如软件图标的icon_url)。示例代码中使用哪个别名,以你的 Fleet 版本实际行为为准;本文档仓库的规范写法是/api/v1

可以接着做什么

原文档列出的扩展方向,结合当前仓库文档可以落得更实:

  • 接入软件端点:主机列表只是起点。Fleet 还提供软件列表端点GET /api/v1/fleet/software/titles(见 REST API 文档 的 "List software" 一节),支持vulnerableavailable_for_installself_serviceplatformquery等过滤参数,按hosts_count排序默认降序——非常适合做一张 "安装最广泛的软件 / 带漏洞软件" 图表,和主机状态图并排放在同一块 Dash 布局里。
  • 给 Flask 应用加鉴权:示例应用监听在127.0.0.1,只适合本地演示。若要部署,应参考 token-based authentication 的做法给 Dash 应用本身加登录,并保证 Fleet API token 不写死在代码里(例如从环境变量读取)。
  • 部署:把 Flask 应用部署到 AWS 或 Heroku 之类的托管环境,配合定时刷新(如 Dash 的Interval组件)即可变成常驻监控页。
  • 探索其他开源看板方案:例如基于 Grafana + Prometheus 数据源做告警与可视化,与本文的 "直连 REST API" 路线互补。

更多 API 调用形态可参考仓库内的 Okta Workflows 每日 OS 报告文章 与 Tines 集成文档。

小结

这条 "Fleet REST API → pandas → Dash/Plotly" 的链路证明了几点:Fleet 的 API 覆盖了 UI 的全部能力,主机列表端点的statusquery、分页参数天然适配做交互式图表;用 Flask + Dash 这类开源 Python 组件,一个下午就能从官方文档的端点参数表走到一个可过滤的在线看板;而 API token + Bearer 头的鉴权模型、per_page限流建议等细节,都直接写在本仓库的 REST API 文档 里,照着做即可。如果你希望继续完善示例代码,欢迎向示例仓库提交 PR 或在社区(如 osquery / MacAdmins Slack,作者@dherder)交流。

【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 8:06:59

低功耗bandgap设计实战:从电流预算到版图的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 8:06:42

替代微软生态:从Edge、Office到Windows的分层迁移指南

“替代微软的一切”这句话听起来像一句口号&#xff0c;真动手做起来更像一次持续大半年的搬家&#xff1a;先把外圈的浏览器、字体、输入法换掉&#xff0c;再动办公套件和云盘&#xff0c;最后才敢碰操作系统和账号体系。我从去年开始&#xff0c;把手上三台机器&#xff08;…

作者头像 李华
网站建设 2026/9/17 8:06:24

V8引擎解析:从JS源码到机器码的优化之旅

1. V8引擎的代码执行全景图当我们在浏览器中运行一段JavaScript代码时&#xff0c;背后实际上经历了一个精密的工业化流水线作业。作为Chromium项目的核心组件&#xff0c;V8引擎的工作机制就像一座现代化的汽车工厂&#xff1a;从原材料&#xff08;JS源码&#xff09;进入&am…

作者头像 李华
网站建设 2026/9/17 8:05:57

Django二手房屋信息采集系统设计与实现

1. 项目概述与核心价值这个基于Django框架的二手房屋信息采集系统&#xff0c;是我在指导计算机专业毕业设计时反复验证过的经典案例。它完美融合了爬虫技术、数据可视化与Web开发三大热门方向&#xff0c;特别适合作为高校计算机专业的综合实践项目。系统通过自动化爬取主流房…

作者头像 李华
网站建设 2026/9/17 8:05:04

AI软件工程落地:算法、Linux、数据库与大数据四维基本功实战解析

AI落地最难的不是模型调参&#xff0c;而是把人工智能软件工程从想法变成稳定系统。我这些年带过不少项目&#xff0c;也带过不少新人&#xff0c;最深的体会是&#xff1a;算法与数据结构决定你能不能写出高效代码&#xff0c;Linux/操作系统决定你能不能把服务跑稳&#xff0…

作者头像 李华