Private
Public Access
1
0
Commit Graph

236 Commits

Author SHA1 Message Date
f55cfbc7a1 chore: bump version to 1.1.11 (#67)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Failing after 1m22s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
v1.1.11
2026-06-09 16:06:40 -05:00
0222b1677d fix: run migrations as patch_manager, remove broken reassign_ownership (#66)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 10s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Failing after 1m32s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
Root cause: postinst ran sqlx migrate as postgres (superuser), creating ALL
database objects owned by postgres. When pm-web connects as patch_manager, it
cannot ALTER TABLE during migrations because it does not own them. The
reassign_ownership() function never worked because REASSIGN OWNED BY postgres
TO patch_manager fails for superuser-owned objects.

Fix: Create the database owned by patch_manager (already done) and run all
migrations as patch_manager via PGPASSWORD auth. When all objects are owned by
patch_manager from the start, pm-web can ALTER them during upgrades.

Changes:
- Add psql_run_as_pm() helper that authenticates as patch_manager via PGPASSWORD
- Replace all psql_run_db calls in apply_migrations() with psql_run_as_pm
- Remove reassign_ownership() function entirely (it never worked)
- Remove reassign_ownership call from main()
- Add ALTER DEFAULT PRIVILEGES FOR ROLE postgres in setup_database() as safety
  net for any future migration that might run as postgres
- Upgrade GRANT USAGE/CREATE to GRANT ALL PRIVILEGES on schema public
- Keep pgcrypto extension creation as postgres (requires superuser)
- Renumber sections after removing reassign_ownership

Proven on live LPM system: service active, port 443 listening, all tables
owned by patch_manager.
2026-06-09 15:56:36 -05:00
dda2fd3b0e chore: bump version to 1.1.10 (#65)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Failing after 1m52s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped
v1.1.10
2026-06-09 14:49:54 -05:00
3b3e129663 fix: reassign DB object ownership to patch_manager after migrations (#64)
The postinst script runs migrations as the postgres superuser, which
means all created tables, enum types, and sequences are owned by
postgres. When pm-web connects as patch_manager and tries to ALTER
tables during upgrades, it fails with 'must be owner of table groups'.

Add reassign_ownership() function that runs after apply_migrations()
and before systemctl start. This function:
- REASSIGN OWNED BY postgres TO patch_manager (tables, types, sequences)
- ALTER SCHEMA public OWNER TO patch_manager
- GRANT ALL PRIVILEGES on database, schema, tables, sequences, functions
- ALTER DEFAULT PRIVILEGES for future objects in public schema

Renumbered sections 6-10 to 6-12 to accommodate the new function.
2026-06-09 14:11:20 -05:00
8acff754e8 chore: bump version to 1.1.9 (#63)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Failing after 1m22s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
v1.1.9
2026-06-09 13:15:05 -05:00
4cac290502 fix: enable services, fix config parsing, make migrations idempotent (#62) 2026-06-09 13:04:11 -05:00
ec41091721 ci: update actions for Node.js 24 compatibility (#61)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 7s
CI Pipeline / Clippy Lints (push) Successful in 50s
CI Pipeline / Rust Unit Tests (push) Failing after 1m28s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped
2026-06-09 12:49:37 -05:00
26f87ebc20 chore: bump version to 1.1.8 (#60)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Failing after 1m25s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
v1.1.8
2026-06-09 12:02:50 -05:00
a1a8eab41a fix(postinst): surgical upgrade/fresh-install handling (#59)
- write_config(): Replace CHANGEME placeholder on upgrade instead of
  skipping entirely; preserve existing real passwords unchanged
- setup_database(): When DB user already exists, recover password from
  existing config and sync to PostgreSQL, or generate a fresh password;
  fixes crash-loop when config password diverges from PostgreSQL
- generate_jwt_keys(): Regenerate missing verify.pem from existing
  signing.pem instead of silently skipping
- Password extraction uses @localhost anchor to correctly handle
  passwords containing @ characters
2026-06-09 11:47:22 -05:00
b2ea6b1f7a chore: bump version to 1.1.7 (#58)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 2s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Failing after 1m29s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped
v1.1.7
2026-06-09 09:27:34 -05:00
592ff6a7ee fix(postinst): thorough audit - fix argon2 salt and verify all password generation logic (#57) 2026-06-09 09:10:31 -05:00
0c0f952f7f chore: bump version to 1.1.6 (#56)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 53s
CI Pipeline / Rust Unit Tests (push) Failing after 1m27s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
v1.1.6
2026-06-09 08:21:20 -05:00
2a18276884 fix(postinst): correct argon2 -m parameter from raw KiB to log2 value (#55)
* chore: bump version to 1.1.5

* fix(postinst): correct argon2 -m parameter from raw KiB to log2 value

* trigger CI
2026-06-09 08:10:00 -05:00
2bdbc8af5a fix(ci): remove arm64 from Docker platforms and add timeout (#53)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 6s
CI Pipeline / Clippy Lints (push) Successful in 53s
CI Pipeline / Rust Unit Tests (push) Failing after 1m58s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped
2026-06-08 20:15:13 -05:00
87bd5d2162 fix: remove duplicate version display from sidebar toolbar (#52)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 2s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Failing after 1m53s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
v1.1.4
2026-06-08 17:54:25 -05:00
836d409e3b feat: add version display to sidebar and bump to v1.1.4 (#51)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 7s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Failing after 1m40s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped
2026-06-08 17:44:20 -05:00
e17b740415 fix(docker): complete Dockerfile audit - migrations, deps, openssl (#49)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 5s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Failing after 1m46s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
Three issues fixed in the multi-stage Docker build:

1. CRITICAL: Add COPY migrations/ to rust-builder stage
   - sqlx::migrate!(../../migrations) is a compile-time proc macro
   - Without migrations/ present, cargo build fails with 'no such file or directory'
   - Previously migrations/ was only copied in runtime stage (too late)

2. Copy individual crate Cargo.toml files for dependency caching
   - The dummy-build caching step only copied workspace Cargo.toml/Cargo.lock
   - Without crate-level manifests, cargo couldn't resolve the workspace
   - This meant the cache layer was ineffective (rebuilt everything on code changes)

3. Add openssl package to runtime stage
   - entrypoint.sh uses openssl rand, openssl genpkey, openssl pkey
   - Only libssl3t64 (shared library) was installed, not the CLI tool
   - Runtime would fail on first-run key generation

All stages verified: Ubuntu 24.04   Rust via rustup (1.85+) 
2026-06-07 22:59:32 -05:00
0d151d36b9 chore: bump version to 1.1.2 (#48)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Failing after 1m22s
CI Pipeline / Security Audit (push) Successful in 6s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped
v1.1.2
2026-06-07 22:08:55 -05:00
4fbcf3d35a fix(docker): use Ubuntu 24.04 throughout all Dockerfile stages (#47)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 6s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Failing after 1m21s
CI Pipeline / Security Audit (push) Successful in 6s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 16s
CI Pipeline / Build .deb & Release (push) Has been skipped
- Stage 1 (Rust): Replace rust:1.85-bookworm with ubuntu:24.04 + rustup stable
- Stage 2 (Frontend): Replace node:20-bookworm-slim with ubuntu:24.04 + NodeSource Node.js 20
- Stage 3 (Runtime): Already ubuntu:24.04 with libssl3t64 (verified correct)
- docker-compose: Change postgres:16-bookworm to postgres:16 (standard image)

This aligns Docker builds with the project's target OS (Ubuntu 24.04) and
matches the CI environment which runs on ubuntu-latest (24.04).
2026-06-07 21:19:07 -05:00
6d4ec8c9ac chore: bump version to 1.1.1 (#45)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Failing after 1m58s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
v1.1.1
2026-06-07 20:14:45 -05:00
bf91b3c6d2 fix(docker): use ubuntu:24.04 runtime instead of debian:bookworm-slim (#44)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 6s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Failing after 1m54s
CI Pipeline / Security Audit (push) Successful in 7s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 17s
CI Pipeline / Build .deb & Release (push) Has been skipped
* fix(docker): add PostgreSQL APT repo for postgresql-client-16

Debian Bookworm default repos only ship PostgreSQL 15. The Docker
runtime stage needs postgresql-client-16 for the entrypoint script,
so add the official PGDG APT repository.

- Add PGDG GPG key and sources.list entry for bookworm-pgdg
- Install ca-certificates and curl first (needed for repo setup)
- Purge gnupg2 after use to keep image lean
- Verify argon2 package name is correct for Bookworm (it is)

* fix(docker): use ubuntu:24.04 runtime instead of debian:bookworm-slim

The project targets Ubuntu 24.04, not Debian Bookworm. Ubuntu 24.04
includes PostgreSQL 16 in default repos, eliminating the need for the
PGDG APT repo workaround. Also fixes libssl3 → libssl3t64 package name
for the time64 transition in Ubuntu 24.04.
2026-06-07 18:55:45 -05:00
2d3be0955b chore: bump version to 1.1.0 (#43)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Failing after 1m25s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped
v1.1.0
2026-06-07 17:01:01 -05:00
a5343760e1 feat: Automated install, Docker deployment, and CI Docker job (#42)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 4s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Failing after 1m20s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
- debian/control: add Pre-Depends and Depends on postgresql-16, argon2
- debian/postinst: idempotent automation for PostgreSQL setup,
  DB/user creation, migration tracking, admin password generation,
  config write, and service enable/start
- Dockerfile: multi-stage build (Rust + frontend + slim runtime)
- docker/entrypoint.sh: first-run DB wait, migrations, admin password
- docker-compose.yml: split db/app architecture with healthcheck
- .env.example: template for DB_PASSWORD and TAG
- .dockerignore: exclude build artifacts from Docker context
- .github/workflows/ci.yml: add Docker job for multi-arch
  (amd64/arm64) GHCR push on tag releases with layer caching
- .gitignore: add .env entry
2026-06-07 16:20:08 -05:00
209480dd43 Release v1.0.0 (#41)
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Failing after 1m26s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
* chore: bump version to 1.0.0

* fix: BusyBox-compatible timing and set -e safety in shell scripts
v1.0.0
2026-06-07 13:27:21 -05:00
5fa1fef6c8 fix: remove committed private keys and add gitleaks CI
Some checks failed
CI Pipeline / Rust Format Check (push) Successful in 5s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Failing after 1m31s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped
- Remove all cert files from git tracking (git rm --cached)
  - crates/pm-agent-client/certs/client.key (private key)
  - crates/pm-agent-client/certs/client.crt (public cert)
  - crates/pm-agent-client/certs/ca.crt (public cert)
- Add .gitignore patterns for *.key, *.key.pem, certs/*.crt, certs/*.pem
- Update pm-agent-client doc examples to use std::fs::read() instead of include_bytes!
- Add gitleaks secret scanning job to CI workflow
- Update security-review.md with critical finding for Issue #12
- Add README.md to crates/pm-agent-client/certs/ explaining runtime cert generation

Private keys were dev/test only - no production key rotation needed.
Git history purge with filter-repo will follow after PR merge.

Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
2026-06-06 13:20:52 -05:00
e6dd1b8489 test: add authz gate integration tests (closes #15)
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 4s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Successful in 1m56s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
* test: add authz gate integration tests (closes #15)

* fix: separate authz gate 403 tests from DB-dependent tests

---------

Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
2026-06-06 11:18:11 -05:00
dd6961265d chore: bump version to 0.2.4
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Successful in 1m10s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 19s
CI Pipeline / Build .deb & Release (push) Successful in 3m41s
CI Pipeline / Security Audit (push) Successful in 5s
Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
v0.2.4
2026-06-06 00:04:08 -05:00
40ba483d35 fix: add ca_chain and crl_pem to EnrollmentStatusResponse
Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
2026-06-05 23:57:23 -05:00
192ebbd47f chore: bump version to 0.2.3
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 3s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Successful in 1m10s
CI Pipeline / Security Audit (push) Successful in 9s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Successful in 3m44s
Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
v0.2.3
2026-06-05 23:05:41 -05:00
050439ee14 fix: add missing CRL columns to Host SQL queries and fix comma syntax
Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
2026-06-05 22:52:59 -05:00
0b12ded1cf chore: bump version to 0.2.2
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 5s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Successful in 1m9s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 16s
CI Pipeline / Build .deb & Release (push) Successful in 3m41s
Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
v0.2.2
2026-06-05 21:23:55 -05:00
0296cf9c51 fix(auth): update SQL queries to use totp_secret_encrypted instead of dropped totp_secret column
Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
2026-06-05 21:08:00 -05:00
604b31b937 chore: bump version to 0.2.1
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 4s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Successful in 1m11s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 17s
CI Pipeline / Build .deb & Release (push) Successful in 3m43s
Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
v0.2.1
2026-06-05 19:41:24 -05:00
89e572faf8 fix(ca): correct not_after column name to expires_at in CRL query
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 7s
CI Pipeline / Clippy Lints (push) Successful in 50s
CI Pipeline / Rust Unit Tests (push) Successful in 1m9s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
The generate_crl() SQL query referenced a non-existent column
"not_after" instead of the actual column "expires_at" in the
certificates table. This caused a 500 error when requesting the CRL
endpoint because PostgreSQL could not find the column.

Fixes: CRL endpoint returns 500 Internal Server Error

Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
2026-06-05 19:27:32 -05:00
78f5304214 chore: bump version to 0.2.0
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 4s
CI Pipeline / Clippy Lints (push) Successful in 55s
CI Pipeline / Rust Unit Tests (push) Successful in 1m12s
CI Pipeline / Security Audit (push) Successful in 6s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 18s
CI Pipeline / Build .deb & Release (push) Has been skipped
Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
2026-06-05 17:41:02 -05:00
899fd4a79a test: add CRL integration and unit tests (PR 6 of 6)
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 6s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Successful in 1m10s
CI Pipeline / Security Audit (push) Successful in 6s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 16s
CI Pipeline / Build .deb & Release (push) Has been skipped
Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
2026-06-05 17:26:20 -05:00
5ab3532833 feat: add CRL health aggregation logic and audit events (PR 5 of 6)
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 5s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Successful in 1m11s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 16s
CI Pipeline / Build .deb & Release (push) Has been skipped
* feat: add CRL health aggregation logic and audit events (PR 5 of 6)

* style: fix cargo fmt in health_poller.rs

---------

Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
2026-06-05 16:42:39 -05:00
ea8337b944 feat: add CRL health status schema and UI (PR 3 of 6)
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 5s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Successful in 1m8s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
* feat: add CRL health status schema and UI (PR 3 of 6)

* fix(lint): strict equality for crl_age_seconds

---------

Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
2026-06-05 16:17:17 -05:00
5aec9e629c feat(pki): add CRL generation, distribution endpoint, and enrollment bundle extension (#26)
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 6s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Successful in 1m10s
CI Pipeline / Security Audit (push) Successful in 1m26s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
* feat(pki): add CRL generation, distribution endpoint, and enrollment bundle extension

Implements manager-side CRL infrastructure for issue #7:
- Add CertAuthority::generate_crl() using rcgen 0.13
- Add GET /api/v1/pki/crl.pem public endpoint
- Extend PkiBundle with ca_chain and crl_pem fields
- Update enrollment route to include CRL in bundle
- Mount pki route as public endpoint
- Add proptest dev-dependency

* style: fix cargo fmt in enrollment.rs

---------

Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
2026-06-05 12:54:14 -05:00
80ffb6b62f feat(security): replace hardcoded admin password with in-app bootstrap (#25)
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 5s
CI Pipeline / Clippy Lints (push) Successful in 50s
CI Pipeline / Rust Unit Tests (push) Successful in 1m8s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped
* feat(security): replace hardcoded admin password with in-app bootstrap (issue #8)

Replace the publicly-known Argon2id hash in 002_seed_admin.sql with a
clearly-invalid placeholder that cannot validate any password (fail-closed).

On first startup, pm-web detects the placeholder and generates a random
24-character alphanumeric password, hashes it with Argon2id, and UPDATEs
the admin row. The plaintext password is printed once to stderr (visible
in systemd journal).

This eliminates the need for a separate hash_password binary, shell
script SQL injection risk, and password leakage in shell variables.

Closes #8

* fix(security): rustfmt compliance for bootstrap function

* fix(security): add trailing commas to match arms per rustfmt
2026-06-04 13:28:44 -05:00
fda70ecf9e feat(jobs): add host_names to job list API and UI (#24)
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 5s
CI Pipeline / Clippy Lints (push) Successful in 51s
CI Pipeline / Rust Unit Tests (push) Successful in 1m7s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
* feat(jobs): add host_names to job list API and UI

Closes #23

* fix(jobs): add mut for host_names merge loop
2026-06-04 12:49:53 -05:00
b9fb3427e0 fix(security): encrypt app secrets at rest with AES-256-GCM (#6)
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 8s
CI Pipeline / Clippy Lints (push) Successful in 50s
CI Pipeline / Rust Unit Tests (push) Successful in 1m8s
CI Pipeline / Security Audit (push) Successful in 5s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
Encrypt three sensitive secrets that were stored in plaintext: OIDC client_secret, SMTP smtp_password, TOTP totp_secret. AES-256-GCM via pm-core::crypto helper. New per-install key at /etc/patch-manager/keys/secret-encryption.key, separate from health-check.key for blast-radius isolation. MASKED placeholder behavior in API responses is preserved.

23 files changed, +1248 / -28. Closes #6.
2026-06-03 15:08:25 -05:00
e0a9037be3 Merge pull request #20 from Draco-Lunaris/Draco-Lunaris-patch-1
Update ARCHITECTURE.md
2026-06-03 14:50:28 -05:00
21d734c662 Update ARCHITECTURE.md 2026-06-03 14:44:02 -05:00
5488b4fd95 Merge pull request #18 from Draco-Lunaris/license/apache-2.0
Update license to Apache 2.0 for full open source
2026-06-03 11:32:22 -05:00
0208d27805 Update license to Apache 2.0 for full open source 2026-06-03 11:20:21 -05:00
88b190ac8d fix(security): restrict auth-config mutations to Admin role (#5)
Restrict manager-wide authentication configuration mutations (OIDC, SMTP, IP allowlist) to Admin role. Operators now receive 403 forbidden_role.

- New admin_required helper in settings.rs
- 4 gate changes: update_settings, discover_oidc, test_oidc, update_ip_whitelist
- 5 new AuditAction variants + migration 019
- SPA friendly error message on 403
- 3 admin_required unit tests pass (43/43)
- Full integration tests deferred to issue #15

Closes #5
2026-06-03 09:16:41 -05:00
f58d7a6f17 fix(security): stop embedding JWT tokens in SSO callback redirect URL (#4) (#14)
Replaces URL-embedded JWT tokens with a single-use, 60-second handoff code that the SPA exchanges via server-to-server POST. The URL now contains only `?handoff=<code>` — no tokens are placed in the browser history, proxy access logs, or Referer header.

Backend: new SsoHandoff store (DashMap, 60s TTL, atomic DashMap::remove for single-use), POST /api/v1/auth/sso/handoff endpoint, 7 new tests.

Frontend: SsoCallbackPage rewritten to use useSearchParams + POST exchange, with history.replaceState to clear the handoff code from the address bar. Switched from window.location.search to useSearchParams() for test compatibility. New Vitest infrastructure (vitest, @testing-library/react, jsdom) and 6 new tests.

CI fix in ccba9e3: cargo fmt --all and added searchParams to useEffect dep array to satisfy CI's Rust Format and Frontend Lint checks.

Refs: closes #4
2026-06-03 06:28:08 -05:00
3bdae4bcc5 fix(security): harden IP allowlist against XFF bypass and spoofing (#3)
Hardens the IP allowlist in require_auth against the two bypasses filed in #3.

1. Bypass via missing X-Forwarded-For (no IP to check, allowlist skipped).
2. Spoofing via attacker-controlled X-Forwarded-For (header trusted unconditionally).

Resolves both by deriving the client IP from the socket peer (ConnectInfo<SocketAddr>) and only honoring X-Forwarded-For when the immediate peer is in a new security.trusted_proxies allowlist (default empty = strict). Fails closed with 403 forbidden_ip when a non-empty allowlist is configured and the client IP cannot be determined. Empty ip_whitelist continues to mean allow all (preserved for dev installs).

27 pm-auth tests pass (12 new resolver + 8 new middleware + 7 existing). Spec: tasks/ip-allowlist-spec.md.
2026-06-02 18:06:43 -05:00
8873b2c70c fix(security): harden enrollment PKI bundle retrieval (#12)
- Add single-retrieval semantics: approved PKI bundles are atomically
  removed from the in-memory cache on first retrieval via DashMap::remove(),
  preventing concurrent requests from obtaining the private key
- Add TTL expiry: ApprovedEntry wraps PkiBundle with approved_at and ttl
  fields; bundles expire after ENROLLMENT_BUNDLE_TTL_SECS (600s / 10 min)
- Replace brute-force clear() purge with TTL-based retain() in background
  task, running every 60s instead of every 600s
- Audit tracing calls: confirm no raw polling token is logged; add security
  comment documenting this policy
- Document CSR-based enrollment as future enhancement in both enrollment.rs
  and SECURITY.md, explaining why server-generated keys are used currently
2026-06-02 15:16:44 -05:00