Ejemplo n.º 1
0
func ExampleQuery() {
	// Initialize context for the example. Normally the caller would obtain the
	// context from an input parameter or instantiate their own.
	ctx := context.Background()

	compiler := ast.NewCompiler()

	// Define a dummy module with rules that produce documents that we will query below.
	module, err := ast.ParseModule("my_module.rego", `

	    package opa.example

	    p[x] :- q[x], not r[x]
	    q[y] :- a = [1,2,3], y = a[_]
	    r[z] :- b = [2,4], z = b[_]

	`)

	mods := map[string]*ast.Module{
		"my_module": module,
	}

	if compiler.Compile(mods); compiler.Failed() {
		fmt.Println(compiler.Errors)
	}

	if err != nil {
		// Handle error.
	}

	// Instantiate the policy engine's storage layer.
	store := storage.New(storage.InMemoryConfig())

	// Create a new transaction. Transactions allow the policy engine to
	// evaluate the query over a consistent snapshot fo the storage layer.
	txn, err := store.NewTransaction(ctx)
	if err != nil {
		// Handle error.
	}

	defer store.Close(ctx, txn)

	// Prepare query parameters. In this case, there are no additional documents
	// required by the policy so the request is nil.
	var request ast.Value
	params := topdown.NewQueryParams(ctx, compiler, store, txn, request, ast.MustParseRef("data.opa.example.p"))

	// Execute the query against "p".
	v1, err1 := topdown.Query(params)

	// Inspect the result.
	fmt.Println("v1:", v1[0].Result)
	fmt.Println("err1:", err1)

	// Output:
	// v1: [1 3]
	// err1: <nil>

}
Ejemplo n.º 2
0
func regoLoad(path string) (interface{}, error) {
	bs, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	module, err := ast.ParseModule(path, string(bs))
	if err != nil {
		return nil, err
	}
	result := &loadedModule{
		Parsed: module,
		Raw:    bs,
	}
	return result, nil
}
Ejemplo n.º 3
0
func ExampleCompiler_Compile() {

	// Define an input module that will be compiled.
	exampleModule := `

		package opa.example

		import data.foo
		import request.bar

		p[x] :- foo[x], not bar[x], x >= min_x

		min_x = 100

	`

	// Parse the input module to obtain the AST representation.
	mod, err := ast.ParseModule("my_module", exampleModule)
	if err != nil {
		fmt.Println("Parse error:", err)
	}

	// Create a new compiler instance and compile the module.
	c := ast.NewCompiler()

	mods := map[string]*ast.Module{
		"my_module": mod,
	}

	if c.Compile(mods); c.Failed() {
		fmt.Println("Compile error:", c.Errors)
	}

	fmt.Println("Expr 1:", c.Modules["my_module"].Rules[0].Body[0])
	fmt.Println("Expr 2:", c.Modules["my_module"].Rules[0].Body[1])
	fmt.Println("Expr 3:", c.Modules["my_module"].Rules[0].Body[2])

	// Output:
	//
	// Expr 1: data.foo[x]
	// Expr 2: not request.bar[x]
	// Expr 3: gte(x, data.opa.example.min_x)
}
Ejemplo n.º 4
0
// loadPolicies is the default callback function that will be used when
// opening the policy store.
func loadPolicies(bufs map[string][]byte) (map[string]*ast.Module, error) {

	parsed := map[string]*ast.Module{}

	for id, bs := range bufs {
		mod, err := ast.ParseModule(id, string(bs))
		if err != nil {
			return nil, err
		}
		parsed[id] = mod
	}

	c := ast.NewCompiler()
	if c.Compile(parsed); c.Failed() {
		return nil, c.Errors
	}

	return parsed, nil
}
Ejemplo n.º 5
0
func ExampleQueryCompiler_Compile() {

	// Define an input module that will be compiled.
	exampleModule := `

		package opa.example

		import data.foo
		import request.bar

		p[x] :- foo[x], not bar[x], x >= min_x

		min_x = 100

	`

	// Parse the input module to obtain the AST representation.
	mod, err := ast.ParseModule("my_module", exampleModule)
	if err != nil {
		fmt.Println("Parse error:", err)
	}

	// Create a new compiler instance and compile the module.
	c := ast.NewCompiler()

	mods := map[string]*ast.Module{
		"my_module": mod,
	}

	if c.Compile(mods); c.Failed() {
		fmt.Println("Compile error:", c.Errors)
	}

	// Obtain the QueryCompiler from the compiler instance. Note, we will
	// compile this query within the context of the opa.example package and
	// declare that a query input named "queryinput" must be supplied.
	qc := c.QueryCompiler().
		WithContext(
			ast.NewQueryContext(
				// Note, the ast.MustParse<X> functions are meant for test
				// purposes only. They will panic if an error occurs. Prefer the
				// ast.Parse<X> functions that return meaningful error messages
				// instead.
				ast.MustParsePackage("package opa.example"),
				ast.MustParseImports("import request.queryinput"),
			))

	// Parse the input query to obtain the AST representation.
	query, err := ast.ParseBody("p[x], x < queryinput")
	if err != nil {
		fmt.Println("Parse error:", err)
	}

	compiled, err := qc.Compile(query)
	if err != nil {
		fmt.Println("Compile error:", err)
	}

	fmt.Println("Compiled:", compiled)

	// Output:
	//
	// Compiled: data.opa.example.p[x], lt(x, request.queryinput)
}
Ejemplo n.º 6
0
func (s *Server) v1PoliciesPut(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	vars := mux.Vars(r)
	id := vars["id"]

	buf, err := ioutil.ReadAll(r.Body)
	if err != nil {
		handleError(w, 500, err)
		return
	}

	parsedMod, err := ast.ParseModule(id, string(buf))

	if err != nil {
		switch err := err.(type) {
		case ast.Errors:
			handleErrorAST(w, 400, compileModErrMsg, err)
		default:
			handleError(w, 400, err)
		}
		return
	}

	if parsedMod == nil {
		handleErrorf(w, 400, "refusing to add empty module")
		return
	}

	txn, err := s.store.NewTransaction(ctx)

	if err != nil {
		handleErrorAuto(w, err)
		return
	}

	defer s.store.Close(ctx, txn)

	mods := s.store.ListPolicies(txn)
	mods[id] = parsedMod

	c := ast.NewCompiler()

	if c.Compile(mods); c.Failed() {
		handleErrorAST(w, 400, compileModErrMsg, c.Errors)
		return
	}

	if err := s.store.InsertPolicy(txn, id, parsedMod, buf, s.persist); err != nil {
		handleErrorAuto(w, err)
		return
	}

	s.setCompiler(c)

	policy := &policyV1{
		ID:     id,
		Module: c.Modules[id],
	}

	handleResponseJSON(w, 200, policy, true)
}