Merge pull request #2516 from rhatdan/secrets
Move secrets package to buildah
This commit is contained in:
		
						commit
						d95f97a63e
					
				|  | @ -18,13 +18,13 @@ import ( | |||
| 
 | ||||
| 	cnitypes "github.com/containernetworking/cni/pkg/types/current" | ||||
| 	"github.com/containernetworking/plugins/pkg/ns" | ||||
| 	"github.com/containers/buildah/pkg/secrets" | ||||
| 	crioAnnotations "github.com/containers/libpod/pkg/annotations" | ||||
| 	"github.com/containers/libpod/pkg/apparmor" | ||||
| 	"github.com/containers/libpod/pkg/criu" | ||||
| 	"github.com/containers/libpod/pkg/lookup" | ||||
| 	"github.com/containers/libpod/pkg/resolvconf" | ||||
| 	"github.com/containers/libpod/pkg/rootless" | ||||
| 	"github.com/containers/libpod/pkg/secrets" | ||||
| 	"github.com/containers/storage/pkg/idtools" | ||||
| 	"github.com/opencontainers/runc/libcontainer/user" | ||||
| 	spec "github.com/opencontainers/runtime-spec/specs-go" | ||||
|  |  | |||
|  | @ -1,323 +0,0 @@ | |||
| package secrets | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/containers/libpod/pkg/rootless" | ||||
| 	"github.com/containers/storage/pkg/idtools" | ||||
| 	rspec "github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/opencontainers/selinux/go-selinux/label" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	// DefaultMountsFile holds the default mount paths in the form
 | ||||
| 	// "host_path:container_path"
 | ||||
| 	DefaultMountsFile = "/usr/share/containers/mounts.conf" | ||||
| 	// OverrideMountsFile holds the default mount paths in the form
 | ||||
| 	// "host_path:container_path" overridden by the user
 | ||||
| 	OverrideMountsFile = "/etc/containers/mounts.conf" | ||||
| 	// UserOverrideMountsFile holds the default mount paths in the form
 | ||||
| 	// "host_path:container_path" overridden by the rootless user
 | ||||
| 	UserOverrideMountsFile = filepath.Join(os.Getenv("HOME"), ".config/containers/mounts.conf") | ||||
| ) | ||||
| 
 | ||||
| // secretData stores the name of the file and the content read from it
 | ||||
| type secretData struct { | ||||
| 	name string | ||||
| 	data []byte | ||||
| } | ||||
| 
 | ||||
| // saveTo saves secret data to given directory
 | ||||
| func (s secretData) saveTo(dir string) error { | ||||
| 	path := filepath.Join(dir, s.name) | ||||
| 	if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil && !os.IsExist(err) { | ||||
| 		return err | ||||
| 	} | ||||
| 	return ioutil.WriteFile(path, s.data, 0700) | ||||
| } | ||||
| 
 | ||||
| func readAll(root, prefix string) ([]secretData, error) { | ||||
| 	path := filepath.Join(root, prefix) | ||||
| 
 | ||||
| 	data := []secretData{} | ||||
| 
 | ||||
| 	files, err := ioutil.ReadDir(path) | ||||
| 	if err != nil { | ||||
| 		if os.IsNotExist(err) { | ||||
| 			return data, nil | ||||
| 		} | ||||
| 
 | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	for _, f := range files { | ||||
| 		fileData, err := readFile(root, filepath.Join(prefix, f.Name())) | ||||
| 		if err != nil { | ||||
| 			// If the file did not exist, might be a dangling symlink
 | ||||
| 			// Ignore the error
 | ||||
| 			if os.IsNotExist(err) { | ||||
| 				continue | ||||
| 			} | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		data = append(data, fileData...) | ||||
| 	} | ||||
| 
 | ||||
| 	return data, nil | ||||
| } | ||||
| 
 | ||||
| func readFile(root, name string) ([]secretData, error) { | ||||
| 	path := filepath.Join(root, name) | ||||
| 
 | ||||
| 	s, err := os.Stat(path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	if s.IsDir() { | ||||
| 		dirData, err := readAll(root, name) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return dirData, nil | ||||
| 	} | ||||
| 	bytes, err := ioutil.ReadFile(path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return []secretData{{name: name, data: bytes}}, nil | ||||
| } | ||||
| 
 | ||||
| func getHostSecretData(hostDir string) ([]secretData, error) { | ||||
| 	var allSecrets []secretData | ||||
| 	hostSecrets, err := readAll(hostDir, "") | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrapf(err, "failed to read secrets from %q", hostDir) | ||||
| 	} | ||||
| 	return append(allSecrets, hostSecrets...), nil | ||||
| } | ||||
| 
 | ||||
| func getMounts(filePath string) []string { | ||||
| 	file, err := os.Open(filePath) | ||||
| 	if err != nil { | ||||
| 		// This is expected on most systems
 | ||||
| 		logrus.Debugf("file %q not found, skipping...", filePath) | ||||
| 		return nil | ||||
| 	} | ||||
| 	defer file.Close() | ||||
| 	scanner := bufio.NewScanner(file) | ||||
| 	if err = scanner.Err(); err != nil { | ||||
| 		logrus.Errorf("error reading file %q, %v skipping...", filePath, err) | ||||
| 		return nil | ||||
| 	} | ||||
| 	var mounts []string | ||||
| 	for scanner.Scan() { | ||||
| 		mounts = append(mounts, scanner.Text()) | ||||
| 	} | ||||
| 	return mounts | ||||
| } | ||||
| 
 | ||||
| // getHostAndCtrDir separates the host:container paths
 | ||||
| func getMountsMap(path string) (string, string, error) { | ||||
| 	arr := strings.SplitN(path, ":", 2) | ||||
| 	if len(arr) == 2 { | ||||
| 		return arr[0], arr[1], nil | ||||
| 	} | ||||
| 	return "", "", errors.Errorf("unable to get host and container dir") | ||||
| } | ||||
| 
 | ||||
| // SecretMounts copies, adds, and mounts the secrets to the container root filesystem
 | ||||
| func SecretMounts(mountLabel, containerWorkingDir, mountFile string) []rspec.Mount { | ||||
| 	return SecretMountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, containerWorkingDir, 0, 0) | ||||
| } | ||||
| 
 | ||||
| // SecretMountsWithUIDGID specifies the uid/gid of the owner
 | ||||
| func SecretMountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPrefix string, uid, gid int) []rspec.Mount { | ||||
| 	var ( | ||||
| 		secretMounts []rspec.Mount | ||||
| 		mountFiles   []string | ||||
| 	) | ||||
| 	// Add secrets from paths given in the mounts.conf files
 | ||||
| 	// mountFile will have a value if the hidden --default-mounts-file flag is set
 | ||||
| 	// Note for testing purposes only
 | ||||
| 	if mountFile == "" { | ||||
| 		mountFiles = append(mountFiles, []string{OverrideMountsFile, DefaultMountsFile}...) | ||||
| 		if rootless.IsRootless() { | ||||
| 			mountFiles = append([]string{UserOverrideMountsFile}, mountFiles...) | ||||
| 			_, err := os.Stat(UserOverrideMountsFile) | ||||
| 			if err != nil && os.IsNotExist(err) { | ||||
| 				os.MkdirAll(filepath.Dir(UserOverrideMountsFile), 0755) | ||||
| 				if f, err := os.Create(UserOverrideMountsFile); err != nil { | ||||
| 					logrus.Warnf("could not create file %s: %v", UserOverrideMountsFile, err) | ||||
| 				} else { | ||||
| 					f.Close() | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} else { | ||||
| 		mountFiles = append(mountFiles, mountFile) | ||||
| 	} | ||||
| 	for _, file := range mountFiles { | ||||
| 		if _, err := os.Stat(file); err == nil { | ||||
| 			mounts, err := addSecretsFromMountsFile(file, mountLabel, containerWorkingDir, mountPrefix, uid, gid) | ||||
| 			if err != nil { | ||||
| 				logrus.Warnf("error mounting secrets, skipping: %v", err) | ||||
| 			} | ||||
| 			secretMounts = mounts | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Add FIPS mode secret if /etc/system-fips exists on the host
 | ||||
| 	_, err := os.Stat("/etc/system-fips") | ||||
| 	if err == nil { | ||||
| 		if err := addFIPSModeSecret(&secretMounts, containerWorkingDir, mountPrefix, mountLabel, uid, gid); err != nil { | ||||
| 			logrus.Errorf("error adding FIPS mode secret to container: %v", err) | ||||
| 		} | ||||
| 	} else if os.IsNotExist(err) { | ||||
| 		logrus.Debug("/etc/system-fips does not exist on host, not mounting FIPS mode secret") | ||||
| 	} else { | ||||
| 		logrus.Errorf("stat /etc/system-fips failed for FIPS mode secret: %v", err) | ||||
| 	} | ||||
| 	return secretMounts | ||||
| } | ||||
| 
 | ||||
| func rchown(chowndir string, uid, gid int) error { | ||||
| 	return filepath.Walk(chowndir, func(filePath string, f os.FileInfo, err error) error { | ||||
| 		return os.Lchown(filePath, uid, gid) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // addSecretsFromMountsFile copies the contents of host directory to container directory
 | ||||
| // and returns a list of mounts
 | ||||
| func addSecretsFromMountsFile(filePath, mountLabel, containerWorkingDir, mountPrefix string, uid, gid int) ([]rspec.Mount, error) { | ||||
| 	var mounts []rspec.Mount | ||||
| 	defaultMountsPaths := getMounts(filePath) | ||||
| 	for _, path := range defaultMountsPaths { | ||||
| 		hostDir, ctrDir, err := getMountsMap(path) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		// skip if the hostDir path doesn't exist
 | ||||
| 		if _, err = os.Stat(hostDir); err != nil { | ||||
| 			if os.IsNotExist(err) { | ||||
| 				logrus.Warnf("Path %q from %q doesn't exist, skipping", hostDir, filePath) | ||||
| 				continue | ||||
| 			} | ||||
| 			return nil, errors.Wrapf(err, "failed to stat %q", hostDir) | ||||
| 		} | ||||
| 
 | ||||
| 		ctrDirOnHost := filepath.Join(containerWorkingDir, ctrDir) | ||||
| 
 | ||||
| 		// In the event of a restart, don't want to copy secrets over again as they already would exist in ctrDirOnHost
 | ||||
| 		_, err = os.Stat(ctrDirOnHost) | ||||
| 		if os.IsNotExist(err) { | ||||
| 			if err = os.MkdirAll(ctrDirOnHost, 0755); err != nil { | ||||
| 				return nil, errors.Wrapf(err, "making container directory %q failed", ctrDirOnHost) | ||||
| 			} | ||||
| 			hostDir, err = resolveSymbolicLink(hostDir) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 
 | ||||
| 			data, err := getHostSecretData(hostDir) | ||||
| 			if err != nil { | ||||
| 				return nil, errors.Wrapf(err, "getting host secret data failed") | ||||
| 			} | ||||
| 			for _, s := range data { | ||||
| 				if err := s.saveTo(ctrDirOnHost); err != nil { | ||||
| 					return nil, errors.Wrapf(err, "error saving data to container filesystem on host %q", ctrDirOnHost) | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			err = label.Relabel(ctrDirOnHost, mountLabel, false) | ||||
| 			if err != nil { | ||||
| 				return nil, errors.Wrap(err, "error applying correct labels") | ||||
| 			} | ||||
| 			if uid != 0 || gid != 0 { | ||||
| 				if err := rchown(ctrDirOnHost, uid, gid); err != nil { | ||||
| 					return nil, err | ||||
| 				} | ||||
| 			} | ||||
| 		} else if err != nil { | ||||
| 			return nil, errors.Wrapf(err, "error getting status of %q", ctrDirOnHost) | ||||
| 		} | ||||
| 
 | ||||
| 		m := rspec.Mount{ | ||||
| 			Source:      filepath.Join(mountPrefix, ctrDir), | ||||
| 			Destination: ctrDir, | ||||
| 			Type:        "bind", | ||||
| 			Options:     []string{"bind", "rprivate"}, | ||||
| 		} | ||||
| 
 | ||||
| 		mounts = append(mounts, m) | ||||
| 	} | ||||
| 	return mounts, nil | ||||
| } | ||||
| 
 | ||||
| // addFIPSModeSecret creates /run/secrets/system-fips in the container
 | ||||
| // root filesystem if /etc/system-fips exists on hosts.
 | ||||
| // This enables the container to be FIPS compliant and run openssl in
 | ||||
| // FIPS mode as the host is also in FIPS mode.
 | ||||
| func addFIPSModeSecret(mounts *[]rspec.Mount, containerWorkingDir, mountPrefix, mountLabel string, uid, gid int) error { | ||||
| 	secretsDir := "/run/secrets" | ||||
| 	ctrDirOnHost := filepath.Join(containerWorkingDir, secretsDir) | ||||
| 	if _, err := os.Stat(ctrDirOnHost); os.IsNotExist(err) { | ||||
| 		if err = idtools.MkdirAllAs(ctrDirOnHost, 0755, uid, gid); err != nil { | ||||
| 			return errors.Wrapf(err, "making container directory on host failed") | ||||
| 		} | ||||
| 		if err = label.Relabel(ctrDirOnHost, mountLabel, false); err != nil { | ||||
| 			return errors.Wrap(err, "error applying correct labels") | ||||
| 		} | ||||
| 	} | ||||
| 	fipsFile := filepath.Join(ctrDirOnHost, "system-fips") | ||||
| 	// In the event of restart, it is possible for the FIPS mode file to already exist
 | ||||
| 	if _, err := os.Stat(fipsFile); os.IsNotExist(err) { | ||||
| 		file, err := os.Create(fipsFile) | ||||
| 		if err != nil { | ||||
| 			return errors.Wrapf(err, "error creating system-fips file in container for FIPS mode") | ||||
| 		} | ||||
| 		defer file.Close() | ||||
| 	} | ||||
| 
 | ||||
| 	if !mountExists(*mounts, secretsDir) { | ||||
| 		m := rspec.Mount{ | ||||
| 			Source:      filepath.Join(mountPrefix, secretsDir), | ||||
| 			Destination: secretsDir, | ||||
| 			Type:        "bind", | ||||
| 			Options:     []string{"bind", "rprivate"}, | ||||
| 		} | ||||
| 		*mounts = append(*mounts, m) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // mountExists checks if a mount already exists in the spec
 | ||||
| func mountExists(mounts []rspec.Mount, dest string) bool { | ||||
| 	for _, mount := range mounts { | ||||
| 		if mount.Destination == dest { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // resolveSymbolicLink resolves a possbile symlink path. If the path is a symlink, returns resolved
 | ||||
| // path; if not, returns the original path.
 | ||||
| func resolveSymbolicLink(path string) (string, error) { | ||||
| 	info, err := os.Lstat(path) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	if info.Mode()&os.ModeSymlink != os.ModeSymlink { | ||||
| 		return path, nil | ||||
| 	} | ||||
| 	return filepath.EvalSymlinks(path) | ||||
| } | ||||
|  | @ -93,7 +93,7 @@ k8s.io/apimachinery kubernetes-1.10.13-beta.0 https://github.com/kubernetes/apim | |||
| k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go | ||||
| github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7 | ||||
| github.com/varlink/go 3ac79db6fd6aec70924193b090962f92985fe199 | ||||
| github.com/containers/buildah v1.7.1 | ||||
| github.com/containers/buildah 11dd2197dfffedb40687de1d667e6c9fb0708de9 | ||||
| # TODO: Gotty has not been updated since 2012. Can we find replacement? | ||||
| github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512 | ||||
| # do not go beyond the below commit as the next one requires a more recent | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ const ( | |||
| 	Package = "buildah" | ||||
| 	// Version for the Package.  Bump version in contrib/rpm/buildah.spec
 | ||||
| 	// too.
 | ||||
| 	Version = "1.7.1" | ||||
| 	Version = "1.8-dev" | ||||
| 	// The value we use to identify what type of information, currently a
 | ||||
| 	// serialized Builder structure, we are using as per-container state.
 | ||||
| 	// This should only be changed when we make incompatible changes to
 | ||||
|  |  | |||
|  | @ -22,27 +22,23 @@ const ( | |||
| 	// BaseImageFakeName is the "name" of a source image which we interpret
 | ||||
| 	// as "no image".
 | ||||
| 	BaseImageFakeName = imagebuilder.NoBaseImageSpecifier | ||||
| 
 | ||||
| 	// minimumTruncatedIDLength is the minimum length of an identifier that
 | ||||
| 	// we'll accept as possibly being a truncated image ID.
 | ||||
| 	minimumTruncatedIDLength = 3 | ||||
| ) | ||||
| 
 | ||||
| func pullAndFindImage(ctx context.Context, store storage.Store, transport string, imageName string, options BuilderOptions, sc *types.SystemContext) (*storage.Image, types.ImageReference, error) { | ||||
| func pullAndFindImage(ctx context.Context, store storage.Store, srcRef types.ImageReference, options BuilderOptions, sc *types.SystemContext) (*storage.Image, types.ImageReference, error) { | ||||
| 	pullOptions := PullOptions{ | ||||
| 		ReportWriter:  options.ReportWriter, | ||||
| 		Store:         store, | ||||
| 		SystemContext: options.SystemContext, | ||||
| 		BlobDirectory: options.PullBlobDirectory, | ||||
| 	} | ||||
| 	ref, err := pullImage(ctx, store, transport, imageName, pullOptions, sc) | ||||
| 	ref, err := pullImage(ctx, store, srcRef, pullOptions, sc) | ||||
| 	if err != nil { | ||||
| 		logrus.Debugf("error pulling image %q: %v", imageName, err) | ||||
| 		logrus.Debugf("error pulling image %q: %v", transports.ImageName(srcRef), err) | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	img, err := is.Transport.GetStoreImage(store, ref) | ||||
| 	if err != nil { | ||||
| 		logrus.Debugf("error reading pulled image %q: %v", imageName, err) | ||||
| 		logrus.Debugf("error reading pulled image %q: %v", transports.ImageName(srcRef), err) | ||||
| 		return nil, nil, errors.Wrapf(err, "error locating image %q in local storage", transports.ImageName(ref)) | ||||
| 	} | ||||
| 	return img, ref, nil | ||||
|  | @ -112,19 +108,36 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store | |||
| 
 | ||||
| 	failures := []failure{} | ||||
| 	for _, image := range candidates { | ||||
| 		var err error | ||||
| 		if len(image) >= minimumTruncatedIDLength { | ||||
| 			if img, err := store.Image(image); err == nil && img != nil && strings.HasPrefix(img.ID, image) { | ||||
| 				ref, err := is.Transport.ParseStoreReference(store, img.ID) | ||||
| 				if err != nil { | ||||
| 					return nil, "", nil, errors.Wrapf(err, "error parsing reference to image %q", img.ID) | ||||
| 				} | ||||
| 				return ref, transport, img, nil | ||||
| 		if transport == "" { | ||||
| 			img, err := store.Image(image) | ||||
| 			if err != nil { | ||||
| 				logrus.Debugf("error looking up known-local image %q: %v", image, err) | ||||
| 				failures = append(failures, failure{resolvedImageName: image, err: err}) | ||||
| 				continue | ||||
| 			} | ||||
| 			ref, err := is.Transport.ParseStoreReference(store, img.ID) | ||||
| 			if err != nil { | ||||
| 				return nil, "", nil, errors.Wrapf(err, "error parsing reference to image %q", img.ID) | ||||
| 			} | ||||
| 			return ref, transport, img, nil | ||||
| 		} | ||||
| 
 | ||||
| 		trans := transport | ||||
| 		if transport != util.DefaultTransport { | ||||
| 			trans = trans + ":" | ||||
| 		} | ||||
| 		srcRef, err := alltransports.ParseImageName(trans + image) | ||||
| 		if err != nil { | ||||
| 			logrus.Debugf("error parsing image name %q: %v", trans+image, err) | ||||
| 			failures = append(failures, failure{ | ||||
| 				resolvedImageName: image, | ||||
| 				err:               errors.Wrapf(err, "error parsing attempted image name %q", trans+image), | ||||
| 			}) | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		if options.PullPolicy == PullAlways { | ||||
| 			pulledImg, pulledReference, err := pullAndFindImage(ctx, store, transport, image, options, systemContext) | ||||
| 			pulledImg, pulledReference, err := pullAndFindImage(ctx, store, srcRef, options, systemContext) | ||||
| 			if err != nil { | ||||
| 				logrus.Debugf("unable to pull and read image %q: %v", image, err) | ||||
| 				failures = append(failures, failure{resolvedImageName: image, err: err}) | ||||
|  | @ -133,35 +146,7 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store | |||
| 			return pulledReference, transport, pulledImg, nil | ||||
| 		} | ||||
| 
 | ||||
| 		srcRef, err := alltransports.ParseImageName(image) | ||||
| 		if err != nil { | ||||
| 			if transport == "" { | ||||
| 				logrus.Debugf("error parsing image name %q: %v", image, err) | ||||
| 				failures = append(failures, failure{ | ||||
| 					resolvedImageName: image, | ||||
| 					err:               errors.Wrapf(err, "error parsing image name"), | ||||
| 				}) | ||||
| 				continue | ||||
| 			} | ||||
| 			logrus.Debugf("error parsing image name %q as given, trying with transport %q: %v", image, transport, err) | ||||
| 
 | ||||
| 			trans := transport | ||||
| 			if transport != util.DefaultTransport { | ||||
| 				trans = trans + ":" | ||||
| 			} | ||||
| 			srcRef2, err := alltransports.ParseImageName(trans + image) | ||||
| 			if err != nil { | ||||
| 				logrus.Debugf("error parsing image name %q: %v", transport+image, err) | ||||
| 				failures = append(failures, failure{ | ||||
| 					resolvedImageName: image, | ||||
| 					err:               errors.Wrapf(err, "error parsing attempted image name %q", transport+image), | ||||
| 				}) | ||||
| 				continue | ||||
| 			} | ||||
| 			srcRef = srcRef2 | ||||
| 		} | ||||
| 
 | ||||
| 		destImage, err := localImageNameForReference(ctx, store, srcRef, options.FromImage) | ||||
| 		destImage, err := localImageNameForReference(ctx, store, srcRef) | ||||
| 		if err != nil { | ||||
| 			return nil, "", nil, errors.Wrapf(err, "error computing local image name for %q", transports.ImageName(srcRef)) | ||||
| 		} | ||||
|  | @ -187,7 +172,7 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store | |||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		pulledImg, pulledReference, err := pullAndFindImage(ctx, store, transport, image, options, systemContext) | ||||
| 		pulledImg, pulledReference, err := pullAndFindImage(ctx, store, srcRef, options, systemContext) | ||||
| 		if err != nil { | ||||
| 			logrus.Debugf("unable to pull and read image %q: %v", image, err) | ||||
| 			failures = append(failures, failure{resolvedImageName: image, err: err}) | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ import ( | |||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/containers/libpod/pkg/rootless" | ||||
| 	"github.com/containers/storage/pkg/idtools" | ||||
| 	rspec "github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/opencontainers/selinux/go-selinux/label" | ||||
| 	"github.com/pkg/errors" | ||||
|  | @ -176,7 +177,7 @@ func SecretMountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPre | |||
| 	// Add FIPS mode secret if /etc/system-fips exists on the host
 | ||||
| 	_, err := os.Stat("/etc/system-fips") | ||||
| 	if err == nil { | ||||
| 		if err := addFIPSModeSecret(&secretMounts, containerWorkingDir); err != nil { | ||||
| 		if err := addFIPSModeSecret(&secretMounts, containerWorkingDir, mountPrefix, mountLabel, uid, gid); err != nil { | ||||
| 			logrus.Errorf("error adding FIPS mode secret to container: %v", err) | ||||
| 		} | ||||
| 	} else if os.IsNotExist(err) { | ||||
|  | @ -264,13 +265,16 @@ func addSecretsFromMountsFile(filePath, mountLabel, containerWorkingDir, mountPr | |||
| // root filesystem if /etc/system-fips exists on hosts.
 | ||||
| // This enables the container to be FIPS compliant and run openssl in
 | ||||
| // FIPS mode as the host is also in FIPS mode.
 | ||||
| func addFIPSModeSecret(mounts *[]rspec.Mount, containerWorkingDir string) error { | ||||
| func addFIPSModeSecret(mounts *[]rspec.Mount, containerWorkingDir, mountPrefix, mountLabel string, uid, gid int) error { | ||||
| 	secretsDir := "/run/secrets" | ||||
| 	ctrDirOnHost := filepath.Join(containerWorkingDir, secretsDir) | ||||
| 	if _, err := os.Stat(ctrDirOnHost); os.IsNotExist(err) { | ||||
| 		if err = os.MkdirAll(ctrDirOnHost, 0755); err != nil { | ||||
| 		if err = idtools.MkdirAllAs(ctrDirOnHost, 0755, uid, gid); err != nil { | ||||
| 			return errors.Wrapf(err, "making container directory on host failed") | ||||
| 		} | ||||
| 		if err = label.Relabel(ctrDirOnHost, mountLabel, false); err != nil { | ||||
| 			return errors.Wrap(err, "error applying correct labels") | ||||
| 		} | ||||
| 	} | ||||
| 	fipsFile := filepath.Join(ctrDirOnHost, "system-fips") | ||||
| 	// In the event of restart, it is possible for the FIPS mode file to already exist
 | ||||
|  | @ -284,7 +288,7 @@ func addFIPSModeSecret(mounts *[]rspec.Mount, containerWorkingDir string) error | |||
| 
 | ||||
| 	if !mountExists(*mounts, secretsDir) { | ||||
| 		m := rspec.Mount{ | ||||
| 			Source:      ctrDirOnHost, | ||||
| 			Source:      filepath.Join(mountPrefix, secretsDir), | ||||
| 			Destination: secretsDir, | ||||
| 			Type:        "bind", | ||||
| 			Options:     []string{"bind", "rprivate"}, | ||||
|  |  | |||
|  | @ -19,10 +19,9 @@ import ( | |||
| 	"github.com/containers/image/signature" | ||||
| 	is "github.com/containers/image/storage" | ||||
| 	"github.com/containers/image/transports" | ||||
| 	"github.com/containers/image/transports/alltransports" | ||||
| 	"github.com/containers/image/types" | ||||
| 	"github.com/containers/storage" | ||||
| 	"github.com/hashicorp/go-multierror" | ||||
| 	multierror "github.com/hashicorp/go-multierror" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | @ -52,15 +51,14 @@ type PullOptions struct { | |||
| 	AllTags bool | ||||
| } | ||||
| 
 | ||||
| func localImageNameForReference(ctx context.Context, store storage.Store, srcRef types.ImageReference, spec string) (string, error) { | ||||
| func localImageNameForReference(ctx context.Context, store storage.Store, srcRef types.ImageReference) (string, error) { | ||||
| 	if srcRef == nil { | ||||
| 		return "", errors.Errorf("reference to image is empty") | ||||
| 	} | ||||
| 	split := strings.SplitN(spec, ":", 2) | ||||
| 	file := split[len(split)-1] | ||||
| 	var name string | ||||
| 	switch srcRef.Transport().Name() { | ||||
| 	case dockerarchive.Transport.Name(): | ||||
| 		file := srcRef.StringWithinTransport() | ||||
| 		tarSource, err := tarfile.NewSourceFromFile(file) | ||||
| 		if err != nil { | ||||
| 			return "", errors.Wrapf(err, "error opening tarfile %q as a source image", file) | ||||
|  | @ -104,14 +102,15 @@ func localImageNameForReference(ctx context.Context, store storage.Store, srcRef | |||
| 		} | ||||
| 	case directory.Transport.Name(): | ||||
| 		// supports pull from a directory
 | ||||
| 		name = split[1] | ||||
| 		name = srcRef.StringWithinTransport() | ||||
| 		// remove leading "/"
 | ||||
| 		if name[:1] == "/" { | ||||
| 			name = name[1:] | ||||
| 		} | ||||
| 	case oci.Transport.Name(): | ||||
| 		// supports pull from a directory
 | ||||
| 		name = split[1] | ||||
| 		split := strings.SplitN(srcRef.StringWithinTransport(), ":", 2) | ||||
| 		name = split[0] | ||||
| 		// remove leading "/"
 | ||||
| 		if name[:1] == "/" { | ||||
| 			name = name[1:] | ||||
|  | @ -175,21 +174,29 @@ func Pull(ctx context.Context, imageName string, options PullOptions) error { | |||
| 			return errors.New("Non-docker transport is not supported, for --all-tags pulling") | ||||
| 		} | ||||
| 
 | ||||
| 		spec := transport + storageRef.DockerReference().Name() | ||||
| 		storageRef, err = alltransports.ParseImageName(spec) | ||||
| 		repo := reference.TrimNamed(storageRef.DockerReference()) | ||||
| 		dockerRef, err := docker.NewReference(reference.TagNameOnly(storageRef.DockerReference())) | ||||
| 		if err != nil { | ||||
| 			return errors.Wrapf(err, "error getting repository tags") | ||||
| 			return errors.Wrapf(err, "internal error creating docker.Transport reference for %s", storageRef.DockerReference().String()) | ||||
| 		} | ||||
| 		tags, err := docker.GetRepositoryTags(ctx, systemContext, storageRef) | ||||
| 		tags, err := docker.GetRepositoryTags(ctx, systemContext, dockerRef) | ||||
| 		if err != nil { | ||||
| 			return errors.Wrapf(err, "error getting repository tags") | ||||
| 		} | ||||
| 		for _, tag := range tags { | ||||
| 			name := spec + ":" + tag | ||||
| 			if options.ReportWriter != nil { | ||||
| 				options.ReportWriter.Write([]byte("Pulling " + name + "\n")) | ||||
| 			tagged, err := reference.WithTag(repo, tag) | ||||
| 			if err != nil { | ||||
| 				errs = multierror.Append(errs, err) | ||||
| 				continue | ||||
| 			} | ||||
| 			ref, err := pullImage(ctx, options.Store, transport, name, options, systemContext) | ||||
| 			taggedRef, err := docker.NewReference(tagged) | ||||
| 			if err != nil { | ||||
| 				return errors.Wrapf(err, "internal error creating docker.Transport reference for %s", tagged.String()) | ||||
| 			} | ||||
| 			if options.ReportWriter != nil { | ||||
| 				options.ReportWriter.Write([]byte("Pulling " + tagged.String() + "\n")) | ||||
| 			} | ||||
| 			ref, err := pullImage(ctx, options.Store, taggedRef, options, systemContext) | ||||
| 			if err != nil { | ||||
| 				errs = multierror.Append(errs, err) | ||||
| 				continue | ||||
|  | @ -208,27 +215,7 @@ func Pull(ctx context.Context, imageName string, options PullOptions) error { | |||
| 	return errs.ErrorOrNil() | ||||
| } | ||||
| 
 | ||||
| func pullImage(ctx context.Context, store storage.Store, transport string, imageName string, options PullOptions, sc *types.SystemContext) (types.ImageReference, error) { | ||||
| 	spec := imageName | ||||
| 	srcRef, err := alltransports.ParseImageName(spec) | ||||
| 	if err != nil { | ||||
| 		logrus.Debugf("error parsing image name %q, trying with transport %q: %v", spec, transport, err) | ||||
| 		if transport == "" { | ||||
| 			transport = util.DefaultTransport | ||||
| 		} else { | ||||
| 			if transport != util.DefaultTransport { | ||||
| 				transport = transport + ":" | ||||
| 			} | ||||
| 		} | ||||
| 		spec = transport + spec | ||||
| 		srcRef2, err2 := alltransports.ParseImageName(spec) | ||||
| 		if err2 != nil { | ||||
| 			return nil, errors.Wrapf(err2, "error parsing image name %q", spec) | ||||
| 		} | ||||
| 		srcRef = srcRef2 | ||||
| 	} | ||||
| 	logrus.Debugf("parsed image name %q", spec) | ||||
| 
 | ||||
| func pullImage(ctx context.Context, store storage.Store, srcRef types.ImageReference, options PullOptions, sc *types.SystemContext) (types.ImageReference, error) { | ||||
| 	blocked, err := isReferenceBlocked(srcRef, sc) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrapf(err, "error checking if pulling from registry for %q is blocked", transports.ImageName(srcRef)) | ||||
|  | @ -237,7 +224,7 @@ func pullImage(ctx context.Context, store storage.Store, transport string, image | |||
| 		return nil, errors.Errorf("pull access to registry for %q is blocked by configuration", transports.ImageName(srcRef)) | ||||
| 	} | ||||
| 
 | ||||
| 	destName, err := localImageNameForReference(ctx, store, srcRef, spec) | ||||
| 	destName, err := localImageNameForReference(ctx, store, srcRef) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrapf(err, "error computing local image name for %q", transports.ImageName(srcRef)) | ||||
| 	} | ||||
|  | @ -274,9 +261,9 @@ func pullImage(ctx context.Context, store storage.Store, transport string, image | |||
| 		} | ||||
| 	}() | ||||
| 
 | ||||
| 	logrus.Debugf("copying %q to %q", spec, destName) | ||||
| 	logrus.Debugf("copying %q to %q", transports.ImageName(srcRef), destName) | ||||
| 	if _, err := cp.Image(ctx, policyContext, maybeCachedDestRef, srcRef, getCopyOptions(options.ReportWriter, srcRef, sc, maybeCachedDestRef, nil, "")); err != nil { | ||||
| 		logrus.Debugf("error copying src image [%q] to dest image [%q] err: %v", spec, destName, err) | ||||
| 		logrus.Debugf("error copying src image [%q] to dest image [%q] err: %v", transports.ImageName(srcRef), destName, err) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return destRef, nil | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ import ( | |||
| 	"github.com/containers/storage" | ||||
| 	"github.com/containers/storage/pkg/idtools" | ||||
| 	"github.com/docker/distribution/registry/api/errcode" | ||||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | @ -47,6 +47,12 @@ var ( | |||
| // correspond to in the set of configured registries, the transport used to
 | ||||
| // pull the image, and a boolean which is true iff
 | ||||
| // 1) the list of search registries was used, and 2) it was empty.
 | ||||
| //
 | ||||
| // The returned image names never include a transport: prefix, and if transport != "",
 | ||||
| // (transport, image) should be a valid input to alltransports.ParseImageName.
 | ||||
| // transport == "" indicates that image that already exists in a local storage,
 | ||||
| // and the name is valid for store.Image() / storage.Transport.ParseStoreReference().
 | ||||
| //
 | ||||
| // NOTE: The "list of search registries is empty" check does not count blocked registries,
 | ||||
| // and neither the implied "localhost" nor a possible firstRegistry are counted
 | ||||
| func ResolveName(name string, firstRegistry string, sc *types.SystemContext, store storage.Store) ([]string, string, bool, error) { | ||||
|  | @ -162,15 +168,7 @@ func ExpandNames(names []string, firstRegistry string, systemContext *types.Syst | |||
| 			name = named | ||||
| 		} | ||||
| 		name = reference.TagNameOnly(name) | ||||
| 		tag := "" | ||||
| 		digest := "" | ||||
| 		if tagged, ok := name.(reference.NamedTagged); ok { | ||||
| 			tag = ":" + tagged.Tag() | ||||
| 		} | ||||
| 		if digested, ok := name.(reference.Digested); ok { | ||||
| 			digest = "@" + digested.Digest().String() | ||||
| 		} | ||||
| 		expanded = append(expanded, name.Name()+tag+digest) | ||||
| 		expanded = append(expanded, name.String()) | ||||
| 	} | ||||
| 	return expanded, nil | ||||
| } | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ github.com/mattn/go-isatty v0.0.4 | |||
| github.com/VividCortex/ewma v1.1.1 | ||||
| github.com/boltdb/bolt v1.3.1 | ||||
| github.com/containers/libpod v1.0 | ||||
| github.com/containers/storage v1.10 | ||||
| github.com/containers/storage v1.11 | ||||
| github.com/docker/distribution 5f6282db7d65e6d72ad7c2cc66310724a57be716 | ||||
| github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00 | ||||
| github.com/docker/docker-credential-helpers v0.6.1 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue