62 Commits

Author SHA1 Message Date
Dave Kempe f58695c7eb Fix deb config: move misplaced keys out of [recording] section (#25)
The default config.toml shipped in the .deb had db_path, static_path,
and other top-level keys placed after the [recording] header, causing
TOML to scope them under [recording] where serde silently ignored them.
The top-level db_path defaulted to ./rustguac.db which the rustguac
user cannot create in the root-owned /opt/rustguac directory.

Fixes: move all top-level keys above section headers in the template.
Adds a postinst migration that detects and repairs broken configs on
upgrade (backs up config first).

Closes #25

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.4.1 v0.4.2-rc2 v0.4.2-rc4 v0.4.2-rc3
2026-02-14 19:36:12 +11:00
Dave Kempe 066a063304 Improve RDP display sizing: match browser dimensions on connect and resize
- Send actual browser window dimensions at session creation (addressbook,
  sessions) instead of defaulting to 1920x1080
- Send initial sendSize() on WebSocket connect so guacd can resize the
  remote display via Display Update channel
- Debounce window resize handler (250ms) to avoid overwhelming RDP server

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.4.0
2026-02-14 10:55:40 +11:00
Dave Kempe f8744603f8 Update dependencies: russh 0.57, toml 1.0, clap 4.5.58, libc 0.2.182
- russh 0.54 → 0.57: Marvin attack mitigation (RSA), server-side ping,
  ML-KEM post-quantum key exchange, extension algo kex fix
- toml 0.9 → 1.0: stable release
- clap 4.5.57 → 4.5.58: patch update
- libc 0.2.180 → 0.2.182: patch update
- rand stays at 0.9: rand 0.10 requires stable rand_core 0.10.0 which
  conflicts with russh 0.57's rand_core 0.10.0-rc-3 pin

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 10:47:10 +11:00
Dave Kempe 3cb8111591 Add RDP RemoteApp/RAIL, recording rotation, per-entry recording overrides
RemoteApp/RAIL (closes #19):
- Pass remote-app, remote-app-dir, remote-app-args through to guacd
- Address book UI: collapsible RemoteApp section for RDP entries

Recording rotation:
- New [recording] config section (backwards-compatible with recording_path)
- Automatic disk-space management: max_disk_percent, max_recordings thresholds
- Background rotation task with configurable interval
- Sidecar .meta JSON files track address book entry per recording

Per-entry recording overrides:
- Address book entries can enable/disable recording and set max recordings
- Per-entry rotation runs on session disconnect
- UI: collapsible Recording Settings section for all connection types

Bump version to 0.4.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 10:39:25 +11:00
Dave Kempe 54c1d5be17 Security hardening: open redirect, cookie flags, constant-time auth, fuzz targets
- Fix open redirect via protocol-relative URLs (//evil.com) in OIDC next parameter
- Add Secure flag to all cookie-clearing Set-Cookie headers
- Add single-quote escaping to html_escape() (defence-in-depth)
- Cross-check OIDC state cookie against state query parameter in callback
- Switch API key and user token validation to constant-time hash comparison (subtle)
- Add 3 new fuzz targets: api_input, vault_response, websocket_message
- Bump version to 0.3.3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.3.3
2026-02-12 08:42:33 +11:00
Dave Kempe 7f454ecda0 Fix custom link port parameter: omit when unset instead of sending empty string
An empty &port= causes "invalid digit found in string" parse error.
Use {% if %} conditional to only include &port= when remote_port is set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.3.2
2026-02-11 19:26:23 +11:00
Dave Kempe 6caf1ef138 Bump version to 0.3.2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:15:37 +11:00
Dave Kempe 3cf21933ea Add credential prompting for /api/connect deep-links, fix NetBox webhook docs
When an address book entry has prompt_credentials: true or no stored
credentials, /api/connect now returns an inline credential form instead
of failing or connecting without auth. The form POSTs to the existing
connect endpoint and redirects to the client page.

Fix NetBox webhook body template docs: use "type" not "session_type"
(matches Vault storage format), replace regex_replace/cut filters with
standard Jinja2 equivalents (lower, split) since NetBox's Jinja2
environment doesn't include Ansible or Django template filters.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:14:53 +11:00
Dave Kempe 5331f25176 Add NetBox integration: GET /api/connect endpoint, OIDC deep-links
- New GET /api/connect quick-connect endpoint for external integrations
  - Ad-hoc mode (poweruser+): hostname/protocol/port params, redirects to client
  - Address book mode (operator+): scope/folder/entry params, credentials from Vault
  - Unauthenticated users redirected through SSO login and back automatically
- OIDC deep-link support: login handler accepts ?next= param, stores as cookie,
  callback redirects there instead of /addressbook.html after authentication
- New docs/netbox.md integration guide: Custom Fields, Custom Links with
  console_enabled/console_mode gating, webhook-driven address book sync
- Updated docs/api.md with GET /api/connect endpoint documentation
- Updated screenshots/screenshots.md with descriptions for all screenshots
- Bump version to 0.3.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.3.1
2026-02-11 11:52:16 +11:00
Dave Kempe a2d79629c5 Bump russh 0.49 → 0.54 (CVE-2025-54804), drop russh-keys and async-trait
russh 0.54.1 fixes CVE-2025-54804 (integer overflow panic in channel
window adjust). Adapts tunnel.rs to the new API: AuthResult enum
instead of bool, native async trait instead of #[async_trait], and
keys module re-exported from russh directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.3.0
2026-02-11 08:48:15 +11:00
Dave Kempe 76c93bc502 Add multi-hop SSH tunnels, VNC sessions, and web session tunnel support
Multi-hop SSH tunnel chains allow routing any session type through
multiple bastion hosts. VNC is now a first-class session type.
Web browser sessions can tunnel through jump hosts with automatic
URL rewriting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 08:22:34 +11:00
Dave Kempe c094a91575 Add files via upload 2026-02-11 07:25:29 +11:00
Dave Kempe 45b1522432 Create screenshots.md 2026-02-11 07:25:08 +11:00
Dave Kempe e595ff437a Bump version to 0.2.2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.2.2
2026-02-10 10:39:49 +11:00
Dave Kempe d07d79c4f2 Add Kerberos NLA support for RDP and credential prompting
- Patch guacd with Kerberos NLA support (002-kerberos-nla.patch),
  based on upstream GUACAMOLE-2057 PR #581, adapted for FreeRDP 3.x
- Add per-entry auth_pkg, kdc_url, and prompt_credentials settings
  to the address book (configurable in admin UI)
- Frontend credential prompt for entries without stored credentials
  or with prompt_credentials enabled (never stored, session-only)
- Wire auth-pkg, kdc-url, kerberos-cache params through rustguac
  to the guacd RDP handshake
- Comprehensive Kerberos NLA docs: krb5.conf setup, KDC discovery
  options, FQDN requirements, troubleshooting guide

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 10:39:18 +11:00
Dave Kempe 02f93fe67a Redesign login page: prominent SSO button, collapsible API key form
SSO button is now the primary action on the login page — larger,
bolder, and displayed first. API key login is hidden behind a
chevron toggle for admin use. Falls back to showing the API key
form directly when OIDC is not configured.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.2.1
2026-02-08 09:10:43 +11:00
Dave Kempe 8ec9a65279 Bump version to 0.2.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.2.0
2026-02-07 16:14:56 +11:00
Dave Kempe 2f0a41d52b Fix db.rs formatting (cargo fmt)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 16:04:16 +11:00
Dave Kempe 997b5f099c Fix auth.rs formatting (cargo fmt)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 15:52:28 +11:00
Dave Kempe 1b86b20fe6 Fix formatting (cargo fmt)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 15:11:39 +11:00
Dave Kempe a94b743d6c Add user API tokens with role-based access and audit logging
User API tokens allow OIDC users to authenticate via bearer token for
automation and scripting. Powerusers and admins can create their own
tokens; admins can create tokens for operators. Tokens use SHA-256
hashing, optional max_role caps, optional expiry, and full audit
logging of create/revoke operations with client IPs.

- DB schema: user_api_tokens and token_audit_log tables
- Auth middleware: validates user tokens as fallback after admin keys
- API: 7 new endpoints (self-service + admin token management)
- UI: tokens.html (self-service) + admin.html token/audit sections
- Nav: Tokens link added to all pages (visible for operator+)
- Docs: API reference, security model, roles/access control updated
- Background cleanup: expired tokens + 90-day audit log retention

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 15:02:54 +11:00
Dave Kempe 065367451b Add Default derive for InstructionParser (clippy fix)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.1.3
2026-02-07 14:21:40 +11:00
Dave Kempe a2bbce73ee Add guacd parser fuzz harness and document fuzzing findings
libFuzzer+ASan+UBSan harness for guac_parser_append() — the C state
machine that parses all Guacamole wire-format input in guacd. 3.2M
iterations found no memory corruption; one non-exploitable signed
integer overflow (UBSan) in the length prefix accumulator noted in
FINDINGS.md.

Also adds FINDINGS.md for the Rust protocol parser fuzzer documenting
the UTF-8 boundary panic fix from v0.1.3.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 14:17:42 +11:00
Dave Kempe 1922bd9987 Add fuzz testing infrastructure and fix UTF-8 boundary panic
Add cargo-fuzz targets for the Guacamole protocol parser:
- protocol_parse: single instruction parsing
- protocol_stream: streaming parser with chunked input

Fix panic in Instruction::parse when a length prefix splits a multi-byte
UTF-8 character (found by fuzzer within seconds). Now returns
ParseError::Truncated instead of panicking on invalid char boundary.

Run with: cargo +nightly fuzz run protocol_parse
          cargo +nightly fuzz run protocol_stream

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 13:39:16 +11:00
Dave Kempe eab04ba2bd Fix clippy type_complexity for OIDC pending flows
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 12:06:47 +11:00
Dave Kempe 4e4279dc5f Bump version to 0.1.3 and fix formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 11:40:06 +11:00
Dave Kempe 2187cfc1e4 Security hardening: 5 fixes from audit
- Vault TLS: replace hardcoded danger_accept_invalid_certs(true) with
  configurable tls_skip_verify option (default: false)
- Share tokens: use constant-time SHA-256 hash comparison to prevent
  timing side-channel attacks
- OIDC pending states: add 10-minute TTL, evict stale entries on each
  login to prevent unbounded HashMap growth
- Recording path traversal: add canonical path validation as defense-
  in-depth alongside existing string checks
- Frontend XSS: escape all user-controlled data (filenames, paths) in
  innerHTML via escapeHtml/escapeAttr in client.html and recordings.html

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 11:34:54 +11:00
Dave Kempe 32c60469e4 Merge pull request #5 from sol1/dependabot/github_actions/actions/checkout-6
ci: bump actions/checkout from 4 to 6
2026-02-07 11:25:24 +11:00
Dave Kempe bf49438ae7 Merge pull request #6 from sol1/dependabot/github_actions/actions/upload-artifact-6
ci: bump actions/upload-artifact from 4 to 6
2026-02-07 11:25:12 +11:00
Dave Kempe 577a28dbcb Merge pull request #7 from sol1/dependabot/github_actions/actions/download-artifact-7
ci: bump actions/download-artifact from 4 to 7
2026-02-07 11:25:00 +11:00
Dave Kempe 177dbda605 Merge pull request #14 from sol1/dependabot/cargo/rcgen-0.14.7
deps: bump rcgen from 0.13.2 to 0.14.7
2026-02-07 11:24:00 +11:00
Dave Kempe d61dfc2072 Merge pull request #15 from sol1/dependabot/cargo/ipnetwork-0.21.1
deps: bump ipnetwork from 0.20.0 to 0.21.1
2026-02-07 11:23:48 +11:00
Dave Kempe 284b4eef66 Merge pull request #10 from sol1/dependabot/cargo/clap-4.5.57
deps: bump clap from 4.5.56 to 4.5.57
2026-02-07 11:23:42 +11:00
Dave Kempe 8fe8d8afa2 Merge pull request #4 from sol1/dependabot/github_actions/actions/cache-5
ci: bump actions/cache from 4 to 5
2026-02-07 11:23:09 +11:00
Dave Kempe 6771e18640 Merge main into dependabot/cargo/rcgen-0.14.7
Resolve conflict: keep axum-server 0.8 (from main) and rcgen 0.14 (from this branch).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 11:15:15 +11:00
dependabot[bot] 1569fe234e ci: bump actions/checkout from 4 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-07 00:13:39 +00:00
dependabot[bot] 868c5ef2c9 ci: bump actions/upload-artifact from 4 to 6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-07 00:13:38 +00:00
dependabot[bot] c40fca09a7 ci: bump actions/cache from 4 to 5
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-07 00:13:37 +00:00
dependabot[bot] 468bb8d342 ci: bump actions/download-artifact from 4 to 7
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-07 00:13:36 +00:00
dependabot[bot] ccb3d168d3 deps: bump clap from 4.5.56 to 4.5.57
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.56 to 4.5.57.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.56...clap_complete-v4.5.57)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.57
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-07 00:13:26 +00:00
dependabot[bot] 9000f33596 deps: bump ipnetwork from 0.20.0 to 0.21.1
Bumps [ipnetwork](https://github.com/achanda/ipnetwork) from 0.20.0 to 0.21.1.
- [Release notes](https://github.com/achanda/ipnetwork/releases)
- [Changelog](https://github.com/achanda/ipnetwork/blob/master/CHANGELOG.md)
- [Commits](https://github.com/achanda/ipnetwork/compare/v0.20.0...v0.21.1)

---
updated-dependencies:
- dependency-name: ipnetwork
  dependency-version: 0.21.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-07 00:13:22 +00:00
Dave Kempe 556ec5a5e0 Merge pull request #17 from sol1/dependabot/cargo/rusqlite-0.38.0
deps: bump rusqlite from 0.32.1 to 0.38.0
2026-02-07 11:12:35 +11:00
Dave Kempe d47c2f2e1f Merge pull request #16 from sol1/dependabot/cargo/pulldown-cmark-0.13.0
deps: bump pulldown-cmark from 0.12.2 to 0.13.0
2026-02-07 11:12:29 +11:00
Dave Kempe 34ae15db72 Merge pull request #13 from sol1/dependabot/cargo/axum-server-0.8.0
deps: bump axum-server from 0.7.3 to 0.8.0
2026-02-07 11:12:24 +11:00
Dave Kempe f6b6948af2 Merge pull request #11 from sol1/dependabot/cargo/tower-cookies-0.11.0
deps: bump tower-cookies from 0.10.0 to 0.11.0
2026-02-07 11:12:17 +11:00
Dave Kempe e616afba08 Merge pull request #8 from sol1/dependabot/cargo/toml-0.9.11spec-1.1.0
deps: bump toml from 0.8.23 to 0.9.11+spec-1.1.0
2026-02-07 11:11:59 +11:00
Dave Kempe 2874396941 Fix rcgen 0.14 API: key_pair renamed to signing_key
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 11:06:46 +11:00
dependabot[bot] b2b843481c deps: bump pulldown-cmark from 0.12.2 to 0.13.0
Bumps [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) from 0.12.2 to 0.13.0.
- [Release notes](https://github.com/raphlinus/pulldown-cmark/releases)
- [Commits](https://github.com/raphlinus/pulldown-cmark/compare/v0.12.2...v0.13.0)

---
updated-dependencies:
- dependency-name: pulldown-cmark
  dependency-version: 0.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-06 23:42:02 +00:00
dependabot[bot] e8b0491d8e deps: bump rcgen from 0.13.2 to 0.14.7
Bumps [rcgen](https://github.com/rustls/rcgen) from 0.13.2 to 0.14.7.
- [Release notes](https://github.com/rustls/rcgen/releases)
- [Commits](https://github.com/rustls/rcgen/compare/v0.13.2...v0.14.7)

---
updated-dependencies:
- dependency-name: rcgen
  dependency-version: 0.14.7
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-06 23:42:00 +00:00
dependabot[bot] b2b77ac7de deps: bump rusqlite from 0.32.1 to 0.38.0
Bumps [rusqlite](https://github.com/rusqlite/rusqlite) from 0.32.1 to 0.38.0.
- [Release notes](https://github.com/rusqlite/rusqlite/releases)
- [Changelog](https://github.com/rusqlite/rusqlite/blob/master/Changelog.md)
- [Commits](https://github.com/rusqlite/rusqlite/compare/v0.32.1...v0.38.0)

---
updated-dependencies:
- dependency-name: rusqlite
  dependency-version: 0.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-06 23:41:59 +00:00