policy: support reading policy from stdin via --file -
Allow passing policy content through stdin by specifying "--file -" in the eval command. This enables piping policy data without requiring a file on disk. Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
+17
-3
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"maps"
|
||||
"os"
|
||||
@@ -191,9 +192,8 @@ func runEval(ctx context.Context, dockerCli command.Cli, source string, opts eva
|
||||
if opts.filename == "" {
|
||||
return errors.New("filename is required")
|
||||
}
|
||||
policyName := opts.filename
|
||||
policyFile := policyName + ".rego"
|
||||
policyData, err := os.ReadFile(policyFile)
|
||||
policyName, policyFile := policyFileNames(opts.filename)
|
||||
policyData, err := readPolicyData(policyFile, os.Stdin)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to read policy file %s", policyFile)
|
||||
}
|
||||
@@ -267,6 +267,20 @@ func runEval(ctx context.Context, dockerCli command.Cli, source string, opts eva
|
||||
}
|
||||
}
|
||||
|
||||
func policyFileNames(filename string) (string, string) {
|
||||
if filename == "-" {
|
||||
return "stdin", filename
|
||||
}
|
||||
return filename, filename + ".rego"
|
||||
}
|
||||
|
||||
func readPolicyData(filename string, stdin io.Reader) ([]byte, error) {
|
||||
if filename == "-" {
|
||||
return io.ReadAll(stdin)
|
||||
}
|
||||
return os.ReadFile(filename)
|
||||
}
|
||||
|
||||
func selectReloadFields(fields []string, unknowns []string) ([]string, []string) {
|
||||
if len(fields) == 0 {
|
||||
return nil, nil
|
||||
|
||||
@@ -10,7 +10,8 @@ Evaluate policy for a source
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| `--fields` | `stringSlice` | | Fields to evaluate |
|
||||
| `--filename` | `string` | `Dockerfile` | Policy filename to evaluate |
|
||||
| `-f`, `--file` | `string` | `Dockerfile` | Policy filename to evaluate |
|
||||
| `--platform` | `string` | | Target platform for policy evaluation |
|
||||
| `--print` | `bool` | | Print policy output |
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
var policyEvalTests = []func(t *testing.T, sb integration.Sandbox){
|
||||
testPolicyEvalAllow,
|
||||
testPolicyEvalDeny,
|
||||
testPolicyEvalStdinFile,
|
||||
testPolicyEvalPrint,
|
||||
testPolicyEvalFields,
|
||||
testPolicyEvalLabel,
|
||||
@@ -88,6 +89,63 @@ decision := {"allow": allow}
|
||||
require.Contains(t, string(out), "policy denied")
|
||||
}
|
||||
|
||||
func testPolicyEvalStdinFile(t *testing.T, sb integration.Sandbox) {
|
||||
skipNoCompatBuildKit(t, sb, ">= 0.26.0-0", "policy input requires BuildKit v0.26.0+")
|
||||
testCases := []struct {
|
||||
name string
|
||||
policy string
|
||||
wantErrContains string
|
||||
}{
|
||||
{
|
||||
name: "allow",
|
||||
policy: `
|
||||
package docker
|
||||
|
||||
default allow = false
|
||||
|
||||
allow if not input.image
|
||||
|
||||
allow if input.image.repo == "busybox"
|
||||
|
||||
decision := {"allow": allow}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "deny",
|
||||
policy: `
|
||||
package docker
|
||||
|
||||
default allow = false
|
||||
|
||||
allow if input.image.repo == "alpine"
|
||||
|
||||
decision := {"allow": allow}
|
||||
`,
|
||||
wantErrContains: "policy denied",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := buildxCmd(sb, withArgs(
|
||||
"policy",
|
||||
"eval",
|
||||
"--file",
|
||||
"-",
|
||||
"docker-image://busybox:latest",
|
||||
))
|
||||
cmd.Stdin = strings.NewReader(tc.policy)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if tc.wantErrContains == "" {
|
||||
require.NoError(t, err, string(out))
|
||||
return
|
||||
}
|
||||
require.Error(t, err, string(out))
|
||||
require.Contains(t, string(out), tc.wantErrContains)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testPolicyEvalPrint(t *testing.T, sb integration.Sandbox) {
|
||||
skipNoCompatBuildKit(t, sb, ">= 0.26.0-0", "policy input requires BuildKit v0.26.0+")
|
||||
cmd := buildxCmd(sb, withArgs(
|
||||
|
||||
Reference in New Issue
Block a user