Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions cmd/podman/artifact/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ import (
// CLI-only fields into the API types.
type pushOptionsWrapper struct {
entities.ArtifactPushOptions
TLSVerifyCLI bool // CLI only
CredentialsCLI string
signing common.SigningCLIOnlyOptions
EncryptionKeys []string
EncryptLayers []int
DigestFile string
TLSVerifyCLI bool // CLI only
CredentialsCLI string
signing common.SigningCLIOnlyOptions
EncryptionKeys []string
EncryptLayers []int
DigestFile string
DigestAlgorithm string
}

var (
Expand Down Expand Up @@ -89,6 +90,10 @@ func pushFlags(cmd *cobra.Command) {

flags.BoolVar(&pushOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")

digestFlagName := "digest"
flags.StringVar(&pushOptions.DigestAlgorithm, digestFlagName, "", "Digest algorithm to use for content addressing (sha256, sha512). Defaults to value from storage.conf or sha256")
_ = cmd.RegisterFlagCompletionFunc(digestFlagName, completion.AutocompleteNone)

// TODO I think these two can be removed?
/*
compFormat := "compression-format"
Expand Down Expand Up @@ -203,6 +208,14 @@ func artifactPush(cmd *cobra.Command, args []string) error {
}
*/

// Validate and copy the digest algorithm from CLI wrapper to ArtifactPushOptions
if pushOptions.DigestAlgorithm != "" {
if pushOptions.DigestAlgorithm != "sha256" && pushOptions.DigestAlgorithm != "sha512" {
return fmt.Errorf("invalid digest algorithm %q: must be sha256 or sha512", pushOptions.DigestAlgorithm)
}
}
pushOptions.ArtifactPushOptions.ImagePushOptions.DigestAlgorithm = pushOptions.DigestAlgorithm

_, err = registry.ImageEngine().ArtifactPush(registry.Context(), source, pushOptions.ArtifactPushOptions)
return err
}
17 changes: 17 additions & 0 deletions cmd/podman/common/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ type BuildFlagsWrapper struct {
SquashAll bool
// Cleanup removes built images from remote connections on success
Cleanup bool
// DigestAlgorithm specifies the digest algorithm to use for content addressing
DigestAlgorithm string
}

// FarmBuildHiddenFlags are the flags hidden from the farm build command because they are either not
Expand Down Expand Up @@ -115,6 +117,11 @@ func DefineBuildFlags(cmd *cobra.Command, buildOpts *BuildFlagsWrapper, isFarmBu
fromAndBudFlagsCompletions := buildahCLI.GetFromAndBudFlagsCompletions()
completion.CompleteCommandFlags(cmd, fromAndBudFlagsCompletions)
flags.SetNormalizeFunc(buildahCLI.AliasFlags)

// Digest algorithm flag
digestFlagName := "digest"
flags.StringVar(&buildOpts.DigestAlgorithm, digestFlagName, "", "Digest algorithm to use for content addressing (sha256, sha512). Defaults to value from storage.conf or sha256")
_ = cmd.RegisterFlagCompletionFunc(digestFlagName, completion.AutocompleteNone)
if registry.IsRemote() {
// Unset the isolation default as we never want to send this over the API
// as it can be wrong (root vs rootless).
Expand Down Expand Up @@ -263,6 +270,16 @@ func ParseBuildOpts(cmd *cobra.Command, args []string, buildOpts *BuildFlagsWrap
apiBuildOpts.ContainerFiles = containerFiles
apiBuildOpts.Authfile = buildOpts.Authfile

// Validate and process digest algorithm
if buildOpts.DigestAlgorithm != "" {
if buildOpts.DigestAlgorithm != "sha256" && buildOpts.DigestAlgorithm != "sha512" {
return nil, fmt.Errorf("invalid digest algorithm %q: must be sha256 or sha512", buildOpts.DigestAlgorithm)
}
// Store the digest algorithm preference in the apiBuildOpts
// This will be used to configure the build environment
apiBuildOpts.DigestAlgorithm = buildOpts.DigestAlgorithm
}

return &apiBuildOpts, err
}

Expand Down
16 changes: 15 additions & 1 deletion cmd/podman/images/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,21 @@ func (i imageReporter) ID() string {
if !listFlag.noTrunc && len(i.ImageSummary.ID) >= 12 {
return i.ImageSummary.ID[0:12]
}
return "sha256:" + i.ImageSummary.ID

// Determine digest algorithm based on ID length
// SHA256 = 64 hex chars, SHA512 = 128 hex chars
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we add more algorithms, this will break. Is there a chance to avoid this guessing?

(As an intuitive guess:

  • either the input IDs, as recorded in storage, should include an explicit algorithm specification (maybe in a new field of the image, IDWithAlgo or something, throughout the ecosystem);
  • or the image IDs should be “meaningless hex values only compared for equality” and we should not be adding a digest indication to the formatted value (unless it is sha256).

But the “what is an image ID” question really starts with “how do we deduplicate images in c/storage”, and that discussion incl. various corner cases (a manifest with sha256 config+sha512 layers?) will probably mostly happen in containers/container-libs#358 .)

var prefix string
switch len(i.ImageSummary.ID) {
case 128:
prefix = "sha512:"
case 64:
prefix = "sha256:"
default:
// For unknown lengths, default to sha256 for backward compatibility
prefix = "sha256:"
}

return prefix + i.ImageSummary.ID
}

func (i imageReporter) Created() string {
Expand Down
25 changes: 19 additions & 6 deletions cmd/podman/images/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ import (
// CLI-only fields into the API types.
type pushOptionsWrapper struct {
entities.ImagePushOptions
TLSVerifyCLI bool // CLI only
CredentialsCLI string
signing common.SigningCLIOnlyOptions
EncryptionKeys []string
EncryptLayers []int
DigestFile string
TLSVerifyCLI bool // CLI only
CredentialsCLI string
signing common.SigningCLIOnlyOptions
EncryptionKeys []string
EncryptLayers []int
DigestFile string
DigestAlgorithm string
}

var (
Expand Down Expand Up @@ -137,6 +138,10 @@ func pushFlags(cmd *cobra.Command) {
flags.IntSliceVar(&pushOptions.EncryptLayers, encryptLayersFlagName, nil, "Layers to encrypt, 0-indexed layer indices with support for negative indexing (e.g. 0 is the first layer, -1 is the last layer). If not defined, will encrypt all layers if encryption-key flag is specified")
_ = cmd.RegisterFlagCompletionFunc(encryptLayersFlagName, completion.AutocompleteDefault)

digestFlagName := "digest"
flags.StringVar(&pushOptions.DigestAlgorithm, digestFlagName, "", "Digest algorithm to use for content addressing (sha256, sha512). Defaults to value from storage.conf or sha256")
_ = cmd.RegisterFlagCompletionFunc(digestFlagName, completion.AutocompleteNone)

if registry.IsRemote() {
_ = flags.MarkHidden("cert-dir")
_ = flags.MarkHidden("compress")
Expand Down Expand Up @@ -229,6 +234,14 @@ func imagePush(cmd *cobra.Command, args []string) error {
}
}

// Validate and copy the digest algorithm from CLI wrapper to ImagePushOptions
if pushOptions.DigestAlgorithm != "" {
if pushOptions.DigestAlgorithm != "sha256" && pushOptions.DigestAlgorithm != "sha512" {
return fmt.Errorf("invalid digest algorithm %q: must be sha256 or sha512", pushOptions.DigestAlgorithm)
}
}
pushOptions.ImagePushOptions.DigestAlgorithm = pushOptions.DigestAlgorithm

// Let's do all the remaining Yoga in the API to prevent us from scattering
// logic across (too) many parts of the code.
report, err := registry.ImageEngine().Push(registry.Context(), source, destination, pushOptions.ImagePushOptions)
Expand Down
13 changes: 13 additions & 0 deletions cmd/podman/manifest/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type manifestPushOptsWrapper struct {
CredentialsCLI string
signing common.SigningCLIOnlyOptions
DigestFile string
DigestAlgorithm string
}

var (
Expand Down Expand Up @@ -96,6 +97,10 @@ func init() {
flags.Int(compressionLevel, 0, "compression level to use")
_ = pushCmd.RegisterFlagCompletionFunc(compressionLevel, completion.AutocompleteNone)

digestFlagName := "digest"
flags.StringVar(&manifestPushOpts.DigestAlgorithm, digestFlagName, "", "Digest algorithm to use for content addressing (sha256, sha512). Defaults to value from storage.conf or sha256")
_ = pushCmd.RegisterFlagCompletionFunc(digestFlagName, completion.AutocompleteNone)

if registry.IsRemote() {
_ = flags.MarkHidden("cert-dir")
}
Expand Down Expand Up @@ -165,6 +170,14 @@ func push(cmd *cobra.Command, args []string) error {
}
}

// Validate and copy the digest algorithm from CLI wrapper to ImagePushOptions
if manifestPushOpts.DigestAlgorithm != "" {
if manifestPushOpts.DigestAlgorithm != "sha256" && manifestPushOpts.DigestAlgorithm != "sha512" {
return fmt.Errorf("invalid digest algorithm %q: must be sha256 or sha512", manifestPushOpts.DigestAlgorithm)
}
}
manifestPushOpts.ImagePushOptions.DigestAlgorithm = manifestPushOpts.DigestAlgorithm

digest, err := registry.ImageEngine().ManifestPush(registry.Context(), listImageSpec, destSpec, manifestPushOpts.ImagePushOptions)
if err != nil {
return err
Expand Down
42 changes: 25 additions & 17 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ module github.com/containers/podman/v5
// Warning: if there is a "toolchain" directive anywhere in this file (and most of the
// time there shouldn't be), its version must be an exact match to the "go" directive.

go 1.24.0
go 1.24.2

require (
github.com/Microsoft/go-winio v0.6.2
github.com/blang/semver/v4 v4.0.0
github.com/checkpoint-restore/checkpointctl v1.4.0
github.com/checkpoint-restore/go-criu/v7 v7.2.0
github.com/containernetworking/plugins v1.7.1
github.com/containernetworking/plugins v1.8.0
github.com/containers/buildah v1.41.1-0.20250829135344-3367a9bc2c9f
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/gvisor-tap-vsock v0.8.7
Expand Down Expand Up @@ -55,7 +55,7 @@ require (
github.com/opencontainers/runtime-spec v1.2.1
github.com/opencontainers/runtime-tools v0.9.1-0.20250523060157-0ea5ed0382a2
github.com/opencontainers/selinux v1.12.0
github.com/openshift/imagebuilder v1.2.16-0.20250828154754-e22ebd3ff511
github.com/openshift/imagebuilder v1.2.17
github.com/rootless-containers/rootlesskit/v2 v2.3.5
github.com/shirou/gopsutil/v4 v4.25.8
github.com/sirupsen/logrus v1.9.3
Expand Down Expand Up @@ -110,7 +110,7 @@ require (
github.com/ebitengine/purego v0.8.4 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fsouza/go-dockerclient v1.12.1 // indirect
github.com/fsouza/go-dockerclient v1.12.2 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
Expand All @@ -119,9 +119,9 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-containerregistry v0.20.3 // indirect
github.com/google/go-containerregistry v0.20.6 // indirect
github.com/google/go-intervals v0.0.2 // indirect
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
Expand All @@ -136,7 +136,7 @@ require (
github.com/mdlayher/socket v0.5.1 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
github.com/moby/buildkit v0.23.2 // indirect
github.com/moby/buildkit v0.24.0 // indirect
github.com/moby/go-archive v0.1.0 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/sys/mountinfo v0.7.2 // indirect
Expand All @@ -145,7 +145,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/runc v1.3.0 // indirect
github.com/opencontainers/runc v1.3.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/sftp v1.13.9 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
Expand All @@ -156,14 +156,14 @@ require (
github.com/seccomp/libseccomp-golang v0.11.1 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect
github.com/segmentio/ksuid v1.0.4 // indirect
github.com/sigstore/fulcio v1.6.6 // indirect
github.com/sigstore/fulcio v1.7.1 // indirect
github.com/sigstore/protobuf-specs v0.4.1 // indirect
github.com/sigstore/sigstore v1.9.5 // indirect
github.com/skeema/knownhosts v1.3.1 // indirect
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
github.com/smallstep/pkcs7 v0.1.1 // indirect
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect
github.com/sylabs/sif/v2 v2.21.1 // indirect
github.com/sylabs/sif/v2 v2.22.0 // indirect
github.com/tchap/go-patricia/v2 v2.3.3 // indirect
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
github.com/tklauser/go-sysconf v0.3.15 // indirect
Expand All @@ -174,21 +174,29 @@ require (
github.com/vishvananda/netns v0.0.5 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.36.0 // indirect
go.opentelemetry.io/otel/metric v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.36.0 // indirect
go.uber.org/automaxprocs v1.6.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/mod v0.27.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/oauth2 v0.31.0 // indirect
golang.org/x/text v0.29.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.36.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect
google.golang.org/grpc v1.72.2 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
tags.cncf.io/container-device-interface/specs-go v1.0.0 // indirect
)

replace go.podman.io/common => /home/lsm5/repositories/containers/container-libs/common/

replace go.podman.io/image/v5 => /home/lsm5/repositories/containers/container-libs/image

replace go.podman.io/storage => /home/lsm5/repositories/containers/container-libs/storage

replace github.com/containers/buildah => /home/lsm5/repositories/containers/buildah
Loading