diff --git a/internal/engine/eval/rego/datasources.go b/internal/engine/eval/rego/datasources.go index 1b719d64e9..6637f938f7 100644 --- a/internal/engine/eval/rego/datasources.go +++ b/internal/engine/eval/rego/datasources.go @@ -12,19 +12,35 @@ import ( "github.com/open-policy-agent/opa/types" v1datasources "github.com/mindersec/minder/pkg/datasources/v1" + "github.com/mindersec/minder/pkg/engine/v1/interfaces" ) // RegisterDataSources implements the Eval interface. func (e *Evaluator) RegisterDataSources(dsr *v1datasources.DataSourceRegistry) { + e.datasources = dsr +} + +// buildDataSourceOptions creates an options set from the functions available in +// a data source registry. +func buildDataSourceOptions(res *interfaces.Result, dsr *v1datasources.DataSourceRegistry) []func(*rego.Rego) { + opts := []func(*rego.Rego){} + if dsr == nil { + return opts + } + for key, dsf := range dsr.GetFuncs() { - e.regoOpts = append(e.regoOpts, buildFromDataSource(key, dsf)) + opts = append(opts, buildFromDataSource(res, key, dsf)) } + + return opts } // buildFromDataSource builds a rego function from a data source function. // It takes a DataSourceFuncDef and returns a function that can be used to // register the function with the rego engine. -func buildFromDataSource(key v1datasources.DataSourceFuncKey, dsf v1datasources.DataSourceFuncDef) func(*rego.Rego) { +func buildFromDataSource( + _ *interfaces.Result, key v1datasources.DataSourceFuncKey, dsf v1datasources.DataSourceFuncDef, +) func(*rego.Rego) { k := normalizeKey(key) return rego.Function1( ®o.Function{ diff --git a/internal/engine/eval/rego/eval.go b/internal/engine/eval/rego/eval.go index 75e6f12b81..7dea5f37e9 100644 --- a/internal/engine/eval/rego/eval.go +++ b/internal/engine/eval/rego/eval.go @@ -15,6 +15,7 @@ import ( eoptions "github.com/mindersec/minder/internal/engine/options" minderv1 "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1" + v1datasources "github.com/mindersec/minder/pkg/datasources/v1" "github.com/mindersec/minder/pkg/engine/v1/interfaces" ) @@ -36,9 +37,10 @@ const ( // It initializes the rego engine and evaluates the rules // The default rego package is "minder" type Evaluator struct { - cfg *Config - regoOpts []func(*rego.Rego) - reseval resultEvaluator + cfg *Config + regoOpts []func(*rego.Rego) + reseval resultEvaluator + datasources *v1datasources.DataSourceRegistry } // Input is the input for the rego evaluator @@ -113,10 +115,20 @@ func (e *Evaluator) Eval( // this explicitly. obj := res.Object - libFuncs := instantiateRegoLib(res) + // Register options to expose functions + regoFuncOptions := []func(*rego.Rego){} + + // Initialize the built-in minder library rego functions + regoFuncOptions = append(regoFuncOptions, instantiateRegoLib(res)...) + + // If the evaluator has data sources defined, expose their functions + regoFuncOptions = append(regoFuncOptions, buildDataSourceOptions(res, e.datasources)...) + + // Create the rego object r := e.newRegoFromOptions( - libFuncs..., + regoFuncOptions..., ) + pq, err := r.PrepareForEval(ctx) if err != nil { return fmt.Errorf("could not prepare Rego: %w", err)