Skip to content
Open
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13227,6 +13227,38 @@ func testSourcePolicy(t *testing.T, sb integration.Sandbox) {
})
}

t.Run("deny canonical git subdir", func(t *testing.T) {
const (
src = "git://github.com/user/repo.git#main:../absolute/path"
canonical = "git://github.com/user/repo.git#main:absolute/path"
)
frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
st := llb.NewState(llb.NewSource(src, nil, llb.Constraints{}).Output())
def, err := st.Marshal(sb.Context())
if err != nil {
return nil, err
}
return c.Solve(ctx, gateway.SolveRequest{
Definition: def.ToPB(),
})
}

_, err = c.Build(sb.Context(), SolveOpt{
SourcePolicy: &sourcepolicypb.Policy{
Rules: []*sourcepolicypb.Rule{
{
Action: sourcepolicypb.PolicyAction_DENY,
Selector: &sourcepolicypb.Selector{
Identifier: canonical,
MatchType: sourcepolicypb.MatchType_EXACT,
},
},
},
},
}, "", frontend, nil)
require.ErrorContains(t, err, sourcepolicy.ErrSourceDenied.Error())
})

t.Run("Frontend policies", func(t *testing.T) {
t.Run("deny http", func(t *testing.T) {
denied := "https://raw.githubusercontent.com/moby/buildkit/v0.10.1/README.md"
Expand Down
4 changes: 4 additions & 0 deletions solver/llbsolver/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ func (b *llbBridge) loadResult(ctx context.Context, def *pb.Definition, cacheImp
}

func (b *llbBridge) policy(engine *sourcepolicy.Engine) SourcePolicyEvaluator {
if engine == nil {
return nil
}
return &policyEvaluator{
llbBridge: b,
engine: engine,
Expand Down Expand Up @@ -279,6 +282,7 @@ func (b *llbBridge) resolveSourceMetadata(ctx context.Context, op *pb.SourceOp,
engine := sourcepolicy.NewEngine(opt.SourcePolicies)

if !withPolicy {
op.Identifier = normalizedSourceIdentifier(w, op)
if _, err := engine.Evaluate(ctx, op); err != nil {
return nil, errors.Wrap(err, "could not resolve image due to policy")
}
Expand Down
17 changes: 17 additions & 0 deletions solver/llbsolver/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/moby/buildkit/sourcepolicy"
spb "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/moby/buildkit/sourcepolicy/policysession"
"github.com/moby/buildkit/worker"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
Expand All @@ -32,6 +33,17 @@ type policyEvaluator struct {
engine *sourcepolicy.Engine
}

func normalizedSourceIdentifier(w worker.Worker, op *pb.SourceOp) string {
if w == nil {
return op.GetIdentifier()
}
id, err := w.ParseSource(op, nil)
if err != nil {
return op.GetIdentifier()
}
return id.String()
}

func (p *policyEvaluator) Evaluate(ctx context.Context, op *pb.Op) (bool, error) {
return p.evaluate(ctx, op, 10)
}
Expand All @@ -41,6 +53,11 @@ func (p *policyEvaluator) evaluate(ctx context.Context, op *pb.Op, max int) (boo
if source == nil {
return false, nil
}
w, err := p.resolveWorker()
if err != nil {
return false, err
}
source.Identifier = normalizedSourceIdentifier(w, source)
ok, err := p.engine.Evaluate(ctx, source)
if err != nil {
return false, err
Expand Down
4 changes: 4 additions & 0 deletions source/containerblob/identifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ func NewImageBlobIdentifier(str string, scheme string) (*ImageBlobIdentifier, er

var _ source.Identifier = (*ImageBlobIdentifier)(nil)

func (id *ImageBlobIdentifier) String() string {
return id.Scheme() + "://" + id.Reference.String()
}

func (id *ImageBlobIdentifier) Scheme() string {
if id.SchemeName == "" {
return srctypes.DockerImageBlobScheme
Expand Down
24 changes: 24 additions & 0 deletions source/containerblob/identifier_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package containerblob

import (
"testing"

srctypes "github.com/moby/buildkit/source/types"
"github.com/stretchr/testify/require"
)

func TestImageBlobIdentifierString(t *testing.T) {
const ref = "docker.io/library/busybox@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

id, err := NewImageBlobIdentifier(ref, srctypes.DockerImageBlobScheme)
require.NoError(t, err)
require.Equal(t, "docker-image+blob://"+ref, id.String())
}

func TestOCIBlobIdentifierString(t *testing.T) {
const ref = "example.com/repo/layout@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

id, err := NewImageBlobIdentifier(ref, srctypes.OCIBlobScheme)
require.NoError(t, err)
require.Equal(t, "oci-layout+blob://"+ref, id.String())
}
8 changes: 8 additions & 0 deletions source/containerimage/identifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ func NewImageIdentifier(str string) (*ImageIdentifier, error) {

var _ source.Identifier = (*ImageIdentifier)(nil)

func (id *ImageIdentifier) String() string {
return srctypes.DockerImageScheme + "://" + id.Reference.String()
}

func (*ImageIdentifier) Scheme() string {
return srctypes.DockerImageScheme
}
Expand Down Expand Up @@ -75,6 +79,10 @@ func NewOCIIdentifier(str string) (*OCIIdentifier, error) {

var _ source.Identifier = (*OCIIdentifier)(nil)

func (id *OCIIdentifier) String() string {
return srctypes.OCIScheme + "://" + id.Reference.String()
}

func (*OCIIdentifier) Scheme() string {
return srctypes.OCIScheme
}
Expand Down
19 changes: 19 additions & 0 deletions source/containerimage/identifier_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package containerimage

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestImageIdentifierString(t *testing.T) {
id, err := NewImageIdentifier("docker.io/library/busybox:latest")
require.NoError(t, err)
require.Equal(t, "docker-image://docker.io/library/busybox:latest", id.String())
}

func TestOCIIdentifierString(t *testing.T) {
id, err := NewOCIIdentifier("example.com/repo/layout:latest")
require.NoError(t, err)
require.Equal(t, "oci-layout://example.com/repo/layout:latest", id.String())
}
17 changes: 17 additions & 0 deletions source/git/identifier.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package git

import (
"path"
"strings"

"github.com/containerd/containerd/v2/pkg/reference"
Expand Down Expand Up @@ -71,6 +72,22 @@ func NewGitIdentifier(remoteURL string) (*GitIdentifier, error) {
return &repo, nil
}

func (id *GitIdentifier) String() string {
remote := id.Remote
if u, err := gitutil.ParseURL(remote); err == nil {
remote = u.Host + path.Join("/", u.Path)
}

ref := srctypes.GitScheme + "://" + remote
if id.Ref != "" || id.Subdir != "" {
ref += "#" + id.Ref
if id.Subdir != "" {
ref += ":" + id.Subdir
}
}
return ref
}

func (GitIdentifier) Scheme() string {
return srctypes.GitScheme
}
Expand Down
9 changes: 9 additions & 0 deletions source/git/identifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ func TestNewGitIdentifier(t *testing.T) {
tests := []struct {
url string
expected GitIdentifier
str string
}{
{
url: "ssh://[email protected]:2222/root/my/really/weird/path/foo.git",
Expand All @@ -37,6 +38,7 @@ func TestNewGitIdentifier(t *testing.T) {
Remote: "https://github.com/moby/buildkit.git",
Ref: "main",
},
str: "git://github.com/moby/buildkit.git#main",
},
{
url: "git://github.com/user/repo.git",
Expand All @@ -51,6 +53,7 @@ func TestNewGitIdentifier(t *testing.T) {
Ref: "mybranch",
Subdir: "mydir/mysubdir",
},
str: "git://github.com/user/repo.git#mybranch:mydir/mysubdir",
},
{
url: "git://github.com/user/repo.git#:mydir/mysubdir/",
Expand All @@ -72,6 +75,7 @@ func TestNewGitIdentifier(t *testing.T) {
Ref: "mybranch",
Subdir: "mydir/mysubdir",
},
str: "git://github.com/user/repo.git#mybranch:mydir/mysubdir",
},
{
url: "[email protected]:user/repo.git",
Expand Down Expand Up @@ -132,6 +136,7 @@ func TestNewGitIdentifier(t *testing.T) {
Ref: "main",
Subdir: "absolute/path",
},
str: "git://github.com/user/repo.git#main:absolute/path",
},
{
url: "https://github.com/user/repo.git#main:../",
Expand Down Expand Up @@ -171,13 +176,17 @@ func TestNewGitIdentifier(t *testing.T) {
Ref: "main",
Subdir: "absolute/path",
},
str: "git://github.com/user/repo.git#main:absolute/path",
},
}
for _, tt := range tests {
t.Run(tt.url, func(t *testing.T) {
gi, err := NewGitIdentifier(tt.url)
require.NoError(t, err)
require.Equal(t, tt.expected, *gi)
if tt.str != "" {
require.Equal(t, tt.str, gi.String())
}
})
}
}
Expand Down
4 changes: 4 additions & 0 deletions source/http/identifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ type HeaderField struct {

var _ source.Identifier = (*HTTPIdentifier)(nil)

func (id *HTTPIdentifier) String() string {
return id.URL
}

func (id *HTTPIdentifier) Scheme() string {
if id.TLS {
return srctypes.HTTPSScheme
Expand Down
19 changes: 19 additions & 0 deletions source/http/identifier_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package http

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestHTTPIdentifierString(t *testing.T) {
id, err := NewHTTPIdentifier("example.com/file.tar.gz", false)
require.NoError(t, err)
require.Equal(t, "http://example.com/file.tar.gz", id.String())
}

func TestHTTPSIdentifierString(t *testing.T) {
id, err := NewHTTPIdentifier("example.com/file.tar.gz", true)
require.NoError(t, err)
require.Equal(t, "https://example.com/file.tar.gz", id.String())
}
3 changes: 3 additions & 0 deletions source/identifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ var (
)

type Identifier interface {
// String returns the canonical source operation identifier.
String() string

// Scheme returns the scheme of the identifier so that it can be routed back
// to an appropriate Source.
Scheme() string
Expand Down
4 changes: 4 additions & 0 deletions source/local/identifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ func NewLocalIdentifier(str string) (*LocalIdentifier, error) {
return &LocalIdentifier{Name: str}, nil
}

func (id *LocalIdentifier) String() string {
return srctypes.LocalScheme + "://" + id.Name
}

func (*LocalIdentifier) Scheme() string {
return srctypes.LocalScheme
}
Expand Down
13 changes: 13 additions & 0 deletions source/local/identifier_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package local

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestLocalIdentifierString(t *testing.T) {
id, err := NewLocalIdentifier("context")
require.NoError(t, err)
require.Equal(t, "local://context", id.String())
}
6 changes: 5 additions & 1 deletion worker/base/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,10 @@ func (w *Worker) PruneCacheMounts(ctx context.Context, ids map[string]bool) erro
return nil
}

func (w *Worker) ParseSource(op *pb.SourceOp, platform *pb.Platform) (source.Identifier, error) {
return w.SourceManager.Identifier(&pb.Op_Source{Source: op}, platform)
}

func (w *Worker) ResolveSourceMetadata(ctx context.Context, op *pb.SourceOp, opt sourceresolver.Opt, sm *session.Manager, jobCtx solver.JobContext) (*sourceresolver.MetaResponse, error) {
if opt.SourcePolicies != nil {
return nil, errors.New("source policies can not be set for worker")
Expand All @@ -487,7 +491,7 @@ func (w *Worker) ResolveSourceMetadata(ctx context.Context, op *pb.SourceOp, opt
}
}

id, err := w.SourceManager.Identifier(&pb.Op_Source{Source: op}, platform)
id, err := w.ParseSource(op, platform)
if err != nil {
return nil, err
}
Expand Down
2 changes: 2 additions & 0 deletions worker/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/moby/buildkit/solver"
"github.com/moby/buildkit/solver/llbsolver/cdidevices"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/source"
"github.com/moby/buildkit/util/leaseutil"
"github.com/moby/buildkit/util/network"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
Expand All @@ -37,6 +38,7 @@ type Worker interface {
LoadRef(ctx context.Context, id string, hidden bool) (cache.ImmutableRef, error)
// ResolveOp resolves Vertex.Sys() to Op implementation.
ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge, sm *session.Manager, proxyOpt ProxyOpt) (solver.Op, error)
ParseSource(op *pb.SourceOp, platform *pb.Platform) (source.Identifier, error)
ResolveSourceMetadata(ctx context.Context, op *pb.SourceOp, opt sourceresolver.Opt, sm *session.Manager, jobCtx solver.JobContext) (*sourceresolver.MetaResponse, error)
DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error)
Exporter(name string, sm *session.Manager) (exporter.Exporter, error)
Expand Down
Loading