Skip to content

Commit 807e109

Browse files
author
Michael Schwarz
committed
Merge branch 'master' into production
2 parents 3fa2283 + 3bfd3d0 commit 807e109

37 files changed

Lines changed: 4387 additions & 4826 deletions

CLAUDE.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,24 @@ job,function=stop_job event="{\"jobId\":123,\"cluster\":\"test\",\"startTime\":1
314314
- Messages are logged; no responses are sent back to publishers
315315
- If NATS client is unavailable, API subscriptions are skipped (logged as warning)
316316

317+
### Security Considerations
318+
319+
**The NATS API has no application-layer authentication or authorization.** Unlike
320+
the REST endpoints (which require a JWT with `RoleAPI`), the subscribers process
321+
any message delivered on the configured subjects. Anyone with publish rights to
322+
those subjects on the broker can:
323+
324+
- Insert arbitrary jobs (potentially attributed to other users)
325+
- Mark running jobs as stopped, triggering archive/finalization
326+
- Overwrite node state and health metadata for any cluster
327+
328+
Operators MUST restrict publish ACLs at the NATS broker (per-account or
329+
per-subject permissions) so that only trusted producers — e.g. the scheduler
330+
integration on a known host or service account — can publish to the configured
331+
`subject-job-event` and `subject-node-state` subjects. A shared, unrestricted
332+
NATS broker is not a safe deployment topology for this API. A startup warning
333+
is logged when these subscriptions are enabled.
334+
317335
## Development Guidelines
318336

319337
### Performance
@@ -323,6 +341,21 @@ records, archives) at scale. All code changes must prioritize maximum throughput
323341
and minimal latency. Avoid unnecessary allocations, prefer streaming over
324342
buffering, and be mindful of lock contention. When in doubt, benchmark.
325343

344+
### Commit Message Convention
345+
346+
Commits must use conventional commit prefixes so goreleaser can generate the
347+
changelog automatically. Only commits with these prefixes appear in releases:
348+
349+
| Prefix | Changelog group |
350+
|---------|------------------------|
351+
| `feat:` | New Features |
352+
| `fix:` | Bug fixes |
353+
| `sec:` | Security updates |
354+
| `docs:` | Documentation updates |
355+
356+
Scoped variants are also recognised, e.g. `feat(api):`, `fix(deps):`.
357+
Commits without one of these prefixes are excluded from the changelog.
358+
326359
### Change Impact Analysis
327360

328361
For any significant change, you MUST:

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
TARGET = ./cc-backend
22
FRONTEND = ./web/frontend
3-
VERSION = 1.5.3
3+
VERSION = 1.5.4
44
GIT_HASH := $(shell git rev-parse --short HEAD || echo 'development')
55
CURRENT_TIME = $(shell date +"%Y-%m-%d:T%H:%M:%S")
66
LD_FLAGS = '-s -X main.date=${CURRENT_TIME} -X main.version=${VERSION} -X main.commit=${GIT_HASH}'

README.md

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
# NOTE
22

3-
While we do our best to keep the master branch in a usable state, there is no guarantee the master branch works.
4-
Please do not use it for production!
3+
While we do our best to keep the main branch in a usable state, there is no
4+
guarantee the main branch works. Please do not use it for production!
55

6-
Please have a look at the [Release
7-
Notes](https://github.com/ClusterCockpit/cc-backend/blob/master/ReleaseNotes.md)
6+
Please have a look at the [Release Notes](https://github.com/ClusterCockpit/cc-backend/blob/main/ReleaseNotes.md)
87
for breaking changes!
98

109
# ClusterCockpit REST and GraphQL API backend
@@ -41,7 +40,7 @@ For real-time integration with HPC systems, the backend can subscribe to
4140
state updates, providing an alternative to REST API polling.
4241

4342
Completed batch jobs are stored in a file-based job archive according to
44-
[this specification](https://github.com/ClusterCockpit/cc-specifications/tree/master/job-archive).
43+
[this specification](https://github.com/ClusterCockpit/cc-specifications/tree/main/job-archive).
4544
The backend supports authentication via local accounts, an external LDAP
4645
directory, and JWT tokens. Authorization for APIs is implemented with
4746
[JWT](https://jwt.io/) tokens created with public/private key encryption.
@@ -243,73 +242,73 @@ The effective configuration is logged at startup for verification.
243242

244243
## Project file structure
245244

246-
- [`.github/`](https://github.com/ClusterCockpit/cc-backend/tree/master/.github)
245+
- [`.github/`](https://github.com/ClusterCockpit/cc-backend/tree/main/.github)
247246
GitHub Actions workflows and dependabot configuration for CI/CD.
248-
- [`api/`](https://github.com/ClusterCockpit/cc-backend/tree/master/api)
247+
- [`api/`](https://github.com/ClusterCockpit/cc-backend/tree/main/api)
249248
contains the API schema files for the REST and GraphQL APIs. The REST API is
250249
documented in the OpenAPI 3.0 format in
251250
[./api/swagger.yaml](./api/swagger.yaml). The GraphQL schema is in
252251
[./api/schema.graphqls](./api/schema.graphqls).
253-
- [`cmd/cc-backend`](https://github.com/ClusterCockpit/cc-backend/tree/master/cmd/cc-backend)
252+
- [`cmd/cc-backend`](https://github.com/ClusterCockpit/cc-backend/tree/main/cmd/cc-backend)
254253
contains the main application entry point and CLI implementation.
255-
- [`configs/`](https://github.com/ClusterCockpit/cc-backend/tree/master/configs)
254+
- [`configs/`](https://github.com/ClusterCockpit/cc-backend/tree/main/configs)
256255
contains documentation about configuration and command line options and required
257256
environment variables. Sample configuration files are provided.
258-
- [`init/`](https://github.com/ClusterCockpit/cc-backend/tree/master/init)
257+
- [`init/`](https://github.com/ClusterCockpit/cc-backend/tree/main/init)
259258
contains an example of setting up systemd for production use.
260-
- [`internal/`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal)
259+
- [`internal/`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal)
261260
contains library source code that is not intended for use by others.
262-
- [`api`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/api)
261+
- [`api`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/api)
263262
REST API handlers and NATS integration
264-
- [`archiver`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/archiver)
263+
- [`archiver`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/archiver)
265264
Job archiving functionality
266-
- [`auth`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/auth)
265+
- [`auth`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/auth)
267266
Authentication (local, LDAP, OIDC) and JWT token handling
268-
- [`config`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/config)
267+
- [`config`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/config)
269268
Configuration management and validation
270-
- [`graph`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/graph)
269+
- [`graph`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/graph)
271270
GraphQL schema and resolvers
272-
- [`importer`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/importer)
271+
- [`importer`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/importer)
273272
Job data import and database initialization
274-
- [`metricdispatch`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/metricdispatch)
273+
- [`metricdispatch`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/metricdispatch)
275274
Dispatches metric data loading to appropriate backends
276-
- [`repository`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/repository)
275+
- [`repository`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/repository)
277276
Database repository layer for jobs and metadata
278-
- [`routerConfig`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/routerConfig)
277+
- [`routerConfig`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/routerConfig)
279278
HTTP router configuration and middleware
280-
- [`tagger`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/tagger)
279+
- [`tagger`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/tagger)
281280
Job classification and application detection
282-
- [`taskmanager`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/taskmanager)
281+
- [`taskmanager`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/taskmanager)
283282
Background task management and scheduled jobs
284-
- [`metricstoreclient`](https://github.com/ClusterCockpit/cc-backend/tree/master/internal/metricstoreclient)
283+
- [`metricstoreclient`](https://github.com/ClusterCockpit/cc-backend/tree/main/internal/metricstoreclient)
285284
Client for cc-metric-store queries
286-
- [`pkg/`](https://github.com/ClusterCockpit/cc-backend/tree/master/pkg)
285+
- [`pkg/`](https://github.com/ClusterCockpit/cc-backend/tree/main/pkg)
287286
contains Go packages that can be used by other projects.
288-
- [`archive`](https://github.com/ClusterCockpit/cc-backend/tree/master/pkg/archive)
287+
- [`archive`](https://github.com/ClusterCockpit/cc-backend/tree/main/pkg/archive)
289288
Job archive backend implementations (filesystem, S3, SQLite)
290-
- [`metricstore`](https://github.com/ClusterCockpit/cc-backend/tree/master/pkg/metricstore)
289+
- [`metricstore`](https://github.com/ClusterCockpit/cc-backend/tree/main/pkg/metricstore)
291290
In-memory metric data store with checkpointing and metric loading
292-
- [`tools/`](https://github.com/ClusterCockpit/cc-backend/tree/master/tools)
291+
- [`tools/`](https://github.com/ClusterCockpit/cc-backend/tree/main/tools)
293292
Additional command line helper tools.
294-
- [`archive-manager`](https://github.com/ClusterCockpit/cc-backend/tree/master/tools/archive-manager)
293+
- [`archive-manager`](https://github.com/ClusterCockpit/cc-backend/tree/main/tools/archive-manager)
295294
Commands for getting infos about an existing job archive, importing jobs
296295
between archive backends, and converting archives between JSON and Parquet formats.
297-
- [`archive-migration`](https://github.com/ClusterCockpit/cc-backend/tree/master/tools/archive-migration)
296+
- [`archive-migration`](https://github.com/ClusterCockpit/cc-backend/tree/main/tools/archive-migration)
298297
Tool for migrating job archives between formats.
299-
- [`convert-pem-pubkey`](https://github.com/ClusterCockpit/cc-backend/tree/master/tools/convert-pem-pubkey)
298+
- [`convert-pem-pubkey`](https://github.com/ClusterCockpit/cc-backend/tree/main/tools/convert-pem-pubkey)
300299
Tool to convert external pubkey for use in `cc-backend`.
301-
- [`gen-keypair`](https://github.com/ClusterCockpit/cc-backend/tree/master/tools/gen-keypair)
300+
- [`gen-keypair`](https://github.com/ClusterCockpit/cc-backend/tree/main/tools/gen-keypair)
302301
contains a small application to generate a compatible JWT keypair. You find
303302
documentation on how to use it
304-
[here](https://github.com/ClusterCockpit/cc-backend/blob/master/docs/JWT-Handling.md).
305-
- [`web/`](https://github.com/ClusterCockpit/cc-backend/tree/master/web)
306-
Server-side templates and frontend-related files:
307-
- [`frontend`](https://github.com/ClusterCockpit/cc-backend/tree/master/web/frontend)
303+
[here](https://github.com/ClusterCockpit/cc-backend/blob/main/docs/JWT-Handling.md).
304+
- [`web/`](https://github.com/ClusterCockpit/cc-backend/tree/main/web)
305+
Server-side templates and frontend-related files:
306+
- [`frontend`](https://github.com/ClusterCockpit/cc-backend/tree/main/web/frontend)
308307
Svelte components and static assets for the frontend UI
309-
- [`templates`](https://github.com/ClusterCockpit/cc-backend/tree/master/web/templates)
308+
- [`templates`](https://github.com/ClusterCockpit/cc-backend/tree/main/web/templates)
310309
Server-side Go templates, including monitoring views
311-
- [`gqlgen.yml`](https://github.com/ClusterCockpit/cc-backend/blob/master/gqlgen.yml)
310+
- [`gqlgen.yml`](https://github.com/ClusterCockpit/cc-backend/blob/main/gqlgen.yml)
312311
Configures the behaviour and generation of
313312
[gqlgen](https://github.com/99designs/gqlgen).
314-
- [`startDemo.sh`](https://github.com/ClusterCockpit/cc-backend/blob/master/startDemo.sh)
313+
- [`startDemo.sh`](https://github.com/ClusterCockpit/cc-backend/blob/main/startDemo.sh)
315314
is a shell script that sets up demo data, and builds and starts `cc-backend`.

ReleaseNotes.md

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# `cc-backend` version 1.5.3
1+
# `cc-backend` version 1.5.4
22

33
Supports job archive version 3 and database version 11.
44

5-
This is a bugfix release of `cc-backend`, the API backend and frontend
6-
implementation of ClusterCockpit.
5+
This is a security and bugfix release of `cc-backend`, the API backend and
6+
frontend implementation of ClusterCockpit.
77
For release specific notes visit the [ClusterCockpit Documentation](https://clusterockpit.org/docs/release/).
88
If you are upgrading from v1.5.1 no database migration is required.
99
If you are upgrading from v1.5.0 you need to do another DB migration. This
@@ -15,6 +15,75 @@ While we are confident that the memory issue with the metricstore cleanup move
1515
policy is fixed, it is still recommended to use delete policy for cleanup.
1616
This is also the default.
1717

18+
## Changes in 1.5.4
19+
20+
### Security fixes
21+
22+
- **JWT HMAC empty-key bypass (critical)**: `jwtSession.go` now refuses to
23+
register when `CROSS_LOGIN_JWT_HS512_KEY` is unset. Previously, an empty HMAC
24+
key allowed unauthenticated admin token forgery because `golang-jwt` verifies
25+
any HS256/HS512 signature against an empty key.
26+
- **SQL injection via metric names (critical)**: Metric names supplied through
27+
GraphQL (`[String!]`) were interpolated raw into `json_extract` SQL expressions.
28+
Names are now validated against `^[a-zA-Z0-9_]+$` in
29+
`jobsMetricStatisticsHistogram` and `buildFloatJSONCondition`.
30+
- **Path traversal via line-protocol tags (critical)**: `cluster` and `host`
31+
tags from the metric line protocol flowed unvalidated into `path.Join` for
32+
checkpoint/WAL file paths, enabling arbitrary file writes outside the
33+
checkpoint root via NATS (unauthenticated) or `POST /api/write`. Path-traversal
34+
sequences are now rejected in `DecodeLine` before the tags become path
35+
components.
36+
- **CORS `AllowCredentials` disabled**: CORS middleware no longer sets
37+
`AllowCredentials: true`, which was incompatible with `AllowedOrigins: ["*"]`
38+
and could enable cross-origin credential theft.
39+
- **HSTS header added**: `Strict-Transport-Security` is now set for all
40+
HTTPS connections.
41+
- **Security response headers**: Added `X-Content-Type-Options: nosniff`,
42+
`X-Frame-Options: DENY`, `Referrer-Policy: same-origin`, and a conservative
43+
`Content-Security-Policy` (blocks `frame-ancestors`, `object-src`, `base-uri`)
44+
to harden against clickjacking and base-tag injection.
45+
- **Stored XSS in job message**: `job.metaData.message` is now rendered as
46+
escaped text (CSS `white-space: pre-wrap`) instead of raw `{@html ...}` in
47+
`Job.root` and `JobFootprint`.
48+
- **SQL injection in tag queries**: The tag-scope `IN` list and manager project
49+
subquery in `CountTags` are now parameterized instead of interpolating
50+
`user.Username` / `user.Projects` values sourced from OIDC/LDAP.
51+
- **GraphQL DoS hardening**: Query cost is bounded with `FixedComplexityLimit`
52+
(5000). Non-positive `items-per-page` and `page` values are rejected with HTTP
53+
400 to prevent integer underflow into unbounded `LIMIT`/`OFFSET` queries.
54+
- **CSRF defense-in-depth**: State-changing requests with a cross-site
55+
`Sec-Fetch-Site` header are now rejected (fails open for non-browser clients),
56+
complementing the existing `SameSite=Lax` session cookie.
57+
- **NATS API security warning**: A startup warning is now logged when NATS
58+
subscriptions are enabled, reminding operators that the NATS API has no
59+
application-layer authentication and that publish ACLs must be restricted at
60+
the broker.
61+
62+
### Bug fixes
63+
64+
- **Roofline legend placement**: Roofline plot legends now use fixed
65+
coordinates instead of dynamic placement, preventing the legend from
66+
overlapping data points or being rendered off-canvas (#546).
67+
- **Subcluster usage tab labels**: Subcluster names in the status dashboard
68+
usage tabs are no longer force-capitalized; the original cluster-defined
69+
casing is preserved.
70+
- **NodeListRow host filter**: The running-jobs query in the node list row now
71+
filters by exact node hostname (`eq`) instead of substring match
72+
(`contains`), avoiding incorrect matches when one hostname is a prefix of
73+
another.
74+
- **WAL files not reset on shutdown**: On graceful shutdown the metricstore wrote
75+
a final binary snapshot but never rotated the per-host `current.wal` files (the
76+
`RotateWALFilesAfterShutdown` helper was defined but never called). The stale
77+
WAL files were replayed and then appended to again on the next start, so they
78+
grew without bound across restarts and were only ever reset at the next periodic
79+
checkpoint. `Shutdown` now rotates the WAL files for all successfully
80+
snapshotted hosts.
81+
82+
### Dependencies
83+
84+
- **Go module upgrades**: Refreshed Go module dependencies to their latest
85+
compatible versions.
86+
1887
## Changes in 1.5.3
1988

2089
### Bug fixes

0 commit comments

Comments
 (0)