vendor latest c/{buildah,common,image,storage}

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger
2024-11-01 13:58:18 +01:00
parent b209474d66
commit f6af35c695
156 changed files with 6396 additions and 3078 deletions

View File

@ -175,8 +175,8 @@ type Copier struct {
// newCopier creates a Copier based on a runtime's system context.
// Note that fields in options *may* overwrite the counterparts of
// the specified system context. Please make sure to call `(*Copier).Close()`.
func (r *Runtime) newCopier(options *CopyOptions) (*Copier, error) {
return NewCopier(options, r.SystemContext())
func (r *Runtime) newCopier(options *CopyOptions, reportResolvedReference *types.ImageReference) (*Copier, error) {
return NewCopier(options, r.SystemContext(), reportResolvedReference)
}
// storageAllowedPolicyScopes overrides the policy for local storage
@ -223,7 +223,7 @@ func getDockerAuthConfig(name, passwd, creds, idToken string) (*types.DockerAuth
// NewCopier creates a Copier based on a provided system context.
// Note that fields in options *may* overwrite the counterparts of
// the specified system context. Please make sure to call `(*Copier).Close()`.
func NewCopier(options *CopyOptions, sc *types.SystemContext) (*Copier, error) {
func NewCopier(options *CopyOptions, sc *types.SystemContext, reportResolvedReference *types.ImageReference) (*Copier, error) {
c := Copier{extendTimeoutSocket: options.extendTimeoutSocket}
sysContextCopy := *sc
c.systemContext = &sysContextCopy
@ -330,6 +330,7 @@ func NewCopier(options *CopyOptions, sc *types.SystemContext) (*Copier, error) {
c.imageCopyOptions.SignBySigstorePrivateKeyFile = options.SignBySigstorePrivateKeyFile
c.imageCopyOptions.SignSigstorePrivateKeyPassphrase = options.SignSigstorePrivateKeyPassphrase
c.imageCopyOptions.ReportWriter = options.Writer
c.imageCopyOptions.ReportResolvedReference = reportResolvedReference
defaultContainerConfig, err := config.Default()
if err != nil {

View File

@ -104,7 +104,7 @@ func (r *Runtime) Import(ctx context.Context, path string, options *ImportOption
return "", err
}
c, err := r.newCopier(&options.CopyOptions)
c, err := r.newCopier(&options.CopyOptions, nil)
if err != nil {
return "", err
}

View File

@ -792,7 +792,7 @@ func (m *ManifestList) Push(ctx context.Context, destination string, options *Ma
// NOTE: we're using the logic in copier to create a proper
// types.SystemContext. This prevents us from having an error prone
// code duplicate here.
copier, err := m.image.runtime.newCopier(&options.CopyOptions)
copier, err := m.image.runtime.newCopier(&options.CopyOptions, nil)
if err != nil {
return "", err
}

View File

@ -17,15 +17,14 @@ import (
dockerArchiveTransport "github.com/containers/image/v5/docker/archive"
dockerDaemonTransport "github.com/containers/image/v5/docker/daemon"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/manifest"
ociArchiveTransport "github.com/containers/image/v5/oci/archive"
ociTransport "github.com/containers/image/v5/oci/layout"
"github.com/containers/image/v5/pkg/shortnames"
storageTransport "github.com/containers/image/v5/storage"
"github.com/containers/image/v5/transports"
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
"github.com/containers/storage"
digest "github.com/opencontainers/go-digest"
ociSpec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/sirupsen/logrus"
)
@ -231,7 +230,7 @@ func nameFromAnnotations(annotations map[string]string) string {
// copyFromDefault is the default copier for a number of transports. Other
// transports require some specific dancing, sometimes Yoga.
func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference, options *CopyOptions) ([]string, error) {
c, err := r.newCopier(options)
c, err := r.newCopier(options, nil)
if err != nil {
return nil, err
}
@ -387,7 +386,7 @@ func (r *Runtime) copyFromDockerArchive(ctx context.Context, ref types.ImageRefe
// copyFromDockerArchiveReaderReference copies the specified readerRef from reader.
func (r *Runtime) copyFromDockerArchiveReaderReference(ctx context.Context, reader *dockerArchiveTransport.Reader, readerRef types.ImageReference, options *CopyOptions) ([]string, error) {
c, err := r.newCopier(options)
c, err := r.newCopier(options, nil)
if err != nil {
return nil, err
}
@ -421,7 +420,11 @@ func (r *Runtime) copyFromRegistry(ctx context.Context, ref types.ImageReference
}
if !options.AllTags {
return r.copySingleImageFromRegistry(ctx, inputName, pullPolicy, options)
pulled, err := r.copySingleImageFromRegistry(ctx, inputName, pullPolicy, options)
if err != nil {
return nil, err
}
return []string{pulled}, nil
}
// Copy all tags
@ -447,68 +450,19 @@ func (r *Runtime) copyFromRegistry(ctx context.Context, ref types.ImageReference
if err != nil {
return nil, err
}
pulledIDs = append(pulledIDs, pulled...)
pulledIDs = append(pulledIDs, pulled)
}
return pulledIDs, nil
}
// imageIDsForManifest() parses the manifest of the copied image and then looks
// up the IDs of the matching image. There's a small slice of time, between
// when we copy the image into local storage and when we go to look for it
// using the name that we gave it when we copied it, when the name we wanted to
// assign to the image could have been moved, but the image's ID will remain
// the same until it is deleted.
func (r *Runtime) imagesIDsForManifest(manifestBytes []byte, sys *types.SystemContext) ([]string, error) {
var imageDigest digest.Digest
manifestType := manifest.GuessMIMEType(manifestBytes)
if manifest.MIMETypeIsMultiImage(manifestType) {
list, err := manifest.ListFromBlob(manifestBytes, manifestType)
if err != nil {
return nil, fmt.Errorf("parsing manifest list: %w", err)
}
d, err := list.ChooseInstance(sys)
if err != nil {
return nil, fmt.Errorf("choosing instance from manifest list: %w", err)
}
imageDigest = d
} else {
d, err := manifest.Digest(manifestBytes)
if err != nil {
return nil, errors.New("digesting manifest")
}
imageDigest = d
}
images, err := r.store.ImagesByDigest(imageDigest)
if err != nil {
return nil, fmt.Errorf("listing images by manifest digest: %w", err)
}
// If you have additionStores defined and the same image stored in
// both storage and additional store, it can be output twice.
// Fixes github.com/containers/podman/issues/18647
results := []string{}
imageMap := map[string]bool{}
for _, image := range images {
if imageMap[image.ID] {
continue
}
imageMap[image.ID] = true
results = append(results, image.ID)
}
if len(results) == 0 {
return nil, fmt.Errorf("identifying new image by manifest digest: %w", storage.ErrImageUnknown)
}
return results, nil
}
// copySingleImageFromRegistry pulls the specified, possibly unqualified, name
// from a registry. On successful pull it returns the ID of the image in local
// storage.
func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName string, pullPolicy config.PullPolicy, options *PullOptions) ([]string, error) { //nolint:gocyclo
// storage (or, FIXME, a name/ID? that could be resolved in local storage)
func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName string, pullPolicy config.PullPolicy, options *PullOptions) (string, error) { //nolint:gocyclo
// Sanity check.
if err := pullPolicy.Validate(); err != nil {
return nil, err
return "", err
}
var (
@ -533,6 +487,14 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
if options.OS != runtime.GOOS {
lookupImageOptions.OS = options.OS
}
// FIXME: We sometimes return resolvedImageName from this function.
// The function documentation says this returns an image ID, resolvedImageName is frequently not an image ID.
//
// Ultimately Runtime.Pull looks up the returned name... again, possibly finding some other match
// than we did.
//
// This should be restructured so that the image we found here is returned to the caller of Pull
// directly, without another image -> name -> image round-trip and possible inconsistency.
localImage, resolvedImageName, err = r.LookupImage(imageName, lookupImageOptions)
if err != nil && !errors.Is(err, storage.ErrImageUnknown) {
logrus.Errorf("Looking up %s in local storage: %v", imageName, err)
@ -563,23 +525,23 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
if pullPolicy == config.PullPolicyNever {
if localImage != nil {
logrus.Debugf("Pull policy %q and %s resolved to local image %s", pullPolicy, imageName, resolvedImageName)
return []string{resolvedImageName}, nil
return resolvedImageName, nil
}
logrus.Debugf("Pull policy %q but no local image has been found for %s", pullPolicy, imageName)
return nil, fmt.Errorf("%s: %w", imageName, storage.ErrImageUnknown)
return "", fmt.Errorf("%s: %w", imageName, storage.ErrImageUnknown)
}
if pullPolicy == config.PullPolicyMissing && localImage != nil {
return []string{resolvedImageName}, nil
return resolvedImageName, nil
}
// If we looked up the image by ID, we cannot really pull from anywhere.
if localImage != nil && strings.HasPrefix(localImage.ID(), imageName) {
switch pullPolicy {
case config.PullPolicyAlways:
return nil, fmt.Errorf("pull policy is always but image has been referred to by ID (%s)", imageName)
return "", fmt.Errorf("pull policy is always but image has been referred to by ID (%s)", imageName)
default:
return []string{resolvedImageName}, nil
return resolvedImageName, nil
}
}
@ -604,9 +566,9 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
resolved, err := shortnames.Resolve(sys, imageName)
if err != nil {
if localImage != nil && pullPolicy == config.PullPolicyNewer {
return []string{resolvedImageName}, nil
return resolvedImageName, nil
}
return nil, err
return "", err
}
// NOTE: Below we print the description from the short-name resolution.
@ -636,9 +598,10 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
if socketPath, ok := os.LookupEnv("NOTIFY_SOCKET"); ok {
options.extendTimeoutSocket = socketPath
}
c, err := r.newCopier(&options.CopyOptions)
var resolvedReference types.ImageReference
c, err := r.newCopier(&options.CopyOptions, &resolvedReference)
if err != nil {
return nil, err
return "", err
}
defer c.Close()
@ -648,7 +611,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
logrus.Debugf("Attempting to pull candidate %s for %s", candidateString, imageName)
srcRef, err := registryTransport.NewReference(candidate.Value)
if err != nil {
return nil, err
return "", err
}
if pullPolicy == config.PullPolicyNewer && localImage != nil {
@ -666,19 +629,18 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
destRef, err := storageTransport.Transport.ParseStoreReference(r.store, candidate.Value.String())
if err != nil {
return nil, err
return "", err
}
if err := writeDesc(); err != nil {
return nil, err
return "", err
}
if options.Writer != nil {
if _, err := io.WriteString(options.Writer, fmt.Sprintf("Trying to pull %s...\n", candidateString)); err != nil {
return nil, err
return "", err
}
}
var manifestBytes []byte
if manifestBytes, err = c.Copy(ctx, srcRef, destRef); err != nil {
if _, err := c.Copy(ctx, srcRef, destRef); err != nil {
logrus.Debugf("Error pulling candidate %s: %v", candidateString, err)
pullErrors = append(pullErrors, err)
continue
@ -691,19 +653,23 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
}
logrus.Debugf("Pulled candidate %s successfully", candidateString)
if ids, err := r.imagesIDsForManifest(manifestBytes, sys); err == nil {
return ids, nil
if resolvedReference == nil { // resolvedReference should always be set for storageTransport destinations
return "", fmt.Errorf("internal error: After pulling %s, resolvedReference is nil", candidateString)
}
return []string{candidate.Value.String()}, nil
_, image, err := storageTransport.ResolveReference(resolvedReference)
if err != nil {
return "", fmt.Errorf("resolving an already-resolved reference %q to the pulled image: %w", transports.ImageName(resolvedReference), err)
}
return image.ID, nil
}
if localImage != nil && pullPolicy == config.PullPolicyNewer {
return []string{resolvedImageName}, nil
return resolvedImageName, nil
}
if len(pullErrors) == 0 {
return nil, fmt.Errorf("internal error: no image pulled (pull policy %s)", pullPolicy)
return "", fmt.Errorf("internal error: no image pulled (pull policy %s)", pullPolicy)
}
return nil, resolved.FormatPullErrors(pullErrors)
return "", resolved.FormatPullErrors(pullErrors)
}

View File

@ -109,7 +109,7 @@ func (r *Runtime) Push(ctx context.Context, source, destination string, options
}
}
c, err := r.newCopier(&options.CopyOptions)
c, err := r.newCopier(&options.CopyOptions, nil)
if err != nil {
return nil, err
}

View File

@ -119,7 +119,7 @@ func (r *Runtime) saveSingleImage(ctx context.Context, name, format, path string
return err
}
c, err := r.newCopier(&options.CopyOptions)
c, err := r.newCopier(&options.CopyOptions, nil)
if err != nil {
return err
}
@ -204,7 +204,7 @@ func (r *Runtime) saveDockerArchive(ctx context.Context, names []string, path st
copyOpts := options.CopyOptions
copyOpts.dockerArchiveAdditionalTags = local.tags
c, err := r.newCopier(&copyOpts)
c, err := r.newCopier(&copyOpts, nil)
if err != nil {
return err
}

View File

@ -201,7 +201,7 @@ func (n *Netns) setupPasta(nsPath string) error {
Netns: nsPath,
ExtraOptions: []string{"--pid", pidPath},
}
res, err := pasta.Setup2(&pastaOpts)
res, err := pasta.Setup(&pastaOpts)
if err != nil {
return fmt.Errorf("setting up Pasta: %w", err)
}

View File

@ -50,11 +50,6 @@ type SetupOptions struct {
ExtraOptions []string
}
// Setup2 alias for Setup()
func Setup2(opts *SetupOptions) (*SetupResult, error) {
return Setup(opts)
}
// Setup start the pasta process for the given netns.
// The pasta binary is looked up in the HelperBinariesDir and $PATH.
// Note that there is no need for any special cleanup logic, the pasta

View File

@ -16,14 +16,20 @@ import (
"strings"
"time"
// We are using skeema/knownhosts rather than
// golang.org/x/crypto/ssh/knownhosts because the
// latter has an issue when the first key returned
// by the server doesn't match the one in known_hosts:
// https://github.com/golang/go/issues/29286
// https://github.com/containers/podman/issues/23575
"github.com/containers/common/pkg/config"
"github.com/containers/storage/pkg/fileutils"
"github.com/containers/storage/pkg/homedir"
"github.com/pkg/sftp"
"github.com/sirupsen/logrus"
"github.com/skeema/knownhosts"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
"golang.org/x/crypto/ssh/knownhosts"
"golang.org/x/exp/maps"
)
@ -301,46 +307,44 @@ func ValidateAndConfigure(uri *url.URL, iden string, insecureIsMachineConnection
return nil, err
}
keyFilePath := filepath.Join(homedir.Get(), ".ssh", "known_hosts")
known, err := knownhosts.NewDB(keyFilePath)
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
return nil, err
}
keyDir := path.Dir(keyFilePath)
if err := fileutils.Exists(keyDir); errors.Is(err, os.ErrNotExist) {
if err := os.Mkdir(keyDir, 0o700); err != nil {
return nil, err
}
}
k, err := os.OpenFile(keyFilePath, os.O_RDWR|os.O_CREATE, 0o600)
if err != nil {
return nil, err
}
k.Close()
known, err = knownhosts.NewDB(keyFilePath)
if err != nil {
return nil, err
}
}
var callback ssh.HostKeyCallback
if insecureIsMachineConnection {
callback = ssh.InsecureIgnoreHostKey()
} else {
callback = ssh.HostKeyCallback(func(host string, remote net.Addr, pubKey ssh.PublicKey) error {
keyFilePath := filepath.Join(homedir.Get(), ".ssh", "known_hosts")
known, err := knownhosts.New(keyFilePath)
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
return err
}
keyDir := path.Dir(keyFilePath)
if err := fileutils.Exists(keyDir); errors.Is(err, os.ErrNotExist) {
if err := os.Mkdir(keyDir, 0o700); err != nil {
return err
}
}
k, err := os.OpenFile(keyFilePath, os.O_RDWR|os.O_CREATE, 0o600)
if err != nil {
return err
}
k.Close()
known, err = knownhosts.New(keyFilePath)
if err != nil {
return err
}
}
// we need to check if there is an error from reading known hosts for this public key and if there is an error, what is it, and why is it happening?
// if it is a key mismatch we want to error since we know the host using another key
// however, if it is a general error not because of a known key, we want to add our key to the known_hosts file
hErr := known(host, remote, pubKey)
var keyErr *knownhosts.KeyError
// if keyErr.Want is not empty, we are receiving a different key meaning the host is known but we are using the wrong key
as := errors.As(hErr, &keyErr)
hErr := known.HostKeyCallback()(host, remote, pubKey)
switch {
case as && len(keyErr.Want) > 0:
case knownhosts.IsHostKeyChanged(hErr):
logrus.Warnf("ssh host key mismatch for host %s, got key %s of type %s", host, ssh.FingerprintSHA256(pubKey), pubKey.Type())
return keyErr
return hErr
// if keyErr.Want is empty that just means we do not know this host yet, add it.
case as && len(keyErr.Want) == 0:
case knownhosts.IsHostUnknown(hErr):
// write to known_hosts
err := addKnownHostsEntry(host, pubKey)
if err != nil {
@ -358,10 +362,11 @@ func ValidateAndConfigure(uri *url.URL, iden string, insecureIsMachineConnection
}
cfg := &ssh.ClientConfig{
User: uri.User.Username(),
Auth: authMethods,
HostKeyCallback: callback,
Timeout: tick,
User: uri.User.Username(),
Auth: authMethods,
HostKeyCallback: callback,
Timeout: tick,
HostKeyAlgorithms: known.HostKeyAlgorithms(uri.Host),
}
return cfg, nil
}

View File

@ -23,18 +23,20 @@ func ConfigureContainerTimeZone(timezone, containerRunDir, mountPoint, etcPath,
switch {
case timezone == "":
return "", nil
case os.Getenv("TZDIR") != "":
// Allow using TZDIR per:
// https://sourceware.org/git/?p=glibc.git;a=blob;f=time/tzfile.c;h=8a923d0cccc927a106dc3e3c641be310893bab4e;hb=HEAD#l149
timezonePath = filepath.Join(os.Getenv("TZDIR"), timezone)
case timezone == "local":
timezonePath, err = filepath.EvalSymlinks("/etc/localtime")
if err != nil {
return "", fmt.Errorf("finding local timezone for container %s: %w", containerID, err)
}
default:
timezonePath = filepath.Join("/usr/share/zoneinfo", timezone)
// Allow using TZDIR per:
// https://sourceware.org/git/?p=glibc.git;a=blob;f=time/tzfile.c;h=8a923d0cccc927a106dc3e3c641be310893bab4e;hb=HEAD#l149
zoneinfo := os.Getenv("TZDIR")
if zoneinfo == "" {
// default zoneinfo location
zoneinfo = "/usr/share/zoneinfo"
}
timezonePath = filepath.Join(zoneinfo, timezone)
}
etcFd, err := openDirectory(etcPath)