mirror of https://github.com/docker/buildx.git
bake: git auth support for remote definitions
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
parent
38fbd9a85c
commit
4d39259f8e
|
@ -4,6 +4,8 @@ import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/buildx/builder"
|
"github.com/docker/buildx/builder"
|
||||||
controllerapi "github.com/docker/buildx/controller/pb"
|
controllerapi "github.com/docker/buildx/controller/pb"
|
||||||
|
@ -23,13 +25,34 @@ type Input struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadRemoteFiles(ctx context.Context, nodes []builder.Node, url string, names []string, pw progress.Writer) ([]File, *Input, error) {
|
func ReadRemoteFiles(ctx context.Context, nodes []builder.Node, url string, names []string, pw progress.Writer) ([]File, *Input, error) {
|
||||||
var session []session.Attachable
|
var sessions []session.Attachable
|
||||||
var filename string
|
var filename string
|
||||||
|
|
||||||
st, ok := dockerui.DetectGitContext(url, false)
|
st, ok := dockerui.DetectGitContext(url, false)
|
||||||
if ok {
|
if ok {
|
||||||
ssh, err := controllerapi.CreateSSH([]*controllerapi.SSH{{ID: "default"}})
|
if ssh, err := controllerapi.CreateSSH([]*controllerapi.SSH{{
|
||||||
if err == nil {
|
ID: "default",
|
||||||
session = append(session, ssh)
|
Paths: strings.Split(os.Getenv("BUILDX_BAKE_GIT_SSH"), ","),
|
||||||
|
}}); err == nil {
|
||||||
|
sessions = append(sessions, ssh)
|
||||||
|
}
|
||||||
|
var gitAuthSecrets []*controllerapi.Secret
|
||||||
|
if _, ok := os.LookupEnv("BUILDX_BAKE_GIT_AUTH_TOKEN"); ok {
|
||||||
|
gitAuthSecrets = append(gitAuthSecrets, &controllerapi.Secret{
|
||||||
|
ID: llb.GitAuthTokenKey,
|
||||||
|
Env: "BUILDX_BAKE_GIT_AUTH_TOKEN",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if _, ok := os.LookupEnv("BUILDX_BAKE_GIT_AUTH_HEADER"); ok {
|
||||||
|
gitAuthSecrets = append(gitAuthSecrets, &controllerapi.Secret{
|
||||||
|
ID: llb.GitAuthHeaderKey,
|
||||||
|
Env: "BUILDX_BAKE_GIT_AUTH_HEADER",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(gitAuthSecrets) > 0 {
|
||||||
|
if secrets, err := controllerapi.CreateSecrets(gitAuthSecrets); err == nil {
|
||||||
|
sessions = append(sessions, secrets)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
st, filename, ok = dockerui.DetectHTTPContext(url)
|
st, filename, ok = dockerui.DetectHTTPContext(url)
|
||||||
|
@ -59,7 +82,7 @@ func ReadRemoteFiles(ctx context.Context, nodes []builder.Node, url string, name
|
||||||
|
|
||||||
ch, done := progress.NewChannel(pw)
|
ch, done := progress.NewChannel(pw)
|
||||||
defer func() { <-done }()
|
defer func() { <-done }()
|
||||||
_, err = c.Build(ctx, client.SolveOpt{Session: session, Internal: true}, "buildx", func(ctx context.Context, c gwclient.Client) (*gwclient.Result, error) {
|
_, err = c.Build(ctx, client.SolveOpt{Session: sessions, Internal: true}, "buildx", func(ctx context.Context, c gwclient.Client) (*gwclient.Result, error) {
|
||||||
def, err := st.Marshal(ctx)
|
def, err := st.Marshal(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -29,6 +29,7 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
|
||||||
testBakeLocal,
|
testBakeLocal,
|
||||||
testBakeLocalMulti,
|
testBakeLocalMulti,
|
||||||
testBakeRemote,
|
testBakeRemote,
|
||||||
|
testBakeRemoteAuth,
|
||||||
testBakeRemoteCmdContext,
|
testBakeRemoteCmdContext,
|
||||||
testBakeRemoteLocalOverride,
|
testBakeRemoteLocalOverride,
|
||||||
testBakeLocalCwdOverride,
|
testBakeLocalCwdOverride,
|
||||||
|
@ -144,6 +145,41 @@ EOT
|
||||||
require.FileExists(t, filepath.Join(dirDest, "foo"))
|
require.FileExists(t, filepath.Join(dirDest, "foo"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testBakeRemoteAuth(t *testing.T, sb integration.Sandbox) {
|
||||||
|
bakefile := []byte(`
|
||||||
|
target "default" {
|
||||||
|
dockerfile-inline = <<EOT
|
||||||
|
FROM scratch
|
||||||
|
COPY foo /foo
|
||||||
|
EOT
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
dir := tmpdir(
|
||||||
|
t,
|
||||||
|
fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
|
||||||
|
fstest.CreateFile("foo", []byte("foo"), 0600),
|
||||||
|
)
|
||||||
|
dirDest := t.TempDir()
|
||||||
|
|
||||||
|
git, err := gitutil.New(gitutil.WithWorkingDir(dir))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
gitutil.GitInit(git, t)
|
||||||
|
gitutil.GitAdd(git, t, "docker-bake.hcl", "foo")
|
||||||
|
gitutil.GitCommit(git, t, "initial commit")
|
||||||
|
|
||||||
|
token := identity.NewID()
|
||||||
|
addr := gitutil.GitServeHTTP(git, t, gitutil.WithAccessToken(token))
|
||||||
|
|
||||||
|
out, err := bakeCmd(sb, withDir(dir),
|
||||||
|
withEnv("BUILDX_BAKE_GIT_AUTH_TOKEN="+token),
|
||||||
|
withArgs(addr, "--set", "*.output=type=local,dest="+dirDest),
|
||||||
|
)
|
||||||
|
require.NoError(t, err, out)
|
||||||
|
|
||||||
|
require.FileExists(t, filepath.Join(dirDest, "foo"))
|
||||||
|
}
|
||||||
|
|
||||||
func testBakeRemoteLocalOverride(t *testing.T, sb integration.Sandbox) {
|
func testBakeRemoteLocalOverride(t *testing.T, sb integration.Sandbox) {
|
||||||
remoteBakefile := []byte(`
|
remoteBakefile := []byte(`
|
||||||
target "default" {
|
target "default" {
|
||||||
|
|
|
@ -10,11 +10,28 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GitServeHTTP(c *Git, t testing.TB) (url string) {
|
type gitServe struct {
|
||||||
|
token string
|
||||||
|
}
|
||||||
|
|
||||||
|
type GitServeOpt func(*gitServe)
|
||||||
|
|
||||||
|
func WithAccessToken(token string) GitServeOpt {
|
||||||
|
return func(s *gitServe) {
|
||||||
|
s.token = token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GitServeHTTP(c *Git, t testing.TB, opts ...GitServeOpt) (url string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
gitUpdateServerInfo(c, t)
|
gitUpdateServerInfo(c, t)
|
||||||
ctx, cancel := context.WithCancel(context.TODO())
|
ctx, cancel := context.WithCancel(context.TODO())
|
||||||
|
|
||||||
|
gs := &gitServe{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(gs)
|
||||||
|
}
|
||||||
|
|
||||||
ready := make(chan struct{})
|
ready := make(chan struct{})
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
|
||||||
|
@ -28,7 +45,25 @@ func GitServeHTTP(c *Git, t testing.TB) (url string) {
|
||||||
go func() {
|
go func() {
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
prefix := fmt.Sprintf("/%s/", name)
|
prefix := fmt.Sprintf("/%s/", name)
|
||||||
mux.Handle(prefix, http.StripPrefix(prefix, http.FileServer(http.Dir(dir))))
|
|
||||||
|
handler := func(next http.Handler) http.Handler {
|
||||||
|
var tokenChecked bool
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if gs.token != "" && !tokenChecked {
|
||||||
|
t.Logf("git access token to check: %q", gs.token)
|
||||||
|
user, pass, _ := r.BasicAuth()
|
||||||
|
t.Logf("basic auth: user=%q pass=%q", user, pass)
|
||||||
|
if pass != gs.token {
|
||||||
|
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tokenChecked = true
|
||||||
|
}
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
mux.Handle(prefix, handler(http.StripPrefix(prefix, http.FileServer(http.Dir(dir)))))
|
||||||
l, err := net.Listen("tcp", "localhost:0")
|
l, err := net.Listen("tcp", "localhost:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
Loading…
Reference in New Issue