11package imagetools
22
33import (
4+ "context"
45 "encoding/base64"
56 "encoding/json"
7+ "net/http"
8+ "sync"
9+ "time"
610
11+ "github.com/containerd/containerd/v2/core/remotes/docker"
712 "github.com/distribution/reference"
13+ "github.com/docker/cli/cli/config/types"
814)
915
10- func toCredentialsFunc (a Auth ) func (string ) (string , string , error ) {
11- return func (host string ) (string , string , error ) {
12- if host == "registry-1.docker.io" {
13- host = "https://index.docker.io/v1/"
14- }
15- ac , err := a .GetAuthConfig (host )
16- if err != nil {
17- return "" , "" , err
18- }
19- if ac .IdentityToken != "" {
20- return "" , ac .IdentityToken , nil
21- }
22- return ac .Username , ac .Password , nil
16+ type authConfig struct {
17+ mu sync.Mutex
18+ authConfigCache map [string ]authConfigCacheEntry
19+ cfg Auth
20+ }
21+
22+ type authConfigCacheEntry struct {
23+ Created time.Time
24+ Auth types.AuthConfig
25+ }
26+
27+ func newAuthConfig (a Auth ) * authConfig {
28+ return & authConfig {
29+ authConfigCache : map [string ]authConfigCacheEntry {},
30+ cfg : a ,
31+ }
32+ }
33+
34+ func (a * authConfig ) credentials (host string ) (string , string , error ) {
35+ ac , err := a .authConfig (host )
36+ if err != nil {
37+ return "" , "" , err
38+ }
39+ if ac .IdentityToken != "" {
40+ return "" , ac .IdentityToken , nil
41+ }
42+ return ac .Username , ac .Password , nil
43+ }
44+
45+ func (a * authConfig ) authConfig (host string ) (types.AuthConfig , error ) {
46+ const defaultExpiration = 2 * time .Minute
47+
48+ if host == "registry-1.docker.io" {
49+ host = "https://index.docker.io/v1/"
50+ }
51+ a .mu .Lock ()
52+ defer a .mu .Unlock ()
53+
54+ if c , ok := a .authConfigCache [host ]; ok && time .Since (c .Created ) <= defaultExpiration {
55+ return c .Auth , nil
56+ }
57+ ac , err := a .cfg .GetAuthConfig (host )
58+ if err != nil {
59+ return types.AuthConfig {}, err
2360 }
61+ a .authConfigCache [host ] = authConfigCacheEntry {
62+ Created : time .Now (),
63+ Auth : ac ,
64+ }
65+ return ac , nil
2466}
2567
2668func RegistryAuthForRef (ref string , a Auth ) (string , error ) {
@@ -45,3 +87,17 @@ func RegistryAuthForRef(ref string, a Auth) (string, error) {
4587 }
4688 return base64 .URLEncoding .EncodeToString (buf ), nil
4789}
90+
91+ type withBearerAuthorizer struct {
92+ docker.Authorizer
93+ AuthConfig * authConfig
94+ }
95+
96+ func (a * withBearerAuthorizer ) Authorize (ctx context.Context , req * http.Request ) error {
97+ ac , err := a .AuthConfig .authConfig (req .Host )
98+ if err == nil && ac .RegistryToken != "" {
99+ req .Header .Set ("Authorization" , "Bearer " + ac .RegistryToken )
100+ return nil
101+ }
102+ return a .Authorizer .Authorize (ctx , req )
103+ }
0 commit comments