policy: add docker_github_builder builtin helper
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package policy
|
||||
|
||||
import "github.com/open-policy-agent/opa/v1/ast"
|
||||
|
||||
const builtinPolicyModuleFilename = "builtin/buildx_defaults.rego"
|
||||
|
||||
const builtinPolicyModule = `package docker
|
||||
|
||||
docker_github_builder(image, repo) if {
|
||||
image.hasProvenance
|
||||
some sig in image.signatures
|
||||
valid_docker_github_builder_signature(sig, repo)
|
||||
}
|
||||
|
||||
valid_docker_github_builder_signature(sig, repo) if {
|
||||
sig.kind == "docker-github-builder"
|
||||
sig.type == "bundle-v0.3"
|
||||
sig.signer.certificateIssuer == "CN=sigstore-intermediate,O=sigstore.dev"
|
||||
sig.signer.issuer == "https://token.actions.githubusercontent.com"
|
||||
sig.signer.sourceRepositoryURI == sprintf("https://github.com/%s", [repo])
|
||||
sig.signer.runnerEnvironment == "github-hosted"
|
||||
count(sig.timestamps) > 0
|
||||
}
|
||||
`
|
||||
|
||||
func builtinPolicyModuleAST() (*ast.Module, error) {
|
||||
return ast.ParseModuleWithOpts(builtinPolicyModuleFilename, builtinPolicyModule, ast.ParserOptions{
|
||||
RegoVersion: ast.RegoV1,
|
||||
})
|
||||
}
|
||||
@@ -195,6 +195,13 @@ func loadPolicyModules(root fs.StatFS, filename string) (map[string]*ast.Module,
|
||||
modules := map[string]*ast.Module{
|
||||
filepath.ToSlash(policyFile): mod,
|
||||
}
|
||||
builtinMod, err := builtinPolicyModuleAST()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "parse builtin policy module %s", builtinPolicyModuleFilename)
|
||||
}
|
||||
if _, ok := modules[builtinPolicyModuleFilename]; !ok {
|
||||
modules[builtinPolicyModuleFilename] = builtinMod
|
||||
}
|
||||
files := []File{
|
||||
{
|
||||
Filename: filepath.ToSlash(policyFile),
|
||||
|
||||
@@ -201,6 +201,7 @@ func (p *Policy) CheckPolicy(ctx context.Context, req *policysession.CheckPolicy
|
||||
opts = append(opts, f.impl(st))
|
||||
}
|
||||
|
||||
opts = append(opts, rego.Module(builtinPolicyModuleFilename, builtinPolicyModule))
|
||||
for _, file := range p.opt.Files {
|
||||
opts = append(opts, rego.Module(file.Filename, string(file.Data)))
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ var policyTestTests = []func(t *testing.T, sb integration.Sandbox){
|
||||
testPolicyTestRunFilter,
|
||||
testPolicyTestFailMissingInput,
|
||||
testPolicyTestNestedPath,
|
||||
testPolicyTestDockerGitHubBuilder,
|
||||
}
|
||||
|
||||
func testPolicyTestRunFilter(t *testing.T, sb integration.Sandbox) {
|
||||
@@ -182,3 +183,82 @@ test_allowlisted_repo if {
|
||||
require.NoError(t, err, string(out))
|
||||
require.Contains(t, string(out), "test_allowlisted_repo: PASS")
|
||||
}
|
||||
|
||||
func testPolicyTestDockerGitHubBuilder(t *testing.T, sb integration.Sandbox) {
|
||||
skipNoCompatBuildKit(t, sb, ">= 0.26.0-0", "policy input requires BuildKit v0.26.0+")
|
||||
dir := tmpdir(
|
||||
t,
|
||||
fstest.CreateFile("policy.rego", []byte(`
|
||||
package docker
|
||||
|
||||
default allow = false
|
||||
|
||||
allow if docker_github_builder(input.image, "org/repo")
|
||||
|
||||
decision := {"allow": allow}
|
||||
`), 0600),
|
||||
fstest.CreateFile("policy_test.rego", []byte(`
|
||||
package docker
|
||||
|
||||
test_docker_github_builder if {
|
||||
result := data.docker.decision with input as {
|
||||
"image": {
|
||||
"hasProvenance": true,
|
||||
"signatures": [{
|
||||
"kind": "docker-github-builder",
|
||||
"type": "bundle-v0.3",
|
||||
"signer": {
|
||||
"certificateIssuer": "CN=sigstore-intermediate,O=sigstore.dev",
|
||||
"issuer": "https://token.actions.githubusercontent.com",
|
||||
"sourceRepositoryURI": "https://github.com/org/repo",
|
||||
"runnerEnvironment": "github-hosted"
|
||||
},
|
||||
"timestamps": [{
|
||||
"type": "tlog",
|
||||
"uri": "https://example.com/tlog",
|
||||
"timestamp": "2024-01-01T00:00:00Z"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
result.allow
|
||||
}
|
||||
|
||||
test_docker_github_builder_denied if {
|
||||
result := data.docker.decision with input as {
|
||||
"image": {
|
||||
"hasProvenance": true,
|
||||
"signatures": [{
|
||||
"kind": "docker-github-builder",
|
||||
"type": "bundle-v0.3",
|
||||
"signer": {
|
||||
"certificateIssuer": "CN=sigstore-intermediate,O=sigstore.dev",
|
||||
"issuer": "https://token.actions.githubusercontent.com",
|
||||
"sourceRepositoryURI": "https://github.com/other/repo",
|
||||
"runnerEnvironment": "github-hosted"
|
||||
},
|
||||
"timestamps": [{
|
||||
"type": "tlog",
|
||||
"uri": "https://example.com/tlog",
|
||||
"timestamp": "2024-01-01T00:00:00Z"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
not result.allow
|
||||
}
|
||||
`), 0600),
|
||||
)
|
||||
|
||||
cmd := buildxCmd(sb, withDir(dir), withArgs(
|
||||
"policy",
|
||||
"test",
|
||||
"--filename",
|
||||
"policy",
|
||||
".",
|
||||
))
|
||||
out, err := cmd.CombinedOutput()
|
||||
require.NoError(t, err, string(out))
|
||||
require.Contains(t, string(out), "test_docker_github_builder: PASS")
|
||||
require.Contains(t, string(out), "test_docker_github_builder_denied: PASS")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user