From 41c8c946ba01172e6c8c90674841f2b9af2a43cf Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 15 Nov 2017 23:59:47 -0800 Subject: [PATCH] Fix chaining of credentials for minio-go chaining failed because chaining provider was only looking for subsequent credentials provider after an error. Writer a new chaining provider which proceeds to fetch new credentials also under situations where providers do not return but instead return no keys at all. Fixes https://github.com/restic/restic/issues/1422 --- internal/backend/s3/s3.go | 44 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/internal/backend/s3/s3.go b/internal/backend/s3/s3.go index f21be437c..1d8cb780c 100644 --- a/internal/backend/s3/s3.go +++ b/internal/backend/s3/s3.go @@ -33,6 +33,48 @@ var _ restic.Backend = &Backend{} const defaultLayout = "default" +type chain struct { + Providers []credentials.Provider + curr credentials.Provider +} + +// FIXME: Remove this code once restic migrates to minio-go 4.0.x +func newChainCredentials(providers []credentials.Provider) *credentials.Credentials { + return credentials.New(&chain{ + Providers: append([]credentials.Provider{}, providers...), + }) +} + +// Retrieve returns the credentials value or error if no provider returned +// without error. +// +// If a provider is found it will be cached and any calls to IsExpired() +// will return the expired state of the cached provider. +func (c *chain) Retrieve() (credentials.Value, error) { + for _, p := range c.Providers { + creds, _ := p.Retrieve() + // If anonymous proceed to the next provider if any. + if creds.SignerType.IsAnonymous() { + continue + } + c.curr = p + return creds, nil + } + return credentials.Value{ + SignerType: credentials.SignatureAnonymous, + }, nil +} + +// IsExpired will returned the expired state of the currently cached provider +// if there is one. If there is no current provider, true will be returned. +func (c *chain) IsExpired() bool { + if c.curr != nil { + return c.curr.IsExpired() + } + + return true +} + func open(cfg Config, rt http.RoundTripper) (*Backend, error) { debug.Log("open, config %#v", cfg) @@ -47,7 +89,7 @@ func open(cfg Config, rt http.RoundTripper) (*Backend, error) { // configured ec2 instances) // AWS env variables such as AWS_ACCESS_KEY_ID // Minio env variables such as MINIO_ACCESS_KEY - creds := credentials.NewChainCredentials([]credentials.Provider{ + creds := newChainCredentials([]credentials.Provider{ &credentials.Static{ Value: credentials.Value{ AccessKeyID: cfg.KeyID,