mirror of
https://github.com/containers/podman.git
synced 2025-06-20 17:13:43 +08:00
vendor c/common@main
Update the `--filter reference=...` tests to reflect recent changes in c/common. The reference values now match as specified without implicitly adding wildcards arounds. Fixes: #11905 Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
4
go.mod
4
go.mod
@ -12,9 +12,9 @@ require (
|
||||
github.com/containernetworking/cni v1.0.1
|
||||
github.com/containernetworking/plugins v1.0.1
|
||||
github.com/containers/buildah v1.23.1
|
||||
github.com/containers/common v0.46.1-0.20211202172647-e77d74bd1976
|
||||
github.com/containers/common v0.46.1-0.20211205182721-515a2805e7b9
|
||||
github.com/containers/conmon v2.0.20+incompatible
|
||||
github.com/containers/image/v5 v5.17.1-0.20211129144953-4f6d0b45be6c
|
||||
github.com/containers/image/v5 v5.17.1-0.20211201214147-603ec1341d58
|
||||
github.com/containers/ocicrypt v1.1.2
|
||||
github.com/containers/psgo v1.7.1
|
||||
github.com/containers/storage v1.37.1-0.20211130181259-1a158c89a518
|
||||
|
9
go.sum
9
go.sum
@ -262,14 +262,13 @@ github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNB
|
||||
github.com/containers/buildah v1.23.1 h1:Tpc9DsRuU+0Oofewpxb6OJVNQjCu7yloN/obUqzfDTY=
|
||||
github.com/containers/buildah v1.23.1/go.mod h1:4WnrN0yrA7ab0ppgunixu2WM1rlD2rG8QLJAKbEkZlQ=
|
||||
github.com/containers/common v0.44.2/go.mod h1:7sdP4vmI5Bm6FPFxb3lvAh1Iktb6tiO1MzjUzhxdoGo=
|
||||
github.com/containers/common v0.46.1-0.20211202172647-e77d74bd1976 h1:xVOGL69ge+1RirZvnrEl9nATL75udt/Hy2BN8qcmeNY=
|
||||
github.com/containers/common v0.46.1-0.20211202172647-e77d74bd1976/go.mod h1:J8MxXan58zAWbNgpj4ODPlzsuJnYvNc2zKJCZPIMHYQ=
|
||||
github.com/containers/common v0.46.1-0.20211205182721-515a2805e7b9 h1:BoPxjWIPX+cn3CGNxd1FC10jcq9TBMk1uvGQEWTXWto=
|
||||
github.com/containers/common v0.46.1-0.20211205182721-515a2805e7b9/go.mod h1:cxAKmvKoYBl/iLZ1YD/SKnJF7wPR9H6xM/Hu75ZN/oA=
|
||||
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
|
||||
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
|
||||
github.com/containers/image/v5 v5.16.0/go.mod h1:XgTpfAPLRGOd1XYyCU5cISFr777bLmOerCSpt/v7+Q4=
|
||||
github.com/containers/image/v5 v5.17.0/go.mod h1:GnYVusVRFPMMTAAUkrcS8NNSpBp8oyrjOUe04AAmRr4=
|
||||
github.com/containers/image/v5 v5.17.1-0.20211129144953-4f6d0b45be6c h1:WfMOQlq3CDvVe5ONUGfj9/MajskqUHnbo24j24Xg2ZM=
|
||||
github.com/containers/image/v5 v5.17.1-0.20211129144953-4f6d0b45be6c/go.mod h1:boW5ckkT0wu9obDEiOIxrtWQmz1znMuHiVMQPcpHnk0=
|
||||
github.com/containers/image/v5 v5.17.1-0.20211201214147-603ec1341d58 h1:DI6d+6aRBC14mbfnh0eYlHeFBSZQ4adDykrS8F/Awrg=
|
||||
github.com/containers/image/v5 v5.17.1-0.20211201214147-603ec1341d58/go.mod h1:iUA6fv9NnqIhEaP3+dqo22nKMNkSWCj8d5o8Dju0j1Q=
|
||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
|
||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
|
||||
github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
|
||||
|
@ -141,12 +141,12 @@ var _ = Describe("Podman images", func() {
|
||||
})
|
||||
|
||||
It("podman images filter reference", func() {
|
||||
result := podmanTest.Podman([]string{"images", "-q", "-f", "reference=quay.io*"})
|
||||
result := podmanTest.Podman([]string{"images", "-q", "-f", "reference=quay.io/libpod/*"})
|
||||
result.WaitWithDefaultTimeout()
|
||||
Expect(result).Should(Exit(0))
|
||||
Expect(result.OutputToStringArray()).To(HaveLen(7))
|
||||
|
||||
retalpine := podmanTest.Podman([]string{"images", "-f", "reference=a*pine"})
|
||||
retalpine := podmanTest.Podman([]string{"images", "-f", "reference=*lpine*"})
|
||||
retalpine.WaitWithDefaultTimeout()
|
||||
Expect(retalpine).Should(Exit(0))
|
||||
Expect(retalpine.OutputToStringArray()).To(HaveLen(6))
|
||||
@ -155,7 +155,7 @@ var _ = Describe("Podman images", func() {
|
||||
retalpine = podmanTest.Podman([]string{"images", "-f", "reference=alpine"})
|
||||
retalpine.WaitWithDefaultTimeout()
|
||||
Expect(retalpine).Should(Exit(0))
|
||||
Expect(retalpine.OutputToStringArray()).To(HaveLen(6))
|
||||
Expect(retalpine.OutputToStringArray()).To(HaveLen(2))
|
||||
Expect(retalpine.OutputToString()).To(ContainSubstring("alpine"))
|
||||
|
||||
retnone := podmanTest.Podman([]string{"images", "-q", "-f", "reference=bogus"})
|
||||
|
54
vendor/github.com/containers/common/libimage/filters.go
generated
vendored
54
vendor/github.com/containers/common/libimage/filters.go
generated
vendored
@ -3,13 +3,14 @@ package libimage
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
filtersPkg "github.com/containers/common/pkg/filters"
|
||||
"github.com/containers/common/pkg/timetype"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -136,7 +137,7 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp
|
||||
filterFuncs = append(filterFuncs, filterReadOnly(readOnly))
|
||||
|
||||
case "reference":
|
||||
filterFuncs = append(filterFuncs, filterReference(value))
|
||||
filterFuncs = append(filterFuncs, filterReferences(value))
|
||||
|
||||
case "until":
|
||||
ts, err := timetype.GetTimestamp(value, time.Now())
|
||||
@ -158,24 +159,43 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp
|
||||
return filterFuncs, nil
|
||||
}
|
||||
|
||||
// filterReference creates a reference filter for matching the specified value.
|
||||
func filterReference(value string) filterFunc {
|
||||
// Replacing all '/' with '|' so that filepath.Match() can work '|'
|
||||
// character is not valid in image name, so this is safe.
|
||||
//
|
||||
// TODO: this has been copied from Podman and requires some more review
|
||||
// and especially tests.
|
||||
filter := fmt.Sprintf("*%s*", value)
|
||||
filter = strings.ReplaceAll(filter, "/", "|")
|
||||
// filterReferences creates a reference filter for matching the specified value.
|
||||
func filterReferences(value string) filterFunc {
|
||||
return func(img *Image) (bool, error) {
|
||||
if len(value) < 1 {
|
||||
refs, err := img.NamesReferences()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, ref := range refs {
|
||||
refString := ref.String() // FQN with tag/digest
|
||||
candidates := []string{refString}
|
||||
|
||||
// Split the reference into 3 components (twice if diggested/tagged):
|
||||
// 1) Fully-qualified reference
|
||||
// 2) Without domain
|
||||
// 3) Without domain and path
|
||||
if named, isNamed := ref.(reference.Named); isNamed {
|
||||
candidates = append(candidates,
|
||||
reference.Path(named), // path/name without tag/digest (Path() removes it)
|
||||
refString[strings.LastIndex(refString, "/")+1:]) // name with tag/digest
|
||||
|
||||
trimmedString := reference.TrimNamed(named).String()
|
||||
if refString != trimmedString {
|
||||
tagOrDigest := refString[len(trimmedString):]
|
||||
candidates = append(candidates,
|
||||
trimmedString, // FQN without tag/digest
|
||||
reference.Path(named)+tagOrDigest, // path/name with tag/digest
|
||||
trimmedString[strings.LastIndex(trimmedString, "/")+1:]) // name without tag/digest
|
||||
}
|
||||
}
|
||||
|
||||
for _, candidate := range candidates {
|
||||
// path.Match() is also used by Docker's reference.FamiliarMatch().
|
||||
matched, _ := path.Match(value, candidate)
|
||||
if matched {
|
||||
return true, nil
|
||||
}
|
||||
for _, name := range img.Names() {
|
||||
newName := strings.ReplaceAll(name, "/", "|")
|
||||
match, _ := filepath.Match(filter, newName)
|
||||
if match {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
|
20
vendor/github.com/containers/common/libimage/image.go
generated
vendored
20
vendor/github.com/containers/common/libimage/image.go
generated
vendored
@ -44,6 +44,8 @@ type Image struct {
|
||||
completeInspectData *ImageData
|
||||
// Corresponding OCI image.
|
||||
ociv1Image *ociv1.Image
|
||||
// Names() parsed into references.
|
||||
namesReferences []reference.Reference
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,6 +61,7 @@ func (i *Image) reload() error {
|
||||
i.cached.partialInspectData = nil
|
||||
i.cached.completeInspectData = nil
|
||||
i.cached.ociv1Image = nil
|
||||
i.cached.namesReferences = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -89,6 +92,23 @@ func (i *Image) Names() []string {
|
||||
return i.storageImage.Names
|
||||
}
|
||||
|
||||
// NamesReferences returns Names() as references.
|
||||
func (i *Image) NamesReferences() ([]reference.Reference, error) {
|
||||
if i.cached.namesReferences != nil {
|
||||
return i.cached.namesReferences, nil
|
||||
}
|
||||
refs := make([]reference.Reference, 0, len(i.Names()))
|
||||
for _, name := range i.Names() {
|
||||
ref, err := reference.Parse(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
refs = append(refs, ref)
|
||||
}
|
||||
i.cached.namesReferences = refs
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
// StorageImage returns the underlying storage.Image.
|
||||
func (i *Image) StorageImage() *storage.Image {
|
||||
return i.storageImage
|
||||
|
100
vendor/github.com/containers/common/pkg/auth/auth.go
generated
vendored
100
vendor/github.com/containers/common/pkg/auth/auth.go
generated
vendored
@ -70,13 +70,10 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO
|
||||
systemContext = systemContextWithOptions(systemContext, opts.AuthFile, opts.CertDir)
|
||||
|
||||
var (
|
||||
authConfig types.DockerAuthConfig
|
||||
key, registry string
|
||||
ref reference.Named
|
||||
err error
|
||||
)
|
||||
l := len(args)
|
||||
switch l {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
if !opts.AcceptUnspecifiedRegistry {
|
||||
return errors.New("please provide a registry to login to")
|
||||
@ -88,27 +85,19 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO
|
||||
logrus.Debugf("registry not specified, default to the first registry %q from registries.conf", key)
|
||||
|
||||
case 1:
|
||||
key, registry, ref, err = parseRegistryArgument(args[0], opts.AcceptRepositories)
|
||||
key, registry, err = parseCredentialsKey(args[0], opts.AcceptRepositories)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
default:
|
||||
return errors.New("login accepts only one registry to login to")
|
||||
|
||||
}
|
||||
|
||||
if ref != nil {
|
||||
authConfig, err = config.GetCredentialsForRef(systemContext, ref)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get credentials for repository")
|
||||
}
|
||||
} else {
|
||||
authConfig, err = config.GetCredentials(systemContext, registry)
|
||||
authConfig, err := config.GetCredentials(systemContext, key)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get credentials")
|
||||
}
|
||||
}
|
||||
|
||||
if opts.GetLoginSet {
|
||||
if authConfig.Username == "" {
|
||||
@ -173,39 +162,44 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO
|
||||
return errors.Wrapf(err, "authenticating creds for %q", key)
|
||||
}
|
||||
|
||||
// parseRegistryArgument verifies the provided arg depending if we accept
|
||||
// repositories or not.
|
||||
func parseRegistryArgument(arg string, acceptRepositories bool) (key, registry string, maybeRef reference.Named, err error) {
|
||||
// parseCredentialsKey turns the provided argument into a valid credential key
|
||||
// and computes the registry part.
|
||||
func parseCredentialsKey(arg string, acceptRepositories bool) (key, registry string, err error) {
|
||||
if !acceptRepositories {
|
||||
registry = getRegistryName(arg)
|
||||
key = registry
|
||||
return key, registry, maybeRef, nil
|
||||
return key, registry, nil
|
||||
}
|
||||
|
||||
key = trimScheme(arg)
|
||||
if key != arg {
|
||||
return key, registry, nil, errors.New("credentials key has https[s]:// prefix")
|
||||
return "", "", errors.New("credentials key has https[s]:// prefix")
|
||||
}
|
||||
|
||||
registry = getRegistryName(key)
|
||||
if registry == key {
|
||||
// We cannot parse a reference from a registry, so we stop here
|
||||
return key, registry, nil, nil
|
||||
// The key is not namespaced
|
||||
return key, registry, nil
|
||||
}
|
||||
|
||||
ref, parseErr := reference.ParseNamed(key)
|
||||
if parseErr != nil {
|
||||
return key, registry, nil, errors.Wrapf(parseErr, "parse reference from %q", key)
|
||||
// Sanity-check that the key looks reasonable (e.g. doesn't use invalid characters),
|
||||
// and does not contain a tag or digest.
|
||||
// WARNING: ref.Named() MUST NOT be used to compute key, because
|
||||
// reference.ParseNormalizedNamed() turns docker.io/vendor to docker.io/library/vendor
|
||||
// Ideally c/image should provide dedicated validation functionality.
|
||||
ref, err := reference.ParseNormalizedNamed(key)
|
||||
if err != nil {
|
||||
return "", "", errors.Wrapf(err, "parse reference from %q", key)
|
||||
}
|
||||
|
||||
if !reference.IsNameOnly(ref) {
|
||||
return key, registry, nil, errors.Errorf("reference %q contains tag or digest", ref.String())
|
||||
return "", "", errors.Errorf("reference %q contains tag or digest", ref.String())
|
||||
}
|
||||
refRegistry := reference.Domain(ref)
|
||||
if refRegistry != registry { // This should never happen, check just to make sure
|
||||
return "", "", fmt.Errorf("internal error: key %q registry mismatch, %q vs. %q", key, ref, refRegistry)
|
||||
}
|
||||
|
||||
maybeRef = ref
|
||||
registry = reference.Domain(ref)
|
||||
|
||||
return key, registry, maybeRef, nil
|
||||
return key, registry, nil
|
||||
}
|
||||
|
||||
// getRegistryName scrubs and parses the input to get the server name
|
||||
@ -271,15 +265,23 @@ func Logout(systemContext *types.SystemContext, opts *LogoutOptions, args []stri
|
||||
}
|
||||
systemContext = systemContextWithOptions(systemContext, opts.AuthFile, "")
|
||||
|
||||
if opts.All {
|
||||
if len(args) != 0 {
|
||||
return errors.New("--all takes no arguments")
|
||||
}
|
||||
if err := config.RemoveAllAuthentication(systemContext); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(opts.Stdout, "Removed login credentials for all registries")
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
key, registry string
|
||||
ref reference.Named
|
||||
err error
|
||||
)
|
||||
if len(args) > 1 {
|
||||
return errors.New("logout accepts only one registry to logout from")
|
||||
}
|
||||
if len(args) == 0 && !opts.All {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
if !opts.AcceptUnspecifiedRegistry {
|
||||
return errors.New("please provide a registry to logout from")
|
||||
}
|
||||
@ -288,23 +290,15 @@ func Logout(systemContext *types.SystemContext, opts *LogoutOptions, args []stri
|
||||
}
|
||||
registry = key
|
||||
logrus.Debugf("registry not specified, default to the first registry %q from registries.conf", key)
|
||||
}
|
||||
if len(args) != 0 {
|
||||
if opts.All {
|
||||
return errors.New("--all takes no arguments")
|
||||
}
|
||||
key, registry, ref, err = parseRegistryArgument(args[0], opts.AcceptRepositories)
|
||||
|
||||
case 1:
|
||||
key, registry, err = parseCredentialsKey(args[0], opts.AcceptRepositories)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if opts.All {
|
||||
if err := config.RemoveAllAuthentication(systemContext); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(opts.Stdout, "Removed login credentials for all registries")
|
||||
return nil
|
||||
default:
|
||||
return errors.New("logout accepts only one registry to logout from")
|
||||
}
|
||||
|
||||
err = config.RemoveAuthentication(systemContext, key)
|
||||
@ -313,18 +307,10 @@ func Logout(systemContext *types.SystemContext, opts *LogoutOptions, args []stri
|
||||
fmt.Fprintf(opts.Stdout, "Removed login credentials for %s\n", key)
|
||||
return nil
|
||||
case config.ErrNotLoggedIn:
|
||||
var authConfig types.DockerAuthConfig
|
||||
if ref != nil {
|
||||
authConfig, err = config.GetCredentialsForRef(systemContext, ref)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get credentials for repository")
|
||||
}
|
||||
} else {
|
||||
authConfig, err = config.GetCredentials(systemContext, registry)
|
||||
authConfig, err := config.GetCredentials(systemContext, key)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get credentials")
|
||||
}
|
||||
}
|
||||
|
||||
authInvalid := docker.CheckAuth(context.Background(), systemContext, authConfig.Username, authConfig.Password, registry)
|
||||
if authConfig.Username != "" && authConfig.Password != "" && authInvalid == nil {
|
||||
|
11
vendor/github.com/containers/common/pkg/retry/retry.go
generated
vendored
11
vendor/github.com/containers/common/pkg/retry/retry.go
generated
vendored
@ -45,8 +45,12 @@ func RetryIfNecessary(ctx context.Context, operation func() error, retryOptions
|
||||
func isRetryable(err error) bool {
|
||||
err = errors.Cause(err)
|
||||
|
||||
if err == context.Canceled || err == context.DeadlineExceeded {
|
||||
switch err {
|
||||
case nil:
|
||||
return false
|
||||
case context.Canceled, context.DeadlineExceeded:
|
||||
return false
|
||||
default: // continue
|
||||
}
|
||||
|
||||
type unwrapper interface {
|
||||
@ -57,7 +61,8 @@ func isRetryable(err error) bool {
|
||||
|
||||
case errcode.Error:
|
||||
switch e.Code {
|
||||
case errcode.ErrorCodeUnauthorized, errcodev2.ErrorCodeNameUnknown, errcodev2.ErrorCodeManifestUnknown:
|
||||
case errcode.ErrorCodeUnauthorized, errcode.ErrorCodeDenied,
|
||||
errcodev2.ErrorCodeNameUnknown, errcodev2.ErrorCodeManifestUnknown:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -86,7 +91,7 @@ func isRetryable(err error) bool {
|
||||
}
|
||||
}
|
||||
return true
|
||||
case unwrapper:
|
||||
case unwrapper: // Test this last, because various error types might implement .Unwrap()
|
||||
err = e.Unwrap()
|
||||
return isRetryable(err)
|
||||
}
|
||||
|
9
vendor/github.com/containers/image/v5/manifest/manifest.go
generated
vendored
9
vendor/github.com/containers/image/v5/manifest/manifest.go
generated
vendored
@ -110,7 +110,8 @@ func GuessMIMEType(manifest []byte) string {
|
||||
}
|
||||
|
||||
switch meta.MediaType {
|
||||
case DockerV2Schema2MediaType, DockerV2ListMediaType: // A recognized type.
|
||||
case DockerV2Schema2MediaType, DockerV2ListMediaType,
|
||||
imgspecv1.MediaTypeImageManifest, imgspecv1.MediaTypeImageIndex: // A recognized type.
|
||||
return meta.MediaType
|
||||
}
|
||||
// this is the only way the function can return DockerV2Schema1MediaType, and recognizing that is essential for stripping the JWS signatures = computing the correct manifest digest.
|
||||
@ -121,9 +122,9 @@ func GuessMIMEType(manifest []byte) string {
|
||||
}
|
||||
return DockerV2Schema1MediaType
|
||||
case 2:
|
||||
// best effort to understand if this is an OCI image since mediaType
|
||||
// isn't in the manifest for OCI anymore
|
||||
// for docker v2s2 meta.MediaType should have been set. But given the data, this is our best guess.
|
||||
// Best effort to understand if this is an OCI image since mediaType
|
||||
// wasn't in the manifest for OCI image-spec < 1.0.2.
|
||||
// For docker v2s2 meta.MediaType should have been set. But given the data, this is our best guess.
|
||||
ociMan := struct {
|
||||
Config struct {
|
||||
MediaType string `json:"mediaType"`
|
||||
|
1
vendor/github.com/containers/image/v5/manifest/oci.go
generated
vendored
1
vendor/github.com/containers/image/v5/manifest/oci.go
generated
vendored
@ -66,6 +66,7 @@ func OCI1FromComponents(config imgspecv1.Descriptor, layers []imgspecv1.Descript
|
||||
return &OCI1{
|
||||
imgspecv1.Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: imgspecv1.MediaTypeImageManifest,
|
||||
Config: config,
|
||||
Layers: layers,
|
||||
},
|
||||
|
2
vendor/github.com/containers/image/v5/manifest/oci_index.go
generated
vendored
2
vendor/github.com/containers/image/v5/manifest/oci_index.go
generated
vendored
@ -119,6 +119,7 @@ func OCI1IndexFromComponents(components []imgspecv1.Descriptor, annotations map[
|
||||
index := OCI1Index{
|
||||
imgspecv1.Index{
|
||||
Versioned: imgspec.Versioned{SchemaVersion: 2},
|
||||
MediaType: imgspecv1.MediaTypeImageIndex,
|
||||
Manifests: make([]imgspecv1.Descriptor, len(components)),
|
||||
Annotations: dupStringStringMap(annotations),
|
||||
},
|
||||
@ -195,6 +196,7 @@ func OCI1IndexFromManifest(manifest []byte) (*OCI1Index, error) {
|
||||
index := OCI1Index{
|
||||
Index: imgspecv1.Index{
|
||||
Versioned: imgspec.Versioned{SchemaVersion: 2},
|
||||
MediaType: imgspecv1.MediaTypeImageIndex,
|
||||
Manifests: []imgspecv1.Descriptor{},
|
||||
Annotations: make(map[string]string),
|
||||
},
|
||||
|
157
vendor/github.com/containers/image/v5/pkg/docker/config/config.go
generated
vendored
157
vendor/github.com/containers/image/v5/pkg/docker/config/config.go
generated
vendored
@ -54,8 +54,8 @@ var (
|
||||
|
||||
// SetCredentials stores the username and password in a location
|
||||
// appropriate for sys and the users’ configuration.
|
||||
// A valid key can be either a registry hostname or additionally a namespace if
|
||||
// the AuthenticationFileHelper is being unsed.
|
||||
// A valid key is a repository, a namespace within a registry, or a registry hostname;
|
||||
// using forms other than just a registry may fail depending on configuration.
|
||||
// Returns a human-redable description of the location that was updated.
|
||||
// NOTE: The return value is only intended to be read by humans; its form is not an API,
|
||||
// it may change (or new forms can be added) any time.
|
||||
@ -128,11 +128,15 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
|
||||
// possible sources, and then call `GetCredentials` on them. That
|
||||
// prevents us from having to reverse engineer the logic in
|
||||
// `GetCredentials`.
|
||||
allRegistries := make(map[string]bool)
|
||||
addRegistry := func(s string) {
|
||||
allRegistries[s] = true
|
||||
allKeys := make(map[string]bool)
|
||||
addKey := func(s string) {
|
||||
allKeys[s] = true
|
||||
}
|
||||
|
||||
// To use GetCredentials, we must at least convert the URL forms into host names.
|
||||
// While we're at it, we’ll also canonicalize docker.io to the standard format.
|
||||
normalizedDockerIORegistry := normalizeRegistry("docker.io")
|
||||
|
||||
helpers, err := sysregistriesv2.CredentialHelpers(sys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -151,10 +155,14 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
|
||||
// direct mapping to a registry, so we can just
|
||||
// walk the map.
|
||||
for registry := range auths.CredHelpers {
|
||||
addRegistry(registry)
|
||||
addKey(registry)
|
||||
}
|
||||
for registry := range auths.AuthConfigs {
|
||||
addRegistry(registry)
|
||||
for key := range auths.AuthConfigs {
|
||||
key := normalizeAuthFileKey(key, path.legacyFormat)
|
||||
if key == normalizedDockerIORegistry {
|
||||
key = "docker.io"
|
||||
}
|
||||
addKey(key)
|
||||
}
|
||||
}
|
||||
// External helpers.
|
||||
@ -166,7 +174,7 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
|
||||
switch errors.Cause(err) {
|
||||
case nil:
|
||||
for registry := range creds {
|
||||
addRegistry(registry)
|
||||
addKey(registry)
|
||||
}
|
||||
case exec.ErrNotFound:
|
||||
// It's okay if the helper doesn't exist.
|
||||
@ -179,8 +187,8 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
|
||||
// Now use `GetCredentials` to the specific auth configs for each
|
||||
// previously listed registry.
|
||||
authConfigs := make(map[string]types.DockerAuthConfig)
|
||||
for registry := range allRegistries {
|
||||
authConf, err := GetCredentials(sys, registry)
|
||||
for key := range allKeys {
|
||||
authConf, err := GetCredentials(sys, key)
|
||||
if err != nil {
|
||||
if credentials.IsErrCredentialsNotFoundMessage(err.Error()) {
|
||||
// Ignore if the credentials could not be found (anymore).
|
||||
@ -189,7 +197,7 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
|
||||
// Note: we rely on the logging in `GetCredentials`.
|
||||
return nil, err
|
||||
}
|
||||
authConfigs[registry] = authConf
|
||||
authConfigs[key] = authConf
|
||||
}
|
||||
|
||||
return authConfigs, nil
|
||||
@ -230,16 +238,14 @@ func getAuthFilePaths(sys *types.SystemContext, homeDir string) []authPath {
|
||||
return paths
|
||||
}
|
||||
|
||||
// GetCredentials returns the registry credentials stored in the
|
||||
// registry-specific credential helpers or in the default global credentials
|
||||
// helpers with falling back to using either auth.json
|
||||
// file or .docker/config.json, including support for OAuth2 and IdentityToken.
|
||||
// GetCredentials returns the registry credentials matching key, appropriate for
|
||||
// sys and the users’ configuration.
|
||||
// If an entry is not found, an empty struct is returned.
|
||||
// A valid key is a repository, a namespace within a registry, or a registry hostname.
|
||||
//
|
||||
// GetCredentialsForRef should almost always be used in favor of this API to
|
||||
// allow different credentials for different repositories on the same registry.
|
||||
func GetCredentials(sys *types.SystemContext, registry string) (types.DockerAuthConfig, error) {
|
||||
return getCredentialsWithHomeDir(sys, nil, registry, homedir.Get())
|
||||
// GetCredentialsForRef should almost always be used in favor of this API.
|
||||
func GetCredentials(sys *types.SystemContext, key string) (types.DockerAuthConfig, error) {
|
||||
return getCredentialsWithHomeDir(sys, key, homedir.Get())
|
||||
}
|
||||
|
||||
// GetCredentialsForRef returns the registry credentials necessary for
|
||||
@ -247,30 +253,34 @@ func GetCredentials(sys *types.SystemContext, registry string) (types.DockerAuth
|
||||
// appropriate for sys and the users’ configuration.
|
||||
// If an entry is not found, an empty struct is returned.
|
||||
func GetCredentialsForRef(sys *types.SystemContext, ref reference.Named) (types.DockerAuthConfig, error) {
|
||||
return getCredentialsWithHomeDir(sys, ref, reference.Domain(ref), homedir.Get())
|
||||
return getCredentialsWithHomeDir(sys, ref.Name(), homedir.Get())
|
||||
}
|
||||
|
||||
// getCredentialsWithHomeDir is an internal implementation detail of
|
||||
// GetCredentialsForRef and GetCredentials. It exists only to allow testing it
|
||||
// with an artificial home directory.
|
||||
func getCredentialsWithHomeDir(sys *types.SystemContext, ref reference.Named, registry, homeDir string) (types.DockerAuthConfig, error) {
|
||||
// consistency check of the ref and registry arguments
|
||||
if ref != nil && reference.Domain(ref) != registry {
|
||||
return types.DockerAuthConfig{}, errors.Errorf(
|
||||
"internal error: provided reference domain %q name does not match registry %q",
|
||||
reference.Domain(ref), registry,
|
||||
)
|
||||
func getCredentialsWithHomeDir(sys *types.SystemContext, key, homeDir string) (types.DockerAuthConfig, error) {
|
||||
_, err := validateKey(key)
|
||||
if err != nil {
|
||||
return types.DockerAuthConfig{}, err
|
||||
}
|
||||
|
||||
if sys != nil && sys.DockerAuthConfig != nil {
|
||||
logrus.Debugf("Returning credentials for %s from DockerAuthConfig", registry)
|
||||
logrus.Debugf("Returning credentials for %s from DockerAuthConfig", key)
|
||||
return *sys.DockerAuthConfig, nil
|
||||
}
|
||||
|
||||
var registry string // We compute this once because it is used in several places.
|
||||
if firstSlash := strings.IndexRune(key, '/'); firstSlash != -1 {
|
||||
registry = key[:firstSlash]
|
||||
} else {
|
||||
registry = key
|
||||
}
|
||||
|
||||
// Anonymous function to query credentials from auth files.
|
||||
getCredentialsFromAuthFiles := func() (types.DockerAuthConfig, string, error) {
|
||||
for _, path := range getAuthFilePaths(sys, homeDir) {
|
||||
authConfig, err := findAuthentication(ref, registry, path.path, path.legacyFormat)
|
||||
authConfig, err := findCredentialsInFile(key, registry, path.path, path.legacyFormat)
|
||||
if err != nil {
|
||||
return types.DockerAuthConfig{}, "", err
|
||||
}
|
||||
@ -291,57 +301,61 @@ func getCredentialsWithHomeDir(sys *types.SystemContext, ref reference.Named, re
|
||||
for _, helper := range helpers {
|
||||
var (
|
||||
creds types.DockerAuthConfig
|
||||
helperKey string
|
||||
credHelperPath string
|
||||
err error
|
||||
)
|
||||
switch helper {
|
||||
// Special-case the built-in helper for auth files.
|
||||
case sysregistriesv2.AuthenticationFileHelper:
|
||||
helperKey = key
|
||||
creds, credHelperPath, err = getCredentialsFromAuthFiles()
|
||||
// External helpers.
|
||||
default:
|
||||
// This intentionally uses "registry", not "key"; we don't support namespaced
|
||||
// credentials in helpers, but a "registry" is a valid parent of "key".
|
||||
helperKey = registry
|
||||
creds, err = getAuthFromCredHelper(helper, registry)
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Debugf("Error looking up credentials for %s in credential helper %s: %v", registry, helper, err)
|
||||
logrus.Debugf("Error looking up credentials for %s in credential helper %s: %v", helperKey, helper, err)
|
||||
multiErr = multierror.Append(multiErr, err)
|
||||
continue
|
||||
}
|
||||
if len(creds.Username)+len(creds.Password)+len(creds.IdentityToken) == 0 {
|
||||
continue
|
||||
}
|
||||
msg := fmt.Sprintf("Found credentials for %s in credential helper %s", registry, helper)
|
||||
if creds != (types.DockerAuthConfig{}) {
|
||||
msg := fmt.Sprintf("Found credentials for %s in credential helper %s", helperKey, helper)
|
||||
if credHelperPath != "" {
|
||||
msg = fmt.Sprintf("%s in file %s", msg, credHelperPath)
|
||||
}
|
||||
logrus.Debug(msg)
|
||||
return creds, nil
|
||||
}
|
||||
}
|
||||
if multiErr != nil {
|
||||
return types.DockerAuthConfig{}, multiErr
|
||||
}
|
||||
|
||||
logrus.Debugf("No credentials for %s found", registry)
|
||||
logrus.Debugf("No credentials for %s found", key)
|
||||
return types.DockerAuthConfig{}, nil
|
||||
}
|
||||
|
||||
// GetAuthentication returns the registry credentials stored in the
|
||||
// registry-specific credential helpers or in the default global credentials
|
||||
// helpers with falling back to using either auth.json file or
|
||||
// .docker/config.json
|
||||
// GetAuthentication returns the registry credentials matching key, appropriate for
|
||||
// sys and the users’ configuration.
|
||||
// If an entry is not found, an empty struct is returned.
|
||||
// A valid key is a repository, a namespace within a registry, or a registry hostname.
|
||||
//
|
||||
// Deprecated: This API only has support for username and password. To get the
|
||||
// support for oauth2 in container registry authentication, we added the new
|
||||
// GetCredentials API. The new API should be used and this API is kept to
|
||||
// GetCredentialsForRef and GetCredentials API. The new API should be used and this API is kept to
|
||||
// maintain backward compatibility.
|
||||
func GetAuthentication(sys *types.SystemContext, registry string) (string, string, error) {
|
||||
return getAuthenticationWithHomeDir(sys, registry, homedir.Get())
|
||||
func GetAuthentication(sys *types.SystemContext, key string) (string, string, error) {
|
||||
return getAuthenticationWithHomeDir(sys, key, homedir.Get())
|
||||
}
|
||||
|
||||
// getAuthenticationWithHomeDir is an internal implementation detail of GetAuthentication,
|
||||
// it exists only to allow testing it with an artificial home directory.
|
||||
func getAuthenticationWithHomeDir(sys *types.SystemContext, registry, homeDir string) (string, string, error) {
|
||||
auth, err := getCredentialsWithHomeDir(sys, nil, registry, homeDir)
|
||||
func getAuthenticationWithHomeDir(sys *types.SystemContext, key, homeDir string) (string, string, error) {
|
||||
auth, err := getCredentialsWithHomeDir(sys, key, homeDir)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
@ -353,8 +367,8 @@ func getAuthenticationWithHomeDir(sys *types.SystemContext, registry, homeDir st
|
||||
|
||||
// RemoveAuthentication removes credentials for `key` from all possible
|
||||
// sources such as credential helpers and auth files.
|
||||
// A valid key can be either a registry hostname or additionally a namespace if
|
||||
// the AuthenticationFileHelper is being unsed.
|
||||
// A valid key is a repository, a namespace within a registry, or a registry hostname;
|
||||
// using forms other than just a registry may fail depending on configuration.
|
||||
func RemoveAuthentication(sys *types.SystemContext, key string) error {
|
||||
isNamespaced, err := validateKey(key)
|
||||
if err != nil {
|
||||
@ -639,26 +653,27 @@ func deleteAuthFromCredHelper(credHelper, registry string) error {
|
||||
return helperclient.Erase(p, registry)
|
||||
}
|
||||
|
||||
// findAuthentication looks for auth of registry in path. If ref is
|
||||
// not nil, then it will be taken into account when looking up the
|
||||
// authentication credentials.
|
||||
func findAuthentication(ref reference.Named, registry, path string, legacyFormat bool) (types.DockerAuthConfig, error) {
|
||||
// findCredentialsInFile looks for credentials matching "key"
|
||||
// (which is "registry" or a namespace in "registry") in "path".
|
||||
func findCredentialsInFile(key, registry, path string, legacyFormat bool) (types.DockerAuthConfig, error) {
|
||||
auths, err := readJSONFile(path, legacyFormat)
|
||||
if err != nil {
|
||||
return types.DockerAuthConfig{}, errors.Wrapf(err, "reading JSON file %q", path)
|
||||
}
|
||||
|
||||
// First try cred helpers. They should always be normalized.
|
||||
// This intentionally uses "registry", not "key"; we don't support namespaced
|
||||
// credentials in helpers.
|
||||
if ch, exists := auths.CredHelpers[registry]; exists {
|
||||
return getAuthFromCredHelper(ch, registry)
|
||||
}
|
||||
|
||||
// Support for different paths in auth.
|
||||
// Support sub-registry namespaces in auth.
|
||||
// (This is not a feature of ~/.docker/config.json; we support it even for
|
||||
// those files as an extension.)
|
||||
var keys []string
|
||||
if !legacyFormat && ref != nil {
|
||||
keys = authKeysForRef(ref)
|
||||
if !legacyFormat {
|
||||
keys = authKeysForKey(key)
|
||||
} else {
|
||||
keys = []string{registry}
|
||||
}
|
||||
@ -689,23 +704,22 @@ func findAuthentication(ref reference.Named, registry, path string, legacyFormat
|
||||
return types.DockerAuthConfig{}, nil
|
||||
}
|
||||
|
||||
// authKeysForRef returns the valid paths for a provided reference. For example,
|
||||
// when given a reference "quay.io/repo/ns/image:tag", then it would return
|
||||
// authKeysForKey returns the keys matching a provided auth file key, in order
|
||||
// from the best match to worst. For example,
|
||||
// when given a repository key "quay.io/repo/ns/image", it returns
|
||||
// - quay.io/repo/ns/image
|
||||
// - quay.io/repo/ns
|
||||
// - quay.io/repo
|
||||
// - quay.io
|
||||
func authKeysForRef(ref reference.Named) (res []string) {
|
||||
name := ref.Name()
|
||||
|
||||
func authKeysForKey(key string) (res []string) {
|
||||
for {
|
||||
res = append(res, name)
|
||||
res = append(res, key)
|
||||
|
||||
lastSlash := strings.LastIndex(name, "/")
|
||||
lastSlash := strings.LastIndex(key, "/")
|
||||
if lastSlash == -1 {
|
||||
break
|
||||
}
|
||||
name = name[:lastSlash]
|
||||
key = key[:lastSlash]
|
||||
}
|
||||
|
||||
return res
|
||||
@ -759,11 +773,24 @@ func normalizeRegistry(registry string) string {
|
||||
|
||||
// validateKey verifies that the input key does not have a prefix that is not
|
||||
// allowed and returns an indicator if the key is namespaced.
|
||||
func validateKey(key string) (isNamespaced bool, err error) {
|
||||
func validateKey(key string) (bool, error) {
|
||||
if strings.HasPrefix(key, "http://") || strings.HasPrefix(key, "https://") {
|
||||
return isNamespaced, errors.Errorf("key %s contains http[s]:// prefix", key)
|
||||
return false, errors.Errorf("key %s contains http[s]:// prefix", key)
|
||||
}
|
||||
|
||||
// Ideally this should only accept explicitly valid keys, compare
|
||||
// validateIdentityRemappingPrefix. For now, just reject values that look
|
||||
// like tagged or digested values.
|
||||
if strings.ContainsRune(key, '@') {
|
||||
return false, fmt.Errorf(`key %s contains a '@' character`, key)
|
||||
}
|
||||
|
||||
firstSlash := strings.IndexRune(key, '/')
|
||||
isNamespaced := firstSlash != -1
|
||||
// Reject host/repo:tag, but allow localhost:5000 and localhost:5000/foo.
|
||||
if isNamespaced && strings.ContainsRune(key[firstSlash+1:], ':') {
|
||||
return false, fmt.Errorf(`key %s contains a ':' character after host[:port]`, key)
|
||||
}
|
||||
// check if the provided key contains one or more subpaths.
|
||||
return strings.ContainsRune(key, '/'), nil
|
||||
return isNamespaced, nil
|
||||
}
|
||||
|
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@ -106,7 +106,7 @@ github.com/containers/buildah/pkg/rusage
|
||||
github.com/containers/buildah/pkg/sshagent
|
||||
github.com/containers/buildah/pkg/util
|
||||
github.com/containers/buildah/util
|
||||
# github.com/containers/common v0.46.1-0.20211202172647-e77d74bd1976
|
||||
# github.com/containers/common v0.46.1-0.20211205182721-515a2805e7b9
|
||||
## explicit
|
||||
github.com/containers/common/libimage
|
||||
github.com/containers/common/libimage/manifests
|
||||
@ -142,7 +142,7 @@ github.com/containers/common/version
|
||||
# github.com/containers/conmon v2.0.20+incompatible
|
||||
## explicit
|
||||
github.com/containers/conmon/runner/config
|
||||
# github.com/containers/image/v5 v5.17.1-0.20211129144953-4f6d0b45be6c
|
||||
# github.com/containers/image/v5 v5.17.1-0.20211201214147-603ec1341d58
|
||||
## explicit
|
||||
github.com/containers/image/v5/copy
|
||||
github.com/containers/image/v5/directory
|
||||
|
Reference in New Issue
Block a user