Skip to content

MtlsHandshakeIT fails only under -Pjfr (fail-open on handshake rejection) #201

Description

@cuioss-oliver

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions