What
MtlsHandshakeIT fails only under the jfr Maven profile. Two of its three tests fail:
MtlsHandshakeIT.noClientCertRejected
a missing client certificate must be rejected at the TLS handshake, not as an HTTP status
==> Expected javax.net.ssl.SSLException to be thrown, but nothing was thrown.
MtlsHandshakeIT.wrongCaClientCertRejected
a client certificate signed by a CA the client_ca does not trust must be rejected
==> Expected javax.net.ssl.SSLException to be thrown, but nothing was thrown.
Both assert that a connection is rejected; both observe it succeeding. That is a fail-open shape in the mTLS lane, so it is worth understanding rather than muting.
Why this was not visible before
The JFR lane never reached the test phase. docker-compose.jfr.yml bind-mounts ./target/jfr-recordings at /tmp/jfr-output, and whichever docker compose command touched the service first created that host directory as root:root 0755. The JFR image runs as uid 1001, so the recording could not be written and the gateway died at startup:
Could not start recording, not able to write to file /tmp/jfr-output/api-sheriff-profile.jfr
verify -Pjfr therefore failed in start-integration-app, before any IT ran. PR #199 fixes the mount permission (integration-tests/scripts/prepare-jfr-output-dir.sh), which is what makes this failure observable.
Provenance — this is not PR #199's doing
Established by running both lanes against the identical working tree:
| Lane |
MtlsHandshakeIT |
verify -Pintegration-tests (distroless) |
3/3 pass |
verify -Pjfr |
1/3 pass, 2 fail |
PR #199's changes are lane-agnostic (OCI image labels plus the bind-mount permission fix); nothing in it touches TLS, the mTLS route, or the api-sheriff-mtls service. The failure is a pre-existing JFR-lane defect that the mount fix merely unmasked.
A likely lead, not a diagnosis
api-sheriff-mtls is pinned to image: "api-sheriff:distroless" (integration-tests/docker-compose.yml), but the jfr profile builds only api-sheriff:jfr — it never builds the distroless image. In that lane the mTLS service therefore runs whatever api-sheriff:distroless happens to be resident on the host, which may be stale or absent. Worth confirming before assuming a TLS-stack difference between the UBI9-micro and distroless bases.
Scope note
jfr is a profiling lane and is not in CI's gating set, so this does not block merges today. It does mean the JFR lane cannot currently be used as a green signal.
What
MtlsHandshakeITfails only under thejfrMaven profile. Two of its three tests fail:Both assert that a connection is rejected; both observe it succeeding. That is a fail-open shape in the mTLS lane, so it is worth understanding rather than muting.
Why this was not visible before
The JFR lane never reached the test phase.
docker-compose.jfr.ymlbind-mounts./target/jfr-recordingsat/tmp/jfr-output, and whicheverdocker composecommand touched the service first created that host directory asroot:root 0755. The JFR image runs as uid 1001, so the recording could not be written and the gateway died at startup:verify -Pjfrtherefore failed instart-integration-app, before any IT ran. PR #199 fixes the mount permission (integration-tests/scripts/prepare-jfr-output-dir.sh), which is what makes this failure observable.Provenance — this is not PR #199's doing
Established by running both lanes against the identical working tree:
MtlsHandshakeITverify -Pintegration-tests(distroless)verify -PjfrPR #199's changes are lane-agnostic (OCI image labels plus the bind-mount permission fix); nothing in it touches TLS, the mTLS route, or the
api-sheriff-mtlsservice. The failure is a pre-existing JFR-lane defect that the mount fix merely unmasked.A likely lead, not a diagnosis
api-sheriff-mtlsis pinned toimage: "api-sheriff:distroless"(integration-tests/docker-compose.yml), but thejfrprofile builds onlyapi-sheriff:jfr— it never builds the distroless image. In that lane the mTLS service therefore runs whateverapi-sheriff:distrolesshappens to be resident on the host, which may be stale or absent. Worth confirming before assuming a TLS-stack difference between the UBI9-micro and distroless bases.Scope note
jfris a profiling lane and is not in CI's gating set, so this does not block merges today. It does mean the JFR lane cannot currently be used as a green signal.