Documentation ¶
Overview ¶
Package rego exposes high level APIs for evaluating Rego policies.
Index ¶
- func Compiler(c *ast.Compiler) func(r *Rego)
- func DisableInlining(paths []string) func(r *Rego)
- func Dump(w io.Writer) func(r *Rego)
- func Function1(decl *Function, f Builtin1) func(*Rego)
- func Function2(decl *Function, f Builtin2) func(*Rego)
- func Function3(decl *Function, f Builtin3) func(*Rego)
- func Function4(decl *Function, f Builtin4) func(*Rego)
- func FunctionDecl(decl *Function) func(*Rego)
- func FunctionDyn(decl *Function, f BuiltinDyn) func(*Rego)
- func Imports(p []string) func(r *Rego)
- func Input(x interface{}) func(r *Rego)
- func Instrument(yes bool) func(r *Rego)
- func Load(paths []string, filter loader.Filter) func(r *Rego)
- func LoadBundle(path string) func(r *Rego)
- func Metrics(m metrics.Metrics) func(r *Rego)
- func Module(filename, input string) func(r *Rego)
- func Package(p string) func(r *Rego)
- func ParsedBundle(name string, b *bundle.Bundle) func(r *Rego)
- func ParsedImports(imp []*ast.Import) func(r *Rego)
- func ParsedInput(x ast.Value) func(r *Rego)
- func ParsedModule(module *ast.Module) func(*Rego)
- func ParsedPackage(pkg *ast.Package) func(r *Rego)
- func ParsedQuery(q ast.Body) func(r *Rego)
- func ParsedUnknowns(unknowns []*ast.Term) func(r *Rego)
- func PartialNamespace(ns string) func(r *Rego)
- func PrintTrace(w io.Writer, r *Rego)
- func Query(q string) func(r *Rego)
- func Runtime(term *ast.Term) func(r *Rego)
- func Store(s storage.Store) func(r *Rego)
- func Trace(yes bool) func(r *Rego)
- func Tracer(t topdown.Tracer) func(r *Rego)
- func Transaction(txn storage.Transaction) func(r *Rego)
- func Unknowns(unknowns []string) func(r *Rego)
- func UnsafeBuiltins(unsafeBuiltins map[string]struct{}) func(r *Rego)
- type Builtin1
- type Builtin2
- type Builtin3
- type Builtin4
- type BuiltinContext
- type BuiltinDyn
- type CompileContext
- type CompileOption
- type CompileResult
- type Errors
- type EvalContext
- type EvalOption
- func EvalDisableInlining(paths []ast.Ref) EvalOption
- func EvalInput(input interface{}) EvalOption
- func EvalInstrument(instrument bool) EvalOption
- func EvalMetrics(metric metrics.Metrics) EvalOption
- func EvalParsedInput(input ast.Value) EvalOption
- func EvalParsedUnknowns(unknowns []*ast.Term) EvalOption
- func EvalPartialNamespace(ns string) EvalOption
- func EvalRuleIndexing(enabled bool) EvalOption
- func EvalTracer(tracer topdown.Tracer) EvalOption
- func EvalTransaction(txn storage.Transaction) EvalOption
- func EvalUnknowns(unknowns []string) EvalOption
- type ExpressionValue
- type Function
- type Location
- type PartialQueries
- type PartialResult
- type PrepareConfig
- type PrepareOption
- type PreparedEvalQuery
- type PreparedPartialQuery
- type Rego
- func (r *Rego) Compile(ctx context.Context, opts ...CompileOption) (*CompileResult, error)
- func (r *Rego) Eval(ctx context.Context) (ResultSet, error)
- func (r *Rego) Partial(ctx context.Context) (*PartialQueries, error)
- func (r *Rego) PartialEval(ctx context.Context) (PartialResult, error)
- func (r *Rego) PartialResult(ctx context.Context) (PartialResult, error)
- func (r *Rego) PrepareForEval(ctx context.Context, opts ...PrepareOption) (PreparedEvalQuery, error)
- func (r *Rego) PrepareForPartial(ctx context.Context, opts ...PrepareOption) (PreparedPartialQuery, error)
- type Result
- type ResultSet
- type Vars
Examples ¶
- Rego (Custom_function_caching)
- Rego (Custom_functional_builtin)
- Rego.Eval (Compiler)
- Rego.Eval (Errors)
- Rego.Eval (Input)
- Rego.Eval (MultipleBindings)
- Rego.Eval (MultipleDocuments)
- Rego.Eval (Simple)
- Rego.Eval (SingleDocument)
- Rego.Eval (Storage)
- Rego.Eval (Tracer)
- Rego.Eval (Transactions)
- Rego.Partial
- Rego.PartialResult
- Rego.PrepareForEval
- Rego.PrepareForPartial
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DisableInlining ¶ added in v0.13.0
DisableInlining adds a set of paths to exclude from partial evaluation inlining.
func Dump ¶ added in v0.10.0
Dump returns an argument that sets the writer to dump debugging information to.
func Function1 ¶ added in v0.14.0
Function1 returns an option that adds a built-in function to the Rego object.
func Function2 ¶ added in v0.14.0
Function2 returns an option that adds a built-in function to the Rego object.
func Function3 ¶ added in v0.14.0
Function3 returns an option that adds a built-in function to the Rego object.
func Function4 ¶ added in v0.14.0
Function4 returns an option that adds a built-in function to the Rego object.
func FunctionDecl ¶ added in v0.15.1
FunctionDecl returns an option that adds a custom-built-in function __declaration__. NO implementation is provided. This is used for non-interpreter execution envs (e.g., Wasm).
func FunctionDyn ¶ added in v0.14.0
func FunctionDyn(decl *Function, f BuiltinDyn) func(*Rego)
FunctionDyn returns an option that adds a built-in function to the Rego object.
func Input ¶
func Input(x interface{}) func(r *Rego)
Input returns an argument that sets the Rego input document. Input should be a native Go value representing the input document.
func Instrument ¶ added in v0.7.0
Instrument returns an argument that enables instrumentation for diagnosing performance issues.
func Load ¶ added in v0.14.0
Load returns an argument that adds a filesystem path to load data and Rego modules from. Any file with a *.rego, *.yaml, or *.json extension will be loaded. The path can be either a directory or file, directories are loaded recursively. The optional ignore string patterns can be used to filter which files are used. The Load option can only be used once. Note: Loading files will require a write transaction on the store.
func LoadBundle ¶ added in v0.14.0
LoadBundle returns an argument that adds a filesystem path to load a bundle from. The path can be a compressed bundle file or a directory to be loaded as a bundle. Note: Loading bundles will require a write transaction on the store.
func ParsedBundle ¶ added in v0.14.0
ParsedBundle returns an argument that adds a bundle to be loaded.
func ParsedImports ¶ added in v0.7.0
ParsedImports returns an argument that adds Rego imports to the query's context.
func ParsedInput ¶ added in v0.7.0
ParsedInput returns an argument that sets the Rego input document.
func ParsedModule ¶ added in v0.13.0
ParsedModule returns an argument that adds a parsed Rego module. If a string module with the same filename name is added, it will override the parsed module.
func ParsedPackage ¶ added in v0.7.0
ParsedPackage returns an argument that sets the Rego package on the query's context.
func ParsedQuery ¶ added in v0.7.0
ParsedQuery returns an argument that sets the Rego query.
func ParsedUnknowns ¶ added in v0.9.0
ParsedUnknowns returns an argument that sets the values to treat as unknown during partial evaluation.
func PartialNamespace ¶ added in v0.7.0
PartialNamespace returns an argument that sets the namespace to use for partial evaluation results. The namespace must be a valid package path component.
func PrintTrace ¶ added in v0.10.2
PrintTrace is a helper function to write a human-readable version of the trace to the writer w.
func Runtime ¶ added in v0.10.0
Runtime returns an argument that sets the runtime data to provide to the evaluation engine.
func Store ¶ added in v0.5.0
Store returns an argument that sets the policy engine's data storage layer.
If using the Load, LoadBundle, or ParsedBundle options then a transaction must also be provided via the Transaction() option. After loading files or bundles the transaction should be aborted or committed.
func Transaction ¶ added in v0.5.2
func Transaction(txn storage.Transaction) func(r *Rego)
Transaction returns an argument that sets the transaction to use for storage layer operations.
Requires the store associated with the transaction to be provided via the Store() option. If using Load(), LoadBundle(), or ParsedBundle() options the transaction will likely require write params.
func Unknowns ¶ added in v0.7.0
Unknowns returns an argument that sets the values to treat as unknown during partial evaluation.
func UnsafeBuiltins ¶ added in v0.13.0
UnsafeBuiltins sets the built-in functions to treat as unsafe and not allow. This option is ignored for module compilation if the caller supplies the compiler. This option is always honored for query compilation. Provide an empty (non-nil) map to disable checks on queries.
Types ¶
type BuiltinContext ¶ added in v0.14.0
type BuiltinContext = topdown.BuiltinContext
BuiltinContext contains additional attributes from the evaluator that built-in functions can use, e.g., the request context.Context, caches, etc.
type BuiltinDyn ¶ added in v0.14.0
BuiltinDyn defines a built-in function that accepts a list of arguments.
type CompileContext ¶ added in v0.11.0
type CompileContext struct {
// contains filtered or unexported fields
}
CompileContext contains options for Compile calls.
type CompileOption ¶ added in v0.11.0
type CompileOption func(*CompileContext)
CompileOption defines a function to set options on Compile calls.
func CompilePartial ¶ added in v0.11.0
func CompilePartial(yes bool) CompileOption
CompilePartial defines an option to control whether partial evaluation is run before the query is planned and compiled.
type CompileResult ¶ added in v0.10.0
type CompileResult struct {
Bytes []byte `json:"bytes"`
}
CompileResult represents the result of compiling a Rego query, zero or more Rego modules, and arbitrary contextual data into an executable.
type Errors ¶
type Errors []error
Errors represents a collection of errors returned when evaluating Rego.
type EvalContext ¶ added in v0.11.0
type EvalContext struct {
// contains filtered or unexported fields
}
EvalContext defines the set of options allowed to be set at evaluation time. Any other options will need to be set on a new Rego object.
type EvalOption ¶ added in v0.11.0
type EvalOption func(*EvalContext)
EvalOption defines a function to set an option on an EvalConfig
func EvalDisableInlining ¶ added in v0.13.0
func EvalDisableInlining(paths []ast.Ref) EvalOption
EvalDisableInlining returns an argument that adds a set of paths to exclude from partial evaluation inlining.
func EvalInput ¶ added in v0.11.0
func EvalInput(input interface{}) EvalOption
EvalInput configures the input for a Prepared Query's evaluation
func EvalInstrument ¶ added in v0.11.0
func EvalInstrument(instrument bool) EvalOption
EvalInstrument enables or disables instrumenting for a Prepared Query's evaluation
func EvalMetrics ¶ added in v0.11.0
func EvalMetrics(metric metrics.Metrics) EvalOption
EvalMetrics configures the metrics for a Prepared Query's evaluation
func EvalParsedInput ¶ added in v0.11.0
func EvalParsedInput(input ast.Value) EvalOption
EvalParsedInput configures the input for a Prepared Query's evaluation
func EvalParsedUnknowns ¶ added in v0.11.0
func EvalParsedUnknowns(unknowns []*ast.Term) EvalOption
EvalParsedUnknowns returns an argument that sets the values to treat as unknown during partial evaluation.
func EvalPartialNamespace ¶ added in v0.11.0
func EvalPartialNamespace(ns string) EvalOption
EvalPartialNamespace returns an argument that sets the namespace to use for partial evaluation results. The namespace must be a valid package path component.
func EvalRuleIndexing ¶ added in v0.15.0
func EvalRuleIndexing(enabled bool) EvalOption
EvalRuleIndexing will disable indexing optimizations for the evaluation. This should only be used when tracing in debug mode.
func EvalTracer ¶ added in v0.11.0
func EvalTracer(tracer topdown.Tracer) EvalOption
EvalTracer configures a tracer for a Prepared Query's evaluation
func EvalTransaction ¶ added in v0.11.0
func EvalTransaction(txn storage.Transaction) EvalOption
EvalTransaction configures the Transaction for a Prepared Query's evaluation
func EvalUnknowns ¶ added in v0.11.0
func EvalUnknowns(unknowns []string) EvalOption
EvalUnknowns returns an argument that sets the values to treat as unknown during partial evaluation.
type ExpressionValue ¶
type ExpressionValue struct { Value interface{} `json:"value"` Text string `json:"text"` Location *Location `json:"location"` }
ExpressionValue defines the value of an expression in a Rego query.
func (*ExpressionValue) String ¶ added in v0.10.2
func (ev *ExpressionValue) String() string
type PartialQueries ¶ added in v0.9.0
type PartialQueries struct { Queries []ast.Body `json:"queries,omitempty"` Support []*ast.Module `json:"modules,omitempty"` }
PartialQueries contains the queries and support modules produced by partial evaluation.
type PartialResult ¶ added in v0.7.0
type PartialResult struct {
// contains filtered or unexported fields
}
PartialResult represents the result of partial evaluation. The result can be used to generate a new query that can be run when inputs are known.
func (PartialResult) Rego ¶ added in v0.7.0
func (pr PartialResult) Rego(options ...func(*Rego)) *Rego
Rego returns an object that can be evaluated to produce a query result.
type PrepareConfig ¶ added in v0.11.0
type PrepareConfig struct {
// contains filtered or unexported fields
}
PrepareConfig holds settings to control the behavior of the Prepare call.
type PrepareOption ¶ added in v0.11.0
type PrepareOption func(*PrepareConfig)
PrepareOption defines a function to set an option to control the behavior of the Prepare call.
func WithNoInline ¶ added in v0.13.0
func WithNoInline(paths []string) PrepareOption
WithNoInline adds a set of paths to exclude from partial evaluation inlining.
func WithPartialEval ¶ added in v0.11.0
func WithPartialEval() PrepareOption
WithPartialEval configures an option for PrepareForEval which will have it perform partial evaluation while preparing the query (similar to rego.Rego#PartialResult)
type PreparedEvalQuery ¶ added in v0.11.0
type PreparedEvalQuery struct {
// contains filtered or unexported fields
}
PreparedEvalQuery holds the prepared Rego state that has been pre-processed for subsequent evaluations.
func (PreparedEvalQuery) Eval ¶ added in v0.11.0
func (pq PreparedEvalQuery) Eval(ctx context.Context, options ...EvalOption) (ResultSet, error)
Eval evaluates this PartialResult's Rego object with additional eval options and returns a ResultSet. If options are provided they will override the original Rego options respective value. The original Rego object transaction will *not* be re-used. A new transaction will be opened if one is not provided with an EvalOption.
type PreparedPartialQuery ¶ added in v0.11.0
type PreparedPartialQuery struct {
// contains filtered or unexported fields
}
PreparedPartialQuery holds the prepared Rego state that has been pre-processed for partial evaluations.
func (PreparedPartialQuery) Partial ¶ added in v0.11.0
func (pq PreparedPartialQuery) Partial(ctx context.Context, options ...EvalOption) (*PartialQueries, error)
Partial runs partial evaluation on the prepared query and returns the result. The original Rego object transaction will *not* be re-used. A new transaction will be opened if one is not provided with an EvalOption.
type Rego ¶
type Rego struct {
// contains filtered or unexported fields
}
Rego constructs a query and can be evaluated to obtain results.
Example (Custom_function_caching) ¶
package main import ( "context" "fmt" "math/rand" "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/rego" "github.com/open-policy-agent/opa/topdown" "github.com/open-policy-agent/opa/types" ) func main() { type builtinCacheKey string source := rand.NewSource(0) r := rego.New( // An example query that uses a custom function. rego.Query(`x = myrandom("foo"); y = myrandom("foo")`), // A custom function that uses caching. rego.FunctionDyn( ®o.Function{ Name: "myrandom", Memoize: true, Decl: types.NewFunction( types.Args(types.S), // one string input types.N, // one number output ), }, func(_ topdown.BuiltinContext, args []*ast.Term) (*ast.Term, error) { return ast.IntNumberTerm(int(source.Int63())), nil }, ), ) rs, err := r.Eval(context.Background()) if err != nil { // handle error } fmt.Println("x:", rs[0].Bindings["x"]) fmt.Println("y:", rs[0].Bindings["y"]) }
Output: x: 8717895732742165505 y: 8717895732742165505
Example (Custom_functional_builtin) ¶
package main import ( "context" "fmt" "strings" "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/rego" "github.com/open-policy-agent/opa/types" ) func main() { r := rego.New( // An example query that uses a custom function. rego.Query(`x = trim_and_split("/foo/bar/baz/", "/")`), // A custom function that trims and splits strings on the same delimiter. rego.Function2( ®o.Function{ Name: "trim_and_split", Decl: types.NewFunction( types.Args(types.S, types.S), // two string inputs types.NewArray(nil, types.S), // variable-length string array output ), }, func(_ rego.BuiltinContext, a, b *ast.Term) (*ast.Term, error) { str, ok1 := a.Value.(ast.String) delim, ok2 := b.Value.(ast.String) // The function is undefined for non-string inputs. Built-in // functions should only return errors in unrecoverable cases. if !ok1 || !ok2 { return nil, nil } result := strings.Split(strings.Trim(string(str), string(delim)), string(delim)) arr := make(ast.Array, len(result)) for i := range result { arr[i] = ast.StringTerm(result[i]) } return ast.NewTerm(arr), nil }, ), ) rs, err := r.Eval(context.Background()) if err != nil { // handle error } fmt.Println(rs[0].Bindings["x"]) }
Output: [foo bar baz]
func (*Rego) Compile ¶ added in v0.10.0
func (r *Rego) Compile(ctx context.Context, opts ...CompileOption) (*CompileResult, error)
Compile returns a compiled policy query.
func (*Rego) Eval ¶
Eval evaluates this Rego object and returns a ResultSet.
Example (Compiler) ¶
package main import ( "context" "fmt" "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/rego" ) func main() { ctx := context.Background() // Define a simple policy. module := ` package example default allow = false allow { input.identity = "admin" } allow { input.method = "GET" } ` // Compile the module. The keys are used as identifiers in error messages. compiler, err := ast.CompileModules(map[string]string{ "example.rego": module, }) // Create a new query that uses the compiled policy from above. rego := rego.New( rego.Query("data.example.allow"), rego.Compiler(compiler), rego.Input( map[string]interface{}{ "identity": "bob", "method": "GET", }, ), ) // Run evaluation. rs, err := rego.Eval(ctx) if err != nil { // Handle error. } // Inspect results. fmt.Println("len:", len(rs)) fmt.Println("value:", rs[0].Expressions[0].Value) }
Output: len: 1 value: true
Example (Errors) ¶
package main import ( "context" "fmt" "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/rego" ) func main() { ctx := context.Background() r := rego.New( rego.Query("data.example.p"), rego.Module("example_error.rego", `package example p = true { not q[x] } q = {1, 2, 3} { true }`, )) _, err := r.Eval(ctx) switch err := err.(type) { case ast.Errors: for _, e := range err { fmt.Println("code:", e.Code) fmt.Println("row:", e.Location.Row) fmt.Println("filename:", e.Location.File) } default: // Some other error occurred. } }
Output: code: rego_unsafe_var_error row: 3 filename: example_error.rego
Example (Input) ¶
package main import ( "bytes" "context" "encoding/json" "fmt" "github.com/open-policy-agent/opa/rego" ) func main() { ctx := context.Background() // Raw input data that will be used in evaluation. raw := `{"users": [{"id": "bob"}, {"id": "alice"}]}` d := json.NewDecoder(bytes.NewBufferString(raw)) // Numeric values must be represented using json.Number. d.UseNumber() var input interface{} if err := d.Decode(&input); err != nil { panic(err) } // Create a simple query over the input. rego := rego.New( rego.Query("input.users[idx].id = user_id"), rego.Input(input)) //Run evaluation. rs, err := rego.Eval(ctx) if err != nil { // Handle error. } // Inspect results. fmt.Println("len:", len(rs)) fmt.Println("bindings.idx:", rs[1].Bindings["idx"]) fmt.Println("bindings.user_id:", rs[1].Bindings["user_id"]) }
Output: len: 2 bindings.idx: 1 bindings.user_id: alice
Example (MultipleBindings) ¶
package main import ( "context" "fmt" "github.com/open-policy-agent/opa/rego" ) func main() { ctx := context.Background() // Create query that produces multiple bindings for variable. rego := rego.New( rego.Query(`a = ["ex", "am", "ple"]; x = a[_]; not p[x]`), rego.Package(`example`), rego.Module("example.rego", `package example p["am"] { true } `), ) // Run evaluation. rs, err := rego.Eval(ctx) // Inspect results. fmt.Println("len:", len(rs)) fmt.Println("err:", err) for i := range rs { fmt.Printf("bindings[\"x\"]: %v (i=%d)\n", rs[i].Bindings["x"], i) } }
Output: len: 2 err: <nil> bindings["x"]: ex (i=0) bindings["x"]: ple (i=1)
Example (MultipleDocuments) ¶
package main import ( "context" "fmt" "github.com/open-policy-agent/opa/rego" ) func main() { ctx := context.Background() // Create query that produces multiple documents. rego := rego.New( rego.Query("data.example.p[x]"), rego.Module("example.rego", `package example p = {"hello": "alice", "goodbye": "bob"} { true }`, )) // Run evaluation. rs, err := rego.Eval(ctx) // Inspect results. fmt.Println("len:", len(rs)) fmt.Println("err:", err) for i := range rs { fmt.Printf("bindings[\"x\"]: %v (i=%d)\n", rs[i].Bindings["x"], i) fmt.Printf("value: %v (i=%d)\n", rs[i].Expressions[0].Value, i) } }
Output: len: 2 err: <nil> bindings["x"]: hello (i=0) value: alice (i=0) bindings["x"]: goodbye (i=1) value: bob (i=1)
Example (Simple) ¶
package main import ( "context" "fmt" "github.com/open-policy-agent/opa/rego" ) func main() { ctx := context.Background() // Create very simple query that binds a single variable. rego := rego.New(rego.Query("x = 1")) // Run evaluation. rs, err := rego.Eval(ctx) // Inspect results. fmt.Println("len:", len(rs)) fmt.Println("bindings:", rs[0].Bindings) fmt.Println("err:", err) }
Output: len: 1 bindings: map[x:1] err: <nil>
Example (SingleDocument) ¶
package main import ( "context" "fmt" "github.com/open-policy-agent/opa/rego" ) func main() { ctx := context.Background() // Create query that produces a single document. rego := rego.New( rego.Query("data.example.p"), rego.Module("example.rego", `package example p = ["hello", "world"] { true }`, )) // Run evaluation. rs, err := rego.Eval(ctx) // Inspect result. fmt.Println("value:", rs[0].Expressions[0].Value) fmt.Println("err:", err) }
Output: value: [hello world] err: <nil>
Example (Storage) ¶
package main import ( "context" "fmt" "github.com/open-policy-agent/opa/rego" "github.com/open-policy-agent/opa/storage/inmem" "github.com/open-policy-agent/opa/util" ) func main() { ctx := context.Background() data := `{ "example": { "users": [ { "name": "alice", "likes": ["dogs", "clouds"] }, { "name": "bob", "likes": ["pizza", "cats"] } ] } }` var json map[string]interface{} err := util.UnmarshalJSON([]byte(data), &json) if err != nil { // Handle error. } // Manually create the storage layer. inmem.NewFromObject returns an // in-memory store containing the supplied data. store := inmem.NewFromObject(json) // Create new query that returns the value rego := rego.New( rego.Query("data.example.users[0].likes"), rego.Store(store)) // Run evaluation. rs, err := rego.Eval(ctx) if err != nil { // Handle error. } // Inspect the result. fmt.Println("value:", rs[0].Expressions[0].Value) }
Output: value: [dogs clouds]
Example (Tracer) ¶
package main import ( "context" "os" "github.com/open-policy-agent/opa/rego" "github.com/open-policy-agent/opa/topdown" ) func main() { ctx := context.Background() buf := topdown.NewBufferTracer() // Create very simple query that binds a single variable, and enables tracing. rego := rego.New( rego.Query("x = 1"), rego.Tracer(buf), ) // Run evaluation. rego.Eval(ctx) // Inspect results. topdown.PrettyTrace(os.Stdout, *buf) }
Output: Enter x = 1 | Eval x = 1 | Exit x = 1 Redo x = 1 | Redo x = 1
Example (Transactions) ¶
package main import ( "bytes" "context" "fmt" "github.com/open-policy-agent/opa/rego" "github.com/open-policy-agent/opa/storage" "github.com/open-policy-agent/opa/storage/inmem" ) func main() { ctx := context.Background() // Create storage layer and load dummy data. store := inmem.NewFromReader(bytes.NewBufferString(`{ "favourites": { "pizza": "cheese", "colour": "violet" } }`)) // Open a write transaction on the store that will perform write operations. txn, err := store.NewTransaction(ctx, storage.WriteParams) if err != nil { // Handle error. } // Create rego query that uses the transaction created above. inside := rego.New( rego.Query("data.favourites.pizza"), rego.Store(store), rego.Transaction(txn), ) // Create rego query that DOES NOT use the transaction created above. Under // the hood, the rego package will create it's own transaction to // ensure it evaluates over a consistent snapshot of the storage layer. outside := rego.New( rego.Query("data.favourites.pizza"), rego.Store(store), ) // Write change to storage layer inside the transaction. err = store.Write(ctx, txn, storage.AddOp, storage.MustParsePath("/favourites/pizza"), "pepperoni") if err != nil { // Handle error. } // Run evaluation INSIDE the transaction. rs, err := inside.Eval(ctx) if err != nil { // Handle error. } fmt.Println("value (inside txn):", rs[0].Expressions[0].Value) // Run evaluation OUTSIDE the transaction. rs, err = outside.Eval(ctx) if err != nil { // Handle error. } fmt.Println("value (outside txn):", rs[0].Expressions[0].Value) if err := store.Commit(ctx, txn); err != nil { // Handle error. } // Run evaluation AFTER the transaction commits. rs, err = outside.Eval(ctx) if err != nil { // Handle error. } fmt.Println("value (after txn):", rs[0].Expressions[0].Value) }
Output: value (inside txn): pepperoni value (outside txn): cheese value (after txn): pepperoni
func (*Rego) Partial ¶ added in v0.9.0
func (r *Rego) Partial(ctx context.Context) (*PartialQueries, error)
Partial runs partial evaluation on r and returns the result.
Example ¶
package main import ( "context" "fmt" "github.com/open-policy-agent/opa/rego" ) func main() { ctx := context.Background() // Define a simple policy for example purposes. module := `package test allow { input.method = read_methods[_] input.path = ["reviews", user] input.user = user } allow { input.method = read_methods[_] input.path = ["reviews", _] input.is_admin } read_methods = ["GET"] ` r := rego.New(rego.Query("data.test.allow == true"), rego.Module("example.rego", module)) pq, err := r.Partial(ctx) if err != nil { // Handle error. } // Inspect result. for i := range pq.Queries { fmt.Printf("Query #%d: %v\n", i+1, pq.Queries[i]) } }
Output: Query #1: "GET" = input.method; input.path = ["reviews", _]; input.is_admin Query #2: "GET" = input.method; input.path = ["reviews", user3]; user3 = input.user
func (*Rego) PartialEval ¶ added in v0.7.0
func (r *Rego) PartialEval(ctx context.Context) (PartialResult, error)
PartialEval has been deprecated and renamed to PartialResult.
func (*Rego) PartialResult ¶ added in v0.9.0
func (r *Rego) PartialResult(ctx context.Context) (PartialResult, error)
PartialResult partially evaluates this Rego object and returns a PartialResult.
Example ¶
package main import ( "bytes" "context" "fmt" "github.com/open-policy-agent/opa/rego" "github.com/open-policy-agent/opa/storage/inmem" ) func main() { ctx := context.Background() // Define a role-based access control (RBAC) policy that decides whether to // allow or deny requests. Requests are allowed if the user is bound to a // role that grants permission to perform the operation on the resource. module := ` package example import data.bindings import data.roles default allow = false allow { user_has_role[role_name] role_has_permission[role_name] } user_has_role[role_name] { b = bindings[_] b.role = role_name b.user = input.subject.user } role_has_permission[role_name] { r = roles[_] r.name = role_name match_with_wildcard(r.operations, input.operation) match_with_wildcard(r.resources, input.resource) } match_with_wildcard(allowed, value) { allowed[_] = "*" } match_with_wildcard(allowed, value) { allowed[_] = value } ` // Define dummy roles and role bindings for the example. In real-world // scenarios, this data would be pushed or pulled into the service // embedding OPA either from an external API or configuration file. store := inmem.NewFromReader(bytes.NewBufferString(`{ "roles": [ { "resources": ["documentA", "documentB"], "operations": ["read"], "name": "analyst" }, { "resources": ["*"], "operations": ["*"], "name": "admin" } ], "bindings": [ { "user": "bob", "role": "admin" }, { "user": "alice", "role": "analyst" } ] }`)) // Prepare and run partial evaluation on the query. The result of partial // evaluation can be cached for performance. When the data or policy // change, partial evaluation should be re-run. r := rego.New( rego.Query("data.example.allow"), rego.Module("example.rego", module), rego.Store(store), ) pr, err := r.PartialEval(ctx) if err != nil { // Handle error. } // Define example inputs (representing requests) that will be used to test // the policy. examples := []map[string]interface{}{ { "resource": "documentA", "operation": "write", "subject": map[string]interface{}{ "user": "bob", }, }, { "resource": "documentB", "operation": "write", "subject": map[string]interface{}{ "user": "alice", }, }, { "resource": "documentB", "operation": "read", "subject": map[string]interface{}{ "user": "alice", }, }, } for i := range examples { // Prepare and run normal evaluation from the result of partial // evaluation. r := pr.Rego( rego.Input(examples[i]), ) rs, err := r.Eval(ctx) if err != nil || len(rs) != 1 || len(rs[0].Expressions) != 1 { // Handle erorr. } else { fmt.Printf("input %d allowed: %v\n", i+1, rs[0].Expressions[0].Value) } } }
Output: input 1 allowed: true input 2 allowed: false input 3 allowed: true
func (*Rego) PrepareForEval ¶ added in v0.11.0
func (r *Rego) PrepareForEval(ctx context.Context, opts ...PrepareOption) (PreparedEvalQuery, error)
PrepareForEval will parse inputs, modules, and query arguments in preparation of evaluating them.
Example ¶
package main import ( "context" "fmt" "github.com/open-policy-agent/opa/rego" ) func main() { ctx := context.Background() // Create a simple query r := rego.New( rego.Query("input.x == 1"), ) // Prepare for evaluation pq, err := r.PrepareForEval(ctx) if err != nil { // Handle error. } // Raw input data that will be used in the first evaluation input := map[string]interface{}{"x": 2} // Run the evaluation rs, err := pq.Eval(ctx, rego.EvalInput(input)) if err != nil { // Handle error. } // Inspect results. fmt.Println("initial result:", rs[0].Expressions[0]) // Update input input["x"] = 1 // Run the evaluation with new input rs, err = pq.Eval(ctx, rego.EvalInput(input)) if err != nil { // Handle error. } // Inspect results. fmt.Println("updated result:", rs[0].Expressions[0]) }
Output: initial result: false updated result: true
func (*Rego) PrepareForPartial ¶ added in v0.11.0
func (r *Rego) PrepareForPartial(ctx context.Context, opts ...PrepareOption) (PreparedPartialQuery, error)
PrepareForPartial will parse inputs, modules, and query arguments in preparation of partially evaluating them.
Example ¶
package main import ( "context" "fmt" "github.com/open-policy-agent/opa/rego" ) func main() { ctx := context.Background() // Define a simple policy for example purposes. module := `package test allow { input.method = read_methods[_] input.path = ["reviews", user] input.user = user } allow { input.method = read_methods[_] input.path = ["reviews", _] input.is_admin } read_methods = ["GET"] ` r := rego.New( rego.Query("data.test.allow == true"), rego.Module("example.rego", module), ) pq, err := r.PrepareForPartial(ctx) if err != nil { // Handle error. } pqs, err := pq.Partial(ctx) if err != nil { // Handle error. } // Inspect result fmt.Println("First evaluation") for i := range pqs.Queries { fmt.Printf("Query #%d: %v\n", i+1, pqs.Queries[i]) } // Evaluate with specified input exampleInput := map[string]string{ "method": "GET", } // Evaluate again with different input and unknowns pqs, err = pq.Partial(ctx, rego.EvalInput(exampleInput), rego.EvalUnknowns([]string{"input.user", "input.is_admin", "input.path"}), ) if err != nil { // Handle error. } // Inspect result fmt.Println("Second evaluation") for i := range pqs.Queries { fmt.Printf("Query #%d: %v\n", i+1, pqs.Queries[i]) } }
Output: First evaluation Query #1: "GET" = input.method; input.path = ["reviews", _]; input.is_admin Query #2: "GET" = input.method; input.path = ["reviews", user3]; user3 = input.user Second evaluation Query #1: input.path = ["reviews", _]; input.is_admin Query #2: input.path = ["reviews", user3]; user3 = input.user
type Result ¶
type Result struct { Expressions []*ExpressionValue `json:"expressions"` Bindings Vars `json:"bindings,omitempty"` }
Result defines the output of Rego evaluation.
type ResultSet ¶
type ResultSet []Result
ResultSet represents a collection of output from Rego evaluation. An empty result set represents an undefined query.
type Vars ¶
type Vars map[string]interface{}
Vars represents a collection of variable bindings. The keys are the variable names and the values are the binding values.
func (Vars) WithoutWildcards ¶ added in v0.5.3
WithoutWildcards returns a copy of v with wildcard variables removed.