cedar

package module
v1.2.6 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2025 License: Apache-2.0 Imports: 15 Imported by: 19

README

cedar-go

Cedar Logo

Build and Test Nightly Corpus Test Go Reference

This repository contains source code of the Go implementation of the Cedar policy language.

Cedar is a language for writing and enforcing authorization policies in your applications. Using Cedar, you can write policies that specify your applications' fine-grained permissions. Your applications then authorize access requests by calling Cedar's authorization engine. Because Cedar policies are separate from application code, they can be independently authored, updated, analyzed, and audited. You can use Cedar's validator to check that Cedar policies are consistent with a declared schema which defines your application's authorization model.

Cedar is:

Expressive

Cedar is a simple yet expressive language that is purpose-built to support authorization use cases for common authorization models such as RBAC and ABAC.

Performant

Cedar is fast and scalable. The policy structure is designed to be indexed for quick retrieval and to support fast and scalable real-time evaluation, with bounded latency.

Analyzable

Cedar is designed for analysis using Automated Reasoning. This enables analyzer tools capable of optimizing your policies and proving that your security model is what you believe it is.

Using Cedar

Cedar can be used in your application by importing the github.com/cedar-policy/cedar-go package.

Comparison to the Rust implementation

The Go implementation includes:

  • the core authorizer
  • JSON marshalling and unmarshalling
  • all core and extended types (including RFC 80's datetime and duration)
  • integration test suite
  • human-readable schema parsing

The Go implementation does not yet include:

Quick Start

Here's a simple example of using Cedar in Go:

package main

import (
	"encoding/json"
	"fmt"
	"log"

	cedar "github.com/cedar-policy/cedar-go"
)

const policyCedar = `permit (
	principal == User::"alice",
	action == Action::"view",
	resource in Album::"jane_vacation"
  );
`

const entitiesJSON = `[
  {
    "uid": { "type": "User", "id": "alice" },
    "attrs": { "age": 18 },
    "parents": []
  },
  {
    "uid": { "type": "Photo", "id": "VacationPhoto94.jpg" },
    "attrs": {},
    "parents": [{ "type": "Album", "id": "jane_vacation" }]
  }
]`

func main() {
	var policy cedar.Policy
	if err := policy.UnmarshalCedar([]byte(policyCedar)); err != nil {
		log.Fatal(err)
	}

	ps := cedar.NewPolicySet()
	ps.Add("policy0", &policy)

	var entities cedar.EntityMap
	if err := json.Unmarshal([]byte(entitiesJSON), &entities); err != nil {
		log.Fatal(err)
	}
	
	req := cedar.Request{
		Principal: cedar.NewEntityUID("User", "alice"),
		Action:    cedar.NewEntityUID("Action", "view"),
		Resource:  cedar.NewEntityUID("Photo", "VacationPhoto94.jpg"),
		Context:   cedar.NewRecord(cedar.RecordMap{
			"demoRequest": cedar.True,
        }),
	}

	ok, _ := cedar.Authorize(ps, entities, req)
	fmt.Println(ok)
}

CLI output:

allow

This request is allowed because VacationPhoto94.jpg belongs to Album::"jane_vacation", and alice can view photos in Album::"jane_vacation".

If you'd like to see more details on what can be expressed as Cedar policies, see the documentation.

Packages

The cedar-go module houses the following public packages:

  • cedar - The main package for interacting with the module, including parsing policies and entities, schemas, and authorizing requests.
  • ast - Programmatic construction of Cedar ASTs
  • types - Basic types common to multiple packages. For convenience, most of these are also projected through the cedar package.
  • x/exp/batch - An experimental batch authorization API supporting high-performance variable substitution via partial evaluation.

Documentation

General documentation for Cedar is available at docs.cedarpolicy.com, with source code in the cedar-policy/cedar-docs repository.

Generated documentation for the latest version of the Go implementation can be accessed here.

If you're looking to integrate Cedar into a production system, please be sure the read the security best practices

Backward Compatibility Considerations

  • x/exp - code in this directory is not subject to the semantic versioning constraints of the rest of the module and breaking changes may be made at any time.
  • Variadics may be added to functions that do not have them to expand the arguments of a function or method.
  • Concrete types may be replaced with compatible interfaces to expand the variety of arguments a function or method can take.
  • Backwards compatibility is maintained for all Go minor versions released within 6 months of a release of cedar-go.

Change log

1.2.5
New Features
  • Adds experimental support for parsing Cedar schema in both Cedar and JSON formats
1.2.4
New Features
  • Adds experimental access to evaluation of AST nodes
1.2.3
New Features
  • Adds Entity.Equal()
1.2.2
New Features
  • Adds experimental support for inspecting Cedar policy AST
1.2.1
New Features
  • Fixes the name of AuthorizationPolicySet and receiver types for PolicySet.Get() and PolicySet.IsAuthorized()
  • Retracts 1.2.0
1.2.0
New Features
  • Support for the .isEmpty() operator.
  • A new top-level Authorize() function, which allows authorization against a generic policy iterator (PolicyIterator) instead of requiring a PolicySet. Like the EntityGetter interface does for entities, using a generic iterator enables policy to be retrieved from external sources or for policy to be selected dynamically by the iterator implementation without having to clone an entire PolicySet.
  • batch.Authorize() likewise now also accepts a PolicyIterator.
  • First class iterator support for EntityUIDSet, Record, Set, and PolicySet container types.
Upgrading from 1.1.0
  • cedar-go now requires Go 1.23
1.1.0
New features
  • Support for entity tags via the .getTag() and .hasTag() operators.
1.0.0
New features
  • AST builder methods for Cedar datetime and duration literals and their extension methods have been added
  • AST builder methods for adding extension function calls with uninterpreted strings
  • Small improvement in evaluation runtime performance for large, shallow entity graphs.
Upgrading from 0.4.x to 1.0.0
  • The Parents field on types.Entity has been changed to an immutable set type with an interface similar to types.Set
  • The UnsafeDecimal() constructor for the types.Decimal type has been removed and replaced with the following safe constructors, which return error on overflow:
    • NewDecimal(int64 i, int exponent) (Decimal, error)
    • NewDecimalFromInt[T constraints.Signed](i T) (Decimal, error)
    • NewDecimalFromFloat[T constraints.Float](f T) (Decimal, error)
  • The Value field on types.Decimal has been made private. Instances of Decimal can be compared with one another via the new Compare method.
  • types.DecimalPrecision has been made private
  • The following error types have been made private: types.ErrDateitme, types.ErrDecimal, types.ErrDuration, types.ErrIP, types.ErrNotComparable
  • The following datetime and duration-related constructors have been renamed:
    • types.FromStdTime() has been renamed to types.NewDatetime()
    • types.DatetimeFromMillis() has been renamed to types.NewDatetimeFromMillis()
    • types.FromStdDuration() has been renamed to types.NewDuration()
    • types.DurationFromMillis() has been renamed to types.NewDurationFromMillis()
  • types.Entities has been renamed to types.EntityMap
  • Because types.Entity is now immutable, types.EntityMap now stores items by value rather than by pointer
  • PolicySet.Store() has been renamed to PolicySet.Add()
  • PolicySet.Delete() has been renamed to PolicySet.Remove()
  • types.Set() now takes variadic arguments of type types.Value instead of a single []types.Value argument
0.4.0
New features
  • types.Set is now implemented as a hash set, turning Set.Contains() into an O(1) operation, on average. This mitigates a worst case quadratic runtime for the evaluation of the containsAny() operator.
  • For convenience, public types, constructors, and constants from the types package are now exported via the cedar package as well.
Upgrading from 0.3.x to 0.4.x
  • types.Set is now an immutable type which must be constructed via types.NewSet()
    • To iterate the values, use Set.Iterate(), which takes an iterator callback.
    • Duplicates are now removed from Sets, so they won't be rendered when calling Set.MarshalCedar() or Set.MarshalJSON.
    • All implementations of types.Value are now safe to copy shallowly, so Set.DeepClone() has been removed.
  • types.Record is now an immutable type which must be constructed via types.NewRecord()
    • To iterate the keys and values, use Record.Iterate(), which takes an iterator callback.
    • All implementations of types.Value are now safe to copy shallowly, so Record.DeepClone() has been removed.
0.3.2
New features
  • An implementation of the datetime and duration extension types specified in RFC 80.
    • Note: While these types have been accepted into the language, they have not yet been formally analyzed in the specification.
0.3.1
New features
  • General performance improvements to the evaluator
  • An experimental batch evaluator has been added to x/exp/batch
  • Reserved keywords are now rejected in all appropriate places when parsing Cedar text
  • A parsing ambiguity between variables, entity UIDs, and extension functions has been resolved
Upgrading from 0.2.x to 0.3.x
  • The JSON marshaling of the Position struct now uses canonical lower-case keys for its fields
0.2.0
New features
  • A programmatic AST is now available in the ast package.
  • Policy sets can be marshaled and unmarshaled from JSON.
  • Policies can also be marshaled to Cedar text.
Upgrading from 0.1.x to 0.2.x
  • The Cedar value types have moved from the cedar package to the types package.
  • The PolicyIDs are now strings, previously they were numeric.
  • Errors and reasons use the new PolicyID form.
  • Combining multiple parsed Cedar files now involves coming up with IDs for each statement in those files. It's best to create an empty NewPolicySet then parse individual files using NewPolicyListFromBytes and subsequently use PolicySet.Store to add each of the policy statements.
  • The Cedar Entity and Entities types have moved from the cedar package to the types package.
  • Stronger typing is being used in many places.
  • The Value method Cedar() string was changed to MarshalCedar() []byte

Security

See CONTRIBUTING for more information.

Contributing

We welcome contributions from the community. Please either file an issue, or see CONTRIBUTING

License

This project is licensed under the Apache-2.0 License.

Documentation

Overview

Package cedar provides an implementation of the Cedar language authorizer.

Example
package main

import (
	"encoding/json"
	"fmt"

	"github.com/cedar-policy/cedar-go"
)

const policyCedar = `permit (
	principal == User::"alice",
	action == Action::"view",
	resource in Album::"jane_vacation"
  );
`

const entitiesJSON = `[
  {
    "uid": { "type": "User", "id": "alice" },
    "attrs": { "age": 18 },
    "parents": []
  },
  {
    "uid": { "type": "Photo", "id": "VacationPhoto94.jpg" },
    "attrs": {},
    "parents": [{ "type": "Album", "id": "jane_vacation" }]
  }
]`

func main() {
	var policy cedar.Policy
	if err := policy.UnmarshalCedar([]byte(policyCedar)); err != nil {
		fmt.Println("policy unmarshal error:", err)
		return
	}

	ps := cedar.NewPolicySet()
	ps.Add("policy0", &policy)

	var entities cedar.EntityMap
	if err := json.Unmarshal([]byte(entitiesJSON), &entities); err != nil {
		fmt.Println("entity unmarshal error:", err)
		return
	}

	req := cedar.Request{
		Principal: cedar.NewEntityUID("User", "alice"),
		Action:    cedar.NewEntityUID("Action", "view"),
		Resource:  cedar.NewEntityUID("Photo", "VacationPhoto94.jpg"),
		Context: cedar.NewRecord(cedar.RecordMap{
			"demoRequest": cedar.True,
		}),
	}

	ok, _ := ps.IsAuthorized(entities, req)
	fmt.Println(ok)
}
Output:

allow

Index

Examples

Constants

View Source
const (
	Allow = types.Allow
	Deny  = types.Deny
)
View Source
const (
	Permit = types.Permit
	Forbid = types.Forbid
)
View Source
const (
	True  = types.True
	False = types.False
)

Variables

This section is empty.

Functions

func Authorize added in v1.2.0

func Authorize(policies PolicyIterator, entities types.EntityGetter, req Request) (Decision, Diagnostic)

Authorize uses the combination of the PolicySet and Entities to determine if the given Request to determine Decision and Diagnostic.

Types

type Annotations

type Annotations = types.Annotations

type Boolean

type Boolean = types.Boolean

type Datetime added in v0.4.0

type Datetime = types.Datetime

func NewDatetime added in v1.0.0

func NewDatetime(t time.Time) Datetime

NewDatetime returns a Cedar Datetime from a Go time.Time value

func NewDatetimeFromMillis added in v1.0.0

func NewDatetimeFromMillis(ms int64) Datetime

NewDatetimeFromMillis returns a Datetime from milliseconds

type Decimal

type Decimal = types.Decimal

func NewDecimal added in v1.0.0

func NewDecimal(i int64, exponent int) (Decimal, error)

NewDecimal returns a Decimal value of i * 10^exponent.

func NewDecimalFromFloat added in v1.0.0

func NewDecimalFromFloat[T constraints.Float](f T) (Decimal, error)

NewDecimalFromFloat returns a Decimal that approximates the given floating point value. The value of the Decimal is calculated by multiplying it by 10^4, truncating it to an int64 representation to cut off any digits beyond the four allowed, and passing it as an integer to NewDecimal() with -4 as the exponent.

WARNING: decimal representations of more than 6 significant digits for float32s and 15 significant digits for float64s can be lossy in terms of precision. To create a precise Decimal above those sizes, use the NewDecimal constructor.

func NewDecimalFromInt added in v1.0.0

func NewDecimalFromInt[T constraints.Signed](i T) (Decimal, error)

NewDecimalFromInt returns a Decimal with the whole integer value provided

type Decision

type Decision = types.Decision

type Diagnostic

type Diagnostic = types.Diagnostic

type DiagnosticError added in v0.3.1

type DiagnosticError = types.DiagnosticError

type DiagnosticReason added in v0.3.1

type DiagnosticReason = types.DiagnosticReason

type Duration added in v0.4.0

type Duration = types.Duration

func NewDuration added in v1.0.0

func NewDuration(d time.Duration) Duration

NewDuration returns a Cedar Duration from a Go time.Duration

func NewDurationFromMillis added in v1.0.0

func NewDurationFromMillis(ms int64) Duration

NewDurationFromMillis returns a Duration from milliseconds

type Effect

type Effect = types.Effect

type Entity

type Entity = types.Entity

type EntityGetter added in v1.0.6

type EntityGetter = types.EntityGetter

type EntityMap added in v1.0.0

type EntityMap = types.EntityMap

type EntityType added in v0.4.0

type EntityType = types.EntityType

type EntityUID

type EntityUID = types.EntityUID

func NewEntityUID

func NewEntityUID(typ EntityType, id String) EntityUID

NewEntityUID returns an EntityUID given an EntityType and identifier

type EntityUIDSet added in v1.0.0

type EntityUIDSet = types.EntityUIDSet

func NewEntityUIDSet added in v1.0.0

func NewEntityUIDSet(args ...EntityUID) EntityUIDSet

NewEntityUIDSet returns an immutable EntityUIDSet ready for use.

type IPAddr

type IPAddr = types.IPAddr

type Long

type Long = types.Long

type Pattern added in v0.4.0

type Pattern = types.Pattern

func NewPattern added in v0.4.0

func NewPattern(components ...any) Pattern

NewPattern permits for the programmatic construction of a Pattern out of a slice of pattern components. The pattern components may be one of string, cedar.String, or cedar.Wildcard. Any other types will cause a panic.

type Policy

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

A Policy is the parsed form of a single Cedar language policy statement.

func NewPolicyFromAST added in v0.2.0

func NewPolicyFromAST(astIn *ast.Policy) *Policy

NewPolicyFromAST lets you create a new policy statement from a programmatically created AST. Do not modify the *ast.Policy after passing it into NewPolicyFromAST.

func (*Policy) AST added in v0.3.1

func (p *Policy) AST() *ast.Policy

AST retrieves the AST of this policy. Do not modify the AST, as the compiled policy will no longer be in sync with the AST.

func (*Policy) Annotations

func (p *Policy) Annotations() Annotations

Annotations retrieves the annotations associated with this policy.

func (*Policy) Effect

func (p *Policy) Effect() Effect

Effect retrieves the effect of this policy.

func (*Policy) MarshalCedar added in v0.2.0

func (p *Policy) MarshalCedar() []byte

MarshalCedar encodes a single Policy statement in the human-readable format specified by the Cedar documentation.

func (*Policy) MarshalJSON added in v0.2.0

func (p *Policy) MarshalJSON() ([]byte, error)

MarshalJSON encodes a single Policy statement in the JSON format specified by the Cedar documentation.

func (*Policy) Position

func (p *Policy) Position() Position

Position retrieves the position of this policy.

func (*Policy) SetFilename added in v0.2.0

func (p *Policy) SetFilename(fileName string)

SetFilename sets the filename of this policy.

func (*Policy) UnmarshalCedar added in v0.2.0

func (p *Policy) UnmarshalCedar(b []byte) error

UnmarshalCedar parses and compiles a single Policy statement in the human-readable format specified by the Cedar documentation.

func (*Policy) UnmarshalJSON added in v0.2.0

func (p *Policy) UnmarshalJSON(b []byte) error

UnmarshalJSON parses and compiles a single Policy statement in the JSON format specified by the Cedar documentation.

type PolicyID added in v0.2.0

type PolicyID = types.PolicyID

type PolicyIterator added in v1.2.1

type PolicyIterator interface {
	// All returns an iterator over all the policies in the set
	All() iter.Seq2[PolicyID, *Policy]
}

PolicyIterator is an interface which abstracts an iterable set of policies.

type PolicyList added in v0.2.0

type PolicyList []*Policy

PolicyList represents a list of un-named Policy's. Cedar documents, unlike the PolicySet form, don't have a means of naming individual policies.

func NewPolicyListFromBytes added in v0.2.0

func NewPolicyListFromBytes(fileName string, document []byte) (PolicyList, error)

NewPolicyListFromBytes will create a Policies from the given text document with the given file name used in Position data. If there is an error parsing the document, it will be returned.

func (PolicyList) MarshalCedar added in v0.2.0

func (p PolicyList) MarshalCedar() []byte

MarshalCedar emits a concatenated Cedar representation of the policies.

func (*PolicyList) UnmarshalCedar added in v0.2.0

func (p *PolicyList) UnmarshalCedar(b []byte) error

UnmarshalCedar parses a concatenation of un-named Cedar policy statements. Names can be assigned to these policies when adding them to a PolicySet.

type PolicyMap added in v0.2.0

type PolicyMap map[PolicyID]*Policy

PolicyMap is a map of policy IDs to policy

func (PolicyMap) All added in v1.2.0

func (p PolicyMap) All() iter.Seq2[PolicyID, *Policy]

All returns an iterator over the policy IDs and policies in the PolicyMap.

type PolicySet

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

PolicySet is a set of named policies against which a request can be authorized.

func NewPolicySet

func NewPolicySet() *PolicySet

NewPolicySet creates a new, empty PolicySet

func NewPolicySetFromBytes added in v0.2.0

func NewPolicySetFromBytes(fileName string, document []byte) (*PolicySet, error)

NewPolicySetFromBytes will create a PolicySet from the given text document with the given file name used in Position data. If there is an error parsing the document, it will be returned.

NewPolicySetFromBytes assigns default PolicyIDs to the policies contained in fileName in the format "policy<n>" where <n> is incremented for each new policy found in the file.

func (*PolicySet) Add added in v1.0.0

func (p *PolicySet) Add(policyID PolicyID, policy *Policy) bool

Add inserts or updates a policy with the given ID. Returns true if a policy with the given ID did not already exist in the set.

func (*PolicySet) All added in v1.2.0

func (p *PolicySet) All() iter.Seq2[PolicyID, *Policy]

All returns an iterator over the (PolicyID, *Policy) tuples in the PolicySet

func (*PolicySet) Get added in v0.2.0

func (p *PolicySet) Get(policyID PolicyID) *Policy

Get returns the Policy with the given ID. If a policy with the given ID does not exist, nil is returned.

func (*PolicySet) IsAuthorized deprecated

func (p *PolicySet) IsAuthorized(entities types.EntityGetter, req Request) (Decision, Diagnostic)

IsAuthorized uses the combination of the PolicySet and Entities to determine if the given Request to determine Decision and Diagnostic.

Deprecated: Use the Authorize() function instead

func (*PolicySet) Map deprecated added in v0.2.0

func (p *PolicySet) Map() PolicyMap

Map returns a new PolicyMap instance of the policies in the PolicySet.

Deprecated: use the iterator returned by All() like so: maps.Collect(ps.All())

func (*PolicySet) MarshalCedar added in v0.2.0

func (p *PolicySet) MarshalCedar() []byte

MarshalCedar emits a concatenated Cedar representation of a PolicySet. The policy names are stripped, but policies are emitted in lexicographical order by ID.

func (*PolicySet) MarshalJSON added in v0.2.0

func (p *PolicySet) MarshalJSON() ([]byte, error)

MarshalJSON encodes a PolicySet in the JSON format specified by the Cedar documentation.

func (*PolicySet) Remove added in v1.0.0

func (p *PolicySet) Remove(policyID PolicyID) bool

Remove removes a policy from the PolicySet. Returns true if a policy with the given ID already existed in the set.

func (*PolicySet) UnmarshalJSON added in v0.2.0

func (p *PolicySet) UnmarshalJSON(b []byte) error

UnmarshalJSON parses and compiles a PolicySet in the JSON format specified by the Cedar documentation.

type Position

type Position = types.Position

type Record

type Record = types.Record

func NewRecord added in v0.4.0

func NewRecord(r RecordMap) Record

NewRecord returns an immutable Record given a Go map of Strings to Values

type RecordMap added in v0.4.0

type RecordMap = types.RecordMap

type Request

type Request = types.Request

type Set

type Set = types.Set

func NewSet added in v0.4.0

func NewSet(s ...types.Value) Set

NewSet returns an immutable Set given a variadic set of Values. Duplicates are removed and order is not preserved.

type String

type String = types.String

type Value

type Value = types.Value

type Wildcard added in v0.4.0

type Wildcard = types.Wildcard

Directories

Path Synopsis
Package ast provides functions for programmatically constructing a Cedar policy AST.
Package ast provides functions for programmatically constructing a Cedar policy AST.
schema/ast
Package ast defines the structure for a Cedar schema file.
Package ast defines the structure for a Cedar schema file.
schema/parser
Code generated by re2go 4.3 on Mon Jul 7 15:42:21 2025, DO NOT EDIT.
Code generated by re2go 4.3 on Mon Jul 7 15:42:21 2025, DO NOT EDIT.
Package types contains primitive, plain-old-data types including:
Package types contains primitive, plain-old-data types including:
x
exp/ast
Package ast exposes the internal AST used within cedar-go.
Package ast exposes the internal AST used within cedar-go.
exp/batch
Package batch allows for performant batch evaluations of Cedar policy given a set of principals, actions, resources, and/or context as variables.
Package batch allows for performant batch evaluations of Cedar policy given a set of principals, actions, resources, and/or context as variables.
exp/eval
Package eval provides a simple interface for evaluating or partially evaluating a policy node in a given environment.
Package eval provides a simple interface for evaluating or partially evaluating a policy node in a given environment.

Jump to

Keyboard shortcuts

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