himanshu2604/acquisitions-api
GitHub: himanshu2604/acquisitions-api
一个围绕 SaaS 业务交易 API 搭建的生产级 DevSecOps 全栈基础设施项目,涵盖安全门禁、GitOps 部署和可观测性监控的完整链路。
Stars: 0 | Forks: 0
# 🏢 Acquisitions API
### 用于买卖 SaaS 业务的生产级 REST API
基于完整的 **DevSecOps CI/CD 流水线**、**GitOps 部署**以及**实时可观测性**构建
          
## 📌 目录
          
点击展开
- [关于项目](-#about-the-project) - [架构](-#-architecture) - [技术栈](-#-tech-stack) - [CI/CD 流水线](-#-cicd-pipeline) - [GitOps 部署](#-gitops-deployment) - [监控与报警](#-monitoring--alerting) - [API 端点](#-api-endpoints) - [本地开发准备](#-getting-started-locally) - [项目结构](#-project-structure) - [安全](#-security) - [测试](#-testing) - [我的收获](#-what-i-learned)
## 🛠️ 技术栈 | 类别 | 工具 | 用途 | | ------------------ | ----------------------------- | ------------------------------------------ | | **运行时** | Node.js 20 + Express | 后端 API 框架 | | **编程语言** | TypeScript | 整个代码库的类型安全 | | **数据库** | Neon DB (Serverless Postgres) | 云托管的 PostgreSQL | | **ORM** | Drizzle ORM | 类型安全的查询和迁移 | | **身份验证** | JWT + bcrypt | 基于令牌的身份验证和密码哈希 | | **校验** | Zod | 请求 schema 验证 | | **日志** | Winston + Morgan | 结构化的应用日志 + HTTP 请求日志 | | **安全** | Helmet + CORS + Arcjet | HTTP 头、跨源、机器人防护 | | **指标** | prom-client | 为 Prometheus 暴露 `/metrics` 端点 | | **CI/CD** | GitHub Actions | 自动化流水线 (代码检查 → 扫描 → 部署) | | **安全门禁** | Trivy + SonarCloud | CVE 扫描 + SAST 代码分析 | | **容器** | Docker (多阶段) | 优化的生产镜像 | | **容器编排** | Kubernetes | 扩展、滚动更新、自我修复 | | **GitOps** | ArgoCD | 具有配置漂移检测的声明式 CD | | **监控** | Prometheus + Grafana | 指标收集和仪表板 | | **报警** | Alertmanager | 基于报警规则的 Slack 通知 | | **测试** | Jest + Supertest | 单元和集成测试 | | **代码质量** | ESLint + Prettier | 代码检查和格式化 | ## ⚙️ CI/CD 流水线 该流水线包含 **4 个顺序阶段**。每个阶段必须通过后才能运行下一个阶段。如果任何阶段失败,镜像将永远不会被推送到 Docker Hub。
**为什么要有两个安全门禁?** - **Trivy** 负责捕获你_构建的镜像_中操作系统包和 npm 依赖项里的漏洞——那些不是你写的但随应用一起发布的东西 - **SonarCloud** 负责捕获_你自己的代码_中的安全问题——硬编码的机密、SQL 注入风险、不安全的模式 两者都无法捕获对方能发现的问题。所以两者都是必不可少的。 ## 🔄 GitOps 部署 本项目采用**双仓库 GitOps 模式**: | 仓库 | 包含内容 | 写入者 | | ------------------------------ | ------------------------------------------- | ------------------ | | `acquisitions-api` (本仓库) | 应用代码 + Dockerfile + CI 流水线 | 开发者 | | `acquisitions-gitops` | 仅 Kubernetes YAML 清单 | CI 机器人 (自动化) | **为什么要分离仓库?** 当 CI 流水线通过所有门禁时,它会将新的 Docker 镜像标签提交到 `acquisitions-gitops`。ArgoCD 监视该仓库并自动部署更改。 这意味着: - **Git 始终是唯一的真相来源** — 而不是 CI 运行器,也不是某个人的终端 - **配置漂移检测** — 如果有人手动更改了集群(例如缩减副本数),ArgoCD 会检测到偏差并在几分钟内自动恢复 - **完整的审计跟踪** — 每次部署都是一个带有消息和作者的 Git 提交 ## 📊 监控与报警 ### 工作原理 API 通过 `prom-client` 暴露 `/metrics` 端点。Prometheus 每 15 秒抓取一次数据。Grafana 负责将数据可视化。 ### 暴露的自定义指标 | 指标 | 类型 | 描述 | | ------------------------------- | --------- | ----------------------------------------------- | | `http_requests_total` | 计数器 | 每个按方法、路由、状态标记的请求 | | `http_request_duration_seconds` | 直方图 | 带有百分位桶的请求持续时间 | | `process_heap_bytes` | 仪表 | Node.js 堆内存使用量 (自动收集) | | `nodejs_eventloop_lag_seconds` | 仪表 | 事件循环延迟 (自动收集) | ### Grafana 仪表板 | 仪表板 | ID | 显示内容 | | ------------------------ | ------- | -------------------------------- | | Kubernetes 集群 | `315` | 节点 CPU/内存,Pod 数量 | | ArgoCD 状态 | `14584` | 同步健康状况,部署历史 | | Node.js API | `11159` | 请求率,堆内存,事件循环 | | **自定义 API 仪表板** | — | 请求量/秒,P95 延迟,错误率 % | ### 报警规则 | 警报 | 触发条件 | 严重程度 | | ----------------------------- | ------------------------- | -------- | | `AcquisitionsPodCrashLooping` | Pod 在 2 分钟内重启 > 3 次 | 严重 | | `AcquisitionsHighCPU` | CPU 超过 80% 持续 5 分钟 | 警告 | | `AcquisitionsHighErrorRate` | 5xx 错误率超过 5% 持续 2 分钟 | 严重 | 警报通过 Alertmanager 发送到 **Slack**。 ## 📡 API 端点 ### 身份验证 | 方法 | 端点 | 描述 | 身份验证 | | ------ | ------------------- | ---------------------------- | -------- | | `POST` | `/api/auth/signup` | 注册一个新用户 | 公开 | | `POST` | `/api/auth/signin` | 登录并获取 JWT cookie | 公开 | | `POST` | `/api/auth/signout` | 登出并清除会话 | 需验证 | ### 用户 | 方法 | 端点 | 描述 | 身份验证 | | -------- | ---------------- | ------------------- | -------------- | | `GET` | `/api/users` | 获取所有用户 | 仅限管理员 | | `GET` | `/api/users/:id` | 按 ID 获取用户 | 需验证 | | `PUT` | `/api/users/:id` | 更新用户资料 | 所有者或管理员 | | `DELETE` | `/api/users/:id` | 删除用户 | 仅限管理员 | ### 业务列表 [正在开发此功能 !!!] | 方法 | 端点 | 描述 | 身份验证 | | -------- | ------------------- | ----------------------- | -------------- | | `GET` | `/api/listings` | 获取所有活跃的列表 | 公开 | | `GET` | `/api/listings/:id` | 按 ID 获取列表 | 公开 | | `POST` | `/api/listings` | 创建新列表 | 需验证 | | `PUT` | `/api/listings/:id` | 更新列表 | 所有者或管理员 | | `DELETE` | `/api/listings/:id` | 删除列表 | 所有者或管理员 | ### 系统 | 方法 | 端点 | 描述 | | ------ | ---------- | ----------------------------------------- | | `GET` | `/health` | 健康检查 — 返回状态 + 时间戳 | | `GET` | `/metrics` | Prometheus 指标端点 | ## 🚀 本地开发准备 ### 前置条件 - Node.js 20+ - Docker + Docker Compose - 一个 [Neon DB](https://neon.tech) 账户 (免费) - 一个 [Arcjet](https://arcjet.com) 账户 (免费) ### 设置 ``` # 1. Clone 仓库 git clone https://github.com/himanshu2604/acquisitions-api.git cd acquisitions-api # 2. 安装依赖 npm install # 3. 设置环境变量 cp .env.example .env # 填写 .env 中的所有值(见下文) # 4. 运行数据库迁移 npm run db:migrate # 5. 启动开发服务器 npm run dev # API 运行于 http://localhost:3000 ``` ### 环境变量 ``` PORT=3000 NODE_ENV=development DATABASE_URL=postgresql://user:pass@host/dbname JWT_SECRET=minimum_32_character_random_string ARCJET_KEY=your_arcjet_api_key COOKIE_SECRET=another_random_secret ``` ### 使用 Docker Compose ``` # 使用 Docker Compose 启动(推荐) docker-compose up # 或者直接构建并运行 Docker 镜像 docker build -t acquisitions-api . docker run -p 3000:3000 --env-file .env acquisitions-api ``` ## 📁 项目结构 ``` acquisitions-api/ ├── src/ │ ├── config/ # DB connection, app config │ ├── controllers/ # Route handlers (thin layer — calls services) │ ├── middleware/ # Auth, validation, rate limiting, metrics │ ├── models/ # Drizzle ORM schemas │ ├── routes/ # Express router definitions │ ├── services/ # Business logic │ ├── utils/ # Logger, JWT helpers, prom-client metrics │ └── validations/ # Zod request schemas ├── tests/ # Jest + Supertest test suites ├── .github/ │ └── workflows/ # Full CI/CD pipeline │ ├── docker-and-trivy.yml │ ├── lint-and-format.yml │ └── tests.yml ├── kubernetes/ # Local K8s reference manifests ├── Dockerfile # Multi-stage build ├── docker-compose.yml # Local development stack ├── screenshot/ # Video + screenshots └── sonar-project.properties ``` ## 🔒 安全 | 层 | 工具 | 防护措施 | | ---------------- | -------------------- | ----------------------------------------------- | | HTTP 头 | Helmet | XSS、点击劫持、MIME 嗅探 | | 跨源 | CORS | 受控的跨源访问 | | 机器人防护 | Arcjet | 实时机器人检测与拦截 | | 速率限制 | Arcjet | 基于路由的请求节流 | | 身份验证 | JWT + bcrypt | 安全的会话,经过哈希处理的密码 | | 输入验证 | Zod | 验证所有请求体 | | CVE 扫描 | Trivy (CI 门禁) | 在部署前拦截容器漏洞 | | 代码分析 | SonarCloud (CI 门禁) | 源中的安全热点 | | 容器 | 非 root 用户 | 应用在 Docker 中以非特权用户运行 | ## 🧪 测试 ``` # 运行所有测试 npm run test # 运行并生成覆盖率报告 npm run test -- --coverage # 以 watch 模式运行 npm run test -- --watch ``` 测试涵盖: - ✅ 身份验证流程 — 注册、登录、登出、无效凭据 - ✅ 受保护路由的强制执行 - ✅ 输入验证错误响应 - ✅ 具有基于角色访问权限的用户 CRUD - ✅ 业务列表的 CRUD 操作 - ✅ 健康检查端点 ## 💡 我的收获 - **为什么 GitOps 比在流水线中使用 `kubectl` 更安全** — 当 CI 运行器直接应用清单时,集群状态存在于一个短暂的作业中。使用 GitOps,每一次更改都是一个 Git 提交。集群状态总是会反映 Git 中的内容,任何偏差都会被自动纠正。 - **livenessProbe 和 readinessProbe 之间的区别** — 存活探针会重启陷入死锁的容器。就绪探针会在启动期间或 Pod 不堪重负时将其从负载均衡器中移除。两者你都需要,而且它们的用途完全不同。 - **Trivy 如何发现 SonarCloud 遗漏的问题(反之亦然)** — Trivy 在镜像层面发现你的依赖项和操作系统包中的 CVE。SonarCloud 在你自己的源代码中发现不安全的模式。这两个工具互不重叠。但都是必不可少的。 - **在实践中,配置漂移检测究竟意味着什么** — 它不仅仅是一个功能。它是一个保证,确保你的集群状态将始终与你的 Git 仓库匹配,即使有人在凌晨 2 点惊慌失措地在生产环境中运行了 `kubectl` 命令。 - **PromQL 查询的工作原理** — `rate()` 用于计算每秒速率,`histogram_quantile()` 用于计算百分位延迟,标签选择器用于按你的应用进行过滤。从头开始编写这些查询是阅读仪表板和构建仪表板之间的区别。 - **为什么多阶段 Docker 构建对安全性至关重要** — 构建器阶段安装开发依赖并编译 TypeScript。生产阶段仅复制 `dist/` 和 `node_modules`。攻击面显著缩小,因为构建工具永远不会被发布到生产环境。 ## 📄 许可证 本项目用于教育和作品集展示目的。
**🔗 相关仓库:** [acquisitions-gitops](https://github.com/himanshu2604/acquisitions-gitops) — K8s 清单和 Helm values
_由 Himanshu 作为 DevOps 作品集项目构建_
标签:ArgoCD, CISA项目, DevSecOps, Docker, GitHub Actions, GitOps, GNU通用公共许可证, Grafana, MITM代理, Node.js, PoC框架, PostgreSQL, REST API, SaaS交易, SonarCloud, TypeScript, 上游代理, 企业收购, 后端开发, 子域名突变, 安全扫描, 安全插件, 安全门禁, 安全防御评估, 容器化部署, 微服务架构, 时序注入, 测试用例, 生产级, 自动化运维, 自动笔记, 自定义请求头, 请求拦截, 软件买卖