Java (PKCS#12)
The Java adapter delivers certificate chains and matching private keys to JVM applications as password-protected PKCS#12 keystores on Linux or Windows. It is an activating adapter: the node stages an immutable keystore generation, atomically replaces the keystore your application reads, runs one pinned reload executable with fixed arguments and commits only when the application serves the exact new leaf certificate. Any failure restores and reloads the previous keystore.
The adapter does not guess vendor-specific restart mechanisms and never invokes a shell.
Security model
- The console stores only the
local/adapter reference, profile, target node and revision. The keystore password and private keys never leave the node. keytooland the reload executable are absolute paths whose lowercase SHA-256 digests are checked before every run.- The password is read from a private local file and passed to
keytoolwith-storepass:file— never as an argument or environment variable. - Reload arguments are a fixed array. The only substitution is the literal
{keystore}, replaced with the absolute active-keystore path. - Keystores use PBES2/PBKDF2-HMAC-SHA-256, AES-256-CBC and HMAC-SHA-256 with 100,000 iterations.
- Certificate/key match, validity, chain order, PKCS#12 decoding, the configured alias and exact file digests are checked independently.
Requirements
- A Linux or Windows Mesh Node on the application host.
- A supported JDK 21 runtime (for
keytool). - A local reload executable for your application (a fixed binary — not a mutable PowerShell, batch or shell script) that makes the JVM pick up the new keystore. An empty argument list is fine if it already knows the path.
- The application's current certificate chain (leaf first, then the ordered issuing chain) and matching key.
- An HTTPS health URL on the application.
Container and Helm deployments do not include a JDK. Keep this adapter disabled there unless you supply and pin a qualified image and reload executable.
Prepare the host
Resolve keytool to its final regular file (never pin a symlink), pin both executables, and create a 32–256 character printable, non-space ASCII password stored alone in a file (an optional single trailing newline is allowed). The active keystore's parent directory must already exist and must not be a symbolic link.
- Linux
- Windows
sudo install -d -o edgepki -g edgepki -m 0700 /var/lib/sectigo-edge/java/generations
sudo install -d -m 0750 /opt/example/conf
openssl rand -base64 48 | tr -d '\n' | sudo tee /etc/sectigo-edge/java-keystore.pass >/dev/null
sudo chown edgepki:edgepki /etc/sectigo-edge/java-keystore.pass
sudo chmod 0600 /etc/sectigo-edge/java-keystore.pass
KEYTOOL="$(readlink -f "$(command -v keytool)")"
sha256sum "$KEYTOOL" /opt/example/bin/reload-tls
5d1c8e2f7a9b0c3d4e6f8a1b2c3d5e7f9a0b1c2d4e6f8a9b0c1d3e5f7a8b9c0d /usr/lib/jvm/java-21-openjdk-amd64/bin/keytool
a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9 /opt/example/bin/reload-tls
The Mesh Node rejects password and bootstrap-key files that are readable by group or others. The installed systemd unit only allows writes to /var/lib/edgepki, so add a drop-in (sudo systemctl edit edgepki-node) with ReadWritePaths= listing the managed directory and the active keystore's directory.
Get-FileHash 'C:\Program Files\Java\jdk-21\bin\keytool.exe' -Algorithm SHA256
Algorithm Hash Path
--------- ---- ----
SHA256 5D1C8E2F7A9B0C3D4E6F8A1B2C3D5E7F9A0B1C2D4E6F8A9B0C1D3E5F7A8B9C0D C:\Program Files\Java\jdk-21\bin\keytool.exe
Get-FileHash 'C:\Program Files\Example\bin\reload-tls.exe' -Algorithm SHA256
icacls 'C:\ProgramData\Sectigo\Edge\java-keystore.pass' /inheritance:r /grant:r 'SYSTEM:R' 'BUILTIN\Administrators:F'
Get-FileHash prints upper-case hex; convert it to lowercase for the configuration. Restrict the password and bootstrap-key files to the Mesh Node service identity with an explicit NTFS ACL — SYSTEM when the service runs as LocalSystem (the default), or your gMSA if you installed with -ServiceAccount.
Never put the password in node JSON, a service argument, an environment variable, a reload script or the console.
Node configuration
{
"java_keystore_enabled": true,
"java_keystore_adapter_reference": "local/java-production",
"java_keystore_profile_id": "prod-service",
"java_keystore_keytool_path": "/usr/lib/jvm/java-21-openjdk-amd64/bin/keytool",
"java_keystore_keytool_sha256": "<64 lowercase hex characters>",
"java_keystore_alias": "server",
"java_keystore_password_file": "/etc/sectigo-edge/java-keystore.pass",
"java_keystore_active_file": "/opt/example/conf/identity.p12",
"java_keystore_managed_directory": "/var/lib/sectigo-edge/java",
"java_keystore_bootstrap_certificate_file": "/etc/sectigo-edge/bootstrap/java-chain.pem",
"java_keystore_bootstrap_private_key_file": "/etc/sectigo-edge/bootstrap/java-key.pem",
"java_keystore_reload_binary_path": "/opt/example/bin/reload-tls",
"java_keystore_reload_binary_sha256": "<64 lowercase hex characters>",
"java_keystore_reload_arguments": ["--keystore", "{keystore}"],
"java_keystore_reload_timeout_seconds": 15,
"java_keystore_rollback_window_seconds": 3600
}
On Windows use the same keys with escaped absolute paths, for example "C:\\ProgramData\\Sectigo\\Edge\\java-keystore.pass".
| Key | Limit |
|---|---|
| Every path | Absolute |
java_keystore_alias | 1–128 characters: letters, digits, ., -, _ |
*_sha256 | 64 lowercase hex characters |
java_keystore_reload_arguments | Up to 32 values, each at most 512 characters, no NUL or line breaks |
java_keystore_reload_timeout_seconds | 2–60 |
java_keystore_rollback_window_seconds | 60–86400 |
Point your application at java_keystore_active_file with keystore type PKCS12 and the configured alias.
Configure in the console
- Open ConsoleIntegrations and select Configure on Java PKCS#12 keystore.
- Select Enable this integration and the exact enrolled Windows or Linux node.
- Enter the profile (for example
prod-service) and the adapter reference (for examplelocal/java-production) exactly as inconfig.json. - Select Save desired state and wait for Healthy.
Disabling or unassigning the integration sends an authority-withdrawal tombstone and blocks new Java activation.
Policy requirements
- Allow
java_keystorein allowed deployment modes only on profiles permitted to activate this adapter. - Java deployment requires dual-slot rotation: configure renewal lead time, overlap, health grace,
manualorautomatic_after_healthpromotion, and a rollback window. - An adapter reference, profile, node assignment or revision mismatch denies the transaction even if issuance already succeeded.
How rotation and rollback work
- The node durably stores the signed intent, CSR, generated key, SANs, policy digest, adapter reference and revision.
- The issued chain and key become a new immutable PKCS#12 generation, verified with the pinned
keytool. - The node records a pending promotion, atomically replaces the active keystore and runs the pinned reload executable.
- It connects to the exact HTTPS health URL and requires the live leaf to match the staged leaf.
- Success commits the generation and keeps the previous one for the rollback window; any failure restores and reloads the exact previous keystore.
- After a crash, the node replays the intent and repairs a pending promotion before reporting a result.
Rotation requests use POST /v1/managed/rotate with "integrationKind": "java_keystore" (see NGINX → How rotation works); manual promotion uses Verify & promote in ConsoleRotation.
Verify
keytool -list -storetype PKCS12 -keystore /opt/example/conf/identity.p12 \
-storepass:file /etc/sectigo-edge/java-keystore.pass
Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 1 entry
server, Oct 1, 2026, PrivateKeyEntry,
Certificate fingerprint (SHA-256): 9A:3C:...:E1
Example output. Also confirm the card is Healthy and that sectigo-edge status reports the adapter healthy. Qualify every operating system, JDK and application combination before production: promotion, rollback, failed health, a changed binary and a restart during promotion.
Troubleshooting
| Code or message | Meaning | What to do |
|---|---|---|
java_keystore_not_configured | The node has no Java settings | Add the keys and restart |
adapter_reference_invalid / profile_not_mapped | Console and node disagree | Make them identical |
java_keystore_active_invalid | The active keystore's digest does not match the committed generation (changed outside the adapter) | Repair the local cause; the node never adopts an uncommitted keystore |
java_keystore_content_invalid | The active keystore failed validation with the pinned keytool (PKCS#12 decoding, alias, key match) | Check the password file, the alias and the keystore contents |
java_keystore_recovery_pending | An interrupted promotion is unresolved | Fix the cause (reload executable, permissions, health URL) |
java_keystore_state_invalid | The manifest cannot be read or verified | Investigate local changes |
java_keystore_integration_unavailable / java_keystore_integration_binding_mismatch | Rotation refused | Fix desired state, then retry |
| Node will not start | Unsafe or relative path, malformed digest, invalid alias or out-of-range timeout | Run edgepki-node -validate-config for the exact reason |
| Adapter fails to initialize | Password file or bootstrap key readable by group/others, password outside 32–256 printable characters, or bootstrap pair mismatch | Fix the file permissions and contents, then restart |