Skip to content

Commit e3f8cb0

Browse files
author
wito
committed
fix: fix buildkit www-authenticate challenges
1 parent 4c155db commit e3f8cb0

File tree

5 files changed

+108
-3
lines changed

5 files changed

+108
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ go.work.sum
1212

1313
ralph.sh
1414
plans*
15+
.idea/

examples/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,13 @@ require (
132132
go.opentelemetry.io/otel/sdk v1.20.0 // indirect
133133
go.opentelemetry.io/otel/trace v1.20.0 // indirect
134134
go.opentelemetry.io/proto/otlp v0.12.0 // indirect
135-
golang.org/x/crypto v0.31.0 // indirect
135+
golang.org/x/crypto v0.33.0 // indirect
136136
golang.org/x/mod v0.17.0 // indirect
137137
golang.org/x/net v0.25.0 // indirect
138138
golang.org/x/oauth2 v0.11.0 // indirect
139139
golang.org/x/sync v0.12.0 // indirect
140140
golang.org/x/sys v0.31.0 // indirect
141-
golang.org/x/term v0.27.0 // indirect
141+
golang.org/x/term v0.29.0 // indirect
142142
golang.org/x/text v0.23.0 // indirect
143143
golang.org/x/time v0.3.0 // indirect
144144
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect

examples/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
624624
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
625625
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
626626
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
627+
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
627628
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
628629
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
629630
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -790,6 +791,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
790791
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
791792
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
792793
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
794+
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
793795
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
794796
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
795797
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

pkg/buildx/build/build.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1010,7 +1010,6 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
10101010

10111011
ch, done := progress.NewChannel(pw)
10121012
defer func() { <-done }()
1013-
10141013
cc := c
10151014
var printRes map[string][]byte
10161015
// DEPOT: stop recording the build steps and traces on the server.

pkg/registry/auth.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@ import (
44
"context"
55
"encoding/base64"
66
"fmt"
7+
"net/http"
78
"os"
89
"strings"
10+
"time"
911

12+
authutil "github.com/containerd/containerd/remotes/docker/auth"
13+
remoteserrors "github.com/containerd/containerd/remotes/errors"
1014
"github.com/depot/cli/pkg/build"
1115
"github.com/docker/cli/cli/config"
1216
"github.com/docker/cli/cli/config/types"
1317
"github.com/moby/buildkit/session"
1418
"github.com/moby/buildkit/session/auth"
1519
"github.com/moby/buildkit/session/auth/authprovider"
20+
"github.com/pkg/errors"
1621
"google.golang.org/grpc"
1722
)
1823

@@ -78,9 +83,76 @@ func (a *AuthProvider) Credentials(ctx context.Context, req *auth.CredentialsReq
7883
}
7984

8085
func (a *AuthProvider) FetchToken(ctx context.Context, req *auth.FetchTokenRequest) (*auth.FetchTokenResponse, error) {
86+
creds := a.findCredentials(req.Host)
87+
if creds == nil {
88+
return a.inner.FetchToken(ctx, req)
89+
}
90+
91+
to := authutil.TokenOptions{
92+
Realm: req.Realm,
93+
Service: req.Service,
94+
Scopes: req.Scopes,
95+
Username: creds.Username,
96+
Secret: creds.Password,
97+
}
98+
99+
if to.Secret != "" {
100+
// Credential information is provided, try the OAuth POST endpoint first.
101+
resp, err := authutil.FetchTokenWithOAuth(ctx, http.DefaultClient, nil, "buildkit-client", to)
102+
if err != nil {
103+
var errStatus remoteserrors.ErrUnexpectedStatus
104+
if errors.As(err, &errStatus) {
105+
// Registries without support for POST may return 404 or 401.
106+
if (errStatus.StatusCode == 405 && to.Username != "") || errStatus.StatusCode == 404 || errStatus.StatusCode == 401 {
107+
getResp, err := authutil.FetchToken(ctx, http.DefaultClient, nil, to)
108+
if err != nil {
109+
return nil, err
110+
}
111+
return toFetchTokenResponse(getResp.Token, getResp.IssuedAt, getResp.ExpiresIn), nil
112+
}
113+
}
114+
return nil, err
115+
}
116+
return toFetchTokenResponse(resp.AccessToken, resp.IssuedAt, resp.ExpiresIn), nil
117+
}
118+
119+
// No secret, fall back to inner provider.
81120
return a.inner.FetchToken(ctx, req)
82121
}
83122

123+
// findCredentials looks up decoded credentials for a host from the depot credential list.
124+
func (a *AuthProvider) findCredentials(host string) *types.AuthConfig {
125+
for _, c := range a.credentials {
126+
if c.Host != host {
127+
continue
128+
}
129+
decoded, err := base64.StdEncoding.DecodeString(c.Token)
130+
if err != nil {
131+
continue
132+
}
133+
parts := strings.SplitN(string(decoded), ":", 2)
134+
if len(parts) != 2 {
135+
continue
136+
}
137+
return &types.AuthConfig{
138+
Username: parts[0],
139+
Password: parts[1],
140+
}
141+
}
142+
return nil
143+
}
144+
145+
func toFetchTokenResponse(token string, issuedAt time.Time, expires int) *auth.FetchTokenResponse {
146+
resp := &auth.FetchTokenResponse{
147+
Token: token,
148+
ExpiresIn: int64(expires),
149+
}
150+
if !issuedAt.IsZero() {
151+
resp.IssuedAt = issuedAt.Unix()
152+
}
153+
return resp
154+
}
155+
84156
func (a *AuthProvider) GetTokenAuthority(ctx context.Context, req *auth.GetTokenAuthorityRequest) (*auth.GetTokenAuthorityResponse, error) {
85157
return a.inner.GetTokenAuthority(ctx, req)
86158
}
@@ -124,6 +196,37 @@ func (a *DepotAuthProvider) Credentials(ctx context.Context, req *auth.Credentia
124196
}
125197

126198
func (a *DepotAuthProvider) FetchToken(ctx context.Context, req *auth.FetchTokenRequest) (*auth.FetchTokenResponse, error) {
199+
creds := GetDepotAuthConfig()
200+
if creds == nil {
201+
return a.inner.FetchToken(ctx, req)
202+
}
203+
204+
to := authutil.TokenOptions{
205+
Realm: req.Realm,
206+
Service: req.Service,
207+
Scopes: req.Scopes,
208+
Username: creds.Username,
209+
Secret: creds.Password,
210+
}
211+
212+
if to.Secret != "" {
213+
resp, err := authutil.FetchTokenWithOAuth(ctx, http.DefaultClient, nil, "buildkit-client", to)
214+
if err != nil {
215+
var errStatus remoteserrors.ErrUnexpectedStatus
216+
if errors.As(err, &errStatus) {
217+
if (errStatus.StatusCode == 405 && to.Username != "") || errStatus.StatusCode == 404 || errStatus.StatusCode == 401 {
218+
getResp, err := authutil.FetchToken(ctx, http.DefaultClient, nil, to)
219+
if err != nil {
220+
return nil, err
221+
}
222+
return toFetchTokenResponse(getResp.Token, getResp.IssuedAt, getResp.ExpiresIn), nil
223+
}
224+
}
225+
return nil, err
226+
}
227+
return toFetchTokenResponse(resp.AccessToken, resp.IssuedAt, resp.ExpiresIn), nil
228+
}
229+
127230
return a.inner.FetchToken(ctx, req)
128231
}
129232

0 commit comments

Comments
 (0)