abac

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package abac provides a bounded, closed expression model for typed attribute-based authorization.

Example
package main

import (
	"context"
	"fmt"

	authorization "github.com/faustbrian/go-authorization"
	"github.com/faustbrian/go-authorization/abac"
)

func main() {
	evaluator, err := abac.New(
		[]abac.Rule{
			{
				ID:           "finance-read",
				Action:       "report.read",
				ResourceType: "report",
				Effect:       authorization.Allow,
				Condition: abac.Equal(
					abac.Reference{Source: abac.Subject, Name: "department"},
					authorization.StringValue("finance"),
				),
			},
		},
		nil,
	)
	if err != nil {
		panic(err)
	}

	decision, err := evaluator.Evaluate(context.Background(), authorization.Request{
		Subject: authorization.Subject{
			Kind: authorization.SubjectUser,
			ID:   "alice",
			Attributes: authorization.Attributes{
				"department": authorization.StringValue("finance"),
			},
		},
		Action:   "report.read",
		Resource: authorization.Resource{Type: "report", ID: "quarterly"},
	})
	if err != nil {
		panic(err)
	}

	fmt.Println(decision.Outcome == authorization.Allow)
}
Output:
true

Index

Examples

Constants

View Source
const (
	ReasonAllow         authorization.ReasonCode = "abac-allow"
	ReasonExplicitDeny  authorization.ReasonCode = "abac-explicit-deny"
	ReasonLimitExceeded authorization.ReasonCode = "abac-limit-exceeded"
)
View Source
const (
	EffectAllow = "allow"
	EffectDeny  = "deny"
)
View Source
const (
	SourceSubject     = "subject"
	SourceResource    = "resource"
	SourceRequest     = "request"
	SourceEnvironment = "environment"
)
View Source
const (
	OperatorEqual          = "equal"
	OperatorExists         = "exists"
	OperatorIsNull         = "is_null"
	OperatorAll            = "all"
	OperatorAny            = "any"
	OperatorNot            = "not"
	OperatorGreaterThan    = "greater_than"
	OperatorLessThan       = "less_than"
	OperatorIn             = "in"
	OperatorSetContains    = "set_contains"
	OperatorHasPrefix      = "has_prefix"
	OperatorHasSuffix      = "has_suffix"
	OperatorStringContains = "string_contains"
	OperatorIPIn           = "ip_in"
)
View Source
const (
	ValueNull      = "null"
	ValueString    = "string"
	ValueBool      = "bool"
	ValueInt       = "int"
	ValueFloat     = "float"
	ValueTime      = "time"
	ValueIP        = "ip"
	ValueStringSet = "string_set"
)
View Source
const DocumentVersion uint64 = 1

Variables

View Source
var (
	ErrInvalidRule             = errors.New("invalid ABAC rule")
	ErrInvalidCondition        = errors.New("invalid ABAC condition")
	ErrCostExceeded            = errors.New("ABAC evaluation cost exceeded")
	ErrDepthExceeded           = errors.New("ABAC condition depth exceeded")
	ErrRuleLimitExceeded       = errors.New("ABAC rule limit exceeded")
	ErrSetLimitExceeded        = errors.New("ABAC set limit exceeded")
	ErrMatchLimitExceeded      = errors.New("ABAC match limit exceeded")
	ErrBatchLimitExceeded      = errors.New("ABAC batch limit exceeded")
	ErrUnknownNamedCondition   = errors.New("unknown named ABAC condition")
	ErrDuplicateNamedCondition = errors.New("duplicate named ABAC condition")
)
View Source
var (
	ErrInvalidDocument            = errors.New("invalid ABAC document")
	ErrUnsupportedDocumentVersion = errors.New("unsupported ABAC document version")
	ErrDocumentLimitExceeded      = errors.New("ABAC document size limit exceeded")
)

Functions

func EncodeDocument

func EncodeDocument(document Document) ([]byte, error)

Types

type Condition

type Condition interface {
	// contains filtered or unexported methods
}

func All

func All(conditions ...Condition) Condition

func Any

func Any(conditions ...Condition) Condition

func Equal

func Equal(reference Reference, want authorization.Value) Condition

func Exists

func Exists(reference Reference) Condition

func GreaterThan

func GreaterThan(reference Reference, want authorization.Value) Condition

func HasPrefix

func HasPrefix(reference Reference, value string) Condition

func HasSuffix

func HasSuffix(reference Reference, value string) Condition

func IPIn

func IPIn(reference Reference, prefix netip.Prefix) Condition

func In

func In(reference Reference, values ...authorization.Value) Condition

func IsNull

func IsNull(reference Reference) Condition

func LessThan

func LessThan(reference Reference, want authorization.Value) Condition

func Not

func Not(condition Condition) Condition

func SetContains

func SetContains(reference Reference, value string) Condition

func StringContains

func StringContains(reference Reference, value string) Condition

type ConditionDocument

type ConditionDocument struct {
	Operator   string                      `json:"operator"`
	Source     string                      `json:"source,omitempty"`
	Attribute  authorization.AttributeName `json:"attribute,omitempty"`
	Value      *ValueDocument              `json:"value,omitempty"`
	Values     []ValueDocument             `json:"values,omitempty"`
	Conditions []ConditionDocument         `json:"conditions,omitempty"`
	Condition  *ConditionDocument          `json:"condition,omitempty"`
	Text       string                      `json:"text,omitempty"`
	Prefix     string                      `json:"prefix,omitempty"`
}

type Decoder

type Decoder struct{}

func (Decoder) Decode

func (Decoder) Decode(document json.RawMessage) (authorization.Evaluator, error)

type Document

type Document struct {
	Version         uint64                   `json:"version"`
	Limits          Limits                   `json:"limits,omitempty"`
	Rules           []RuleDocument           `json:"rules"`
	NamedConditions []NamedConditionDocument `json:"named_conditions"`
}

func (Document) Build

func (document Document) Build() (*Evaluator, error)

type Evaluator

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

func DecodeDocument

func DecodeDocument(encoded []byte) (*Evaluator, error)

func New

func New(
	rules []Rule,
	namedConditions []NamedCondition,
	options ...Option,
) (*Evaluator, error)

func (*Evaluator) Evaluate

func (evaluator *Evaluator) Evaluate(
	ctx context.Context,
	request authorization.Request,
) (authorization.Decision, error)

func (*Evaluator) EvaluateBatch

func (evaluator *Evaluator) EvaluateBatch(
	ctx context.Context,
	requests []authorization.Request,
) ([]authorization.Decision, error)

type Limits

type Limits struct {
	MaxRules           int `json:"max_rules,omitempty"`
	MaxDepth           int `json:"max_depth,omitempty"`
	MaxCost            int `json:"max_cost,omitempty"`
	MaxMatches         int `json:"max_matches,omitempty"`
	MaxSetSize         int `json:"max_set_size,omitempty"`
	MaxBatchSize       int `json:"max_batch_size,omitempty"`
	MaxNamedConditions int `json:"max_named_conditions,omitempty"`
}

type NamedCondition

type NamedCondition struct {
	Name      string
	Version   uint64
	Condition Condition
}

type NamedConditionDocument

type NamedConditionDocument struct {
	Name      string            `json:"name"`
	Version   uint64            `json:"version"`
	Condition ConditionDocument `json:"condition"`
}

type Option

type Option func(*Evaluator)

func WithLimits

func WithLimits(limits Limits) Option

type Reference

type Reference struct {
	Source Source
	Name   authorization.AttributeName
}

type Result

type Result struct {
	Matched bool
	Status  Status
	Cost    int
}

func EvaluateCondition

func EvaluateCondition(
	ctx context.Context,
	condition Condition,
	request authorization.Request,
	limits Limits,
) (Result, error)

type Rule

type Rule struct {
	ID               authorization.PolicyID
	Priority         int
	Tenant           authorization.TenantID
	Action           authorization.Action
	ResourceType     authorization.ResourceType
	ResourceID       authorization.ResourceID
	Effect           authorization.Outcome
	Condition        Condition
	ConditionName    string
	ConditionVersion uint64
}

type RuleDocument

type RuleDocument struct {
	ID               authorization.PolicyID     `json:"id"`
	Priority         int                        `json:"priority,omitempty"`
	Tenant           authorization.TenantID     `json:"tenant,omitempty"`
	Action           authorization.Action       `json:"action"`
	ResourceType     authorization.ResourceType `json:"resource_type"`
	ResourceID       authorization.ResourceID   `json:"resource_id,omitempty"`
	Effect           string                     `json:"effect"`
	Condition        *ConditionDocument         `json:"condition,omitempty"`
	ConditionName    string                     `json:"condition_name,omitempty"`
	ConditionVersion uint64                     `json:"condition_version,omitempty"`
}

type Source

type Source uint8
const (
	Subject Source = iota
	Resource
	Request
	Environment
)

type Status

type Status uint8
const (
	StatusNoMatch Status = iota
	StatusMatch
	StatusMissing
	StatusNull
	StatusTypeMismatch
)

type ValueDocument

type ValueDocument struct {
	Kind      string   `json:"kind"`
	String    string   `json:"string,omitempty"`
	Bool      bool     `json:"bool,omitempty"`
	Int       int64    `json:"int,omitempty"`
	Float     float64  `json:"float,omitempty"`
	Time      string   `json:"time,omitempty"`
	IP        string   `json:"ip,omitempty"`
	StringSet []string `json:"string_set,omitempty"`
}

Jump to

Keyboard shortcuts

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