chore(deps): bump github.com/google/go-containerregistry (#3206)

Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.19.1 to 0.19.2.
- [Release notes](https://github.com/google/go-containerregistry/releases)
- [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml)
- [Commits](https://github.com/google/go-containerregistry/compare/v0.19.1...v0.19.2)

---
updated-dependencies:
- dependency-name: github.com/google/go-containerregistry
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
dependabot[bot] 2024-06-17 12:20:48 -07:00 committed by GitHub
parent 50850006ce
commit 407904a688
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 138 additions and 32 deletions

2
go.mod
View File

@ -17,7 +17,7 @@ require (
github.com/go-git/go-git/v5 v5.12.0
github.com/golang/mock v1.6.0
github.com/google/go-cmp v0.6.0
github.com/google/go-containerregistry v0.19.1
github.com/google/go-containerregistry v0.19.2
github.com/google/go-github v17.0.0+incompatible
github.com/google/slowjam v1.1.1
github.com/karrick/godirwalk v1.16.1

4
go.sum
View File

@ -276,8 +276,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.19.1 h1:yMQ62Al6/V0Z7CqIrrS1iYoA5/oQCm88DeNujc7C1KY=
github.com/google/go-containerregistry v0.19.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI=
github.com/google/go-containerregistry v0.19.2 h1:TannFKE1QSajsP6hPWb5oJNgKe1IKjHukIKDUmvsV6w=
github.com/google/go-containerregistry v0.19.2/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=

View File

@ -15,6 +15,7 @@
package authn
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
@ -27,6 +28,22 @@ type Authenticator interface {
Authorization() (*AuthConfig, error)
}
// ContextAuthenticator is like Authenticator, but allows for context to be passed in.
type ContextAuthenticator interface {
// Authorization returns the value to use in an http transport's Authorization header.
AuthorizationContext(context.Context) (*AuthConfig, error)
}
// Authorization calls AuthorizationContext with ctx if the given [Authenticator] implements [ContextAuthenticator],
// otherwise it calls Resolve with the given [Resource].
func Authorization(ctx context.Context, authn Authenticator) (*AuthConfig, error) {
if actx, ok := authn.(ContextAuthenticator); ok {
return actx.AuthorizationContext(ctx)
}
return authn.Authorization()
}
// AuthConfig contains authorization information for connecting to a Registry
// Inlined what we use from github.com/docker/cli/cli/config/types
type AuthConfig struct {

View File

@ -15,6 +15,7 @@
package authn
import (
"context"
"os"
"path/filepath"
"sync"
@ -45,6 +46,11 @@ type Keychain interface {
Resolve(Resource) (Authenticator, error)
}
// ContextKeychain is like Keychain, but allows for context to be passed in.
type ContextKeychain interface {
ResolveContext(context.Context, Resource) (Authenticator, error)
}
// defaultKeychain implements Keychain with the semantics of the standard Docker
// credential keychain.
type defaultKeychain struct {
@ -62,8 +68,23 @@ const (
DefaultAuthKey = "https://" + name.DefaultRegistry + "/v1/"
)
// Resolve implements Keychain.
// Resolve calls ResolveContext with ctx if the given [Keychain] implements [ContextKeychain],
// otherwise it calls Resolve with the given [Resource].
func Resolve(ctx context.Context, keychain Keychain, target Resource) (Authenticator, error) {
if rctx, ok := keychain.(ContextKeychain); ok {
return rctx.ResolveContext(ctx, target)
}
return keychain.Resolve(target)
}
// ResolveContext implements ContextKeychain.
func (dk *defaultKeychain) Resolve(target Resource) (Authenticator, error) {
return dk.ResolveContext(context.Background(), target)
}
// Resolve implements Keychain.
func (dk *defaultKeychain) ResolveContext(ctx context.Context, target Resource) (Authenticator, error) {
dk.mu.Lock()
defer dk.mu.Unlock()
@ -86,8 +107,8 @@ func (dk *defaultKeychain) Resolve(target Resource) (Authenticator, error) {
// config.Load, which may fail if the config can't be parsed.
//
// If neither was found, look for Podman's auth at
// $XDG_RUNTIME_DIR/containers/auth.json and attempt to load it as a
// Docker config.
// $REGISTRY_AUTH_FILE or $XDG_RUNTIME_DIR/containers/auth.json
// and attempt to load it as a Docker config.
//
// If neither are found, fallback to Anonymous.
var cf *configfile.ConfigFile
@ -96,16 +117,28 @@ func (dk *defaultKeychain) Resolve(target Resource) (Authenticator, error) {
if err != nil {
return nil, err
}
} else {
f, err := os.Open(filepath.Join(os.Getenv("XDG_RUNTIME_DIR"), "containers/auth.json"))
} else if fileExists(os.Getenv("REGISTRY_AUTH_FILE")) {
f, err := os.Open(os.Getenv("REGISTRY_AUTH_FILE"))
if err != nil {
return Anonymous, nil
return nil, err
}
defer f.Close()
cf, err = config.LoadFromReader(f)
if err != nil {
return nil, err
}
} else if fileExists(filepath.Join(os.Getenv("XDG_RUNTIME_DIR"), "containers/auth.json")) {
f, err := os.Open(filepath.Join(os.Getenv("XDG_RUNTIME_DIR"), "containers/auth.json"))
if err != nil {
return nil, err
}
defer f.Close()
cf, err = config.LoadFromReader(f)
if err != nil {
return nil, err
}
} else {
return Anonymous, nil
}
// See:
@ -168,6 +201,10 @@ func NewKeychainFromHelper(h Helper) Keychain { return wrapper{h} }
type wrapper struct{ h Helper }
func (w wrapper) Resolve(r Resource) (Authenticator, error) {
return w.ResolveContext(context.Background(), r)
}
func (w wrapper) ResolveContext(ctx context.Context, r Resource) (Authenticator, error) {
u, p, err := w.h.Get(r.RegistryStr())
if err != nil {
return Anonymous, nil
@ -194,8 +231,12 @@ type refreshingKeychain struct {
}
func (r *refreshingKeychain) Resolve(target Resource) (Authenticator, error) {
return r.ResolveContext(context.Background(), target)
}
func (r *refreshingKeychain) ResolveContext(ctx context.Context, target Resource) (Authenticator, error) {
last := time.Now()
auth, err := r.keychain.Resolve(target)
auth, err := Resolve(ctx, r.keychain, target)
if err != nil || auth == Anonymous {
return auth, err
}
@ -224,17 +265,21 @@ type refreshing struct {
}
func (r *refreshing) Authorization() (*AuthConfig, error) {
return r.AuthorizationContext(context.Background())
}
func (r *refreshing) AuthorizationContext(ctx context.Context) (*AuthConfig, error) {
r.Lock()
defer r.Unlock()
if r.cached == nil || r.expired() {
r.last = r.now()
auth, err := r.keychain.Resolve(r.target)
auth, err := Resolve(ctx, r.keychain, r.target)
if err != nil {
return nil, err
}
r.cached = auth
}
return r.cached.Authorization()
return Authorization(ctx, r.cached)
}
func (r *refreshing) now() time.Time {

View File

@ -14,6 +14,8 @@
package authn
import "context"
type multiKeychain struct {
keychains []Keychain
}
@ -28,8 +30,12 @@ func NewMultiKeychain(kcs ...Keychain) Keychain {
// Resolve implements Keychain.
func (mk *multiKeychain) Resolve(target Resource) (Authenticator, error) {
return mk.ResolveContext(context.Background(), target)
}
func (mk *multiKeychain) ResolveContext(ctx context.Context, target Resource) (Authenticator, error) {
for _, kc := range mk.keychains {
auth, err := kc.Resolve(target)
auth, err := Resolve(ctx, kc, target)
if err != nil {
return nil, err
}

View File

@ -17,6 +17,7 @@ package name
import (
// nolint: depguard
_ "crypto/sha256" // Recommended by go-digest.
"encoding/json"
"strings"
"github.com/opencontainers/go-digest"
@ -59,6 +60,25 @@ func (d Digest) String() string {
return d.original
}
// MarshalJSON formats the digest into a string for JSON serialization.
func (d Digest) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}
// UnmarshalJSON parses a JSON string into a Digest.
func (d *Digest) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
n, err := NewDigest(s)
if err != nil {
return err
}
*d = n
return nil
}
// NewDigest returns a new Digest representing the given name.
func NewDigest(name string, opts ...Option) (Digest, error) {
// Split on "@"

View File

@ -31,7 +31,7 @@ import (
const cloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"
// GetGcloudCmd is exposed so we can test this.
var GetGcloudCmd = func() *exec.Cmd {
var GetGcloudCmd = func(ctx context.Context) *exec.Cmd {
// This is odd, but basically what docker-credential-gcr does.
//
// config-helper is undocumented, but it's purportedly the only supported way
@ -39,15 +39,15 @@ var GetGcloudCmd = func() *exec.Cmd {
//
// --force-auth-refresh means we are getting a token that is valid for about
// an hour (we reuse it until it's expired).
return exec.Command("gcloud", "config", "config-helper", "--force-auth-refresh", "--format=json(credential)")
return exec.CommandContext(ctx, "gcloud", "config", "config-helper", "--force-auth-refresh", "--format=json(credential)")
}
// NewEnvAuthenticator returns an authn.Authenticator that generates access
// tokens from the environment we're running in.
//
// See: https://godoc.org/golang.org/x/oauth2/google#FindDefaultCredentials
func NewEnvAuthenticator() (authn.Authenticator, error) {
ts, err := googauth.DefaultTokenSource(context.Background(), cloudPlatformScope)
func NewEnvAuthenticator(ctx context.Context) (authn.Authenticator, error) {
ts, err := googauth.DefaultTokenSource(ctx, cloudPlatformScope)
if err != nil {
return nil, err
}
@ -62,14 +62,14 @@ func NewEnvAuthenticator() (authn.Authenticator, error) {
// NewGcloudAuthenticator returns an oauth2.TokenSource that generates access
// tokens by shelling out to the gcloud sdk.
func NewGcloudAuthenticator() (authn.Authenticator, error) {
func NewGcloudAuthenticator(ctx context.Context) (authn.Authenticator, error) {
if _, err := exec.LookPath("gcloud"); err != nil {
// gcloud is not available, fall back to anonymous
logs.Warn.Println("gcloud binary not found")
return authn.Anonymous, nil
}
ts := gcloudSource{GetGcloudCmd}
ts := gcloudSource{ctx, GetGcloudCmd}
// Attempt to fetch a token to ensure gcloud is installed and we can run it.
token, err := ts.Token()
@ -143,13 +143,15 @@ type gcloudOutput struct {
}
type gcloudSource struct {
ctx context.Context
// This is passed in so that we mock out gcloud and test Token.
exec func() *exec.Cmd
exec func(ctx context.Context) *exec.Cmd
}
// Token implements oauath2.TokenSource.
func (gs gcloudSource) Token() (*oauth2.Token, error) {
cmd := gs.exec()
cmd := gs.exec(gs.ctx)
var out bytes.Buffer
cmd.Stdout = &out

View File

@ -15,6 +15,7 @@
package google
import (
"context"
"strings"
"sync"
@ -52,26 +53,31 @@ type googleKeychain struct {
// In general, we don't worry about that here because we expect to use the same
// gcloud configuration in the scope of this one process.
func (gk *googleKeychain) Resolve(target authn.Resource) (authn.Authenticator, error) {
return gk.ResolveContext(context.Background(), target)
}
// ResolveContext implements authn.ContextKeychain.
func (gk *googleKeychain) ResolveContext(ctx context.Context, target authn.Resource) (authn.Authenticator, error) {
// Only authenticate GCR and AR so it works with authn.NewMultiKeychain to fallback.
if !isGoogle(target.RegistryStr()) {
return authn.Anonymous, nil
}
gk.once.Do(func() {
gk.auth = resolve()
gk.auth = resolve(ctx)
})
return gk.auth, nil
}
func resolve() authn.Authenticator {
auth, envErr := NewEnvAuthenticator()
func resolve(ctx context.Context) authn.Authenticator {
auth, envErr := NewEnvAuthenticator(ctx)
if envErr == nil && auth != authn.Anonymous {
logs.Debug.Println("google.Keychain: using Application Default Credentials")
return auth
}
auth, gErr := NewGcloudAuthenticator()
auth, gErr := NewGcloudAuthenticator(ctx)
if gErr == nil && auth != authn.Anonymous {
logs.Debug.Println("google.Keychain: using gcloud fallback")
return auth

View File

@ -22,6 +22,8 @@ import (
"io"
"os"
"path/filepath"
"runtime"
"sync"
"github.com/google/go-containerregistry/pkg/logs"
v1 "github.com/google/go-containerregistry/pkg/v1"
@ -37,6 +39,9 @@ var layoutFile = `{
"imageLayoutVersion": "1.0.0"
}`
// renameMutex guards os.Rename calls in AppendImage on Windows only.
var renameMutex sync.Mutex
// AppendImage writes a v1.Image to the Path and updates
// the index.json to reference it.
func (l Path) AppendImage(img v1.Image, options ...Option) error {
@ -259,6 +264,11 @@ func (l Path) writeBlob(hash v1.Hash, size int64, rc io.ReadCloser, renamer func
}
renamePath := l.path("blobs", finalHash.Algorithm, finalHash.Hex)
if runtime.GOOS == "windows" {
renameMutex.Lock()
defer renameMutex.Unlock()
}
return os.Rename(w.Name(), renamePath)
}

View File

@ -47,7 +47,7 @@ type fetcher struct {
func makeFetcher(ctx context.Context, target resource, o *options) (*fetcher, error) {
auth := o.auth
if o.keychain != nil {
kauth, err := o.keychain.Resolve(target)
kauth, err := authn.Resolve(ctx, o.keychain, target)
if err != nil {
return nil, err
}

View File

@ -33,7 +33,7 @@ var _ http.RoundTripper = (*basicTransport)(nil)
// RoundTrip implements http.RoundTripper
func (bt *basicTransport) RoundTrip(in *http.Request) (*http.Response, error) {
if bt.auth != authn.Anonymous {
auth, err := bt.auth.Authorization()
auth, err := authn.Authorization(in.Context(), bt.auth)
if err != nil {
return nil, err
}

View File

@ -49,7 +49,7 @@ func Exchange(ctx context.Context, reg name.Registry, auth authn.Authenticator,
if err != nil {
return nil, err
}
authcfg, err := auth.Authorization()
authcfg, err := authn.Authorization(ctx, auth)
if err != nil {
return nil, err
}
@ -190,7 +190,7 @@ func (bt *bearerTransport) RoundTrip(in *http.Request) (*http.Response, error) {
// The basic token exchange is attempted first, falling back to the oauth flow.
// If the IdentityToken is set, this indicates that we should start with the oauth flow.
func (bt *bearerTransport) refresh(ctx context.Context) error {
auth, err := bt.basic.Authorization()
auth, err := authn.Authorization(ctx, bt.basic)
if err != nil {
return err
}
@ -295,7 +295,7 @@ func canonicalAddress(host, scheme string) (address string) {
// https://docs.docker.com/registry/spec/auth/oauth/
func (bt *bearerTransport) refreshOauth(ctx context.Context) ([]byte, error) {
auth, err := bt.basic.Authorization()
auth, err := authn.Authorization(ctx, bt.basic)
if err != nil {
return nil, err
}

View File

@ -76,7 +76,7 @@ type writer struct {
func makeWriter(ctx context.Context, repo name.Repository, ls []v1.Layer, o *options) (*writer, error) {
auth := o.auth
if o.keychain != nil {
kauth, err := o.keychain.Resolve(repo)
kauth, err := authn.Resolve(ctx, o.keychain, repo)
if err != nil {
return nil, err
}

2
vendor/modules.txt vendored
View File

@ -740,7 +740,7 @@ github.com/google/go-cmp/cmp/internal/diff
github.com/google/go-cmp/cmp/internal/flags
github.com/google/go-cmp/cmp/internal/function
github.com/google/go-cmp/cmp/internal/value
# github.com/google/go-containerregistry v0.19.1
# github.com/google/go-containerregistry v0.19.2
## explicit; go 1.18
github.com/google/go-containerregistry/internal/and
github.com/google/go-containerregistry/internal/compression