Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/cli/internal/policydevel/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ import (
"github.com/chainloop-dev/chainloop/pkg/attestation/crafter/materials"
)

const (
enablePrint = true
)

type EvalOptions struct {
PolicyPath string
MaterialKind string
Expand Down Expand Up @@ -100,6 +104,7 @@ func verifyMaterial(schema *v1.CraftingSchema, material *v12.Attestation_Materia
}

opts = append(opts, policies.WithIncludeRawData(debug))
opts = append(opts, policies.WithEnablePrint(enablePrint))

v := policies.NewPolicyVerifier(schema, nil, logger, opts...)
policyEvs, err := v.VerifyMaterial(context.Background(), material, materialPath)
Expand Down
36 changes: 33 additions & 3 deletions pkg/policies/engine/rego/rego.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/chainloop-dev/chainloop/pkg/policies/engine"
"github.com/open-policy-agent/opa/ast"
"github.com/open-policy-agent/opa/rego"
"github.com/open-policy-agent/opa/v1/topdown/print"
"golang.org/x/exp/maps"
)

Expand All @@ -37,6 +38,8 @@ type Engine struct {
allowedNetworkDomains []string
// includeRawData determines whether to collect raw evaluation data
includeRawData bool
// enablePrint determines whether to enable print statements in rego policies
enablePrint bool
}

type EngineOption func(*newEngineOptions)
Expand All @@ -59,10 +62,17 @@ func WithIncludeRawData(include bool) EngineOption {
}
}

func WithEnablePrint(enable bool) EngineOption {
return func(e *newEngineOptions) {
e.enablePrint = enable
}
}

type newEngineOptions struct {
operatingMode EnvironmentMode
allowedNetworkDomains []string
includeRawData bool
enablePrint bool
}

// NewEngine creates a new policy engine with the given options
Expand All @@ -88,6 +98,7 @@ func NewEngine(opts ...EngineOption) *Engine {
// append base allowed network domains to the user provided ones
allowedNetworkDomains: append(baseAllowedNetworkDomains, options.allowedNetworkDomains...),
includeRawData: options.includeRawData,
enablePrint: options.enablePrint,
}
}

Expand All @@ -112,6 +123,15 @@ var builtinFuncNotAllowed = []*ast.Builtin{
ast.Trace,
}

// Implements the OPA print.Hook interface to capture and output
// print statements from Rego policies during evaluation.
type regoOutputHook struct{}

func (p *regoOutputHook) Print(_ print.Context, msg string) error { //nolint:forbidigo
fmt.Println(msg)
return nil
}

// Force interface
var _ engine.PolicyEngine = (*Engine)(nil)

Expand Down Expand Up @@ -156,11 +176,21 @@ func (r *Engine) Verify(ctx context.Context, policy *engine.Policy, input []byte
var res rego.ResultSet
// Function to execute the query with appropriate parameters
executeQuery := func(rule string, strict bool) error {
options := []func(r *rego.Rego){regoInput, regoFunc, rego.Capabilities(r.Capabilities())}

// Add print support if enabled
if r.enablePrint {
options = append(options,
rego.EnablePrintStatements(true),
rego.PrintHook(&regoOutputHook{}),
)
}

if strict {
res, err = queryRego(ctx, rule, regoInput, regoFunc, rego.Capabilities(r.Capabilities()), rego.StrictBuiltinErrors(true))
} else {
res, err = queryRego(ctx, rule, regoInput, regoFunc, rego.Capabilities(r.Capabilities()))
options = append(options, rego.StrictBuiltinErrors(true))
}

res, err = queryRego(ctx, rule, options...)
return err
}

Expand Down
13 changes: 13 additions & 0 deletions pkg/policies/policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ type PolicyVerifier struct {
client v13.AttestationServiceClient
allowedHostnames []string
includeRawData bool
enablePrint bool
}

var _ Verifier = (*PolicyVerifier)(nil)

type PolicyVerifierOptions struct {
AllowedHostnames []string
IncludeRawData bool
EnablePrint bool
}

type PolicyVerifierOption func(*PolicyVerifierOptions)
Expand All @@ -89,6 +91,12 @@ func WithIncludeRawData(include bool) PolicyVerifierOption {
}
}

func WithEnablePrint(enable bool) PolicyVerifierOption {
return func(o *PolicyVerifierOptions) {
o.EnablePrint = enable
}
}

func NewPolicyVerifier(schema *v1.CraftingSchema, client v13.AttestationServiceClient, logger *zerolog.Logger, opts ...PolicyVerifierOption) *PolicyVerifier {
options := &PolicyVerifierOptions{}
for _, opt := range opts {
Expand All @@ -101,6 +109,7 @@ func NewPolicyVerifier(schema *v1.CraftingSchema, client v13.AttestationServiceC
logger: logger,
allowedHostnames: options.AllowedHostnames,
includeRawData: options.IncludeRawData,
enablePrint: options.EnablePrint,
}
}

Expand Down Expand Up @@ -349,6 +358,10 @@ func (pv *PolicyVerifier) executeScript(ctx context.Context, script *engine.Poli
engineOpts = append(engineOpts, rego.WithIncludeRawData(true))
}

if pv.enablePrint {
engineOpts = append(engineOpts, rego.WithEnablePrint(true))
}

// verify the policy
ng := rego.NewEngine(engineOpts...)
res, err := ng.Verify(ctx, script, material, getInputArguments(args))
Expand Down
Loading