Skip to content

Releases: evsinev/dc-agent

1.7.0

Choose a tag to compare

@github-actions github-actions released this 01 Oct 02:50
e9b122e

New command zip-archive-version: publish an immutable version directory, switch a pointer file and wait for the service's reload — in one call, one curl --fail-with-body (#98).

curl --fail-with-body -H "api-key: $DC_AGENT_KEY" --data-binary @"v0.4.1.zip" \
  "https://agents.example.com/dc-agent/zip-archive-version/app-bundle/v0.4.1"

Upgrade notes (read before rolling out)

  • New WEB_SERVER_IDLE_TIMEOUT, default 10m — the idle timeout of the agent's connector, for every endpoint. Before, Jetty's own default of 30 s applied. A zip-archive-version config is refused unless its waitTimeout plus the 1 minute lock wait fits in it; a reverse proxy in front needs the same read timeout for that path (nginx proxy_read_timeout, 60 s by default).
  • The operator now pins dc-agent-react v1.10.0 (create / view / edit forms for the new command).
  • Control-plane create/update responses may carry the new status INVALID with a message (the field, never its value); the operator answers it with 400. An older operator cannot create the new command; a new operator against an older agent reports it as unreachable for this type only.

zip-archive-version

  • A transaction with three outcomes: confirmed (200, published|present active <version> sha256 <digest>), rolled back (the service's 409/422/503, or 502 — the pointer is back where it was), unknown (504/500 — a retry of the same command is always safe).
  • A version appears complete or not at all: staged next to its place, fsynced, published by one rename; the pointer is replaced atomically, its previous value kept on disk first, so a rollback survives the agent's own restart. Once the service confirms, the previous value is dropped, so a failed retry of a confirmed version does not roll it back.
  • Retries are cheap: contents are compared by a digest of the files (not the ZIP bytes) — a rebuilt archive of the same files is present; a tag that now carries other files is 409.
  • Archives are checked before anything is written: \ in names (on the raw bytes), absolute names, ./.., duplicates, symlinks and other special entries, encrypted entries; maxUploadBytes (413), maxBytes counted from the bytes actually read, maxEntries; at most two uploads in flight per agent.
  • Reload call: bounded by waitTimeout for the whole exchange (a service dripping its answer is cut), body capped at 256 bytes, no redirects; ${version} is allowed in the path and query only, never in the scheme, host or port.
  • Files 0644, directories 0755, set explicitly — the reading service runs as another user, so the command is not for secrets. reloadHeaders values are never logged and are masked in the command list.
  • Configs are checked on every call right after authorization and when saved through the control plane; readable values: 50mb, 10k, 5m.

Other fixes

  • The operator closes its command-list thread pool (it was only shut down).
  • GsonApiServlet (control-plane / operator API) is pinned to INFO in logback.xml: at DEBUG it logged whole create/update bodies, api keys included.

Docs: https://evsinev.github.io/dc-agent/commands/zip-archive-version/


What's Changed

  • feat: zip-archive-version — publish a version, switch the pointer and wait for the service in one call by @evsinev in #102

Full Changelog: 1.6.0...1.7.0

1.6.0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 23:32
0547ce3

Authenticate before anything: every agent task endpoint checks the api-key before it reads the request body, builds a path or touches the disk — and every refusal looks the same.

Upgrade notes (read before rolling out)

  • CONTROL_PLANE_ENABLED=true now requires your own CONTROL_PLANE_TOKEN. The agent refuses to start when it is empty or the published default REPLACE_THIS_TEST_CONTROL_PLANE_TOKEN. With the control plane off nothing changes. The token is now masked in the startup log.
  • The config type must match the endpoint (ZIP_ARCHIVE, ZIP_DIRS, SAVE_ARTIFACT, FETCH_URL, JAR, WAR, NODE, DOCKER); another type gets 401. A config without type still works, with a "has no type" warning in the agent log — add the field. Watch for an old node config saved through the operator as JAR. Before upgrading, on each host: grep -H '"type"\|^type:' $CONFIG_DIR/* and compare with the endpoint each command is called through.
  • Command names outside 0-9 a-z A-Z . _ - or containing .. get 401 (the operator never created such names).
  • zip-dirs: the sub-path segments . and .. are rejected.

Security fixes

  • zip-dirs escaped its dir: Jetty 12 passes a raw .. through to the servlet, so /zip-dirs/{name}/.. extracted above dir; a link inside dir could lead out too. Now ./.. are refused and the target must stay inside the canonical dir. Also, an anonymous request created directories under dir — directories are now created only after authorization.
  • A key of one command worked on another endpoint: keys belong to a config name and type was never checked, so a save-artifact key could unpack an arbitrary archive through /zip-archive/{same name} into the same dir (likewise jar/war/node).
  • Name enumeration and path disclosure: an unknown command name returned 500 with the absolute CONFIG_DIR path; empty or broken configs leaked parser messages. Every refusal — no key, wrong key, unknown command, broken config, another type — is now the same 401 Unauthorized; the reason goes to the agent log only, never a key.
  • Control plane behind the published default token let anyone create a command with their own key and deploy through it — see the upgrade note.
  • Authorization header: only Basic is accepted (a Bearer value is no longer Base64-decoded), bad Base64 is a 401 instead of a 500, and a password may contain :.

Docs

  • The false "a config without apiKeys accepts any request" is gone (the code already refused every request); security, configuration, installation and every command page describe the new checks, and each example config carries its type.

Known issues: #99 (a misspelled type value reads as no type), #100 (Jetty 12 rejects /fetch-url/https://... with 400 — pre-existing).

Full docs: https://evsinev.github.io/dc-agent/


What's Changed

  • fix(agent)!: authenticate before anything on every task endpoint by @evsinev in #101

Full Changelog: 1.5.0...1.6.0

1.5.0

Choose a tag to compare

@github-actions github-actions released this 29 Sep 10:24
3cccbc6

Run containers as a dedicated user, safely: securityContext for dc-docker.yml, a hardened agent file system, strict config parsing, and every open dependency CVE closed.

Upgrade notes (read before rolling out)

  • Unknown or duplicate keys in dc-docker.yml are now errors (#75). A typo such as readOnly: or readOnlyRootFilesysem: used to be ignored silently, which turned a protection off. After upgrading, run DOCKER_CHECK for every service: each stray key is listed with its path and the closest known name.
  • name in dc-docker.yml must be a docker container name ([a-zA-Z0-9][a-zA-Z0-9_.-]*). Any other name already failed docker run --name=.
  • TEMP_DIR must be on a path only root can change. A sticky /tmp is fine. The agent refuses an unsafe TEMP_DIR before extracting anything.
  • New agent parameter CONTAINER_RUNTIME (podman by default, or docker). It only matters for securityContext.passwdEntry. Set docker on hosts with real Docker before using it; the agent refuses a mismatch with docker --version.
  • save-artifact: the x-dc-agent-file-extension header must be a plain extension (e.g. tar.gz). A missing or blank header still falls back to the configured extension.

Containers as a user (securityContext)

  • runAsUser / runAsGroup → --user U:G
  • readOnlyRootFilesystem → --read-only
  • allowPrivilegeEscalation: false → --security-opt no-new-privileges
  • directoryOrCreate volumes get owner (runAs or {user, group}) and mode. These are applied behind a write-path preflight that checks every path the root agent writes, for CHECK and PUSH alike (#74).
  • passwdEntry gives a UID that is not in the image a passwd entry, the way imagekit's runtime.passwd_entry does, so Java gets a real user.name and a writable user.home. Podman receives its own --passwd-entry; with docker the agent mounts a small generated container-passwd read-only over /etc/passwd. The host's /etc/passwd is never used.
  • tmpfs → --tmpfs <path>[:<options>], e.g. a writable /tmp under --read-only.

Security fixes

  • Local privilege escalation via a predictable work dir: tasks were extracted into /tmp/docker-<name>-<ms>, created non-exclusively, so a local user could pre-create it and swap dc-docker.yml or steer root's writes. The work dir is now created exclusively with mode 0700 and a random suffix, under a TEMP_DIR whose whole path is checked first.
  • Deleting trees no longer follows symbolic links (#76). On Linux the deletion goes through SecureDirectoryStream, relative to open directory descriptors.
  • save-artifact: the api-key is now checked before anything touches the disk; before, a request without a key made the root agent create arbitrary directories. The stored file must stay inside dir, and the header extension is validated.
  • Operator: HTML auto-escaping in the FreeMarker templates (reflected/stored XSS).
  • dc-docker.yml name can no longer place the service directory outside SERVICES_DEFINITION_DIR.

Dependencies

  • FreeMarker 2.3.35 (CVE-2026-84939), Jetty 12.1.13 (CVE-2026-19203, CVE-2026-19204), logback 1.6.4 (CVE-2026-19880), plus slf4j, jgit, guava, handlebars and snakeyaml-engine updates.
  • Docs site on pnpm 10 with minimumReleaseAge; all website dependency alerts closed.
  • Build: Maven 3.9.16 through a script-only wrapper with a checksum; surefire pinned. CI: CodeQL Action v4.

Full docs: https://evsinev.github.io/dc-agent/

1.4.0

Choose a tag to compare

@github-actions github-actions released this 31 Jul 01:31

Honest GC / host diagnostics: makes the operator's GC report tell the truth and adds the signals needed to tell an idle JVM, a swapping host, and a real leak apart from noise.

Fixes (were misleading)

  • Live set now counts heap pools only — no longer inflated by Metaspace / CodeHeap.
  • Uptime and process CPU time are separate, clearly labelled figures (CPU time was mislabelled as uptime).
  • MemAvailable added; MemFree is de-emphasised (it excludes page cache and is not a pressure signal on DB hosts).

New signals

  • Linux /proc: MemAvailable, swap-in/out rate, and how much of the JVM is swapped out.
  • Collectors in use, allocation rate, interval between collections, a full-GC / old-gen series, max pause over the last hour, sub-millisecond pause count.

Interpretation

  • GcDoctor gains Idle / host-swapping / heap-in-swap / low-MemAvailable rules; an idle-but-healthy JVM now reports OK with the idle note leading.
  • The "copy for LLM" payload is rewritten into labelled sections with explicit units and caveats.
  • Byte sizes now use binary units (KiB/MiB/GiB).

UI

  • Bundles dc-agent-react v1.9.0, which renders all the new fields in the agent view.

Wire-compatible: new fields are optional; older agents on the fleet report n/a, never a fabricated 0.

1.3.1

Choose a tag to compare

@github-actions github-actions released this 22 Jul 23:00

Full Changelog: 1.2.0...1.3.1

1.2.0

Choose a tag to compare

@github-actions github-actions released this 18 Jul 22:20

What's Changed

  • Potential fix for code scanning alert no. 641: Log Injection by @evsinev in #26
  • Potential fix for code scanning alert no. 65: Local information disclosure in a temporary directory by @evsinev in #27
  • Potential fix for code scanning alert no. 64: Local information disclosure in a temporary directory by @evsinev in #28
  • feat(gc): per-pause GC diagnostics, verdict, and copy-for-LLM payload by @evsinev in #29

New Contributors

Full Changelog: 1.1.0...1.2.0

1.1.0

Choose a tag to compare

@github-actions github-actions released this 14 Jul 20:17

1.1.0

✨ Features

  • System & JVM metrics — new per-agent metrics endpoint (SystemInfoRequest/SystemInfoResponse, TSystemInfo), with a CpuLoadSampler and SystemInfoCollector on the agent and operator-side aggregation (AgentMetricsMapper, TAgentMetrics).
  • Enriched command DTOs — operator command details now carry service state resolved server-side (TCommandDetail, TCommandInfo).

🔒 Security & Dependencies

  • Replaced OkHttp with java.net.http.HttpClient to drop the transitive Kotlin CVE-2026-53914.
  • Switched to the maintained net.i2p.crypto:eddsa fork to fix CVE-2020-36843 (also enables reading ed25519 SSH keys from the fat jar).
  • Fixed the OWASP suppression schema so CVE suppressions apply correctly in CI.
  • Suppressed the by-design SSRF alert in FetchUrlServlet via a CodeQL inline comment.
  • Bumped com.github.jknack:handlebars 4.5.0 → 4.5.2 and org.assertj:assertj-core 3.27.6 → 3.27.7.

🔧 CI

  • Cache the NVD database weekly so the OWASP scan stops re-downloading it on every run.

🧩 Compatibility

  • Operator UI pin bumped to dc-agent-react v1.5.0.

Full Changelog: 1.0.13...1.1.0

1.0.13

Choose a tag to compare

@github-actions github-actions released this 14 Jul 04:22

1.0.13 — Security & CI hardening

Dependency CVE bumps, new supply-chain scanning workflows, and the operator UI
pinned to dc-agent-react v1.3.0.

Changes

  • Bumped dependencies for CVEs: Jetty 12.0.20 → 12.0.34, JGit
    7.1.0 → 7.7.0, Handlebars; added OWASP suppressions.
  • Added CI security scanning: CodeQL, OWASP Dependency-Check, SpotBugs, and
    Dependabot; plus OpenSSF Scorecard and SonarCloud workflows.
  • Fixed Trivy / OWASP / SpotBugs / Scorecard workflow failures.
  • Pinned the operator UI to dc-agent-react v1.3.0 (frontend.version).

Full Changelog: 1.0.12...1.0.13

1.0.12

Choose a tag to compare

@github-actions github-actions released this 14 Jul 01:27

Remove BouncyCastle

  • Dropped unused pgpainless-sop PGP code (PgpSignatureCheck, PgpTest) and removed the BouncyCastle dependency from all modules.
  • Pinned Apache MINA sshd to JDK-native crypto (org.apache.sshd.security.provider.BC.enabled=false) as a defensive guard against SSH key exchange breaking if BC is ever reintroduced.
  • Improved git pull error message to surface the actual cause instead of the stale GIT_SSH hint.

Full Changelog: 1.0.11...1.0.12

1.0.11

Choose a tag to compare

@github-actions github-actions released this 13 Jul 02:54

dc-agent 1.0.11

This release delivers the backend side of Commands management for the dc-operator console — list, details, and fully-typed create/edit over the control plane with write-only API keys — plus periodic agent-config backups on the operator, a mirror mode for zip-dirs, a local verification harness, and a git pull fix for non-SSH remotes. The bundled operator UI is updated to dc-agent-react v1.2.0.

Commands over the control plane

  • New command/list endpoint on the agent's control plane, with a matching operator API. Commands are discovered by scanning CONFIG_DIR for *.json / *.yml config files (the docker command dc-docker.* is excluded); the name comes from the file name, and the type is taken from an explicit type field or inferred from the present fields.
  • Command details now return all configuration parameters, with API keys masked to stable ids.
  • Create and edit are fully typed: one request DTO per command type (WAR, JAR, NODE, SAVE_ARTIFACT, ZIP_ARCHIVE, ZIP_DIRS, FETCH_URL, DOCKER), serialized from the finished config model — no hand-built JSON. API keys are write-only: the client sends masked ids to keep plus new secrets to add, and the agent merges them against the on-disk map. A server-side CommandValidator mirrors the UI validation rules.
  • Together these power the new Commands screens in the React console.

Agent config backups

  • The operator now periodically backs up every agent's config files over the control plane, archiving them locally — one subdirectory per agent, each backup a <agent>-yyyy-MM-dd-HH-mm-ss.zip. Unchanged snapshots are skipped via a stable content hash, only the last N archives are kept, and each run is logged to .last.txt.
  • New operator startup parameters: DC_AGENT_BACKUP_INTERVAL (ISO-8601 duration, default PT1H), DC_AGENT_BACKUP_DIR, and DC_AGENT_BACKUP_KEEP (default 5).

zip-dirs: mirror mode

  • New delete option (default false). With delete: true, the target directory exactly mirrors the uploaded archive: after extraction, every file under the resolved target dir that is not in the ZIP is removed, along with directories left empty. This is destructive by design — it applies to the whole resolved target dir — and is documented with an explicit caution in the docs.

Fixes

  • git pull no longer throws ClassCastException on non-SSH remotes. The publickey session factory is now applied only to SshTransport, so file:// and http(s) config-repo remotes work as expected.

Operator

  • New /info endpoint reporting the operator's build version from the jar manifest (Implementation-Version, set by the operator-shaded profile; falls back to dev when running unshaded). This powers the new version footer in the console.
  • Bundled UI pin bumped to dc-agent-react v1.2.0 (SHA-256 verified): Commands screens, renamed navigation (Applications / Agents / Services / Commands), reworked error handling, and the frontend/backend version footer.

Developer experience

  • New verify/ harness for a repeatable local run of the whole system — dc-agent, dc-operator, and the React UI wired together with test config — to manually verify the UI before cutting a release. Two frontend modes: separate (Rsbuild dev server on :3000 proxying the API) and bundled (UI baked into the operator jar, mirroring a real release).
  • New frontend-local Maven profile builds the operator with a locally built dc-agent-react dist instead of downloading the pinned GitHub release: ./mvnw -pl dc-agent-operator -am -Pfrontend-local,operator-shaded package.

Documentation

  • Documented the /app-status endpoint: guarded by its own bearer token (APP_STATUS_TOKEN, separate from the control-plane token), response fields (appInstanceName, appVersion, uptimeMs, …), and the match-all/host/{h}/instance/{i}/port/{p} variant that returns 412 on mismatch — handy as a load-balancer or deploy sanity check.
  • Documented the operator's agent/list endpoint that powers the dc-agent list screen, and updated the architecture page with the per-host token channels.

Full changelog: 1.0.10...1.0.11