fix: #23915 podman build is not parsing sbom command line arguments

Signed-off-by: Alex Guidi <aguidi@redhat.com>

add sbom flags on server side for podman-remote

Signed-off-by: Alex Guidi <aguidi@redhat.com>
This commit is contained in:
Alex Guidi
2025-03-21 14:11:24 +01:00
parent a118fdf4e2
commit 4bd6aff4b6
4 changed files with 121 additions and 0 deletions

View File

@ -7,6 +7,7 @@ import (
"maps"
"os"
"path/filepath"
"slices"
"strconv"
"strings"
"syscall"
@ -515,6 +516,24 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *Buil
}
}
var sbomScanOptions []buildahDefine.SBOMScanOptions
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 {
sbomScanOption, err := parse.SBOMScanOptions(c)
if err != nil {
return nil, err
}
if !slices.Contains(sbomScanOption.ContextDir, contextDir) {
sbomScanOption.ContextDir = append(sbomScanOption.ContextDir, contextDir)
}
for _, abc := range additionalBuildContext {
if !abc.IsURL && !abc.IsImage {
sbomScanOption.ContextDir = append(sbomScanOption.ContextDir, abc.Value)
}
}
sbomScanOption.PullPolicy = pullPolicy
sbomScanOptions = append(sbomScanOptions, *sbomScanOption)
}
opts := buildahDefine.BuildOptions{
AddCapabilities: flags.CapAdd,
AdditionalTags: tags,
@ -571,6 +590,7 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *Buil
Runtime: podmanConfig.RuntimePath,
RuntimeArgs: runtimeFlags,
RusageLogFile: flags.RusageLogFile,
SBOMScanOptions: sbomScanOptions,
SignBy: flags.SignBy,
SignaturePolicyPath: flags.SignaturePolicy,
Squash: flags.Squash,

View File

@ -13,6 +13,7 @@ import (
"net/url"
"os"
"path/filepath"
"slices"
"strconv"
"strings"
"syscall"
@ -125,6 +126,13 @@ type BuildQuery struct {
UnsetLabels []string `schema:"unsetlabel"`
UnsetAnnotations []string `schema:"unsetannotation"`
Volumes []string `schema:"volume"`
SBOMOutput string `schema:"sbom-output"`
SBOMPURLOutput string `schema:"sbom-purl-output"`
ImageSBOMOutput string `schema:"sbom-image-output"`
ImageSBOMPURLOutput string `schema:"sbom-image-purl-output"`
ImageSBOM string `schema:"sbom-scanner-image"`
SBOMCommands string `schema:"sbom-scanner-command"`
SBOMMergeStrategy string `schema:"sbom-merge-strategy"`
}
// BuildContext represents processed build context and metadata for container image builds.
@ -619,6 +627,44 @@ func createBuildOptions(query *BuildQuery, buildCtx *BuildContext, queryValues u
return nil, cleanup, utils.GetBadRequestError("retry-delay", query.RetryDelay, err)
}
}
var sbomScanOptions []buildahDefine.SBOMScanOptions
if query.ImageSBOM != "" ||
query.SBOMOutput != "" ||
query.ImageSBOMOutput != "" ||
query.SBOMPURLOutput != "" ||
query.ImageSBOMPURLOutput != "" ||
query.SBOMCommands != "" ||
query.SBOMMergeStrategy != "" {
sbomScanOption := &buildahDefine.SBOMScanOptions{
SBOMOutput: query.SBOMOutput,
PURLOutput: query.SBOMPURLOutput,
ImageSBOMOutput: query.ImageSBOMOutput,
ImagePURLOutput: query.ImageSBOMPURLOutput,
Image: query.ImageSBOM,
MergeStrategy: buildahDefine.SBOMMergeStrategy(query.SBOMMergeStrategy),
PullPolicy: pullPolicy,
}
if _, found := r.URL.Query()["sbom-scanner-command"]; found {
var m = []string{}
if err := json.Unmarshal([]byte(query.SBOMCommands), &m); err != nil {
return nil, cleanup, utils.GetBadRequestError("sbom-scanner-command", query.SBOMCommands, err)
}
sbomScanOption.Commands = m
}
if !slices.Contains(sbomScanOption.ContextDir, buildCtx.ContextDirectory) {
sbomScanOption.ContextDir = append(sbomScanOption.ContextDir, buildCtx.ContextDirectory)
}
for _, abc := range buildCtx.AdditionalBuildContexts {
if !abc.IsURL && !abc.IsImage {
sbomScanOption.ContextDir = append(sbomScanOption.ContextDir, abc.Value)
}
}
sbomScanOptions = append(sbomScanOptions, *sbomScanOption)
}
// Create build options
buildOptions := &buildahDefine.BuildOptions{
@ -702,6 +748,7 @@ func createBuildOptions(query *BuildQuery, buildCtx *BuildContext, queryValues u
UnsetEnvs: query.UnsetEnvs,
UnsetLabels: query.UnsetLabels,
UnsetAnnotations: query.UnsetAnnotations,
SBOMScanOptions: sbomScanOptions,
}
// Process platforms

View File

@ -670,6 +670,42 @@ func prepareRequestBody(ctx context.Context, requestParts *RequestParts, buildFi
return nil, err
}
if len(options.SBOMScanOptions) > 0 {
for _, sbomScanOpts := range options.SBOMScanOptions {
if sbomScanOpts.SBOMOutput != "" {
requestParts.Params.Set("sbom-output", sbomScanOpts.SBOMOutput)
}
if sbomScanOpts.PURLOutput != "" {
requestParts.Params.Set("sbom-purl-output", sbomScanOpts.PURLOutput)
}
if sbomScanOpts.ImageSBOMOutput != "" {
requestParts.Params.Set("sbom-image-output", sbomScanOpts.ImageSBOMOutput)
}
if sbomScanOpts.ImagePURLOutput != "" {
requestParts.Params.Set("sbom-image-purl-output", sbomScanOpts.ImagePURLOutput)
}
if sbomScanOpts.Image != "" {
requestParts.Params.Set("sbom-scanner-image", sbomScanOpts.Image)
}
if commands := sbomScanOpts.Commands; len(commands) > 0 {
c, err := jsoniter.MarshalToString(commands)
if err != nil {
return nil, err
}
requestParts.Params.Add("sbom-scanner-command", c)
}
if sbomScanOpts.MergeStrategy != "" {
requestParts.Params.Set("sbom-merge-strategy", string(sbomScanOpts.MergeStrategy))
}
}
}
if len(options.AdditionalBuildContexts) == 0 {
requestParts.Body = tarfile
logrus.Debugf("Using main build context: %q", options.ContextDirectory)

View File

@ -973,6 +973,24 @@ RUN ls /dev/test1`, CITEST_IMAGE)
Expect(session).Should(ExitWithError(1, `building at STEP "RUN --mount=type=cache,target=/test,z cat /test/world": while running runtime: exit status 1`))
})
It("podman build with sbom flags", func() {
podmanTest.AddImageToRWStore(ALPINE)
localsbomFile := filepath.Join(podmanTest.TempDir, "localsbom.txt")
localPurlFile := filepath.Join(podmanTest.TempDir, "localpurl.txt")
podmanTest.PodmanExitCleanly("build", "-t", "sbom-img", "--sbom-output="+localsbomFile, "--sbom-purl-output="+localPurlFile, "--sbom-image-output=/tmp/sbom.txt", "--sbom-image-purl-output=/tmp/purl.txt",
"--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}'",
"--sbom-merge-strategy=cat", "build/basicalpine")
Expect(localsbomFile).To(BeARegularFile())
Expect(localPurlFile).To(BeARegularFile())
session := podmanTest.PodmanExitCleanly("run", "--rm", "sbom-img", "ls", "/tmp")
Expect(session.OutputToString()).To(ContainSubstring("purl.txt"))
Expect(session.OutputToString()).To(ContainSubstring("sbom.txt"))
})
It("podman build --build-context: local source", func() {
podmanTest.RestartRemoteService()