Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 10 additions & 1 deletion build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"encoding/json"
"fmt"
"io"
"io/fs"
"maps"
"os"
"slices"
Expand All @@ -21,6 +22,7 @@ import (
noderesolver "github.com/docker/buildx/build/resolver"
"github.com/docker/buildx/builder"
"github.com/docker/buildx/driver"
"github.com/docker/buildx/policy"
"github.com/docker/buildx/util/buildflags"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/desktop"
Expand Down Expand Up @@ -113,6 +115,13 @@ type Inputs struct {
// DockerfileMappingSrc and DockerfileMappingDst are filled in by the builder.
DockerfileMappingSrc string
DockerfileMappingDst string

policy *policyOpt
}

type policyOpt struct {
Files []policy.File
FS func() (fs.StatFS, func() error, error)
}

type NamedContext struct {
Expand Down Expand Up @@ -927,7 +936,7 @@ func detectSharedMounts(ctx context.Context, reqs map[string][]*reqForNode) (_ m
}
fsMap := m[nodeName]
for name, m := range req.so.LocalMounts {
fs, ok := m.(*fs)
fs, ok := m.(*fsMount)
if !ok {
continue
}
Expand Down
2 changes: 1 addition & 1 deletion build/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func getGitAttributes(ctx context.Context, contextPath, dockerfilePath string) (
}

for key, mount := range so.LocalMounts {
fs, ok := mount.(*fs)
fs, ok := mount.(*fsMount)
if !ok {
continue
}
Expand Down
70 changes: 67 additions & 3 deletions build/opt.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import (
"bytes"
"context"
"io"
"io/fs"
"log"
"maps"
"os"
"path"
"path/filepath"
"slices"
"strconv"
Expand All @@ -21,6 +24,7 @@ import (
"github.com/distribution/reference"
"github.com/docker/buildx/builder"
"github.com/docker/buildx/driver"
"github.com/docker/buildx/policy"
"github.com/docker/buildx/util/buildflags"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/dockerutil"
Expand All @@ -38,6 +42,7 @@ import (
"github.com/moby/buildkit/session/sshforward/sshprovider"
"github.com/moby/buildkit/session/upload/uploadprovider"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/sourcepolicy/policysession"
"github.com/moby/buildkit/util/apicaps"
"github.com/moby/buildkit/util/entitlements"
"github.com/moby/buildkit/util/gitutil"
Expand Down Expand Up @@ -322,6 +327,29 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt *O
}
defers = append(defers, releaseLoad)

if opt.Inputs.policy != nil {
env := policy.Env{}
for k, v := range opt.BuildArgs {
if env.Args == nil {
env.Args = map[string]*string{}
}
env.Args[k] = &v
}
env.Filename = path.Base(opt.Inputs.DockerfilePath)
env.Target = opt.Target
env.Labels = opt.Labels
p := policy.NewPolicy(policy.Opt{
Files: opt.Inputs.policy.Files,
Env: env,
Log: func(msg string) {
log.Printf("[policy] %s", msg)
},
FS: opt.Inputs.policy.FS,
Config: cfg,
})
so.SourcePolicyProvider = policysession.NewPolicyProvider(p.CheckPolicy)
}

// add node identifier to shared key if one was specified
if so.SharedKey != "" {
so.SharedKey += ":" + cfg.TryNodeIdentifier()
Expand Down Expand Up @@ -413,6 +441,7 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro
var (
err error
dockerfileReader io.ReadCloser
contextDir string
dockerfileDir string
dockerfileName = inp.DockerfilePath
dockerfileSrcName = inp.DockerfilePath
Expand Down Expand Up @@ -454,12 +483,14 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro
if err := setLocalMount("context", inp.ContextPath, target); err != nil {
return nil, err
}
contextDir = inp.ContextPath
}
}
case osutil.IsLocalDir(inp.ContextPath):
if err := setLocalMount("context", inp.ContextPath, target); err != nil {
return nil, err
}
contextDir = inp.ContextPath
sharedKey := inp.ContextPath
if p, err := filepath.Abs(sharedKey); err == nil {
sharedKey = filepath.Base(p)
Expand Down Expand Up @@ -535,6 +566,39 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro
return nil, err
}
dockerfileName = handleLowercaseDockerfile(dockerfileDir, dockerfileName)

if fi, err := os.Lstat(filepath.Join(dockerfileDir, dockerfileName+".rego")); err == nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: err should be returned if err != nil && !errors.Is(err, os.ErrNotExist)
e.g., EACCES

if fi.Mode().IsRegular() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to reject symlink?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wanted to make sure there is no breakout here. Normally this shouldn't matter as Dockerfile path symlinks are already resolved and default policy is relative to that resolved path. But I'm ok with symlinks only for policy as well, as long as breakout cases are protected.

dt, err := os.ReadFile(filepath.Join(dockerfileDir, dockerfileName+".rego"))
if err != nil {
return nil, errors.Wrapf(err, "failed to read policy file %s.rego", dockerfileName)
}
inp.policy = &policyOpt{
Files: []policy.File{
{
Filename: dockerfileName + ".rego",
Data: dt,
},
},
FS: func() (fs.StatFS, func() error, error) {
if contextDir == "" {
return nil, nil, errors.Errorf("unimplemented, cannot use policy file without a local build context")
}
root, err := os.OpenRoot(contextDir)
if err != nil {
return nil, nil, errors.Wrapf(err, "failed to open root for policy file %s.rego", dockerfileName)
}
baseFS := root.FS()
statFS, ok := baseFS.(fs.StatFS)
if !ok {
root.Close()
return nil, nil, errors.Errorf("invalid root FS type %T", baseFS)
}
return statFS, root.Close, nil
},
}
}
}
}

target.FrontendAttrs["filename"] = dockerfileName
Expand Down Expand Up @@ -653,7 +717,7 @@ func setLocalMount(name, dir string, so *client.SolveOpt) error {
if so.LocalMounts == nil {
so.LocalMounts = map[string]fsutil.FS{}
}
so.LocalMounts[name] = &fs{FS: lm, dir: dir}
so.LocalMounts[name] = &fsMount{FS: lm, dir: dir}
return nil
}

Expand Down Expand Up @@ -765,12 +829,12 @@ func handleLowercaseDockerfile(dir, p string) string {
return p
}

type fs struct {
type fsMount struct {
fsutil.FS
dir string
}

var _ fsutil.FS = &fs{}
var _ fsutil.FS = &fsMount{}

func CreateSSH(ssh []*buildflags.SSH) (session.Attachable, error) {
configs := make([]sshprovider.AgentConfig, 0, len(ssh))
Expand Down
6 changes: 2 additions & 4 deletions dap/thread.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,11 +355,9 @@ func (t *thread) prepareResultHandle(c Context, ref gateway.Reference, err error

// Start the attach. Use the context we created and perform it in
// a goroutine. We aren't necessarily assuming this will actually work.
wg.Add(1)
go func() {
defer wg.Done()
wg.Go(func() {
t.sh.Attach(ctx, t)
}()
})
}

func (t *thread) Continue() {
Expand Down
Loading
Loading