tests: add git based policy tests

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi
2026-01-14 09:34:15 -08:00
parent 6d80e701f6
commit 6f9a1cfb17
2 changed files with 311 additions and 2 deletions
+3 -1
View File
@@ -630,7 +630,9 @@ func AddUnknownsWithLogger(logf func(logrus.Level, string), req *gwpb.ResolveSou
// HTTP checksums are resolved by BuildKit for the HTTP source itself. // HTTP checksums are resolved by BuildKit for the HTTP source itself.
case "git.ref", "git.checksum", "git.commitChecksum", "git.isAnnotatedTag", "git.isSHA256", "git.tagName", "git.branch": case "git.ref", "git.checksum", "git.commitChecksum", "git.isAnnotatedTag", "git.isSHA256", "git.tagName", "git.branch":
if req.Git == nil {
req.Git = &gwpb.ResolveSourceGitRequest{}
}
case "git.commit", "git.tag": case "git.commit", "git.tag":
if req.Git == nil { if req.Git == nil {
req.Git = &gwpb.ResolveSourceGitRequest{} req.Git = &gwpb.ResolveSourceGitRequest{}
+308 -1
View File
@@ -4,12 +4,15 @@ import (
"errors" "errors"
"fmt" "fmt"
"net/url" "net/url"
"os"
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/containerd/continuity/fs/fstest" "github.com/containerd/continuity/fs/fstest"
"github.com/containerd/platforms" "github.com/containerd/platforms"
"github.com/distribution/reference" "github.com/distribution/reference"
"github.com/docker/buildx/util/gitutil"
"github.com/docker/buildx/util/gitutil/gittestutil"
"github.com/moby/buildkit/identity" "github.com/moby/buildkit/identity"
"github.com/moby/buildkit/util/contentutil" "github.com/moby/buildkit/util/contentutil"
"github.com/moby/buildkit/util/testutil" "github.com/moby/buildkit/util/testutil"
@@ -25,6 +28,7 @@ var policyBuildTests = []func(t *testing.T, sb integration.Sandbox){
testBuildPolicyImageName, testBuildPolicyImageName,
testBuildPolicyEnv, testBuildPolicyEnv,
testBuildPolicyHTTP, testBuildPolicyHTTP,
testBuildPolicyGit,
testBuildPolicyConfigFlags, testBuildPolicyConfigFlags,
} }
@@ -705,13 +709,316 @@ decision := {"allow": allow}
fstest.CreateFile("policy.rego", []byte(tc.policy), 0600), fstest.CreateFile("policy.rego", []byte(tc.policy), 0600),
) )
policyPath := filepath.Join(dir, "policy.rego") policyPath := filepath.Join(dir, "policy.rego")
policyArg := "filename=" + policyPath
if tc.name == "git-schema-allow" {
policyArg = "log-level=debug," + policyArg
}
cmd := buildxCmd(sb, withDir(dir), withArgs(
"build",
"--progress=plain",
"--policy", policyArg,
"--output=type=cacheonly",
dir,
))
out, err := cmd.CombinedOutput()
if tc.wantErrContains == "" {
require.NoError(t, err, string(out))
require.Contains(t, string(out), "loading policies "+policyPath)
} else {
require.Error(t, err, string(out))
require.Contains(t, string(out), tc.wantErrContains)
}
})
}
}
func testBuildPolicyGit(t *testing.T, sb integration.Sandbox) {
skipNoCompatBuildKit(t, sb, ">= 0.26.0-0", "policy input requires BuildKit v0.26.0+")
gitDir := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(gitDir, "Dockerfile"), []byte("FROM busybox:latest\nRUN echo git\n"), 0600))
require.NoError(t, os.WriteFile(filepath.Join(gitDir, "a"), []byte("a"), 0600))
git, err := gitutil.New(gitutil.WithWorkingDir(gitDir))
require.NoError(t, err)
gittestutil.GitInit(git, t)
gittestutil.GitAdd(git, t, "Dockerfile", "a")
gittestutil.GitCommit(git, t, "initial commit")
_, err = git.Run("tag", "-a", "v0.1", "-m", "v0.1release")
require.NoError(t, err)
require.NoError(t, os.WriteFile(filepath.Join(gitDir, "b"), []byte("b"), 0600))
gittestutil.GitAdd(git, t, "b")
gittestutil.GitCommit(git, t, "b")
_, err = git.Run("checkout", "-B", "v2")
require.NoError(t, err)
commitHead, err := git.Run("rev-parse", "HEAD")
require.NoError(t, err)
commitTag, err := git.Run("rev-parse", "v0.1")
require.NoError(t, err)
commitTagCommit, err := git.Run("rev-parse", "v0.1^{commit}")
require.NoError(t, err)
baseURL := gittestutil.GitServeHTTP(git, t)
tagURL := baseURL + "#v0.1"
branchURL := baseURL + "#v2"
parsedURL, err := url.Parse(baseURL)
require.NoError(t, err)
testCases := []struct {
name string
policy string
context string
wantErrContains string
requiresGitResolve bool
}{
{
name: "git-schema-allow",
policy: `
package docker
default allow = false
allow if not input.git
allow if input.git.schema != ""
decision := {"allow": allow}
`,
context: baseURL,
},
{
name: "git-host-allow",
policy: fmt.Sprintf(`
package docker
default allow = false
allow if not input.git
allow if input.git.host == "%s"
decision := {"allow": allow}
`, parsedURL.Host),
context: baseURL,
},
{
name: "git-remote-allow",
policy: fmt.Sprintf(`
package docker
default allow = false
allow if not input.git
allow if endswith(input.git.remote, "%s")
decision := {"allow": allow}
`, parsedURL.Path),
context: baseURL,
},
{
name: "git-ref-tag-allow",
policy: `
package docker
default allow = false
allow if not input.git
allow if input.git.ref == "refs/tags/v0.1"
decision := {"allow": allow}
`,
context: tagURL,
requiresGitResolve: true,
},
{
name: "git-branch-allow",
policy: `
package docker
default allow = false
allow if not input.git
allow if input.git.branch == "v2"
decision := {"allow": allow}
`,
context: branchURL,
requiresGitResolve: true,
},
{
name: "git-tagname-allow",
policy: `
package docker
default allow = false
allow if not input.git
allow if input.git.tagName == "v0.1"
decision := {"allow": allow}
`,
context: tagURL,
requiresGitResolve: true,
},
{
name: "git-checksum-allow",
policy: fmt.Sprintf(`
package docker
default allow = false
allow if not input.git
allow if input.git.checksum == "%s"
decision := {"allow": allow}
`, commitTag),
context: tagURL,
requiresGitResolve: true,
},
{
name: "git-commit-checksum-allow",
policy: fmt.Sprintf(`
package docker
default allow = false
allow if not input.git
allow if input.git.commitChecksum == "%s"
decision := {"allow": allow}
`, commitTagCommit),
context: tagURL,
requiresGitResolve: true,
},
{
name: "git-annotated-tag-allow",
policy: `
package docker
default allow = false
allow if not input.git
allow if input.git.isAnnotatedTag == true
decision := {"allow": allow}
`,
context: tagURL,
requiresGitResolve: true,
},
{
name: "git-commit-message-allow",
policy: `
package docker
default allow = false
allow if not input.git
allow if input.git.commit.message == "initial commit"
decision := {"allow": allow}
`,
context: tagURL,
requiresGitResolve: true,
},
{
name: "git-tag-object-allow",
policy: `
package docker
default allow = false
allow if not input.git
allow if input.git.tag.tag == "v0.1"
decision := {"allow": allow}
`,
context: tagURL,
requiresGitResolve: true,
},
{
name: "git-checksum-deny",
policy: `
package docker
default allow = false
allow if not input.git
allow if input.git.checksum == "deadbeef"
decision := {"allow": allow}
`,
context: tagURL,
wantErrContains: "not allowed by policy",
requiresGitResolve: true,
},
{
name: "git-commit-ref-allow",
policy: `
package docker
default allow = false
allow if not input.git
allow if input.git.isCommitRef == true
decision := {"allow": allow}
`,
context: baseURL + "#" + commitHead,
requiresGitResolve: true,
},
{
name: "git-host-deny",
policy: `
package docker
default allow = false
allow if not input.git
allow if input.git.host == "example.invalid"
decision := {"allow": allow}
`,
context: tagURL,
wantErrContains: "not allowed by policy",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if tc.requiresGitResolve {
sbDriver, _, _ := driverName(sb.Name())
if sbDriver != "remote" {
t.Skip("git policy metadata requires remote driver")
}
}
dir := tmpdir(
t,
fstest.CreateFile("policy.rego", []byte(tc.policy), 0600),
)
policyPath := filepath.Join(dir, "policy.rego")
cmd := buildxCmd(sb, withDir(dir), withArgs( cmd := buildxCmd(sb, withDir(dir), withArgs(
"build", "build",
"--progress=plain", "--progress=plain",
"--policy", "filename="+policyPath, "--policy", "filename="+policyPath,
"--output=type=cacheonly", "--output=type=cacheonly",
dir, tc.context,
)) ))
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if tc.wantErrContains == "" { if tc.wantErrContains == "" {