policy: move custom functions to separate file
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
+133
@@ -0,0 +1,133 @@
|
||||
package policy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log"
|
||||
|
||||
"github.com/moby/buildkit/util/gitutil/gitsign"
|
||||
"github.com/open-policy-agent/opa/v1/ast"
|
||||
"github.com/open-policy-agent/opa/v1/rego"
|
||||
"github.com/open-policy-agent/opa/v1/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (p *Policy) initBuiltinFuncs() {
|
||||
builtinLoadJSON := ®o.Function{
|
||||
Name: "load_json",
|
||||
Decl: types.NewFunction(
|
||||
types.Args(
|
||||
types.S,
|
||||
),
|
||||
types.A,
|
||||
),
|
||||
Memoize: true,
|
||||
}
|
||||
p.funcs = append(p.funcs, fun{
|
||||
decl: builtinLoadJSON,
|
||||
impl: funcNoInput(rego.Function1(builtinLoadJSON, p.builtinLoadJSONImpl)),
|
||||
})
|
||||
|
||||
verifyGitSignature := ®o.Function{
|
||||
Name: "verify_git_signature",
|
||||
Decl: types.NewFunction(
|
||||
types.Args(
|
||||
types.S,
|
||||
),
|
||||
types.B,
|
||||
),
|
||||
Memoize: false, // TODO:optimize
|
||||
}
|
||||
p.funcs = append(p.funcs, fun{
|
||||
decl: verifyGitSignature,
|
||||
impl: func(s *state) func(*rego.Rego) {
|
||||
return rego.Function1(verifyGitSignature, func(bctx rego.BuiltinContext, a *ast.Term) (*ast.Term, error) {
|
||||
return p.builtinVerifyGitSignatureImpl(bctx, a, s)
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Policy) builtinVerifyGitSignatureImpl(_ rego.BuiltinContext, a *ast.Term, s *state) (*ast.Term, error) {
|
||||
inp := s.Input
|
||||
if inp.Git == nil {
|
||||
return ast.BooleanTerm(false), nil
|
||||
}
|
||||
|
||||
if inp.Git.Commit == nil {
|
||||
s.addUnknown("verify_git_signature")
|
||||
return ast.BooleanTerm(false), nil
|
||||
}
|
||||
|
||||
path, ok := a.Value.(ast.String)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("load_json: expected string path, got %T", a.Value)
|
||||
}
|
||||
|
||||
pubkey, err := p.readFile(string(path), 128*1024)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj := inp.Git.Commit.obj
|
||||
if inp.Git.Tag != nil {
|
||||
obj = inp.Git.Tag.obj
|
||||
}
|
||||
|
||||
if err := gitsign.VerifySignature(obj, pubkey, &gitsign.VerifyPolicy{
|
||||
RejectExpiredKeys: false,
|
||||
}); err != nil {
|
||||
log.Printf("git signature verification failed: %+v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ast.BooleanTerm(true), nil
|
||||
}
|
||||
|
||||
func (p *Policy) readFile(path string, limit int64) ([]byte, error) {
|
||||
if p.opt.FS == nil {
|
||||
return nil, errors.Errorf("no policy FS defined for reading context files")
|
||||
}
|
||||
fs, cf, err := p.opt.FS()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get policy FS for reading context files")
|
||||
}
|
||||
defer cf()
|
||||
|
||||
f, err := fs.Open(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed opening file %q", path)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
rdr := io.LimitReader(f, limit)
|
||||
data, err := io.ReadAll(rdr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed reading %q", path)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (p *Policy) builtinLoadJSONImpl(bctx rego.BuiltinContext, a *ast.Term) (*ast.Term, error) {
|
||||
path, ok := a.Value.(ast.String)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("load_json: expected string path, got %T", a.Value)
|
||||
}
|
||||
|
||||
data, err := p.readFile(string(path), 4*1024*1024)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var v any
|
||||
if err := json.Unmarshal(data, &v); err != nil {
|
||||
return nil, errors.Wrapf(err, "load_json: invalid JSON in %q", path)
|
||||
}
|
||||
|
||||
astVal, err := ast.InterfaceToValue(v)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "load_json: failed converting JSON from %q", path)
|
||||
}
|
||||
|
||||
return ast.NewTerm(astVal), nil
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package policy
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/url"
|
||||
@@ -25,12 +24,10 @@ import (
|
||||
"github.com/moby/buildkit/sourcepolicy/policysession"
|
||||
"github.com/moby/buildkit/util/gitutil"
|
||||
"github.com/moby/buildkit/util/gitutil/gitobject"
|
||||
"github.com/moby/buildkit/util/gitutil/gitsign"
|
||||
policyverifier "github.com/moby/policy-helpers"
|
||||
"github.com/open-policy-agent/opa/v1/ast"
|
||||
"github.com/open-policy-agent/opa/v1/rego"
|
||||
"github.com/open-policy-agent/opa/v1/topdown/print"
|
||||
"github.com/open-policy-agent/opa/v1/types"
|
||||
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -123,125 +120,6 @@ func (p *Policy) getVerifier() (*policyverifier.Verifier, error) {
|
||||
return p.verifier, nil
|
||||
}
|
||||
|
||||
func (p *Policy) initBuiltinFuncs() {
|
||||
builtinLoadJSON := ®o.Function{
|
||||
Name: "load_json",
|
||||
Decl: types.NewFunction(
|
||||
types.Args(
|
||||
types.S,
|
||||
),
|
||||
types.A,
|
||||
),
|
||||
Memoize: true,
|
||||
}
|
||||
p.funcs = append(p.funcs, fun{
|
||||
decl: builtinLoadJSON,
|
||||
impl: funcNoInput(rego.Function1(builtinLoadJSON, p.builtinLoadJSONImpl)),
|
||||
})
|
||||
|
||||
verifyGitSignature := ®o.Function{
|
||||
Name: "verify_git_signature",
|
||||
Decl: types.NewFunction(
|
||||
types.Args(
|
||||
types.S,
|
||||
),
|
||||
types.B,
|
||||
),
|
||||
Memoize: false, // TODO:optimize
|
||||
}
|
||||
p.funcs = append(p.funcs, fun{
|
||||
decl: verifyGitSignature,
|
||||
impl: func(s *state) func(*rego.Rego) {
|
||||
return rego.Function1(verifyGitSignature, func(bctx rego.BuiltinContext, a *ast.Term) (*ast.Term, error) {
|
||||
return p.builtinVerifyGitSignatureImpl(bctx, a, s)
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Policy) builtinVerifyGitSignatureImpl(_ rego.BuiltinContext, a *ast.Term, s *state) (*ast.Term, error) {
|
||||
inp := s.Input
|
||||
if inp.Git == nil {
|
||||
return ast.BooleanTerm(false), nil
|
||||
}
|
||||
|
||||
if inp.Git.Commit == nil {
|
||||
s.addUnknown("verify_git_signature")
|
||||
return ast.BooleanTerm(false), nil
|
||||
}
|
||||
|
||||
path, ok := a.Value.(ast.String)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("load_json: expected string path, got %T", a.Value)
|
||||
}
|
||||
|
||||
pubkey, err := p.readFile(string(path), 128*1024)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj := inp.Git.Commit.obj
|
||||
if inp.Git.Tag != nil {
|
||||
obj = inp.Git.Tag.obj
|
||||
}
|
||||
|
||||
if err := gitsign.VerifySignature(obj, pubkey, &gitsign.VerifyPolicy{
|
||||
RejectExpiredKeys: false,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ast.BooleanTerm(true), nil
|
||||
}
|
||||
|
||||
func (p *Policy) readFile(path string, limit int64) ([]byte, error) {
|
||||
if p.opt.FS == nil {
|
||||
return nil, errors.Errorf("no policy FS defined for reading context files")
|
||||
}
|
||||
fs, cf, err := p.opt.FS()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get policy FS for reading context files")
|
||||
}
|
||||
defer cf()
|
||||
|
||||
f, err := fs.Open(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed opening file %q", path)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
rdr := io.LimitReader(f, limit)
|
||||
data, err := io.ReadAll(rdr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed reading %q", path)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (p *Policy) builtinLoadJSONImpl(bctx rego.BuiltinContext, a *ast.Term) (*ast.Term, error) {
|
||||
path, ok := a.Value.(ast.String)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("load_json: expected string path, got %T", a.Value)
|
||||
}
|
||||
|
||||
data, err := p.readFile(string(path), 4*1024*1024)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var v any
|
||||
if err := json.Unmarshal(data, &v); err != nil {
|
||||
return nil, errors.Wrapf(err, "load_json: invalid JSON in %q", path)
|
||||
}
|
||||
|
||||
astVal, err := ast.InterfaceToValue(v)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "load_json: failed converting JSON from %q", path)
|
||||
}
|
||||
|
||||
return ast.NewTerm(astVal), nil
|
||||
}
|
||||
|
||||
func (p *Policy) CheckPolicy(ctx context.Context, req *policysession.CheckPolicyRequest) (*policysession.DecisionResponse, *gwpb.ResolveSourceMetaRequest, error) {
|
||||
var inp Input
|
||||
var unknowns []string
|
||||
|
||||
Reference in New Issue
Block a user