Skip to content

Commit 6f9a1cf

Browse files
committed
tests: add git based policy tests
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
1 parent 6d80e70 commit 6f9a1cf

2 files changed

Lines changed: 311 additions & 2 deletions

File tree

policy/validate.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,9 @@ func AddUnknownsWithLogger(logf func(logrus.Level, string), req *gwpb.ResolveSou
630630
// HTTP checksums are resolved by BuildKit for the HTTP source itself.
631631

632632
case "git.ref", "git.checksum", "git.commitChecksum", "git.isAnnotatedTag", "git.isSHA256", "git.tagName", "git.branch":
633-
633+
if req.Git == nil {
634+
req.Git = &gwpb.ResolveSourceGitRequest{}
635+
}
634636
case "git.commit", "git.tag":
635637
if req.Git == nil {
636638
req.Git = &gwpb.ResolveSourceGitRequest{}

tests/policy_build.go

Lines changed: 308 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ import (
44
"errors"
55
"fmt"
66
"net/url"
7+
"os"
78
"path/filepath"
89
"testing"
910

1011
"github.com/containerd/continuity/fs/fstest"
1112
"github.com/containerd/platforms"
1213
"github.com/distribution/reference"
14+
"github.com/docker/buildx/util/gitutil"
15+
"github.com/docker/buildx/util/gitutil/gittestutil"
1316
"github.com/moby/buildkit/identity"
1417
"github.com/moby/buildkit/util/contentutil"
1518
"github.com/moby/buildkit/util/testutil"
@@ -25,6 +28,7 @@ var policyBuildTests = []func(t *testing.T, sb integration.Sandbox){
2528
testBuildPolicyImageName,
2629
testBuildPolicyEnv,
2730
testBuildPolicyHTTP,
31+
testBuildPolicyGit,
2832
testBuildPolicyConfigFlags,
2933
}
3034

@@ -705,11 +709,15 @@ decision := {"allow": allow}
705709
fstest.CreateFile("policy.rego", []byte(tc.policy), 0600),
706710
)
707711
policyPath := filepath.Join(dir, "policy.rego")
712+
policyArg := "filename=" + policyPath
713+
if tc.name == "git-schema-allow" {
714+
policyArg = "log-level=debug," + policyArg
715+
}
708716

709717
cmd := buildxCmd(sb, withDir(dir), withArgs(
710718
"build",
711719
"--progress=plain",
712-
"--policy", "filename="+policyPath,
720+
"--policy", policyArg,
713721
"--output=type=cacheonly",
714722
dir,
715723
))
@@ -725,6 +733,305 @@ decision := {"allow": allow}
725733
}
726734
}
727735

736+
func testBuildPolicyGit(t *testing.T, sb integration.Sandbox) {
737+
skipNoCompatBuildKit(t, sb, ">= 0.26.0-0", "policy input requires BuildKit v0.26.0+")
738+
739+
gitDir := t.TempDir()
740+
require.NoError(t, os.WriteFile(filepath.Join(gitDir, "Dockerfile"), []byte("FROM busybox:latest\nRUN echo git\n"), 0600))
741+
require.NoError(t, os.WriteFile(filepath.Join(gitDir, "a"), []byte("a"), 0600))
742+
743+
git, err := gitutil.New(gitutil.WithWorkingDir(gitDir))
744+
require.NoError(t, err)
745+
746+
gittestutil.GitInit(git, t)
747+
gittestutil.GitAdd(git, t, "Dockerfile", "a")
748+
gittestutil.GitCommit(git, t, "initial commit")
749+
750+
_, err = git.Run("tag", "-a", "v0.1", "-m", "v0.1release")
751+
require.NoError(t, err)
752+
753+
require.NoError(t, os.WriteFile(filepath.Join(gitDir, "b"), []byte("b"), 0600))
754+
gittestutil.GitAdd(git, t, "b")
755+
gittestutil.GitCommit(git, t, "b")
756+
_, err = git.Run("checkout", "-B", "v2")
757+
require.NoError(t, err)
758+
759+
commitHead, err := git.Run("rev-parse", "HEAD")
760+
require.NoError(t, err)
761+
commitTag, err := git.Run("rev-parse", "v0.1")
762+
require.NoError(t, err)
763+
commitTagCommit, err := git.Run("rev-parse", "v0.1^{commit}")
764+
require.NoError(t, err)
765+
baseURL := gittestutil.GitServeHTTP(git, t)
766+
tagURL := baseURL + "#v0.1"
767+
branchURL := baseURL + "#v2"
768+
parsedURL, err := url.Parse(baseURL)
769+
require.NoError(t, err)
770+
771+
testCases := []struct {
772+
name string
773+
policy string
774+
context string
775+
wantErrContains string
776+
requiresGitResolve bool
777+
}{
778+
{
779+
name: "git-schema-allow",
780+
policy: `
781+
package docker
782+
783+
default allow = false
784+
785+
allow if not input.git
786+
787+
allow if input.git.schema != ""
788+
789+
decision := {"allow": allow}
790+
`,
791+
context: baseURL,
792+
},
793+
{
794+
name: "git-host-allow",
795+
policy: fmt.Sprintf(`
796+
package docker
797+
798+
default allow = false
799+
800+
allow if not input.git
801+
802+
allow if input.git.host == "%s"
803+
804+
decision := {"allow": allow}
805+
`, parsedURL.Host),
806+
context: baseURL,
807+
},
808+
{
809+
name: "git-remote-allow",
810+
policy: fmt.Sprintf(`
811+
package docker
812+
813+
default allow = false
814+
815+
allow if not input.git
816+
817+
allow if endswith(input.git.remote, "%s")
818+
819+
decision := {"allow": allow}
820+
`, parsedURL.Path),
821+
context: baseURL,
822+
},
823+
{
824+
name: "git-ref-tag-allow",
825+
policy: `
826+
package docker
827+
828+
default allow = false
829+
830+
allow if not input.git
831+
832+
allow if input.git.ref == "refs/tags/v0.1"
833+
834+
decision := {"allow": allow}
835+
`,
836+
context: tagURL,
837+
requiresGitResolve: true,
838+
},
839+
{
840+
name: "git-branch-allow",
841+
policy: `
842+
package docker
843+
844+
default allow = false
845+
846+
allow if not input.git
847+
848+
allow if input.git.branch == "v2"
849+
850+
decision := {"allow": allow}
851+
`,
852+
context: branchURL,
853+
requiresGitResolve: true,
854+
},
855+
{
856+
name: "git-tagname-allow",
857+
policy: `
858+
package docker
859+
860+
default allow = false
861+
862+
allow if not input.git
863+
864+
allow if input.git.tagName == "v0.1"
865+
866+
decision := {"allow": allow}
867+
`,
868+
context: tagURL,
869+
requiresGitResolve: true,
870+
},
871+
{
872+
name: "git-checksum-allow",
873+
policy: fmt.Sprintf(`
874+
package docker
875+
876+
default allow = false
877+
878+
allow if not input.git
879+
880+
allow if input.git.checksum == "%s"
881+
882+
decision := {"allow": allow}
883+
`, commitTag),
884+
context: tagURL,
885+
requiresGitResolve: true,
886+
},
887+
{
888+
name: "git-commit-checksum-allow",
889+
policy: fmt.Sprintf(`
890+
package docker
891+
892+
default allow = false
893+
894+
allow if not input.git
895+
896+
allow if input.git.commitChecksum == "%s"
897+
898+
decision := {"allow": allow}
899+
`, commitTagCommit),
900+
context: tagURL,
901+
requiresGitResolve: true,
902+
},
903+
{
904+
name: "git-annotated-tag-allow",
905+
policy: `
906+
package docker
907+
908+
default allow = false
909+
910+
allow if not input.git
911+
912+
allow if input.git.isAnnotatedTag == true
913+
914+
decision := {"allow": allow}
915+
`,
916+
context: tagURL,
917+
requiresGitResolve: true,
918+
},
919+
{
920+
name: "git-commit-message-allow",
921+
policy: `
922+
package docker
923+
924+
default allow = false
925+
926+
allow if not input.git
927+
928+
allow if input.git.commit.message == "initial commit"
929+
930+
decision := {"allow": allow}
931+
`,
932+
context: tagURL,
933+
requiresGitResolve: true,
934+
},
935+
{
936+
name: "git-tag-object-allow",
937+
policy: `
938+
package docker
939+
940+
default allow = false
941+
942+
allow if not input.git
943+
944+
allow if input.git.tag.tag == "v0.1"
945+
946+
decision := {"allow": allow}
947+
`,
948+
context: tagURL,
949+
requiresGitResolve: true,
950+
},
951+
{
952+
name: "git-checksum-deny",
953+
policy: `
954+
package docker
955+
956+
default allow = false
957+
958+
allow if not input.git
959+
960+
allow if input.git.checksum == "deadbeef"
961+
962+
decision := {"allow": allow}
963+
`,
964+
context: tagURL,
965+
wantErrContains: "not allowed by policy",
966+
requiresGitResolve: true,
967+
},
968+
{
969+
name: "git-commit-ref-allow",
970+
policy: `
971+
package docker
972+
973+
default allow = false
974+
975+
allow if not input.git
976+
977+
allow if input.git.isCommitRef == true
978+
979+
decision := {"allow": allow}
980+
`,
981+
context: baseURL + "#" + commitHead,
982+
requiresGitResolve: true,
983+
},
984+
{
985+
name: "git-host-deny",
986+
policy: `
987+
package docker
988+
989+
default allow = false
990+
991+
allow if not input.git
992+
993+
allow if input.git.host == "example.invalid"
994+
995+
decision := {"allow": allow}
996+
`,
997+
context: tagURL,
998+
wantErrContains: "not allowed by policy",
999+
},
1000+
}
1001+
1002+
for _, tc := range testCases {
1003+
t.Run(tc.name, func(t *testing.T) {
1004+
if tc.requiresGitResolve {
1005+
sbDriver, _, _ := driverName(sb.Name())
1006+
if sbDriver != "remote" {
1007+
t.Skip("git policy metadata requires remote driver")
1008+
}
1009+
}
1010+
dir := tmpdir(
1011+
t,
1012+
fstest.CreateFile("policy.rego", []byte(tc.policy), 0600),
1013+
)
1014+
policyPath := filepath.Join(dir, "policy.rego")
1015+
1016+
cmd := buildxCmd(sb, withDir(dir), withArgs(
1017+
"build",
1018+
"--progress=plain",
1019+
"--policy", "filename="+policyPath,
1020+
"--output=type=cacheonly",
1021+
tc.context,
1022+
))
1023+
out, err := cmd.CombinedOutput()
1024+
if tc.wantErrContains == "" {
1025+
require.NoError(t, err, string(out))
1026+
require.Contains(t, string(out), "loading policies "+policyPath)
1027+
} else {
1028+
require.Error(t, err, string(out))
1029+
require.Contains(t, string(out), tc.wantErrContains)
1030+
}
1031+
})
1032+
}
1033+
}
1034+
7281035
func testBuildPolicyConfigFlags(t *testing.T, sb integration.Sandbox) {
7291036
skipNoCompatBuildKit(t, sb, ">= 0.26.0-0", "policy input requires BuildKit v0.26.0+")
7301037

0 commit comments

Comments
 (0)