Skip to content

Secure keystores with filesystem acl, use pkcs12 - #422

Open
mgaffigan wants to merge 2 commits into
OpenIntegrationEngine:mainfrom
mgaffigan:fix/keystore-privs
Open

Secure keystores with filesystem acl, use pkcs12#422
mgaffigan wants to merge 2 commits into
OpenIntegrationEngine:mainfrom
mgaffigan:fix/keystore-privs

Conversation

@mgaffigan

Copy link
Copy Markdown
Contributor

Related to #307

Sets default access controls for key material created on first boot to only be accessible to the owner (600-equivalent):

Posix:

# ls -al server/setup/appdata/keystore.jks
-rw-------@ 1 user  staff  3973 Aug 26 17:23 server/setup/appdata/keystore.jks

Windows:

PS C:\drop\setup> icacls .\appdata\keystore.jks
.\appdata\keystore.jks COMPUTER\mirthuser:(F)

Successfully processed 1 files; Failed processing 0 files
PS C:\drop\setup>

Removes the 81uWxplDtB password in favor of a password-less PKCS12 (pfx) file instead of the deprecated jks format for new installs. Upgrades retain their prior password.

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

Test Results

677 tests  +2   676 ✅ +1   1m 44s ⏱️ +23s
115 suites +1     1 💤 +1 
115 files   +1     0 ❌ ±0 

Results for commit 63b3489. ± Comparison against base commit e8afb74.

♻️ This comment has been updated with latest results.

@jonbartels jonbartels left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is making my brain itch. I feel like there could be some cyclic problem, maybe with containers? where the keystore is generated and a PW set, then the keystore is retained as a file (like if appdata is a persistent volume) but the generated keystore pass isn't retained because conf isnt in a persistent volume and the env var isn't set.

Instinctively - I'd document this, but theres a massive curse of knowledge problem because I am intimate with my keystores but a more casual, first-time user won't know how to process the big error

# no longer a password to pin here. Keystores created by earlier versions are JCEKS and were pinned
# to 'changeme', so keep those settings when one is already present in appdata.
KEYSTORE_FILE="$APP_DIR/appdata/keystore.jks"
if [ -f "$KEYSTORE_FILE" ] && [ "$(head -c 4 "$KEYSTORE_FILE" | od -An -tx1 | tr -d '[:space:]')" = "cececece" ]; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explan what this is checking and how it knows its a jceks?

@mgaffigan mgaffigan Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a dirty hack suggested to me by AI. It's checking if the first 4 bytes of the file are cececece - which is the magic signature for a JCEKS keystore (the legacy format that would require the "changeme" default password).

TL;DR: backcompat hack.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed it in favor of a filename check.

import java.util.EnumSet;
import java.util.Set;

public class FilePermissionUtil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non blocking comment - I checked if file utils does this for us. It does not. I dont live introducing a util class but its appropriate here

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe touch to create the file? But then you still gotta mess with perms. https://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/FileUtils.html#touch(java.io.File)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see an alternative here for any major portion.

keystore.storepass = 81uWxplDtB
keystore.keypass = 81uWxplDtB
keystore.type = JCEKS
keystore.storepass =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per Tonys comments from chat - add a comment in the props file explaining how this is generated if its blank.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did on line 28. With pkcs12, there is no need to have a password, so the blank is not a sentinel value - there just is no password.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry. I was off: this is a test resource, not a published asset.

.setPermissions(EnumSet.allOf(AclEntryPermission.class))
.build();
// @formatter:on
aclView.setAcl(Collections.singletonList(entry));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the local admin group should also be added with full control?

root always has access in linux, but windows does not automatically give permission to local admins.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree in principle, but it is a pain. Added as a separate commit in case we change our minds.

Comment thread server/conf/mirth.properties Outdated
Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
@mgaffigan
mgaffigan requested a review from tonygermano August 27, 2026 18:10
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.

3 participants