DFLOW-152 - JVM client setup (macOS)#9
Closed
akushsky wants to merge 1 commit into
Closed
Conversation
akushsky
added a commit
that referenced
this pull request
Jun 9, 2026
C4: rewrite the test-runner header docstring. The previous "Cleans up between cases so each invariant runs against a fresh state" was wrong; cleanup runs only at the start of cases 1, 4, 10, 11 (the positive / fresh-state cases). The new docstring lists which cases reuse the prior install on purpose. C5: `iter_all_users` comment in the installer no longer claims to "mirror" install_certs_macos.sh:256-312. It's a STRICTER filter (adds .localized skip + dscl stale-account rejection); the cited line range was wrong too (only :256-261 is filter logic). I5/M3: install_as_test_user / validate_as_test_user now capture combined stdout/stderr to a tempfile and dump on UNEXPECTED exit. Green-run logs stay tight; negative-case surprises produce a useful diagnostic instead of a silent BUG line. Exit-capture trap: the obvious `if cmd; then …; fi` reports $?=0 of the if-statement itself, not the command. `if ! cmd; then` doesn't help either (the `!` operator returns 0). Reliable capture pattern is pre-init `rc=0` then `cmd || rc=$?`. Verified by side-test of `false || rc=$?` (rc=1) and `true || rc=$?` (rc=0). Without this fix test #2 (subject mismatch) was producing a false BUG report — the validator did exit 1 but the wrapper reported success. I8: new test #11 — `--all-users` mode. Runs the installer without SUDO_USER, asserts iter_all_users iterates at least the test user, the "Installed for N user(s)" summary appears, and the resulting plist is owned by the target user (catches a chown silent-fail regression). I10: new test #10 — plist content. plutil -lint + plutil -extract on ProgramArguments.3 confirms the JTO arg points at the expected JKS path. This is the only invariant that covers the write_launch_agent_plist code path on CI runners with no GUI session (where the launchctl getenv check SKIPs). I11: test #9 (launchctl getenv) now retries 20×100ms (was 0×), mirroring the installer's bootstrap_launch_agent retry. Could flake on GUI-enabled macos-latest runners without this. I13: new test #12 — validate_pem warn paths. Asserts the 30-day-expiry warn and the multi-cert-bundle warn fire on appropriate inputs without failing the install. Without coverage a future regression flipping warn to fail (or vice versa) ships silently. Smoke matrix: 12/12 green locally on dev Mac. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
akushsky
added a commit
that referenced
this pull request
Jun 9, 2026
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5c6acfb to
0741ec4
Compare
15 tasks
0e236f5 to
3403ac6
Compare
akushsky
added a commit
that referenced
this pull request
Jun 10, 2026
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0741ec4 to
b51ed3e
Compare
akushsky
added a commit
that referenced
this pull request
Jun 10, 2026
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
b51ed3e to
8276bcb
Compare
akushsky
added a commit
that referenced
this pull request
Jun 10, 2026
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8276bcb to
a7b7274
Compare
akushsky
added a commit
that referenced
this pull request
Jun 10, 2026
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
a7b7274 to
b45d81e
Compare
akushsky
added a commit
that referenced
this pull request
Jun 10, 2026
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
b45d81e to
e597dcf
Compare
3403ac6 to
65f4ff1
Compare
akushsky
added a commit
that referenced
this pull request
Jun 10, 2026
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
e597dcf to
69e37aa
Compare
65f4ff1 to
8703a4e
Compare
akushsky
added a commit
that referenced
this pull request
Jun 10, 2026
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
69e37aa to
57b27a7
Compare
akushsky
added a commit
that referenced
this pull request
Jun 10, 2026
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
57b27a7 to
caf69f9
Compare
akushsky
added a commit
that referenced
this pull request
Jun 10, 2026
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
caf69f9 to
5982ef4
Compare
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5982ef4 to
8c0a901
Compare
RaniLinkov
pushed a commit
that referenced
this pull request
Jun 24, 2026
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
RaniLinkov
added a commit
that referenced
this pull request
Jun 25, 2026
* DFLOW-150 - JVM client setup (Linux) Adds a Linux client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_debian_ubuntu.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Two lab-verified paths, auto-detected: Path A — update-ca-trust RHEL/Fedora/CentOS/Amazon-Linux when a JDK whose lib/security/cacerts symlinks to /etc/pki/ca-trust/extracted/java/cacerts is on PATH (Red Hat OpenJDK). Drops the CA into /etc/pki/ca-trust/source/anchors/ and runs `update-ca-trust extract`. No env var. Path B — JKS + JAVA_TOOL_OPTIONS Everything else (Debian/Ubuntu, Amazon Corretto, Eclipse Temurin, SDKMAN, manual .tar.gz installs). Builds a JKS at /etc/ssl/package-route-jvm/truststore.jks containing only the customer CA; writes JAVA_TOOL_OPTIONS to /etc/environment plus the developer user's .bashrc/.zshrc. JDK-version-agnostic by construction. Detection rule (detect_mode): 1. No update-ca-trust on PATH -> Path B 2. /etc/pki/ca-trust/extracted/java/cacerts absent -> Path B 3. No `java` on PATH -> Path A (assumes Red Hat OpenJDK will follow via dnf; emits a loud end-of-run warning) 4. `java`'s cacerts symlinks to RHEL store -> Path A; else Path B --mode java-tool-options / --mode update-ca-trust overrides detection. Files: install_certs_jvm_linux.sh Installer (mirrors install_certs_debian_ubuntu.sh patterns). validate_certs_jvm_linux.sh Companion validator; subject-substring match. _jvm_linux_paths.sh Shared constants sourced by both scripts so they cannot drift. testing/test_install_certs_jvm_linux.sh Docker matrix runner (4 distros x 10 invariants). .github/workflows/ci.yml New test-linux-jvm job runs the matrix runner. README.md New "Linux (JVM)" section with the full design + caveats. Hardening fixes folded in from two rounds of pr-review-toolkit review: Critical: - --cert-name actually propagates to the Path B JKS alias and the validator accepts --cert-name so Path A's anchor file can be located when a non-default basename was used. - validate_pem rejects expired certs, leaf certs (CA:FALSE), warns on bundles (keytool -importcert -noprompt only imports the first cert). - install_via_update_ca_trust and validate_keystore_contains_subject capture keytool output explicitly; the previous pipefail+SIGPIPE pattern (... | grep -qi "$subject") silently turned real keytool failures into "subject not found" misdiagnoses AND real positive matches into false negatives. - validator detect_mode "both paths present" branch now routes the whole warn block to stderr; previously the warn lines leaked into the command-substitution capture and broke the case dispatch, yielding a silent exit-0 with NO checks run. Important: - validator FAILs (not OKs) when keytool is missing on the JKS path. - --all-users root check moved into parse_args (fast-fail exit 1). - update_user_shell_rc tracks RC_UPDATED and the final summary prints a loud WARNING when the per-user rc step was skipped. - --mode jto -> --mode java-tool-options for self-documenting CLI. - mktemp is -p $(dirname target) so `mv` is rename(2) (atomic), and an empty-awk-output check refuses to clobber /etc/environment. - --cert-name regex-validated to [A-Za-z0-9._-]+ to prevent path traversal in the anchor file path. - chown failure on the user's rc file captured + warned. - get_target_user verifies the picked username exists in /etc/passwd. Smoke matrix (testing/test_install_certs_jvm_linux.sh): Ubuntu 22.04, Debian 12, RHEL UBI 9, Amazon Linux 2023, in parallel. Per-container invariants: positive install+validate, subject mismatch -> exit 1, idempotent re-install (no duplicate lines/aliases), custom --cert-name round-trips, path-traversal rejected, malformed PEM rejected, expired CA rejected (skipped when openssl can't produce a verifiably-expired test cert), leaf cert (CA:FALSE) rejected, forced --mode update-ca-trust (Path A) on hosts with update-ca-trust, dual-artifact validator regression test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * DFLOW-152 - JVM client setup (macOS) Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_macos.sh if you need those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux). Single path on macOS — there is no update-ca-trust fork because KeychainStore is broken per JDK-8321045: 1. Build a per-user JKS truststore at ~/Library/Application Support/JFrog/package-route-jvm/truststore.jks 2. Write a per-user LaunchAgent at ~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plist calling `launchctl setenv JAVA_TOOL_OPTIONS=…` at RunAtLoad 3. Bootstrap the agent into `gui/<uid>` so Dock-launched IDEs (IntelliJ, JetBrains Toolbox, `open -a …`) inherit the env var The ~/.zshrc / ~/.bash_profile shortcut is deliberately NOT touched — verified in the research wiki to silently fail for GUI-launched IDE builds. Files: install_certs_jvm_macos.sh Installer (~540 lines). validate_certs_jvm_macos.sh Companion validator. _jvm_macos_paths.sh Shared constants sourced by both. testing/test_install_certs_jvm_macos.sh 12-invariant smoke runner. .github/workflows/ci.yml New test-macos-jvm job. README.md New "macOS (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 21 findings: 5 Critical + 13 Important + 3 Minor): Critical: - validate_pem leaf-cert (CA:FALSE) check now works on stock macOS LibreSSL. The previous `openssl x509 -ext` flag is OpenSSL 3.x-only; LibreSSL silently failed → leaf certs accepted as trust anchors. New path parses `-noout -text` output (portable across both). - chown failure capture at both call sites (JKS dir + plist). Under --all-users a silent chown would leave root-owned plists in a user's ~/Library/LaunchAgents/, which launchd silently refuses to load — exactly the phantom-success the project bans. - --cert-name semantics clarified in constants file + --help. The previous "LaunchAgent label suffix" claim was wishful thinking; the flag is alias-cosmetic only. - Test runner docstring rewritten (cleanup runs only on positive cases) and the iter_all_users "mirrors install_certs_macos.sh" claim corrected (it's a stricter filter, not a mirror). Important: - get_single_target_user filter+order matches install_certs_macos.sh (SUDO_USER → /dev/console → logname; rejects loginwindow pseudo-user). - get_user_home eval-on-username fallback replaced with dscacheutil. - bootstrap_launch_agent retry bumped 5×100ms → 20×100ms to survive EDR exec latency; warn text no longer suggests a logout dance. - Validator --help documents the absence of --cert-name. - Validator final summary qualifies "All checks passed" with a WARN count so a green exit doesn't over-promise when launchctl getenv was skipped (no GUI session). - install_as_test_user / validate_as_test_user capture combined stdout/stderr to a tempfile; dump on UNEXPECTED exit only. - Smoke matrix gained 3 new invariants: --all-users iteration (#11), plist content validation via plutil -extract (#10), validate_pem warn-paths for 30-day-expiry and multi-cert bundle (#12). - Test #9 (launchctl getenv) now retries 20×100ms to mirror the installer. - CI workflow uses explicit `sudo env JAVA_HOME=… PATH=…` instead of --preserve-env, surviving future actions/setup-java renames. PATH includes /usr/sbin so chown is resolvable under sudo. Minor: - README requirements list names plutil/launchctl/dscl/stat. - README "five launch contexts" claim scoped to what the test actually verifies. - JKS_PASSWORD "not a secret" comment scoped to trustedCertEntry-only stores (PrivateKeyEntry would change the calculus). Smoke matrix: 12/12 green locally on dev Mac, 12/12 green on CI (Test (macOS JVM) job, macos-latest runner with Temurin 21). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * DFLOW-151 - JVM client setup (Windows) Adds a Windows client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through package-reroute validates correctly. JVM trust only -- does not configure Node/npm/Python and does not touch Docker credentials. Pair with install_certs_windows.ps1 for those flows. Based on the published research wiki (DFLOW-136): https://jfrog-int.atlassian.net/wiki/spaces/RTFACT/pages/2440101931 Sibling to DFLOW-150 (Linux) and DFLOW-152 (macOS). Single path on Windows -- there is no Windows-ROOT trustStoreType option because the Gradle Daemon caches a stale store (gradle/gradle#6584): 1. Build a per-user JKS truststore at %LOCALAPPDATA%\JFrog\package-route-jvm\truststore.jks 2. Set JAVA_TOOL_OPTIONS at User scope via [Environment]::SetEnvironmentVariable(..., 'User') which writes HKCU\Environment AND broadcasts WM_SETTINGCHANGE. No Administrator required (User-scope writes to HKCU\Environment without elevation; %LOCALAPPDATA% is per-user). Files: install_certs_jvm_windows.ps1 Installer (~370 lines). validate_certs_jvm_windows.ps1 Companion validator. _jvm_windows_paths.ps1 Shared constants dot-sourced. testing/test_install_certs_jvm_windows.ps1 14-invariant smoke runner. .github/workflows/ci.yml New test-windows-jvm job. README.md New "Windows (JVM)" section. Hardening fixes folded in from a round of pr-review-toolkit review (5 agents, 28 findings: 2 Critical + 21 Important + 5 Minor): Critical: - SetEnvironmentVariable round-trip verify. Windows 10 1607+ silently truncates user-env values > 2047 chars rather than throwing; future JTO extensions would corrupt HKCU. Now reads back and hard-fails on mismatch. - Test runner captures $LASTEXITCODE IMMEDIATELY after the native powershell.exe call, BEFORE the Out-String pipeline. Without this an intervening pipeline error leaves $rc carrying a stale value from a previous step and -ExpectFail can phantom-pass. Important production-code: - Require-Keytool now probes `keytool -help` to reject corrupt 0-byte stubs and broken-runtime keytools. - Build-JksTruststore post-import verify: runs keytool -list and asserts at least one trustedCertEntry, catching JBR-bundled keytool cases where rc=0 hides a non-standard java.security provider list. - Build-JksTruststore precondition checks for $env:LOCALAPPDATA existence + readability (OneDrive Known-Folder-Move, roaming-profile failures get actionable diagnostics). - Test-CaCertificate basicConstraints comment documents the legacy-cert behavior (extension absent -> accept, matches Linux/macOS siblings). - Maintenance comment on $prevEAP capture / restore. - Set-JavaToolOptions now quotes the trustStorePassword value. - Build-JksTruststore surfaces keytool's non-failure stderr warnings (JKS deprecation, weak-algo notices) on the success path. - Test-UserEnvVar regex anchors both branches so a path like $JksPath.bak.pkcs12 doesn't false-positive as a prefix match. - Test-UserEnvVar warns on Machine-scope sibling env vars to flag mixed-scope misconfig. - Validator's WarnCount infrastructure now actually fires on the Machine-scope path. Important test-runner: - Invoke-Keytool helper wraps inline `keytool -list` in tests with EAP=Continue, matching the installer/validator pattern. JDK 17+ crypto-policy notices to stderr won't terminate the test. - Cleanup() switched from -ErrorAction SilentlyContinue to probe-then- warn so locked $JksDir from a leaked keytool.exe child surfaces. - openssl version banner + warning when < 3.2 (required by test #7). - 4 new tests raise the matrix from 10 to 14: JTO env var replaces on re-install (catches future append-mode regression), missing keytool fails cleanly, mandatory -UseCert no-args fails non-interactively, docstring split #10 -> #10+#11 (30-day expiry vs bundle warn). - Explicit exit 0 so child-rc from negative tests doesn't leak to the shell wrapper. Docs / future-proofing: - PowerShell 5.1+ named as a requirement in installer header. - README "JDK-version-agnostic" claim qualified ("across currently- supported JDKs; JKS format still read by JDK 8-25; future JDK dropping JKS would require a format bump"). - README "covered for free" for Gradle auto-provisioned JDKs now cross-references the Gradle Daemon caveat. - README validation row clarifies that basicConstraints absent -> accept; CA:TRUE required only when extension present. - _jvm_windows_paths.ps1 header documents the "UTF-8 BOM + ASCII-only content" guard for PowerShell 5.1's Windows-1252 default; em-dashes in source files terminate string literals mid-line under cp1252 decoding and the parser reports a baffling error 100+ lines later. Smoke matrix: 14/14 green on windows-latest in CI (Test (Windows JVM) job, Temurin 21 via actions/setup-java). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * DFLOW-140 - Use bundled JVM truststores on macOS and Windows Signed-off-by: rani <ranil@jfrog.com> * DFLOW-140 - Split Linux JVM trust installers * DFLOW-140 - Add JVM truststore bundle builders --------- Signed-off-by: rani <ranil@jfrog.com> Co-authored-by: Michael Akushsky <michaelak@jfrog.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a macOS client-side installer + validator that wires a corporate CA into the JVM trust path so Maven / Gradle / sbt / Apache Ivy traffic redirected through
package-reroutevalidates correctly. JVM trust only — does not configure Node/npm/Python and does not touch Docker credentials (pair withinstall_certs_macos.shif you need those).Single path on macOS (no
update-ca-trustfork like Linux):~/Library/Application Support/JFrog/package-route-jvm/truststore.jkscontaining the customer CA.~/Library/LaunchAgents/com.jfrog.package-reroute.jto-env.plistthat callslaunchctl setenv JAVA_TOOL_OPTIONS=…atRunAtLoad.gui/<uid>so Dock-launched IDEs (IntelliJ, JetBrains Toolbox,open -a …) inherit the env var at next launch.The
~/.zshrcshortcut is deliberately NOT used — verified in the research wiki to silently fail for GUI-launched IDE builds.KeychainStoretruststoreType is also excluded (broken per JDK-8321045).Base branch
Based on
feature/DFLOW-150-jvm-linux(PR #8), notmain— DFLOW-152 reuses the hardenedvalidate_pem,--cert-nameregex, JKS build pattern, and SIGPIPE-safe keystore-subject match from the Linux installer. When PR #8 merges, GitHub will auto-rebase this PR's base tomainand the diff will shrink to just macOS files.Files
install_certs_jvm_macos.sh— installer (~490 lines, mirrorsinstall_certs_jvm_linux.shpatterns).validate_certs_jvm_macos.sh— companion validator._jvm_macos_paths.sh— shared constants sourced by both.testing/test_install_certs_jvm_macos.sh— 9-invariant smoke runner..github/workflows/ci.yml— newtest-macos-jvmjob.README.md— new "macOS (JVM)" section.Test plan
The smoke runner exercises 9 invariants on
macos-latestin CI and locally:--cert-nameround-trips (JKS alias = cert-name)--cert-namerejectedCA:FALSE) rejectedlaunchctl getenv JAVA_TOOL_OPTIONSingui/<uid>returns the JKS path (SKIP on CI runners with no GUI session; verified on local dev Mac)Locally smoke-passed on a 2-user box (
admin+michaelak): all 9 invariants green including--all-usersiteration (admin gets plist+JKS withbootstrapsoft-skipped since not in active GUI; michaelak gets full bootstrap).Run locally:
CI runs the same matrix on every push and PR via the new
test-macos-jvmjob.🤖 Generated with Claude Code