JFrog Artifactory — governing a binary, not just a container
Every compliance pipeline in this platform gates on a container image digest. Most enterprise software is not a container image. It is a jar, a wheel, a tarball — published to an artifact repository, consumed by other teams, and wrapped in a container only at the very end, if at all.
This integration closes that gap. SARC publishes a jar to JFrog Artifactory, records it in Fides against its sha256, builds the container from that published jar, and refuses to deploy unless the binary is compliant.
Why this is not just “another registry”
Section titled “Why this is not just “another registry””A container image is built by us, from our Dockerfile, and never leaves our pipeline until it is pushed. A jar is different: it is the unit other teams depend on, it is resolved transitively into builds we do not own, and it frequently outlives the container that first shipped it.
So the interesting question is not “can we scan the image”, it is:
Can you prove that the exact bytes sitting in your artifact repository were built from a known commit, scanned, SBOM’d, and approved — and that the thing running in production came from those bytes and no others?
That is what this lane demonstrates.
How it works
Section titled “How it works”build jar → test → scan → publish to Artifactory → attest to Fides → build the image FROM the published jar → deploy, gated on the JAREach step, and what makes it non-obvious:
1. Build and scan the jar
Section titled “1. Build and scan the jar”A small Java service (apps/arc-binary-demo) builds to a shaded (fat) jar.
Shading is deliberate: scanners read what is inside the artifact, so a plain
jar containing only our own classes reports zero vulnerabilities whether or not
the build declares a vulnerable dependency. A scan that cannot fail is not
evidence.
trivy rootfs scans the jar and syft generates a CycloneDX SBOM directly from
it. Both produce exactly the reports Fides already parses — the evidence
pipeline never needed to learn what a jar is.
2. Publish with jf mvn
Section titled “2. Publish with jf mvn”Publishing goes through the JFrog CLI, not mvn deploy. Plain mvn deploy
produces no build-info, and on OSS build-info is the only native provenance
carrier available (see the limitations below).
Two things are written alongside the jar:
- build-info — JFrog’s own record of the build: name, number, VCS revision,
and every artifact with its checksums. Retrievable with
GET /api/build/{name}/{number}. provenance.json— a companion file in the same GAV directory carrying the commit, pipeline URL, Fides trail and the jar’s own sha256. Anyone who can resolve the jar can resolve its provenance, with no licensed features.
3. Attest to Fides
Section titled “3. Attest to Fides”The jar is registered against its bare 64-character sha256 with
type: "binary", then the trivy report and the SBOM are attached to the same
trail.
4. Build the image from the published jar
Section titled “4. Build the image from the published jar”This is the step that makes the claim true rather than rhetorical. The Dockerfile does not copy a locally-built jar. It downloads the jar from Artifactory and verifies its sha256 against the digest the pipeline attested:
FATAL: fetched jar does not match the attested digestWithout that check the image could ship a jar no evidence covers, and
Artifactory would have returned 200 either way.
5. Gate the deployment on the jar
Section titled “5. Gate the deployment on the jar”envs/<env>/artifact-digest.yaml pins the published jar’s digest beside the
usual image tag — both written in a single commit, so ArgoCD can never see a
new image alongside a stale digest.
An ArgoCD PreSync hook then asks Fides about that digest before the sync is allowed to proceed:
Asserting Fides compliance for JAR sha256=3e645230…Fides compliance response: {"compliant":true,…}Fides assert passed — the published binary holds the door open.The gate fails closed. If Fides is unreachable, unconfigured, or returns anything the parser does not recognise, the sync is refused. An unconfigured gate that lets everything through is worse than no gate, because the pipeline still reports that a gate ran.
What Artifactory OSS cannot do
Section titled “What Artifactory OSS cannot do”Verified against a live Artifactory OSS 7.161.20, not read from a datasheet. Several of these contradict JFrog’s own documentation, and all of them shaped the design above.
| Capability | OSS | Consequence for us |
|---|---|---|
| Maven local / remote / virtual repos | ✅ | Full customer-shaped topology works |
| Build-info publish + retrieve | ✅ | The provenance carrier |
| Checksum-verified upload | ✅ | X-Checksum-Sha256 enforced server-side |
| Access tokens | ✅ | The CI credential |
| Artifact properties | ❌ Pro | Provenance cannot hang on the jar as metadata |
| AQL / search API | ❌ JCR+ | Cannot ask “which artifact has this checksum” |
| OIDC | ❌ Enterprise X+ | CI must hold a long-lived token |
| User management REST | ❌ Pro | Default admin password cannot be rotated post-boot |
| Repository creation REST | ❌ Pro | …but see the workaround below |
| Docker / OCI registry | ❌ (JCR is free) | Irrelevant here — we publish jars |
| Xray, build promotion, replication, webhooks | ❌ Pro/Enterprise | Not used |
The three that actually hurt
Section titled “The three that actually hurt”No OIDC — and it is Enterprise X, not Pro. This is the one worth raising with any customer planning a migration. Every other integration in this platform uses short-lived credentials: cosign keyless via Sigstore, GCP Workload Identity Federation, AWS role assumption. Artifactory is the sole exception, and it is not a choice we made — OSS and Pro both lack the feature. If a customer has been told to move to OIDC token exchange, that migration requires an Enterprise licence. Better they hear it from us now than discover it mid-rollout.
No properties, and no search to query them with. The instinctive design —
tag the jar with commit SHA, build id, scan verdict and evidence URL — is a Pro
feature, and matrix-parameter uploads (path;key=value) are the same feature
under another name. Provenance therefore rides in build-info plus the
provenance.json companion. Both survive a Pro upgrade unchanged, so nothing
has to be redesigned if a licence arrives later.
No user management REST. POST /api/security/users/{name} answers “This
REST API is available only in Artifactory Pro”, and the Access API rejects basic
auth. The default admin password therefore cannot be changed after boot —
it must be set through the Helm chart’s bootstrap. That matters a great deal if
the instance is reachable from the internet.
One thing that is possible, contrary to appearances
Section titled “One thing that is possible, contrary to appearances”Repository creation via PUT /api/repositories/{key} is Pro and returns 400. It
would be reasonable to conclude that OSS setup cannot be automated at all and to
write a page of click-here instructions instead.
It can. The config descriptor API — PATCH /api/system/configuration with a
YAML body — is available on OSS and merges repository definitions happily. That
is the difference between a reproducible environment and a runbook. See
scripts/ci/artifactory-bootstrap.sh, which is idempotent.
How we run it
Section titled “How we run it”Artifactory OSS is installed on the demo cluster from the official Helm chart
(jfrog/artifactory-oss), with values in apps/artifactory/values.yaml:
- PostgreSQL enabled (mandatory, above)
- Bundled nginx disabled — the cluster’s ingress-nginx plus cert-manager handles TLS, matching how Fides and the portal are exposed
- Admin password set through the chart’s bootstrap, because it cannot be changed afterwards on OSS
- Three repositories:
libs-release-local(deploy target),maven-central-remote(proxy), andlibs-release(virtual, for resolution)
In the portal
Section titled “In the portal”Settings → Artifactory connects a tenant: platform URL, a scoped access token, and the repository key. Test connection distinguishes connected from connected but that repository is not visible to this token — a valid token against the wrong repo key otherwise produces an empty view that looks exactly like “nothing has been published yet”.
Once configured, a Binaries entry appears in the sidebar listing each published artifact with its full, untruncated sha256 — because that is the value you paste into a Fides compliance query, and a shortened one would be useless for exactly that.
The portal lists binaries by walking a repository folder, not by searching, because OSS has neither AQL nor the search API. That is why the view takes a GAV path rather than a filter.
The demo
Section titled “The demo”Run it with just demo-artifactory (just demo-artifactory-dry rehearses
safely), with the companion slide deck on just demo-artifactory-slides.
It is deliberately separate from just demo, the podtato-head container
walkthrough: its own child pipeline, its own Fides flow, its own ArgoCD app, its
own deck on a different port. Either can be shown alone, and neither can disturb
the other’s trail, change request or environments.
Eight beats:
- What is published today — start from the repository, not the pipeline
- An ordinary change — a small Java service, deliberately uninteresting
- One push, one pipeline — the container demo does not run and cannot break
- The same evidence, over a jar — build, trivy, syft, publish, attest
- The jar in Artifactory — checksums, build-info,
provenance.json - The same digest, in Fides — registered
type: "binary" - The image comes from the jar — and refuses a mismatched digest
- The gate asks about the binary — a non-compliant jar stops the deploy
Showing the gate say no
Section titled “Showing the gate say no”A gate nobody has watched refuse is not a demonstration of a gate. Re-run the
pipeline with DEMO_VULNERABLE=true and the build pulls in log4j-core 2.14.1
— CVE-2021-44228, which an audience recognises on sight. trivy then reports
8 vulnerabilities, 2 of them CRITICAL, and the PreSync gate stops the deployment
on the jar’s digest while the container itself is perfectly fine.
The point for a regulated audience
Section titled “The point for a regulated audience”The controls are org-scoped in Fides, not per-flow. That was a constraint, and it turned into the strongest thing this lane demonstrates:
The same controls pass over a jar and over a container, without being rewritten.
Nothing was special-cased for binaries. The evidence spine never knew or cared that the other demo’s artifacts happened to be OCI images — which is exactly the property you want when the next artifact type arrives.