ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Dependency-Track实战:基于SBOM的持续依赖漏洞治理与CI/CD集成

Dependency-Track实战:基于SBOM的持续依赖漏洞治理与CI/CD集成 1. 为什么是Dependency-Track从一次性扫描到持续治理先说个真实场景。上个月有个研发团队找到我说他们上线前被安全部门卡住了原因是第三方依赖库里的漏洞报告一直无法闭环——OWASP Dependency-Check扫出来的问题没人跟进下次扫描又全部冒出来开发说“我改了这版依赖”安全说“报告里没体现”最后只能靠截图和Excel表格来回拉扯。我给他们部署了一套Dependency-Track两周后这个问题基本消停了。Dependency-Track是一个开源的软件组件分析平台核心思路非常直接它不站在“扫描一次”的角度工作而是以软件物料清单SBOM为中心帮你做持续性的安全治理。开发把当前版本的依赖清单交上去平台负责入库、关联漏洞库、持续监控新披露的漏洞、跟踪审计状态并把结果通知给相关人员。和常见依赖扫描工具做个对比差异就很明显对比项Dependency-CheckDependency-Track工作方式构建时扫描出报告即结束平台化持续分析记录每次快照漏洞跟踪无状态下次扫描重新开始有状态标记审计结论、修复进度数据输入自动探测项目依赖接收SBOM、自动检测也可手工管理团队协作单机报告多用户、权限、通知、策略管理生态扩展插件形式REST API 平台级集成一句话概括Dependency-Check是“安全体检”Dependency-Track是“健康档案”。如果你的团队只是偶尔看一下依赖有没有问题前者够用如果你需要应对合规审计、漏洞闭环、供应链安全治理那Dependency-Track这个层级才是真正需要的。这篇文章就基于我实际部署和使用的经历把从环境搭建、CI/CD接入、SBOM分析遇到的核心问题到团队落地经验一次性讲透。适合正在选型或已经部署但用不起来的同学。2. 从零搭建Docker Compose部署与初始配置2.1 部署方式选型Dependency-Track官方提供了多种部署方式包括Docker Compose、Kubernetes Helm Chart、以及传统的WAR包部署。个人建议直接上Docker Compose理由有三点官方维护了一套配置好的多容器编排前端前端服务、API服务、数据库服务的关系已经理清不需要自己去折腾环境变量对接。升级方便拉新镜像重启即可备份也简单。对大多数团队来说单节点部署完全够用——它不需要ES那套复杂组件默认用的数据库是内置的H2也可以切换成PostgreSQL或SQL Server。下面是生产环境推荐的结构图文字版浏览器请求通过Nginx进入前端容器前端容器通过反向代理访问API服务API服务连接数据库和各类漏洞数据源。所有组件通过docker-compose统一管理。2.2 实际部署步骤部署前先看看机器配置。官方建议的最低配置是4核8GB内存但我强烈建议给8核16GB以上。很多人忽视了内存问题后面同步NVD漏洞库时直接OutOfMemory这是最常踩的坑后面专门说。部署过程分四步第一步准备docker-compose.yml。官方仓库里有现成的docker-compose.yml也可以自己写一个精简版本。我用的配置类似这样version: 3 services: dtrack-frontend: image: dependencytrack/frontend:4.11.6 restart: unless-stopped depends_on: - dtrack-apiserver ports: - 8080:8080 dtrack-apiserver: image: dependencytrack/apiserver:4.11.6 restart: unless-stopped environment: - ALPINE_DATABASE_MODEexternal - ALPINE_DATABASE_URLjdbc:postgresql://dtrack-db:5432/dtrack - ALPINE_DATABASE_DRIVERorg.postgresql.Driver - ALPINE_DATABASE_USERNAMEdtrack - ALPINE_DATABASE_PASSWORDchange_me_to_a_strong_password - ALPINE_HTTP_PORT8081 depends_on: - dtrack-db volumes: - dtrack-data:/data dtrack-db: image: postgres:16-alpine restart: unless-stopped environment: - POSTGRES_DBdtrack - POSTGRES_USERdtrack - POSTGRES_PASSWORDchange_me_to_a_strong_password volumes: - dtrack-db-data:/var/lib/postgresql/data volumes: dtrack-data: dtrack-db-data:第二步启动容器docker-compose up -d第三步打开前端页面地址是http://你的服务器IP:8080初始账号是admin密码是admin。登录后系统会强制要求修改密码这是官方的安全策略不要跳过。第四步强烈建议开启TOTP双因素认证。Dependency-Track支持基于时间的一次性验证码在个人账号设置里扫描二维码绑定即可。安全团队的对账审计会要求账号必须有双因素提前做好能省不少事。2.3 初始配置的关键细节有几个配置项在部署的时候就要想清楚不然后面改起来麻烦一是数据库密码。不要在默认compose文件上直接跑改成强密码是底线。如果是在云服务器上部署建议把数据库端口完全关闭只允许内部网络访问API容器。二是API服务的端口映射。前端默认8080API服务默认8081。前端页面访问的不是API端口它自己会做代理所以正常使用只需暴露8080。但后面做CI/CD集成时API请求直接走8081会更清晰建议在安全组里只允许公司内部IP访问8081。三是数据目录的持久化。API容器里的/data目录存了漏洞数据库索引、上传的SBOM文件、任务日志数据库容器里的数据文件存了所有业务数据。这两个volume一定要保留好容器没了可以重建数据没了就很被动。生产环境建议用云盘或NFS避免宿主机磁盘损坏导致数据丢失。四是升级策略。Dependency-Track的版本迭代不算慢但其间涉及数据库schema迁移升级前务必做一次完整备份。它没有自动备份功能我是写了一个cron脚本每天凌晨用docker exec导出PostgreSQL的数据保留最近14天的备份文件实测恢复过两次都很顺利。3. 接入研发流程CI/CD集成与API调用3.1 设计思路生成SBOM而不是直接扫描很多人第一次用Dependency-Track第一反应是“它怎么像Dependency-Check那样扫我项目”这里有个关键的设计理念需要转变Dependency-Track的核心输入是SBOM而不是项目源码。它不直接扫描代码它消费的是描述“我这版本用了哪些组件、哪些版本”的结构化清单。把SBOM生成和漏洞分析解耦的最大好处是什么生成SBOM是编译期的事情速度快、反馈及时漏洞分析是平台侧的事情可以后台慢慢跑不会拖慢构建流水线也不会因为NVD同步慢而让开发等结果。所以在CI/CD里的正确姿势是构建阶段生成SBOM格式选CycloneDX JSON。调用Dependency-Track API上传SBOM绑定项目名称和版本。平台异步处理分析结果通过Webhook或后续查询反馈也可以在发布前通过策略检查决定是否阻断。3.2 生成SBOM的工具选型不同技术栈生成SBOM的工具不一样我这里列几个亲测好用的技术栈推荐工具说明Java/MavenCycloneDX Maven Plugin执行mvn cyclonedx:makeAggregateBom生成整个多模块项目的完整清单Java/GradleCycloneDX Gradle Plugin用法类似能处理依赖约束和BOM引入Node.jscyclonedx/cyclonedx-npm支持读取package-lock.json生成SBOMPythonCycloneDX Python库或pip-audit的SBOM输出虚拟环境里直接生成通用容器镜像SyftAnchore出品一条命令扫描镜像输出CycloneDX JSON支持各种镜像格式Syft几乎成了我团队的标准配置因为现在服务大多是容器化部署直接扫镜像最省事不用管内部是什么语言syft packages your-registry/app:1.2.3 -o cyclonedx-json sbom.json3.3 在GitLab CI里集成以GitLab CI为例一个完整的阶段可以这样设计。dependency-track阶段负责生成和上报SBOMsecurity-check阶段在发布前做策略判定generate-sbom: stage: dependency-track image: anchore/syft:latest script: - syft packages ${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG:-latest} -o cyclonedx-json sbom.json artifacts: paths: - sbom.json expire_in: 1 week only: - tags upload-sbom: stage: dependency-track image: alpine:latest variables: DEPENDENCY_TRACK_URL: http://dtrack.internal.example.com/api DEPENDENCY_TRACK_API_KEY: $DTRACK_API_KEY script: - apk add --no-cache curl jq - | curl -sS -X POST ${DEPENDENCY_TRACK_URL}/v1/bom -H X-Api-Key: ${DEPENDENCY_TRACK_API_KEY} -H Content-Type: application/json -d { \projectName\: \${CI_PROJECT_NAME}\, \projectVersion\: \${CI_COMMIT_TAG}\, \bom\: \$(cat sbom.json | base64 -w0)\, \autoCreate\: true } only: - tags这里有两个容易忽略的细节bom字段需要base64编码不是直接传JSON。很多人第一次调API报400就是死在这个地方。autoCreate设置为true后平台发现项目不存在会自动创建省去手工建项目的步骤。但如果项目已经有固定归属团队建议还是预先创建好避免一人一个命名风格搞出很多重复项目。上传之后平台返回一串token可以用来查询分析状态curl -sS -X GET ${DEPENDENCY_TRACK_URL}/v1/bom/token/你的token -H X-Api-Key: ${DEPENDENCY_TRACK_API_KEY} | jq .status返回PROCESSING表示还没解析完COMPLETED表示可以去看结果了。3.4 API Key的管理权限Dependency-Track的API Key分三种层级管理员、发布经理、观察者。CI/CD里用的Key建议单独创建一个观察者或发布经理角色的Key不要直接拿管理员Key到处用。在“管理-访问管理-团队”里新建团队赋权后生成KeyKey本身很长建议放到CI/CD的变量里统一管理不要写死在代码仓库。关于projectName的设计我的建议是应用名留CI_PROJECT_NAME即可版本号用CI_COMMIT_TAG或构建号这样每次发版都会形成一条独立的快照记录。以后安全团队说“v1.2.3这个版本有高危漏洞”你在平台上点一下就能看到当时的完整依赖情况这就是审计追溯的价值。4. SBOM上传与漏洞分析的正确姿势4.1 项目、版本与SBOM的对应关系先理解Dependency-Track的数据模型项目Project是顶层对象一个项目下有多个版本Project Version每个版本关联一份或多份SBOM快照。漏洞分析的结果是挂在项目版本下面的。所以正确用法不是每次上传都建新项目而是按“应用名版本号”上报。这样同一个应用的历史漏洞记录都在一个项目下可以按版本切换查看。我见过不少团队把每个构建版本都建一个独立项目最后平台上一堆同名项目看不到时间线审计状态也串了。这就是数据模型没理解到位。4.2 漏洞数据源与同步管理平台能分析出漏洞核心在于它聚合了多个漏洞数据源。管理界面Administration-System Configuration里可以配置数据源包括NVD美国国家漏洞数据库最基础的数据源官方接口有速率限制第一次同步特别慢要耐心等。GitHub Advisories开源生态的漏洞公告覆盖很及时但需要配置GitHub Token才能拉取。OSV谷歌维护的开源漏洞数据库覆盖面广不少新披露的漏洞第一时间在这里出现。CISA KEV已知被利用漏洞目录用于优先级排序。这些数据源不是一次性拉完就结束了平台会按固定周期增量更新。默认的同步周期可以保留生产环境建议NVD每天同步一次GitHub Advisories每6小时一次这样新漏洞披露到平台可查的窗口期不会太长。同步状态可以在后台任务面板里看如果哪个数据源一直失败通常是网络代理问题或者Token失效排查思路很直接先看API服务日志里对应任务的报错再确认出网是否有白名单限制。4.3 分析页面怎么用上传SBOM并完成分析后主要看这几个页面项目视图选中项目版本能看到本次SBOM包含的组件总数、漏洞数、策略违例数。按风险等级严重/高危/中危/低危分布也在这里展示。组件视图点进某个组件能看到它涉及的漏洞列表、CVE详情、CVSS评分、EPSS分数利用概率评分以及该组件在哪些项目里被使用。漏洞视图从漏洞维度看影响面知道“这个CVE影响了我们哪几个项目”用于评估紧急程度。策略违例视图如果你配置了策略Policy这里会显示哪些组件触发了限制性规则。审计操作就在漏洞视图里做。打开一个漏洞右侧面板里可以设置审计状态审计状态含义使用场景存在Vulnerable确认受影响需要修复默认状态不受影响Not Affected分析后确认实际不受影响例如组件虽然匹配CVE但代码路径未用到误报False Positive确认不是真实漏洞例如CVE实际影响的是另一个语言生态的同名包已修复Resolved该版本已验证修复升级依赖后确认不再存在加上注释后审计状态会被记录下次再有人看这个漏洞时就能看到结论。这就是闭环开发说“这个组件实际没用到危险函数”安全同学同意后标记为误报并附上分析说明以后重复扫描不会再次报警。实际操作下来比较费时间的是刚接入平台第一周旧项目的存量漏洞需要批量审计。好在平台支持多选组件后批量设置审计状态并添加统一注释不需要逐条点。4.4 保险起见利用策略做发布防线Dependency-Track的策略Policy能力值得单独说明。策略可以基于漏洞严重程度、组件名称、组件版本、CISA KEV标记等条件来定义“违规”。例如策略A存在CISA KEV标记漏洞的组件不允许发布。策略B存在CVSS评分9.0以上的严重漏洞不允许发布。策略C禁止使用已EOL的组件版本。配置策略后CI里调用“策略违例查询”接口就能拿到当前项目是否有阻断级的违规项再决定流水线是否放行curl -sS -X GET ${DEPENDENCY_TRACK_URL}/v1/project/lookup?name项目名version版本号 -H X-Api-Key: ${DEPENDENCY_TRACK_API_KEY} | jq -r .uuid拿到UUID后查询违例curl -sS -X GET ${DEPENDENCY_TRACK_URL}/v1/violation/project/项目UUID -H X-Api-Key: ${DEPENDENCY_TRACK_API_KEY} | jq [.[] | select(.type VULNERABILITY and .severity CRITICAL)] | length返回数量大于0就阻断。有的团队担心“阻断发布会拖慢交付”我的建议是刚开始策略先做成“审计视线”不加阻断跑两个迭代看误报率稳定后再从最关键的项目开启阻断。安全建设不是一次性到位而是逐步收紧。5. 日常运维中最容易翻车的几个点5.1 内存不足导致NVD同步失败这是Dependency-Track部署后最常见的故障。NVD全量数据同步时API服务需要把大量CVE数据写入本地索引如果JVM堆内存分配不够直接抛出OutOfMemoryError后台任务显示失败前端页面可能出现组件漏洞信息缺失。排查思路是先看容器日志里有没有java.lang.OutOfMemoryError: Java heap space如果有基本可以锁定。解决办法有两个方向一是给Docker分配更大内存把宿主机内存从8GB升到16GB同时确认API容器的JVM参数允许大堆内存二是在/data目录下合理配置索引存储不要让它和系统其他服务抢磁盘。我给一个小团队的部署建议是如果公司只是做几十个项目的依赖治理单机16GB内存绰绰有余如果上百个项目、SBOM上传频率高考虑把所有组件迁到PostgreSQL、API服务独立部署、数据库交给云厂商托管那一套。5.2 同步NVD走了代理Token失效很多公司内网服务器不能直连外网NVD同步必须走代理。Dependency-Track本身没有在UI里直接配置代理的地方需要在API服务的启动参数里设export JAVA_OPTIONS-Dhttps.proxyHost代理IP -Dhttps.proxyPort代理端口更隐蔽的问题是GitHub Token失效。平台每次同步GitHub Advisories需要有效的Token。Token过期后后台任务报401但UI上的“上次同步时间”看起来还正常容易忽略。运维上我建议用公司统一的机器账号Token加上告警每天检查同步任务日志里有没有401/403报错有就通知安全负责人。5.3 上传SBOM后漏洞数量异常可能出现“上传的SBOM明明很小但平台分析出的组件数量翻了几倍”的情况。这种一般是SBOM里的components字段嵌套了元组件和子组件比如Java的BOM引入传递性依赖平台在解析CycloneDX时会把所有传递依赖全部展开。这不一定是问题但会导致审计工作量变大。如果业务上只关心直接依赖可以在生成SBOM时关闭传递依赖解析以CycloneDX Maven插件为例设置includeTransitive为false或者在上传前用jq过滤掉非直接依赖。权衡下来我是建议保留传递依赖因为不少高危漏洞恰恰藏在二级依赖里。5.4 前端页面加载慢、卡顿前端大量数据的表格渲染在项目组件数量过万时确实会卡。除了清理浏览器的缓存更有效的是开启API服务的压缩功能在Nginx层配置gzip on; gzip_min_length 1k; gzip_types application/json application/javascript text/css image/svgxml;另一个常见原因是平台自动刷新漏洞视图每次切换项目版本都会重新拉全量数据。数据量很大的项目建议通过左侧的过滤器缩小范围不要一上来就全量加载“所有项目”。5.5 备份和恢复备份这事儿嘴上说再多不如实际演练一次。我是用cron脚本每天备份PostgreSQL数据库具体流程是docker exec dtrack-db pg_dump -U dtrack dtrack dtrack_$(date %Y%m%d).sql注意/data目录下的索引文件不备份问题也不大但数据库必须备份。恢复的时候先把API和前端容器停掉启动一个临时PostgreSQL容器导入SQL再启动业务容器。整个过程我实测过10分钟内能完成。有一种情况比较麻烦数据库备份是在业务还在运行的时候导出的可能要恢复的瞬间有未提交事务不过Dependency-Track不会有那么高写入频率所以只要不是正在大量上传SBOM的窗口正常备份恢复是可靠的。6. 团队落地推广从部署到真正被用起来工具部署好只是第一步真正难的是让团队成员接受并养成习惯。我在这几个项目里总结了一些适用经验。6.1 从两个项目试点切入不要试图一次性把所有项目都接入Dependency-Track。我的习惯是选两个代表性项目试点一个是对外提供服务的核心应用一个是内部工具类应用。试点时间定两个迭代周期目标不是看漏洞数量而是验证CI里集成SBOM上传是否稳定。开发人员能否看懂漏洞审计页面。安全团队能否接收通知并处理告警。试点通过后再批量接入其他项目推广阻力会小很多。6.2 通知规则要分层配置Dependency-Track的通知机制支持通过Webhook、邮件等方式推送漏洞信息。这里最忌讳的是“所有漏洞都通知所有人”那样很快就被当做垃圾消息忽略了。我的配置经验是通知对象漏洞级别频率应用负责人高危/严重实时Webhook到企业微信/钉钉群开发团队中危日报汇总安全团队全部实时或日报视团队人力而定管理层严重漏洞无法修复的漏洞周报细分下来通知数量可控也能保证漏洞出现后有人响应。6.3 权限要分角色默认的admin账号不建议给所有人用。Dependency-Track基于角色的访问控制支持自定义角色和映射。落地时我是这样分的安全团队管理员权限负责配置数据源、策略、分析审计。研发负责人项目的查看权限审计权限。普通开发人员查看权限可以标记误报但不能修改策略配置。这样既保证开发能参与漏洞闭环又避免误操作把全局策略改坏。6.4 与Jira等工单系统联动漏洞闭环最怕“看了就没了”。Dependency-Track支持Webhook触发配合自动化脚本把高危漏洞自动创建Jira工单分配给对应应用负责人工单关联漏洞详情修复后在平台上反查确认。这个联动逻辑不复杂本质是一个接收Webhook的小服务但对流程闭环的意义非常大。没有这类自动化之前漏洞记录和安全运营割裂有了联动KPI就变成“工单关闭率”了。6.5 定期做数据治理和报告运行一两个月后平台里会有大量项目、组件和审计记录。项目如果废弃了可以归档组件如果长时间没有版本更新要关注一下是不是没人维护。建议安全团队每月拉一次全量报告看三个指标高危漏洞数量环比变化。平均修复时间从漏洞发现到标记已修复的天数。审计率已审计漏洞占全部漏洞的比例。审计率的价值容易被忽略。如果审计率低说明开发和安全没有真正在用这个平台漏洞都可能没被点开过审计率高说明流程是活的有安全运营在里面。Dependency-Track不是装了就能“自动解决安全合规”的银弹但它确实把供应链依赖治理这件事从“手工扫码发邮件”推进到了“平台化持续运营”的层面。按这套方法部署、接入、运维、推广下来团队能真正把这套系统用起来而不是让它沦为摆设。
返回列表