1
0
mirror of https://github.com/moby/buildkit.git synced 2025-04-18 18:04:03 +03:00
buildkit/sourcepolicy/engine_test.go
Tonis Tiigi 03c7a6d769
lint: fix some testifylint warnings
This does not cover all warning yet but split
into chunks to ease review.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-05-30 11:32:55 -07:00

454 lines
10 KiB
Go

package sourcepolicy
import (
"context"
"testing"
"github.com/moby/buildkit/solver/pb"
spb "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/moby/buildkit/util/bklog"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
)
func TestEngineEvaluate(t *testing.T) {
t.Run("Deny All", testDenyAll)
t.Run("Allow Deny", testAllowDeny)
t.Run("Convert", testConvert)
t.Run("Convert Deny", testConvertDeny)
t.Run("Allow Convert Deny", testAllowConvertDeny)
t.Run("Test convert loop", testConvertLoop)
t.Run("Test convert http", testConvertHTTP)
t.Run("Test convert regex", testConvertRegex)
t.Run("Test convert wildcard", testConvertWildcard)
t.Run("Test convert multiple", testConvertMultiple)
t.Run("test multiple policies", testMultiplePolicies)
t.Run("Last rule wins", testLastRuleWins)
}
func testLastRuleWins(t *testing.T) {
pol := []*spb.Policy{
{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_ALLOW,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/busybox:latest",
},
},
{
Action: spb.PolicyAction_DENY,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/busybox:latest",
},
},
{
Action: spb.PolicyAction_ALLOW,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/busybox:latest",
},
},
},
},
}
e := NewEngine(pol)
mut, err := e.Evaluate(context.Background(), &pb.SourceOp{
Identifier: "docker-image://docker.io/library/busybox:latest",
})
require.NoError(t, err)
require.False(t, mut)
}
func testMultiplePolicies(t *testing.T) {
pol := []*spb.Policy{
{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_ALLOW,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/busybox:latest",
},
},
},
},
{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_DENY,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/busybox:latest",
},
},
},
},
}
e := NewEngine(pol)
mut, err := e.Evaluate(context.Background(), &pb.SourceOp{
Identifier: "docker-image://docker.io/library/busybox:latest",
})
require.ErrorIs(t, err, ErrSourceDenied)
require.False(t, mut)
}
func testConvertMultiple(t *testing.T) {
pol := []*spb.Policy{
{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_CONVERT,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/busybox:latest",
},
Updates: &spb.Update{
Identifier: "docker-image://docker.io/library/alpine:latest",
},
},
{
Action: spb.PolicyAction_CONVERT,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/alpine:latest",
},
Updates: &spb.Update{
Identifier: "docker-image://docker.io/library/debian:buster",
},
},
{
Action: spb.PolicyAction_CONVERT,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/debian:buster",
},
Updates: &spb.Update{
Identifier: "docker-image://docker.io/library/debian:bullseye",
},
},
},
},
}
op := &pb.SourceOp{
Identifier: "docker-image://docker.io/library/busybox:latest",
}
ctx := context.Background()
e := NewEngine(pol)
mutated, err := e.Evaluate(ctx, op)
require.True(t, mutated)
require.NoError(t, err)
}
func testConvertWildcard(t *testing.T) {
pol := []*spb.Policy{
{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_CONVERT,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/golang:*",
MatchType: spb.MatchType_WILDCARD,
},
Updates: &spb.Update{
Identifier: "docker-image://fakereg.io/library/golang:${1}",
},
},
},
},
}
op := &pb.SourceOp{
Identifier: "docker-image://docker.io/library/golang:1.19",
}
ctx := context.Background()
e := NewEngine(pol)
mutated, err := e.Evaluate(ctx, op)
require.True(t, mutated)
require.NoError(t, err)
require.Equal(t, "docker-image://fakereg.io/library/golang:1.19", op.Identifier)
}
func testConvertRegex(t *testing.T) {
pol := &spb.Policy{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_CONVERT,
Selector: &spb.Selector{
Identifier: `docker\-image://docker\.io/library/golang:(.*)`,
MatchType: spb.MatchType_REGEX,
},
Updates: &spb.Update{
Identifier: "docker-image://fakereg.io/library/golang:${1}",
},
},
},
}
op := &pb.SourceOp{
Identifier: "docker-image://docker.io/library/golang:1.19",
}
ctx := context.Background()
e := NewEngine([]*spb.Policy{pol})
mutated, err := e.Evaluate(ctx, op)
require.True(t, mutated)
require.NoError(t, err)
require.Equal(t, "docker-image://fakereg.io/library/golang:1.19", op.Identifier)
}
func testConvertHTTP(t *testing.T) {
pol := &spb.Policy{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_CONVERT,
Selector: &spb.Selector{
Identifier: "https://example.com/foo",
},
Updates: &spb.Update{
Attrs: map[string]string{"http.checksum": "sha256:1234"},
},
},
},
}
op := &pb.SourceOp{
Identifier: "https://example.com/foo",
}
ctx := context.Background()
e := NewEngine([]*spb.Policy{pol})
mutated, err := e.Evaluate(ctx, op)
require.True(t, mutated)
require.NoError(t, err)
require.Equal(t, "https://example.com/foo", op.Identifier)
}
func testConvertLoop(t *testing.T) {
pol := &spb.Policy{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_CONVERT,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/busybox:latest",
},
Updates: &spb.Update{
Identifier: "docker-image://docker.io/library/alpine:latest",
},
},
{
Action: spb.PolicyAction_CONVERT,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/alpine:latest",
},
Updates: &spb.Update{
Identifier: "docker-image://docker.io/library/busybox:latest",
},
},
},
}
op := &pb.SourceOp{
Identifier: "docker-image://docker.io/library/busybox:latest",
}
ctx := context.Background()
e := NewEngine([]*spb.Policy{pol})
mutated, err := e.Evaluate(ctx, op)
require.True(t, mutated)
require.ErrorIs(t, err, ErrTooManyOps)
}
func testAllowConvertDeny(t *testing.T) {
pol := &spb.Policy{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_CONVERT,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/busybox:latest",
},
Updates: &spb.Update{
Identifier: "docker-image://docker.io/library/alpine:latest",
},
},
{
Action: spb.PolicyAction_ALLOW,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/alpine:latest",
},
},
{
Action: spb.PolicyAction_DENY,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/alpine:*",
},
},
{
Action: spb.PolicyAction_DENY,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/busybox:latest",
},
},
},
}
op := &pb.SourceOp{
Identifier: "docker-image://docker.io/library/busybox:latest",
}
ctx := context.Background()
e := NewEngine([]*spb.Policy{pol})
mutated, err := e.Evaluate(ctx, op)
require.True(t, mutated)
require.ErrorIs(t, err, ErrSourceDenied)
require.Equal(t, "docker-image://docker.io/library/alpine:latest", op.Identifier)
}
func testConvertDeny(t *testing.T) {
pol := &spb.Policy{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_DENY,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/alpine:*",
},
},
{
Action: spb.PolicyAction_CONVERT,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/busybox:latest",
},
Updates: &spb.Update{
Identifier: "docker-image://docker.io/library/alpine:latest",
},
},
},
}
op := &pb.SourceOp{
Identifier: "docker-image://docker.io/library/busybox:latest",
}
ctx := context.Background()
e := NewEngine([]*spb.Policy{pol})
mutated, err := e.Evaluate(ctx, op)
require.True(t, mutated)
require.ErrorIs(t, err, ErrSourceDenied)
require.Equal(t, "docker-image://docker.io/library/alpine:latest", op.Identifier)
}
func testConvert(t *testing.T) {
cases := map[string]string{
"docker-image://docker.io/library/busybox:latest": "docker-image://docker.io/library/alpine:latest",
"docker-image://docker.io/library/alpine:latest": "docker-image://docker.io/library/alpine:latest@sha256:c0d488a800e4127c334ad20d61d7bc21b4097540327217dfab52262adc02380c",
}
bklog.L.Logger.SetLevel(logrus.DebugLevel)
for src, dst := range cases {
t.Run(src+"=>"+dst, func(t *testing.T) {
op := &pb.SourceOp{
Identifier: src,
}
pol := &spb.Policy{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_CONVERT,
Selector: &spb.Selector{
Identifier: src,
},
Updates: &spb.Update{
Identifier: dst,
},
},
},
}
ctx := context.Background()
e := NewEngine([]*spb.Policy{pol})
mutated, err := e.Evaluate(ctx, op)
require.True(t, mutated)
require.NoError(t, err)
require.Equal(t, dst, op.Identifier)
})
}
}
func testAllowDeny(t *testing.T) {
op := &pb.SourceOp{
Identifier: "docker-image://docker.io/library/alpine:latest",
}
pol := &spb.Policy{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_ALLOW,
Selector: &spb.Selector{
Identifier: "docker-image://docker.io/library/alpine:latest",
},
},
{
Action: spb.PolicyAction_DENY,
Selector: &spb.Selector{
Identifier: "docker-image://*",
},
},
},
}
ctx := context.Background()
e := NewEngine([]*spb.Policy{pol})
mutated, err := e.Evaluate(ctx, op)
require.False(t, mutated)
require.ErrorIs(t, err, ErrSourceDenied)
op = &pb.SourceOp{
Identifier: "docker-image://docker.io/library/busybox:latest",
}
mutated, err = e.Evaluate(ctx, op)
require.False(t, mutated)
require.ErrorIs(t, err, ErrSourceDenied)
}
func testDenyAll(t *testing.T) {
cases := map[string]string{
"docker-image": "docker-image://docker.io/library/alpine:latest",
"https": "https://github.com/moby/buildkit.git",
"http": "http://example.com",
}
for kind, ref := range cases {
t.Run(ref, func(t *testing.T) {
pol := &spb.Policy{
Rules: []*spb.Rule{
{
Action: spb.PolicyAction_DENY,
Selector: &spb.Selector{
Identifier: kind + "://*",
},
},
},
}
e := NewEngine([]*spb.Policy{pol})
ctx := context.Background()
op := &pb.SourceOp{
Identifier: ref,
}
mutated, err := e.Evaluate(ctx, op)
require.False(t, mutated)
require.ErrorIs(t, err, ErrSourceDenied)
})
}
}