fix(wfctl): use docker buildx build in hardened mode#425
Conversation
The classic docker build driver rejects --provenance and --sbom flags with "Attestation is not supported for the docker driver." Only buildx with the docker-container driver supports supply-chain attestation. When hardened=true, prepend "buildx" to the docker args so the command becomes "docker buildx build ...". Non-hardened builds keep plain "docker build" for backward compat. Also adds a driver readiness check (docker buildx inspect --bootstrap) before the live hardened build with an actionable error message guiding users to run "docker buildx create --use" or add setup-buildx-action@v3.
7691d78 to
6d1c437
Compare
There was a problem hiding this comment.
Pull request overview
Updates wfctl container-image build behavior to support hardened builds with provenance/SBOM flags, and additionally introduces a new DigitalOcean deploy provider.
Changes:
- Switch hardened Dockerfile builds to invoke
docker buildx buildand add a buildx “readiness” check before live hardened builds. - Add/extend tests to assert hardened vs non-hardened dry-run output (
buildx buildvsbuild). - Add a new
digitalocean(do) deploy provider implementation plus unit tests.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| cmd/wfctl/build_image.go | Hardened builds use docker buildx build and run a preflight buildx inspect check. |
| cmd/wfctl/build_image_test.go | Adds tests ensuring dry-run output reflects buildx usage when hardened. |
| cmd/wfctl/deploy_providers.go | Registers and implements a new DigitalOcean deploy provider (create/update app, health check). |
| cmd/wfctl/deploy_providers_test.go | Adds unit tests covering DigitalOcean provider behaviors. |
| // hardened mode uses buildx for provenance/SBOM attestation support. | ||
| var args []string | ||
| if hardened { | ||
| args = []string{"buildx", "build", "--file", dockerfile, "--tag", imageRef} |
There was a problem hiding this comment.
In hardened mode this switches to docker buildx build, but no output mode is specified. With the recommended docker-container driver, buildx build does not load the image into the local Docker image store by default, which will break subsequent wfctl build push/docker push steps that expect the tagged image to exist locally. Consider adding an explicit output mode (e.g., load for single-platform builds or push when appropriate) and adjusting tests accordingly.
| args = []string{"buildx", "build", "--file", dockerfile, "--tag", imageRef} | |
| args = []string{"buildx", "build", "--file", dockerfile, "--tag", imageRef} | |
| // With the recommended docker-container driver, buildx does not load | |
| // the resulting image into the local Docker image store unless an | |
| // explicit output mode is set. Preserve the non-hardened local-build | |
| // behavior for builds that can be loaded into the daemon. | |
| if len(ctr.Platforms) <= 1 { | |
| args = append(args, "--load") | |
| } |
| if hardened { | ||
| // buildx with the docker-container driver is required for attestation flags. | ||
| // Verify a non-default builder is active; the default "docker" driver rejects --provenance. | ||
| if err := exec.Command("docker", "buildx", "inspect", "--bootstrap").Run(); err != nil { | ||
| return fmt.Errorf("hardened build requires docker buildx: run 'docker buildx create --use' " + | ||
| "or add 'docker/setup-buildx-action@v3' to your CI workflow (%w)", err) | ||
| } |
There was a problem hiding this comment.
The buildx readiness check runs docker buildx inspect --bootstrap but doesn’t actually verify that the active builder is using a driver that supports attestations (the default "docker" driver can still inspect successfully, and the subsequent build will fail with the same attestation error). Consider checking the inspect output (or using a formatted inspect) to assert the driver is non-docker (e.g., docker-container), and include stderr/stdout in the returned error to make failures actionable.
⏱ Benchmark Results✅ No significant performance regressions detected. benchstat comparison (baseline → PR)
|
Problem
buildWithDockerfileappended--provenance=mode=max --sbom=truewhenci.build.security.hardened=truebut still calleddocker build. The classic docker driver rejects attestation flags with:This was the root cause of the BMW CI failure that required a manual retag + push workaround.
Fix
hardened=true: invokedocker buildx build(prependbuildxto args). The docker-container driver supports--provenanceand--sbom.hardened=false: keep existingdocker buildbehavior unchanged (backward compat).docker buildx inspect --bootstrap) before the live hardened build. If it fails, returns a clear error:run 'docker buildx create --use' or add 'docker/setup-buildx-action@v3' to your CI workflow.docker buildx build ...vsdocker build ....Test plan
TestRunBuildImage_HardenedUsesBuildx— hardened=true dry-run output containsdocker buildx buildTestRunBuildImage_NonHardenedUsesPlainDocker— hardened=false dry-run output hasdocker build, nobuildxTestRunBuildImage_HardenedProvenanceArgs— still passes (provenance/sbom flags present)TestRunBuildImage_NotHardenedNoProvenanceArgs— still passes (no provenance flags)GOWORK=off go test ./cmd/wfctl/...✓🤖 Generated with Claude Code