mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
vendor: update buildkit to v0.8
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
179
vendor/github.com/moby/buildkit/session/auth/authprovider/authprovider.go
generated
vendored
179
vendor/github.com/moby/buildkit/session/auth/authprovider/authprovider.go
generated
vendored
@ -2,24 +2,46 @@ package authprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
authutil "github.com/containerd/containerd/remotes/docker/auth"
|
||||
remoteserrors "github.com/containerd/containerd/remotes/errors"
|
||||
"github.com/docker/cli/cli/config"
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/moby/buildkit/session"
|
||||
"github.com/moby/buildkit/session/auth"
|
||||
"github.com/moby/buildkit/util/progress/progresswriter"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/nacl/sign"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func NewDockerAuthProvider(stderr io.Writer) session.Attachable {
|
||||
return &authProvider{
|
||||
config: config.LoadDefaultConfigFile(stderr),
|
||||
config: config.LoadDefaultConfigFile(stderr),
|
||||
seeds: &tokenSeeds{dir: config.Dir()},
|
||||
loggerCache: map[string]struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
type authProvider struct {
|
||||
config *configfile.ConfigFile
|
||||
config *configfile.ConfigFile
|
||||
seeds *tokenSeeds
|
||||
logger progresswriter.Logger
|
||||
loggerCache map[string]struct{}
|
||||
|
||||
// The need for this mutex is not well understood.
|
||||
// Without it, the docker cli on OS X hangs when
|
||||
@ -28,17 +50,80 @@ type authProvider struct {
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (ap *authProvider) SetLogger(l progresswriter.Logger) {
|
||||
ap.mu.Lock()
|
||||
ap.logger = l
|
||||
ap.mu.Unlock()
|
||||
}
|
||||
|
||||
func (ap *authProvider) Register(server *grpc.Server) {
|
||||
auth.RegisterAuthServer(server, ap)
|
||||
}
|
||||
|
||||
func (ap *authProvider) Credentials(ctx context.Context, req *auth.CredentialsRequest) (*auth.CredentialsResponse, error) {
|
||||
func (ap *authProvider) FetchToken(ctx context.Context, req *auth.FetchTokenRequest) (rr *auth.FetchTokenResponse, err error) {
|
||||
creds, err := ap.credentials(req.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
to := authutil.TokenOptions{
|
||||
Realm: req.Realm,
|
||||
Service: req.Service,
|
||||
Scopes: req.Scopes,
|
||||
Username: creds.Username,
|
||||
Secret: creds.Secret,
|
||||
}
|
||||
|
||||
if creds.Secret != "" {
|
||||
done := func(progresswriter.SubLogger) error {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
err = errors.Wrap(err, "failed to fetch oauth token")
|
||||
}()
|
||||
ap.mu.Lock()
|
||||
name := fmt.Sprintf("[auth] %v token for %s", strings.Join(trimScopePrefix(req.Scopes), " "), req.Host)
|
||||
if _, ok := ap.loggerCache[name]; !ok {
|
||||
progresswriter.Wrap(name, ap.logger, done)
|
||||
}
|
||||
ap.mu.Unlock()
|
||||
// try GET first because Docker Hub does not support POST
|
||||
// switch once support has landed
|
||||
resp, err := authutil.FetchToken(ctx, http.DefaultClient, nil, to)
|
||||
if err != nil {
|
||||
var errStatus remoteserrors.ErrUnexpectedStatus
|
||||
if errors.As(err, &errStatus) {
|
||||
// retry with POST request
|
||||
// As of September 2017, GCR is known to return 404.
|
||||
// As of February 2018, JFrog Artifactory is known to return 401.
|
||||
if (errStatus.StatusCode == 405 && to.Username != "") || errStatus.StatusCode == 404 || errStatus.StatusCode == 401 {
|
||||
resp, err := authutil.FetchTokenWithOAuth(ctx, http.DefaultClient, nil, "buildkit-client", to)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return toTokenResponse(resp.AccessToken, resp.IssuedAt, resp.ExpiresIn), nil
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return toTokenResponse(resp.Token, resp.IssuedAt, resp.ExpiresIn), nil
|
||||
}
|
||||
// do request anonymously
|
||||
resp, err := authutil.FetchToken(ctx, http.DefaultClient, nil, to)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to fetch anonymous token")
|
||||
}
|
||||
return toTokenResponse(resp.Token, resp.IssuedAt, resp.ExpiresIn), nil
|
||||
}
|
||||
|
||||
func (ap *authProvider) credentials(host string) (*auth.CredentialsResponse, error) {
|
||||
ap.mu.Lock()
|
||||
defer ap.mu.Unlock()
|
||||
if req.Host == "registry-1.docker.io" {
|
||||
req.Host = "https://index.docker.io/v1/"
|
||||
if host == "registry-1.docker.io" {
|
||||
host = "https://index.docker.io/v1/"
|
||||
}
|
||||
ac, err := ap.config.GetAuthConfig(req.Host)
|
||||
ac, err := ap.config.GetAuthConfig(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -51,3 +136,85 @@ func (ap *authProvider) Credentials(ctx context.Context, req *auth.CredentialsRe
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (ap *authProvider) Credentials(ctx context.Context, req *auth.CredentialsRequest) (*auth.CredentialsResponse, error) {
|
||||
resp, err := ap.credentials(req.Host)
|
||||
if err != nil || resp.Secret != "" {
|
||||
ap.mu.Lock()
|
||||
defer ap.mu.Unlock()
|
||||
_, ok := ap.loggerCache[req.Host]
|
||||
ap.loggerCache[req.Host] = struct{}{}
|
||||
if !ok {
|
||||
return resp, progresswriter.Wrap(fmt.Sprintf("[auth] sharing credentials for %s", req.Host), ap.logger, func(progresswriter.SubLogger) error {
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (ap *authProvider) GetTokenAuthority(ctx context.Context, req *auth.GetTokenAuthorityRequest) (*auth.GetTokenAuthorityResponse, error) {
|
||||
key, err := ap.getAuthorityKey(req.Host, req.Salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &auth.GetTokenAuthorityResponse{PublicKey: key[32:]}, nil
|
||||
}
|
||||
|
||||
func (ap *authProvider) VerifyTokenAuthority(ctx context.Context, req *auth.VerifyTokenAuthorityRequest) (*auth.VerifyTokenAuthorityResponse, error) {
|
||||
key, err := ap.getAuthorityKey(req.Host, req.Salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
priv := new([64]byte)
|
||||
copy((*priv)[:], key)
|
||||
|
||||
return &auth.VerifyTokenAuthorityResponse{Signed: sign.Sign(nil, req.Payload, priv)}, nil
|
||||
}
|
||||
|
||||
func (ap *authProvider) getAuthorityKey(host string, salt []byte) (ed25519.PrivateKey, error) {
|
||||
if v, err := strconv.ParseBool(os.Getenv("BUILDKIT_NO_CLIENT_TOKEN")); err == nil && v {
|
||||
return nil, status.Errorf(codes.Unavailable, "client side tokens disabled")
|
||||
}
|
||||
|
||||
creds, err := ap.credentials(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
seed, err := ap.seeds.getSeed(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mac := hmac.New(sha256.New, salt)
|
||||
if creds.Secret != "" {
|
||||
mac.Write(seed)
|
||||
enc := json.NewEncoder(mac)
|
||||
enc.Encode(creds)
|
||||
}
|
||||
|
||||
sum := mac.Sum(nil)
|
||||
|
||||
return ed25519.NewKeyFromSeed(sum[:ed25519.SeedSize]), nil
|
||||
}
|
||||
|
||||
func toTokenResponse(token string, issuedAt time.Time, expires int) *auth.FetchTokenResponse {
|
||||
resp := &auth.FetchTokenResponse{
|
||||
Token: token,
|
||||
ExpiresIn: int64(expires),
|
||||
}
|
||||
if !issuedAt.IsZero() {
|
||||
resp.IssuedAt = issuedAt.Unix()
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func trimScopePrefix(scopes []string) []string {
|
||||
out := make([]string, len(scopes))
|
||||
for i, s := range scopes {
|
||||
out[i] = strings.TrimPrefix(s, "repository:")
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
Reference in New Issue
Block a user