Skip to content

Commit d583f16

Browse files
committed
fix: #23915 podman build is not parsing sbom command line arguments
Signed-off-by: Alex Guidi <[email protected]> add sbom flags on server side for podman-remote Signed-off-by: Alex Guidi <[email protected]>
1 parent b74a717 commit d583f16

File tree

5 files changed

+169
-0
lines changed

5 files changed

+169
-0
lines changed

cmd/podman/common/build.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io"
77
"os"
88
"path/filepath"
9+
"slices"
910
"strings"
1011
"syscall"
1112
"time"
@@ -515,6 +516,24 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *Buil
515516
}
516517
}
517518

519+
var sbomScanOptions []buildahDefine.SBOMScanOptions
520+
if c.Flag("sbom").Changed || c.Flag("sbom-scanner-command").Changed || c.Flag("sbom-scanner-image").Changed || c.Flag("sbom-image-output").Changed || c.Flag("sbom-merge-strategy").Changed || c.Flag("sbom-output").Changed || c.Flag("sbom-image-output").Changed || c.Flag("sbom-purl-output").Changed || c.Flag("sbom-image-purl-output").Changed {
521+
sbomScanOption, err := parse.SBOMScanOptions(c)
522+
if err != nil {
523+
return nil, err
524+
}
525+
if !slices.Contains(sbomScanOption.ContextDir, contextDir) {
526+
sbomScanOption.ContextDir = append(sbomScanOption.ContextDir, contextDir)
527+
}
528+
for _, abc := range additionalBuildContext {
529+
if !abc.IsURL && !abc.IsImage {
530+
sbomScanOption.ContextDir = append(sbomScanOption.ContextDir, abc.Value)
531+
}
532+
}
533+
sbomScanOption.PullPolicy = pullPolicy
534+
sbomScanOptions = append(sbomScanOptions, *sbomScanOption)
535+
}
536+
518537
opts := buildahDefine.BuildOptions{
519538
AddCapabilities: flags.CapAdd,
520539
AdditionalTags: tags,
@@ -571,6 +590,7 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *Buil
571590
Runtime: podmanConfig.RuntimePath,
572591
RuntimeArgs: runtimeFlags,
573592
RusageLogFile: flags.RusageLogFile,
593+
SBOMScanOptions: sbomScanOptions,
574594
SignBy: flags.SignBy,
575595
SignaturePolicyPath: flags.SignaturePolicy,
576596
Squash: flags.Squash,

pkg/api/handlers/compat/images_build.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"net/http"
1212
"os"
1313
"path/filepath"
14+
"slices"
1415
"strconv"
1516
"strings"
1617
"syscall"
@@ -172,6 +173,13 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
172173
UnsetEnvs []string `schema:"unsetenv"`
173174
UnsetLabels []string `schema:"unsetlabel"`
174175
Volumes []string `schema:"volume"`
176+
SBOMOutput string `schema:"sbom-output"`
177+
SBOMPURLOutput string `schema:"sbom-purl-output"`
178+
ImageSBOMOutput string `schema:"sbom-image-output"`
179+
ImageSBOMPURLOutput string `schema:"sbom-image-purl-output"`
180+
ImageSBOM string `schema:"sbom-scanner-image"`
181+
SBOMCommands string `schema:"sbom-scanner-command"`
182+
SBOMMergeStrategy string `schema:"sbom-merge-strategy"`
175183
}{
176184
Dockerfile: "Dockerfile",
177185
IdentityLabel: true,
@@ -694,6 +702,46 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
694702
}
695703
}
696704

705+
var sbomScanOptions []buildahDefine.SBOMScanOptions
706+
if query.ImageSBOM != "" ||
707+
query.SBOMOutput != "" ||
708+
query.ImageSBOMOutput != "" ||
709+
query.SBOMPURLOutput != "" ||
710+
query.ImageSBOMPURLOutput != "" ||
711+
query.SBOMCommands != "" ||
712+
query.SBOMMergeStrategy != "" {
713+
sbomScanOption := &buildahDefine.SBOMScanOptions{
714+
SBOMOutput: query.SBOMOutput,
715+
PURLOutput: query.SBOMPURLOutput,
716+
ImageSBOMOutput: query.ImageSBOMOutput,
717+
ImagePURLOutput: query.ImageSBOMPURLOutput,
718+
Image: query.ImageSBOM,
719+
MergeStrategy: buildahDefine.SBOMMergeStrategy(query.SBOMMergeStrategy),
720+
PullPolicy: pullPolicy,
721+
}
722+
723+
if _, found := r.URL.Query()["sbom-scanner-command"]; found {
724+
var m = []string{}
725+
if err := json.Unmarshal([]byte(query.SBOMCommands), &m); err != nil {
726+
utils.BadRequest(w, "sbom-scanner-command", query.SBOMCommands, err)
727+
return
728+
}
729+
sbomScanOption.Commands = m
730+
}
731+
732+
if !slices.Contains(sbomScanOption.ContextDir, contextDirectory) {
733+
sbomScanOption.ContextDir = append(sbomScanOption.ContextDir, contextDirectory)
734+
}
735+
736+
for _, abc := range additionalBuildContexts {
737+
if !abc.IsURL && !abc.IsImage {
738+
sbomScanOption.ContextDir = append(sbomScanOption.ContextDir, abc.Value)
739+
}
740+
}
741+
742+
sbomScanOptions = append(sbomScanOptions, *sbomScanOption)
743+
}
744+
697745
buildOptions := buildahDefine.BuildOptions{
698746
AddCapabilities: addCaps,
699747
AdditionalBuildContexts: additionalBuildContexts,
@@ -774,6 +822,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
774822
Target: query.Target,
775823
UnsetEnvs: query.UnsetEnvs,
776824
UnsetLabels: query.UnsetLabels,
825+
SBOMScanOptions: sbomScanOptions,
777826
}
778827

779828
platforms := query.Platform

pkg/bindings/images/build.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,42 @@ func Build(ctx context.Context, containerFiles []string, options types.BuildOpti
489489
stdout = options.Out
490490
}
491491

492+
if len(options.SBOMScanOptions) > 0 {
493+
for _, sbomScanOpts := range options.SBOMScanOptions {
494+
if sbomScanOpts.SBOMOutput != "" {
495+
params.Set("sbom-output", sbomScanOpts.SBOMOutput)
496+
}
497+
498+
if sbomScanOpts.PURLOutput != "" {
499+
params.Set("sbom-purl-output", sbomScanOpts.PURLOutput)
500+
}
501+
502+
if sbomScanOpts.ImageSBOMOutput != "" {
503+
params.Set("sbom-image-output", sbomScanOpts.ImageSBOMOutput)
504+
}
505+
506+
if sbomScanOpts.ImagePURLOutput != "" {
507+
params.Set("sbom-image-purl-output", sbomScanOpts.ImagePURLOutput)
508+
}
509+
510+
if sbomScanOpts.Image != "" {
511+
params.Set("sbom-scanner-image", sbomScanOpts.Image)
512+
}
513+
514+
if commands := sbomScanOpts.Commands; len(commands) > 0 {
515+
c, err := jsoniter.MarshalToString(commands)
516+
if err != nil {
517+
return nil, err
518+
}
519+
params.Add("sbom-scanner-command", c)
520+
}
521+
522+
if sbomScanOpts.MergeStrategy != "" {
523+
params.Set("sbom-merge-strategy", string(sbomScanOpts.MergeStrategy))
524+
}
525+
}
526+
}
527+
492528
contextDir, err = filepath.Abs(options.ContextDirectory)
493529
if err != nil {
494530
logrus.Errorf("Cannot find absolute path of %v: %v", options.ContextDirectory, err)

pkg/machine/e2e/basic_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,47 @@ var _ = Describe("run basic podman commands", func() {
285285
Expect(run).To(Exit(0))
286286
Expect(build.outputToString()).To(ContainSubstring(name))
287287
})
288+
289+
It("podman build with sbom flags", func() {
290+
291+
name := randomString()
292+
i := new(initMachine)
293+
session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withNow()).run()
294+
Expect(err).ToNot(HaveOccurred())
295+
Expect(session).To(Exit(0))
296+
297+
ALPINE := "quay.io/libpod/alpine:latest"
298+
bm := basicMachine{}
299+
300+
contextDir := GinkgoT().TempDir()
301+
cfile := filepath.Join(contextDir, "Containerfile")
302+
err = os.WriteFile(cfile, []byte("FROM "+ALPINE), 0o644)
303+
Expect(err).ToNot(HaveOccurred())
304+
305+
build, err := mb.setCmd(bm.withPodmanCommand([]string{"build", "-t", "sbom-img", "--sbom-output=localsbom.txt", "--sbom-purl-output=localpurl.txt", "--sbom-image-output=/tmp/sbom.txt", "--sbom-image-purl-output=/tmp/purl.txt",
306+
"--sbom-scanner-image=alpine", "--sbom-scanner-command=/bin/sh -c 'echo SCANNED ROOT {ROOTFS} > {OUTPUT}'", "--sbom-scanner-command=/bin/sh -c 'echo SCANNED BUILD CONTEXT {CONTEXT} > {OUTPUT}'",
307+
"--sbom-merge-strategy=cat", contextDir})).run()
308+
309+
Expect(err).ToNot(HaveOccurred())
310+
Expect(build).To(Exit(0))
311+
312+
// defer os.Remove("./localsbom.txt")
313+
// if _, err := os.Stat("./localsbom.txt"); err != nil {
314+
// Expect(errors.Is(err, fs.ErrNotExist)).To(BeFalse())
315+
// }
316+
317+
// defer os.Remove("./localpurl.txt")
318+
// if _, err := os.Stat("./localpurl.txt"); err != nil {
319+
// Expect(errors.Is(err, fs.ErrNotExist)).To(BeFalse())
320+
// }
321+
322+
run, err := mb.setCmd(bm.withPodmanCommand([]string{"run", "--rm", "sbom-img", "ls", "/tmp"})).run()
323+
fmt.Println("ALEX TEST: " + run.outputToString())
324+
Expect(err).ToNot(HaveOccurred())
325+
Expect(run).To(Exit(0))
326+
// Expect(run.outputToString()).To(ContainSubstring("purl.txt"))
327+
// Expect(run.outputToString()).To(ContainSubstring("sbom.txt"))
328+
})
288329
})
289330

290331
func testHTTPServer(port string, shouldErr bool, expectedResponse string) {

test/e2e/build_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ package integration
44

55
import (
66
"bytes"
7+
"errors"
78
"fmt"
9+
"io/fs"
810
"os"
911
"os/exec"
1012
"path/filepath"
@@ -972,4 +974,25 @@ RUN ls /dev/test1`, CITEST_IMAGE)
972974
session.WaitWithDefaultTimeout()
973975
Expect(session).Should(ExitWithError(1, `building at STEP "RUN --mount=type=cache,target=/test,z cat /test/world": while running runtime: exit status 1`))
974976
})
977+
It("podman build with sbom flags", func() {
978+
podmanTest.AddImageToRWStore(ALPINE)
979+
980+
podmanTest.PodmanExitCleanly("build", "-t", "sbom-img", "--sbom-output=localsbom.txt", "--sbom-purl-output=localpurl.txt", "--sbom-image-output=/tmp/sbom.txt", "--sbom-image-purl-output=/tmp/purl.txt",
981+
"--sbom-scanner-image=alpine", "--sbom-scanner-command=/bin/sh -c 'echo SCANNED ROOT {ROOTFS} > {OUTPUT}'", "--sbom-scanner-command=/bin/sh -c 'echo SCANNED BUILD CONTEXT {CONTEXT} > {OUTPUT}'",
982+
"--sbom-merge-strategy=cat", "build/basicalpine")
983+
984+
defer os.Remove("./localsbom.txt")
985+
if _, err := os.Stat("./localsbom.txt"); err != nil {
986+
Expect(errors.Is(err, fs.ErrNotExist)).To(BeFalse())
987+
}
988+
989+
defer os.Remove("./localpurl.txt")
990+
if _, err := os.Stat("./localpurl.txt"); err != nil {
991+
Expect(errors.Is(err, fs.ErrNotExist)).To(BeFalse())
992+
}
993+
994+
session := podmanTest.PodmanExitCleanly("run", "--rm", "sbom-img", "ls", "/tmp")
995+
Expect(session.OutputToString()).To(ContainSubstring("purl.txt"))
996+
Expect(session.OutputToString()).To(ContainSubstring("sbom.txt"))
997+
})
975998
})

0 commit comments

Comments
 (0)