cedar

package module
v0.0.0-...-4ead9e5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 15, 2023 License: Apache-2.0 Imports: 6 Imported by: 0

README

Cedar Go

Go Report Card GoDoc License

A Go binding for the Cedar project using Wasm to run the Cedar engine in a Go project with near zero overhead.

Logo

Installation

go get github.com/Joffref/cedar

Usage

The following example shows how to use the Cedar engine to evaluate a policy inside your Go code.

package main

import (
	"context"
	"fmt"
	"github.com/Joffref/cedar"
)

const policies = `
permit(
  principal == User::"alice", 
  action    == Action::"update", 
  resource  == Photo::"VacationPhoto94.jpg"
);
`

const entities = `[]`

func main() {
	engine, err := cedar.NewCedarEngine(context.Background())
	if err != nil {
		panic(err)
	}
	defer engine.Close(context.Background())
	err = engine.SetEntitiesFromJson(context.Background(), entities)
	if err != nil {
		panic(err)
	}
	err = engine.SetPolicies(context.Background(), policies)
	if err != nil {
		panic(err)
	}
	res, err := engine.Eval(context.Background(), cedar.EvalRequest{
		Principal: "User::\"alice\"",
		Action:    "Action::\"update\"",
		Resource:  "Photo::\"VacationPhoto94.jpg\"",
		Context:   "{}", // Don't forget to set the context to an empty JSON object if you don't need it.
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(res)
}

TODO

  • Add more tests and examples.
  • Add a benchmark between the Go and the Rust version.
  • Support policy templates.
  • Support Partial Evaluation.
  • Add validation of the policy, the entities and the EvalRequest before sending them to the engine.
  • ...

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests.

License

This project is licensed under the Apache License v2.0 - see the LICENSE file for details.

Misc

This section contains some information about the project.

Why this binding?

The Cedar project is a great project but it only provides a Rust binding. I wanted to use it in a Go project so I decided to create this binding to embed the Cedar engine in a Go project. Another solution would have been to call Cedar through a REST API but I wanted to avoid the overhead of the network.

Why Wasm?

The main reason is to avoid using CGO for performance reasons. Thanks to Wasm, we can call the Cedar engine directly from Go without using CGO and with near native performance.

For more information about the considerations that led to this choice, I recommend watching this video : GopherCon 2022: Takeshi Yoneda - CGO-less Foreign Function Interface with WebAssembly.

Why not using the FFI interface provided by the Cedar project?

The FFI interface provided by the Cedar project initializes the policy and the entities store during the call to the eval function. This means that if you want to evaluate multiple requests, you will have to initialize the policy and the entities store for each request. This is not optimal if you want to evaluate a lot of requests.

This binding initializes the policy and the entities store only once and then evaluates the requests without having to reinitialize the policy and the entities store.

Cedar affiliation

This project is not affiliated with the Cedar project, thus it is not an official binding.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CedarEngine

type CedarEngine struct {
	// contains filtered or unexported fields
}

CedarEngine is an instance of the cedar wasm engine.

func NewCedarEngine

func NewCedarEngine(ctx context.Context) (*CedarEngine, error)

NewCedarEngine creates a new instance of the cedar wasm engine. This is blocking and may take a while to complete. Ensure you do not call this from a hot path.

func (*CedarEngine) Close

func (c *CedarEngine) Close(ctx context.Context) error

Close closes the engine and cleanup the wasm runtime. Ensure you call this when you are done with the engine to free up resources used by the engine.

func (*CedarEngine) Eval

func (c *CedarEngine) Eval(ctx context.Context, req EvalRequest) (EvalResult, error)

Eval evaluates the request against the policies and entities in the engine. See EvalRequest for more information.

func (*CedarEngine) IsAuthorized

func (c *CedarEngine) IsAuthorized(ctx context.Context, req EvalRequest) (bool, error)

IsAuthorized evaluates the request against the policies and entities in the engine and returns true if the request is authorized. It is a convenience method that is equivalent to calling Eval and checking the result. See Eval for more information.

func (*CedarEngine) SetEntitiesFromJson

func (c *CedarEngine) SetEntitiesFromJson(ctx context.Context, entities string) error

SetEntitiesFromJson sets the entities in the engine from a json string. See https://docs.cedarpolicy.com/syntax-entity.html for more information.

func (*CedarEngine) SetPolicies

func (c *CedarEngine) SetPolicies(ctx context.Context, policies string) error

SetPolicies sets the policies in the engine from a string. See https://docs.cedarpolicy.com/syntax-policy.htmle for more information.

func (*CedarEngine) ValidatePolices

func (c *CedarEngine) ValidatePolices(ctx context.Context, policies string, schema string) (*ValidationResult, error)

ValidatePolices validates the policies against the schema. See https://docs.cedarpolicy.com/syntax-policy.htmle for more information.

type EvalRequest

type EvalRequest struct {
	// Who is making the request. This is a string in the form of "User::\"alice\"".
	Principal string `json:"principal"`
	// What action is being requested. This is a string in the form of "Action::\"update\"".
	Action string `json:"action"`
	// What resource is being requested. This is a string in the form of "Photo::\"VacationPhoto94.jpg\"".
	Resource string `json:"resource"`
	// Context is a json string that can be used to pass additional information to the policy engine
	// for use in policy evaluation.
	// For more information, see https://www.cedarpolicy.com/en/tutorial/context
	Context string `json:"context"`
}

EvalRequest is the request object for the Eval function. Instantion should look like this:

res, err := engine.Eval(context.Background(), cedar.EvalRequest{
	Principal: "User::\"alice\"",
	Action:    "Action::\"update\"",
	Resource:  "Photo::\"VacationPhoto94.jpg\"",
	Context:   "{}",
})

Do not forget to add a context to the eval call in a json format and escape the quotes. For more information, see https://www.cedarpolicy.com/en/tutorial/abac-pt1

type EvalResult

type EvalResult string

EvalResult is the response object for the Eval function.

const (
	EvalResultPermit EvalResult = "Allow"
	EvalResultDeny   EvalResult = "Deny"
)

func (EvalResult) IsPermit

func (e EvalResult) IsPermit() bool

func (EvalResult) String

func (e EvalResult) String() string

type SourceLocation

type SourceLocation struct {
	PolicyID   string `json:"policy_id"`
	RangeStart int    `json:"range_start"`
	RangeEnd   int    `json:"range_end"`
}

type ValidationError

type ValidationError struct {
	ErrorKind string         `json:"error_kind"`
	Location  SourceLocation `json:"source_location"`
}

type ValidationResult

type ValidationResult struct {
	PolicyError      *string           `json:"policy_error"`
	SchemaError      *string           `json:"schema_error"`
	ValidationErrors []ValidationError `json:"validation_errors"`
}

func (ValidationResult) HasPolicyParsingErrors

func (v ValidationResult) HasPolicyParsingErrors() bool

func (ValidationResult) HasSchemaParsingErrors

func (v ValidationResult) HasSchemaParsingErrors() bool

func (ValidationResult) HasValidationErrors

func (v ValidationResult) HasValidationErrors() bool

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL