|
2 | 2 |
|
3 | 3 | ## Overview |
4 | 4 |
|
5 | | -UTMStack is a SIEM/XDR platform. Multi-language monorepo with three technology stacks: |
6 | | - |
7 | | -| Directory | Language | Build | Notes | |
8 | | -|---|---|---|---| |
9 | | -| `backend/` | Java 17 (Spring Boot 3.1, JHipster 7.3) | Maven (`./mvnw`) | WAR packaging, Liquibase migrations | |
10 | | -| `frontend/` | Angular 7 (TypeScript 3.2, Node 14) | Angular CLI + npm | Very old Angular — no modern APIs | |
11 | | -| `agent/` | Go 1.25.5 | `go build` | Cross-compiled for Linux/Windows/macOS | |
12 | | -| `agent-manager/` | Go 1.25.5 | `go build` | Distributes agent binaries | |
13 | | -| `utmstack-collector/` | Go 1.25.5 | `go build` | Log collector service | |
14 | | -| `as400/` | Go 1.25.5 | `go build` | AS400 log collector | |
15 | | -| `plugins/*/` | Go 1.25.5 | `go build` | 16 independent plugin modules | |
16 | | -| `shared/` | Go 1.25.1 | — | Shared library (consumed via `replace`) | |
17 | | -| `installer/` | Go 1.25.1 | `go build` | Self-updating installer binary | |
18 | | -| `user-auditor/` | Java 11 | Maven | Standalone microservice | |
19 | | -| `web-pdf/` | Java 11 | Maven | Standalone microservice | |
| 5 | +SIEM/XDR platform. Multi-language monorepo: |
| 6 | + |
| 7 | +| Directory | Language | Build | |
| 8 | +|---|---|---| |
| 9 | +| `backend/` | Java 17 (Spring Boot 3.1, JHipster 7.3) | Maven (`mvn`) | |
| 10 | +| `frontend/` | Angular 7 (TypeScript 3.2, Node 14) | Angular CLI + npm | |
| 11 | +| `agent/` | Go 1.25.5 | `go build` (+ ldflags) | |
| 12 | +| `agent-manager/` | Go 1.25.5 | `go build` | |
| 13 | +| `utmstack-collector/` | Go 1.25.5 | `go build` (+ ldflags) | |
| 14 | +| `as400/` | Go 1.25.5 | `go build` (+ ldflags) | |
| 15 | +| `plugins/*/` | Go 1.25.5 | `go build` (17 modules) | |
| 16 | +| `shared/` | Go 1.25.1 | — (shared library) | |
| 17 | +| `installer/` | Go 1.25.1 | `go build` (+ ldflags) | |
| 18 | +| `user-auditor/` | Java 11 | Maven | |
| 19 | +| `web-pdf/` | Java 11 | Maven | |
20 | 20 |
|
21 | 21 | ## Build Commands |
22 | 22 |
|
23 | 23 | ### Backend (Java) |
24 | 24 | ```bash |
25 | 25 | cd backend |
26 | | -./mvnw # Run Spring Boot dev server (port 8080) |
27 | | -./mvnw -Pprod clean package # Production WAR build → target/utmstack.war |
28 | | -./mvnw clean test # Run tests |
| 26 | +mvn -s settings.xml -B # Run Spring Boot dev server (port 8080) |
| 27 | +mvn -B -Pprod clean package -s settings.xml # Production WAR → target/utmstack.war |
29 | 28 | ``` |
30 | | -- Maven settings: `backend/settings.xml` authenticates to GitHub Packages via `$MAVEN_TK` env var (GitHub PAT). |
| 29 | +- Maven settings: `backend/settings.xml` authenticates to GitHub Packages via `MAVEN_TK` env var (GitHub PAT with `read:packages`). |
31 | 30 | - Spring profiles: `dev` (default), `prod`, `tls`. Config in `backend/src/main/resources/config/`. |
32 | 31 | - Docker dev database: `docker-compose -f backend/src/main/docker/mysql.yml up -d` |
33 | | -- **No `src/test/` directory exists** — tests are embedded in `src/main/java/`. |
| 32 | +- **No `src/test/` directory** — tests are embedded in `src/main/java/`. |
34 | 33 |
|
35 | 34 | ### Frontend (Angular 7) |
36 | 35 | ```bash |
37 | 36 | cd frontend |
38 | 37 | npm install |
39 | 38 | npm start # ng serve --host 0.0.0.0 |
40 | | -npm run build # ng build --prod --base-href / |
| 39 | +NODE_OPTIONS=--max_old_space_size=8192 npm run build # ng build --prod |
41 | 40 | npm test # ng test (Karma + Jasmine) |
42 | 41 | npm run lint # ng lint (TSLint, NOT ESLint) |
43 | 42 | ``` |
44 | | -- **Node 14.16.1 required** (pinned in CI). Newer Node will break `node-sass@4`. |
| 43 | +- **Node 14.16.1 required**. Newer Node breaks `node-sass@4`. |
45 | 44 | - Linter is **TSLint** (`tslint.json`), not ESLint. Uses `codelyzer` rules. |
46 | | -- Output: `dist/utm-stack` |
47 | | -- Styles use SCSS (see `angular.json` schematic config). |
48 | | -- **CI sets `NODE_OPTIONS=--max_old_space_size=8192`** for builds — you may need this locally too. |
| 45 | +- Output: `dist/utm-stack`. Styles use SCSS (`angular.json`). |
| 46 | +- **Builds need 8 GB heap**: `NODE_OPTIONS=--max_old_space_size=8192`. |
49 | 47 |
|
50 | 48 | ### Go Components |
51 | | -Each Go module is independent. Build from its directory: |
| 49 | +Each module is independent. Build from its directory: |
52 | 50 | ```bash |
53 | 51 | cd agent |
54 | 52 | go build -o utmstack_agent_service . |
55 | 53 | ``` |
56 | 54 |
|
57 | | -**`shared/` replace directives:** Only `agent/go.mod` and `agent/updater/go.mod` have `replace github.com/utmstack/UTMStack/shared => ../shared`. You cannot build those two modules outside the repo structure. All other Go modules (plugins, agent-manager, installer, etc.) are fully independent. |
| 55 | +**`shared/` replace directives:** `agent/go.mod` and `agent/updater/go.mod` have `replace github.com/utmstack/UTMStack/shared => ../shared` (or `../../shared`). These two modules cannot be built outside the repo. |
58 | 56 |
|
59 | | -**Agent ldflags:** Agent binaries require `-ldflags "-X 'github.com/utmstack/UTMStack/agent/config.REPLACE_KEY=<secret>'"` to inject an auth prefix. Without it, agents won't authenticate. CI uses `$AGENT_SECRET_PREFIX` secret. |
| 57 | +**ldflags required for agent, collector, and as400:** |
| 58 | +```bash |
| 59 | +# Agent |
| 60 | +go build -ldflags "-X 'github.com/utmstack/UTMStack/agent/config.REPLACE_KEY=<secret>'" . |
| 61 | + |
| 62 | +# UTMStack Collector |
| 63 | +go build -ldflags "-X 'github.com/utmstack/UTMStack/utmstack-collector/config.REPLACE_KEY=<secret>'" . |
60 | 64 |
|
61 | | -**Cross-compilation:** Set `GOOS`/`GOARCH`/`CGO_ENABLED=0` before `go build`. CI builds Linux (amd64/arm64), Windows (amd64/arm64), and macOS (arm64). |
| 65 | +# AS400 Collector |
| 66 | +go build -ldflags "-X 'github.com/utmstack/UTMStack/as400/config.REPLACE_KEY=<secret>'" . |
| 67 | +``` |
| 68 | +CI injects `$AGENT_SECRET_PREFIX` for all three. Without it, these services cannot authenticate. |
62 | 69 |
|
63 | | -**Geolocation data:** The event processor needs external CSV files downloaded from `storage.googleapis.com/utmstack-updates/dependencies/geolocation/` at build time. |
| 70 | +**Cross-compilation:** Set `GOOS`/`GOARCH`/`CGO_ENABLED=0` before `go build`. CI builds Linux (amd64/arm64), Windows (amd64/arm64), macOS (arm64). |
64 | 71 |
|
65 | 72 | ### Plugins |
66 | | -Each plugin under `plugins/*/` is a standalone Go module. Build output is a single binary named `com.utmstack.<name>.plugin`. The `event_processor.Dockerfile` copies all 16 plugin binaries into the event processor container. |
| 73 | +Each plugin under `plugins/*/` is a standalone Go module. Build binary named `com.utmstack.<name>.plugin`. |
| 74 | + |
| 75 | +**16 plugins** are copied into `event_processor.Dockerfile`. The `plugins/` directory currently has 17 modules — `compliance-orchestrator` exists but is not yet in the Dockerfile. |
67 | 76 |
|
68 | 77 | ### Installer |
69 | 78 | ```bash |
70 | 79 | cd installer |
71 | 80 | bash build.sh # Uses ldflags for config injection |
72 | 81 | ``` |
73 | | -`build.sh` sets `GOPRIVATE=github.com/utmstack` and injects `DEFAULT_BRANCH`, `INSTALLER_VERSION`, `REPLACE` (encryption salt), and `PUBLIC_KEY` via `-ldflags`. |
| 82 | +`build.sh` injects `DEFAULT_BRANCH`, `INSTALLER_VERSION`, `REPLACE` (encryption salt), and `PUBLIC_KEY` via `-ldflags`. |
| 83 | + |
| 84 | +### Geolocation Data |
| 85 | +Event processor needs CSV files downloaded at build time from: |
| 86 | +``` |
| 87 | +https://storage.googleapis.com/utmstack-updates/dependencies/geolocation/ |
| 88 | +``` |
| 89 | +`geolocation/` is gitignored — must be populated from GCS before Docker build. |
74 | 90 |
|
75 | 91 | ## CI / CD |
76 | 92 |
|
77 | | -Two active deployment pipelines: |
| 93 | +### PR Checks |
| 94 | +`.github/workflows/pr-checks.yml` — runs on PRs to `release/**`, `v10`, `v11`. Triggers Go dependency checks, AI review, and approver job. |
78 | 95 |
|
79 | | -- **v11** (`.github/workflows/v11-deployment-pipeline.yml`) — current active line. Triggers on push to `release/v11*` branches (dev) or prerelease events (rc). |
80 | | -- **v10** (`.github/workflows/v10-deployment-pipeline.yml`) — legacy. Triggers on push to `release/v10*` and prerelease/release events. |
| 96 | +### Deployment Pipelines |
| 97 | +- **v11** (`.github/workflows/v11-deployment-pipeline.yml`) — active line. Triggers: push to `release/v11**` (dev), push to `v11` (rc), `release.released` (prod). |
| 98 | +- **v10** (`.github/workflows/v10-deployment-pipeline.yml`) — legacy. Triggers: push to `release/v10**` (dev), push to `v10` (rc), `release.released` with `v10.*` tag (prod). |
81 | 99 |
|
82 | | -Reusable workflow building blocks: |
83 | | -- `reusable-java.yml` — builds Maven projects, pushes Docker image to `ghcr.io/utmstack/utmstack/<image>:<tag>` |
84 | | -- `reusable-golang.yml` — runs `go test ./...`, builds binary, pushes Docker image |
85 | | -- `reusable-node.yml` — Node 14.16.1, `npm install && npm run-script build`, pushes Docker image |
86 | | -- `reusable-sign-agent.yml` — signs Windows binaries (jsign + GCP KMS) and macOS binaries (codesign + notarytool) |
87 | | -- `reusable-basic.yml` — Docker build-only, no compile step |
| 100 | +### Reusable Workflows |
| 101 | +- `reusable-java.yml` — Maven build + Docker push to `ghcr.io/utmstack/utmstack/<image>:<tag>` |
| 102 | +- `reusable-golang.yml` — `go test ./...`, `go build`, Docker push |
| 103 | +- `reusable-node.yml` — Node 14.16.1, `npm install && npm run-script build`, Docker push |
| 104 | +- `reusable-sign-agent.yml` — Windows (jsign + GCP KMS) and macOS (codesign + notarytool) signing |
| 105 | +- `reusable-basic.yml` — Docker build-only |
88 | 106 |
|
89 | | -All Docker images push to **ghcr.io/utmstack/utmstack/**. Agent binary signing requires GCP KMS credentials (Windows) or Apple Developer certificates (macOS). |
| 107 | +### Agent Signing Workflow |
| 108 | +`installer-release.yml` builds the installer binary with ldflags using `CM_ENCRYPT_SALT` and `CM_SIGN_PUBLIC_KEY` secrets. |
90 | 109 |
|
91 | 110 | ## Key Architecture Notes |
92 | 111 |
|
93 | | -- **Event processor** is the core log correlation engine. It's a standalone Go-based service that loads compiled plugin binaries at runtime. The `event_processor.Dockerfile` expects all plugins pre-built alongside it. |
94 | | -- **Backend** serves the REST API and the Angular frontend. The frontend is a separate directory but gets built and deployed as its own container. |
95 | | -- **Agent** runs on endpoints (Windows/Linux/macOS). Communicates with `agent-manager` via gRPC. The agent-manager container bundles all agent binaries for distribution. |
96 | | -- **Filters** (`filters/`) and **rules** (`rules/`) are YAML files defining log parsing filters and detection rules. The backend Dockerfile copies these into the container at `/utmstack/filters` and `/utmstack/rules`. |
97 | | -- **UTMStack Collector** (`utmstack-collector/`) and **AS400** (`as400/`) are log collectors — separate from the endpoint agent. |
| 112 | +- **Event processor** is the core Go-based log correlation engine. Loads compiled plugin binaries at runtime. `event_processor.Dockerfile` expects all plugins pre-built alongside it. |
| 113 | +- **Backend** serves the REST API. WAR packaging. `filters/` and `rules/` are YAML files copied into the container at `/utmstack/filters` and `/utmstack/rules`. |
| 114 | +- **Frontend** is a standalone Angular app in a separate container. |
| 115 | +- **Agent** runs on endpoints (Windows/Linux/macOS). Communicates with `agent-manager` via gRPC. |
| 116 | +- **Collector** (`utmstack-collector/`) and **AS400** (`as400/`) are separate log collection services. |
98 | 117 |
|
99 | 118 | ## Gotchas |
100 | 119 |
|
101 | | -- **No `src/test/` in backend** — Maven test phase runs but the directory doesn't exist yet. Tests are embedded in `src/main/java/`. |
102 | | -- **Agent ldflags required** — `config.REPLACE_KEY` is injected at build time. Without it, agents won't authenticate. |
103 | | -- **Backend uses GitHub Packages** — `settings.xml` references `maven.pkg.github.com/utmstack/**`. You need a GitHub PAT with `read:packages` scope in `$MAVEN_TK`. |
104 | | -- **Frontend is Angular 7** — many modern Angular patterns (standalone components, signals, etc.) do not exist. CLI is v7.3.6. |
105 | | -- **Node 14 required for frontend** — CI pins 14.16.1. `npm install` on Node 16+ will fail on `node-sass@4`. |
106 | | -- **`npm run build` needs 8 GB heap** — CI sets `NODE_OPTIONS=--max_old_space_size=8192`. |
107 | | -- **Installer build requires ldflags** — `installer/build.sh` shows the required `-ldflags` for `DEFAULT_BRANCH`, `INSTALLER_VERSION`, `REPLACE`, and `PUBLIC_KEY`. |
108 | | -- **Geolocation data must be downloaded** — event processor needs CSV files from GCS at build time. |
109 | | -- **`geolocation/` directory is gitignored** — must be populated at build time from GCS. |
110 | | -- **`.plugin` files are gitignored** — plugin binaries are build artifacts, not committed. |
| 120 | +- **ldflags are mandatory** for `agent`, `utmstack-collector`, and `as400` — `REPLACE_KEY` is injected at build time. Without it, services cannot authenticate. |
| 121 | +- **Backend uses GitHub Packages** — `settings.xml` references `maven.pkg.github.com/utmstack/**`. Requires GitHub PAT in `$MAVEN_TK`. |
| 122 | +- **Frontend is Angular 7** — no standalone components, signals, or modern APIs. CLI v7.3.6. |
| 123 | +- **Node 14.16.1 required for frontend** — `npm install` on Node 16+ fails on `node-sass@4`. |
| 124 | +- **Frontend build needs 8 GB heap** — set `NODE_OPTIONS=--max_old_space_size=8192`. |
| 125 | +- **Installer build requires ldflags** — see `installer/build.sh` for `DEFAULT_BRANCH`, `INSTALLER_VERSION`, `REPLACE`, `PUBLIC_KEY`. |
| 126 | +- **Geolocation data must be downloaded** — event processor Docker build fails without `./geolocation/` CSV files from GCS. |
| 127 | +- **`.plugin` binaries are gitignored** — build artifacts, not committed. |
| 128 | +- **`jib-maven-plugin` image mismatch** — pom.xml references `eclipse-temurin:11-jre-focal` but the backend requires Java 17. |
0 commit comments