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 @@ -20,6 +21,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/desktop"
Expand Down Expand Up @@ -112,6 +114,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 @@ -922,7 +931,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
69 changes: 66 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,28 @@ 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,
})
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 +440,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 +482,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 +565,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 +716,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 +828,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
39 changes: 35 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/docker/buildx

go 1.24.3
go 1.24.6

require (
github.com/Masterminds/semver/v3 v3.4.0
Expand Down Expand Up @@ -36,22 +36,23 @@ require (
github.com/moby/sys/atomicwriter v0.1.0
github.com/moby/sys/mountinfo v0.7.2
github.com/morikuni/aec v1.0.0
github.com/open-policy-agent/opa v1.10.1
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.1
github.com/pelletier/go-toml v1.9.5
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
github.com/pkg/errors v0.9.1
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10
github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b
github.com/sirupsen/logrus v1.9.3
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af
github.com/spf13/cobra v1.10.1
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
github.com/tonistiigi/fsutil v0.0.0-20250605211040-586307ad452f
github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0
github.com/tonistiigi/jaeger-ui-rest v0.0.0-20250408171107-3dd17559e117
github.com/zclconf/go-cty v1.17.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0
go.opentelemetry.io/otel v1.38.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0
go.opentelemetry.io/otel/metric v1.38.0
Expand All @@ -74,7 +75,9 @@ require (

require (
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/ProtonMail/go-crypto v1.3.0 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/agnivade/levenshtein v1.2.1 // indirect
github.com/apparentlymart/go-cidr v1.0.1 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.38.1 // indirect
Expand All @@ -89,25 +92,32 @@ require (
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 // indirect
github.com/aws/smithy-go v1.22.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudflare/circl v1.6.0 // indirect
github.com/containerd/containerd/api v1.10.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.4 // indirect
github.com/docker/go-connections v0.6.0 // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fvbommel/sortorder v1.1.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
Expand All @@ -117,10 +127,19 @@ require (
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hiddeco/sshsig v0.2.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.1 // indirect
github.com/lestrrat-go/blackmagic v1.0.4 // indirect
github.com/lestrrat-go/dsig v1.0.0 // indirect
github.com/lestrrat-go/dsig-secp256k1 v1.0.0 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc/v3 v3.0.1 // indirect
github.com/lestrrat-go/jwx/v3 v3.0.11 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/lestrrat-go/option/v2 v2.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
Expand All @@ -139,16 +158,28 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/tchap/go-patricia/v2 v2.3.3 // indirect
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab // indirect
github.com/valyala/fastjson v1.6.4 // indirect
github.com/vektah/gqlparser/v2 v2.5.30 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
github.com/yashtewari/glob-intersection v0.2.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.61.0 // indirect
Expand Down
Loading