Skip to content

Fix RS256 JWT node key (1024->2048) and add EL8/EL9 httpd ProtectSystem drop-in - #24

Merged
tahiralmas merged 3 commits into
ictcorefrom
fix/jwt-node-key-2048-and-el9-httpd
Aug 31, 2026
Merged

tahiralmas merged 3 commits into
ictcorefrom
fix/jwt-node-key-2048-and-el9-httpd

Conversation

@tahiralmas

Copy link
Copy Markdown
Member

Two Community-Edition issues, both reproduced before fixing.

1. RS256 JWT node key too short — Fixes #125, Fixes #123

bin/keygen generated the internal node key with openssl genrsa 1024. A 1024-bit RSA key cannot sign an RS256 JWT under a modern/FIPS OpenSSL — firebase/php-jwt throws DomainException: Provided key is too short, so core/User.php::generate_token() fails and POST /api/authenticate returns 401 and logs the client straight back out. (The self-contained image added auto-keygen on boot, which is why #123 looked fixed — but it still generated a 1024-bit key, so #125 resurfaced.)

Reproduced in ictinnovations/ictfax:latest (PHP 8.3.33 / OpenSSL 1.1.1k FIPS):

1024-bit RS256 JWT::encode: FAIL -> DomainException: Provided key is too short
2048-bit RS256 JWT::encode: OK (422 chars)
  • generate the key at 2048-bit
  • regenerate an existing sub-2048-bit / unreadable ib_node instead of skipping, so installs already carrying a weak key get fixed on next run

Stuck-box workaround: openssl genrsa -out ib_node 2048, fix ictcore:ictcore ownership, restart.

2. EL8/EL9 httpd ProtectSystem blocks data/log writes — Refs #124

On RHEL/Rocky/Alma the packaged httpd.service runs with ProtectSystem, mounting /usr read-only in Apache's namespace, so ICTCore can't write /usr/ictcore/data or /usr/ictcore/log and document upload/conversion fails despite correct permissions.

Adds a ready-to-install systemd drop-in (etc/http/ictcore-httpd-rw.conf) with ReadWritePaths for both dirs + docs/deploy-el-httpd.md. The RPM packaging still needs to install the drop-in on EL hosts, so #124 stays open.

tahiralmas and others added 3 commits August 31, 2026 11:28
bin/keygen created ib_node with `openssl genrsa 1024`. A 1024-bit RSA key
cannot sign an RS256 JWT under a modern/FIPS OpenSSL: firebase/php-jwt
rejects it with DomainException "Provided key is too short", so
core/User.php generate_token() fails and every /api/authenticate call
returns 401 and immediately logs the client back out.

Reproduced in the ictfax image (PHP 8.3 / OpenSSL 1.1.1k FIPS): a 1024-bit
RS256 JWT::encode fails with that exact message, 2048-bit succeeds.

- generate the key at 2048-bit
- regenerate an existing sub-2048-bit (or unreadable) ib_node instead of
  skipping, so installs that were upgraded with a weak key get fixed on the
  next run rather than keeping the broken key

Fixes #125
Fixes #123

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UCrkrgRyikinE4VZWVNLyD
On RHEL/Rocky/Alma 8 and 9 the packaged httpd.service runs with ProtectSystem
enabled, mounting /usr read-only in Apache's namespace. ICTCore writes to
/usr/ictcore/data and /usr/ictcore/log, so document upload/conversion fails
even with correct Unix permissions.

Add a ready-to-install systemd drop-in (etc/http/ictcore-httpd-rw.conf) that
grants ReadWritePaths for those two directories, plus docs/deploy-el-httpd.md
explaining the cause and the install/verify steps. The RPM packaging still needs
to install this drop-in on EL hosts.

Refs #124

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UCrkrgRyikinE4VZWVNLyD
etc/ssh/ib_node was a real 1024-bit RSA private key committed to the repo, so
every install that did not regenerate shared one publicly known key, and its
JWTs could be forged. bin/keygen already creates the keypair per install (now
2048-bit), so the tracked key is unnecessary and a security risk.

- git rm the tracked ib_node (and ib_node.pub if present)
- gitignore the generated keypair, cert and known_hosts so they cannot be
  re-committed by accident

Treat the previously committed key as compromised. Existing installs get a
fresh 2048-bit key on the next keygen run (regen guard added earlier in this PR).

Refs #125

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UCrkrgRyikinE4VZWVNLyD
@tahiralmas
tahiralmas merged commit d827420 into ictcore Aug 31, 2026
1 check passed
@tahiralmas
tahiralmas deleted the fix/jwt-node-key-2048-and-el9-httpd branch August 31, 2026 06:39
bushra927 pushed a commit to bushra927/ictfax that referenced this pull request Sep 9, 2026
Two changes so a plain `docker build` produces a functioning REST API:

- Bump ICTCORE_REF to the merged ictcore commit that generates the internal
  node key at 2048-bit and no longer ships a shared private key
  (ictinnovations/ictcore#24). The old pin generated a 1024-bit key that could
  not sign an RS256 JWT, so authenticate failed outright.

- The php83 patch upgrades firebase/php-jwt to v7 and had already fixed decode
  in core/lib/Token.php, but missed core/User.php, the bearer-auth path. With
  the old JWT::decode() signature every authenticated request threw
  "Argument ictinnovations#3 ($headers) could not be passed by reference" and 500'd. Add the
  same `new Key(...)` fix for User.php.

Verified end to end on a rebuilt image: authenticate, document upload
(PDF -> TIFF), sendfax program, contact, transmission and status all work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UCrkrgRyikinE4VZWVNLyD
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant