Help us shape the future of Go! Take the 2026 Go Developer Survey

authz

package
v0.21.0 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: AGPL-3.0 Imports: 16 Imported by: 0

Documentation

Overview

Package authz is Atlas's policy decision point: it decides whether one external Worker action may run, and why (ADR-0475).

It is pure. Set.Evaluate reads its arguments and nothing else — no store, no network, no clock (the instant is in the request) — so a decision is a function of its request and can be explained, tested and simulated as one. Assembling the request from trusted server-side facts is the caller's job (the policy information point), and acting on the answer is the enforcement point's; neither lives here.

It fails closed. The zero Decision is Indeterminate, an evaluation error is Indeterminate, no applicable policy is NotApplicable, and only Decision.Permitted lets an action through.

Index

Constants

View Source
const (
	FirstApplicable = "first-applicable"
	DenyOverrides   = "deny-overrides"
)

Rule-combining algorithms a policy may declare. There is no default: an algorithm left out is refused, because the two answer the same rules differently.

View Source
const (
	ObligationApproval            = "approval"
	ObligationFreshAuthentication = "fresh-authentication"
)

Obligation types.

View Source
const (
	ReasonPermit              = "PERMIT"
	ReasonPolicyDeny          = "POLICY_DENY"
	ReasonPolicyIndeterminate = "POLICY_INDETERMINATE"
	ReasonNoApplicablePolicy  = "NO_APPLICABLE_POLICY"
	ReasonSetUnavailable      = "POLICY_SET_UNAVAILABLE"
	ReasonApprovalRequired    = "APPROVAL_REQUIRED"
	ReasonApprovalRejected    = "APPROVAL_REJECTED"
	ReasonApprovalExpired     = "APPROVAL_EXPIRED"
	ReasonReauthRequired      = "REAUTHENTICATION_REQUIRED"
)

Reason codes the PDP itself produces. Rules add their own.

View Source
const (
	// ModeService executes as the Worker's own service identity. The Worker
	// Instance holds that credential, so enforcement is cooperative.
	ModeService = "service"
	// ModeDelegatedFixed executes as one connection's external identity, for the
	// connection's owner.
	ModeDelegatedFixed = "delegated-fixed"
	// ModeDelegatedPerJob executes as the executing subject's own connection,
	// chosen for each job.
	ModeDelegatedPerJob = "delegated-per-job"
)

Identity modes a configured Worker may declare.

View Source
const (
	ConnectionActive         = "active"
	ConnectionReauthRequired = "reauth_required"
	ConnectionRevoked        = "revoked"
)

Connection states.

View Source
const (
	ApprovalGranted  = "granted"
	ApprovalRejected = "rejected"
)

Approval outcomes.

View Source
const (
	MaxListLen   = 256
	MaxApprovals = 64
)

MaxListLen bounds every list a request carries, and MaxApprovals the approvals: evaluation time is bounded by its input, because neither FEEL nor temis offers a step budget to bound it otherwise.

Variables

This section is empty.

Functions

func Digest

func Digest(workerType, worker, operation, resource string, params map[string]any) (string, error)

Digest is the identity of one action: SHA-256 over a canonical JSON of the Worker Type, the Worker, the operation, the canonical resource and every material parameter. An approval is of a digest, so approving one action can never be replayed for another (ADR-0475 §9).

The JSON is canonical because encoding/json writes map keys in sorted order and a value decoded from JSON re-encodes to the same bytes. Only the server computes a digest, over the parameters it resolved itself; a digest a Worker reports is never read.

func IsDelegated

func IsDelegated(mode string) bool

IsDelegated reports whether mode executes as a person through a connection, which is what makes a subject and a connection mandatory.

Types

type Action

type Action struct {
	Operation string
	// Digest is [Digest] over the Worker Type, the Worker, the operation, the
	// resource and every material parameter. Approvals are of a digest.
	Digest string
}

Action is the operation and the digest of everything it will do.

type Actor

type Actor struct {
	IdentityMode string
	Worker       string // the configured Worker the compiled task names
	WorkerType   string
	// WorkerInstance is the lease holder's self-asserted label. It is recorded and
	// may be matched by nothing that decides — it is not a credential.
	WorkerInstance string
	// ExecutedAs is the external identity key, or "service:<worker>".
	ExecutedAs string
	// Connection is the connection a delegated mode uses; nil when there is none.
	Connection *Connection
}

Actor is what executes the action: the configured Worker, its identity mode, and the identity it acts as.

type Approval

type Approval struct {
	ID             string   `json:"id"`
	Digest         string   `json:"digest"`
	ApproverID     string   `json:"approverId"`
	ApproverGroups []string `json:"approverGroups"` // the approver's groups now, not when they decided
	Outcome        string   `json:"outcome"`        // ApprovalGranted or ApprovalRejected
	DecidedAt      int64    `json:"decidedAt"`      // Unix nanoseconds
	Revoked        bool     `json:"revoked"`
}

Approval is one approver's decision about one action digest.

type Connection

type Connection struct {
	ID             string   `json:"id"`
	OwnerID        string   `json:"ownerId"`
	Status         string   `json:"status"`
	AllowedWorkers []string `json:"allowedWorkers"`
	// LastInteractiveAuth is when its owner last signed in at the provider, Unix
	// nanoseconds; 0 when unknown.
	LastInteractiveAuth int64 `json:"lastInteractiveAuth"`
}

Connection is the public half of a connection: never its credential.

type Context

type Context struct {
	// Time is the evaluation instant, Unix nanoseconds, read by the caller from its
	// clock and frozen into the decision's event.
	Time               int64
	ProcessID          string // the BPMN process id
	ProcessInstanceKey uint64
	JobKey             uint64
	// InitiatedBy is the principal who started the process instance, as the engine
	// recorded it at creation; empty when nobody authenticated did.
	InitiatedBy string
	// Approvals are the approval facts recorded for this instance, with each
	// approver's current group membership.
	Approvals []Approval
}

Context is when and in which process the action happens.

type Decision

type Decision struct {
	Effect     Effect
	ReasonCode string
	// PolicyID and PolicyVersion name the deciding policy: the first Deny under
	// deny-overrides, else the first Permit. Empty for a guard's or a default answer.
	PolicyID      string
	PolicyVersion int
	// Obligations are those of every contributing Permit, satisfied or not.
	Obligations []ObligationResult
	// Trace is every policy that was asked and what it said, in evaluation order.
	Trace []Step
}

Decision is the PDP's answer, with everything needed to explain it.

func (Decision) Permitted

func (d Decision) Permitted() bool

Permitted is the only question an enforcement point asks.

type Document

type Document struct {
	ID          string `json:"id"`
	Description string `json:"description,omitempty"`
	// Priority orders policies, lowest first. It decides nothing under the fixed
	// deny-overrides combination; it decides which policy is reported as deciding
	// and the order of the explanation.
	Priority      int       `json:"priority,omitempty"`
	Target        Target    `json:"target,omitempty"`
	RuleCombining string    `json:"ruleCombining"`
	Rules         []RuleDoc `json:"rules"`
	// DMN is a DMN model whose decisions rules may name. It is compiled once, at
	// publication.
	DMN string `json:"dmn,omitempty"`
}

Document is a policy as an administrator writes it. It is decoded strictly: a field this build does not know is refused rather than ignored, because an ignored matcher ("subjectGroupAny") is a rule that matches everyone.

func ParseDocument

func ParseDocument(src []byte) (Document, error)

ParseDocument decodes one policy, refusing unknown fields and trailing content.

type Effect

type Effect uint8

Effect is what a decision, a policy or a rule says.

const (
	// Indeterminate is the zero value: something could not be decided — a missing
	// attribute, a condition that did not evaluate to a boolean, a policy set that
	// is not there. Never a permit.
	Indeterminate Effect = iota
	// Permit lets the action run, once every obligation it carries is satisfied.
	Permit
	// Deny refuses it.
	Deny
	// NotApplicable means nothing spoke to this request. The enforcement point
	// treats it as a refusal: Atlas authorizes by default deny.
	NotApplicable
)

func ParseEffect

func ParseEffect(s string) (Effect, bool)

ParseEffect reads an effect as a policy or a DMN decision writes it. Indeterminate is not something a rule may answer on purpose, so it does not parse.

func (Effect) String

func (e Effect) String() string

type Match

type Match struct {
	SubjectRolesAny  []string `json:"subjectRolesAny,omitempty"`
	SubjectGroupsAny []string `json:"subjectGroupsAny,omitempty"`
	SubjectIDs       []string `json:"subjectIds,omitempty"`
	Operations       []string `json:"operations,omitempty"`
	Workers          []string `json:"workers,omitempty"`
	IdentityModes    []string `json:"identityModes,omitempty"`
	ProcessIDs       []string `json:"processIds,omitempty"`
	// ResourcePrefixes match when the canonical resource id starts with one.
	ResourcePrefixes []string `json:"resourcePrefixes,omitempty"`
}

Match is a rule's structured matchers. Every set list must match; a list matches when it contains the request's value (or, for SubjectRolesAny and SubjectGroupsAny, any of the subject's).

type ObligationDoc

type ObligationDoc struct {
	ID   string `json:"id"`
	Type string `json:"type"`
	// approval
	ApproverGroup    string `json:"approverGroup,omitempty"`
	Approvals        int    `json:"approvals,omitempty"`
	ValidForSeconds  int64  `json:"validForSeconds,omitempty"`
	ExcludeRequester bool   `json:"excludeRequester,omitempty"`
	// fresh-authentication
	MaxAgeSeconds int64 `json:"maxAgeSeconds,omitempty"`
}

ObligationDoc is a condition a Permit carries that the server verifies from its own records before the action runs.

type ObligationResult

type ObligationResult struct {
	ID            string `json:"id"`
	Type          string `json:"type"`
	PolicyID      string `json:"policyId"`
	PolicyVersion int    `json:"policyVersion"`
	RuleID        string `json:"ruleId,omitempty"`
	Satisfied     bool   `json:"satisfied"`
	Reason        string `json:"reason,omitempty"` // why it is not satisfied; empty when it is
	// ApprovalsUsed are the ids of the approvals that satisfied it, sorted.
	ApprovalsUsed []string `json:"approvalsUsed,omitempty"`
	// What the approval asks for, so the enforcement point can open a request.
	ApproverGroup    string `json:"approverGroup,omitempty"`
	Approvals        int    `json:"approvals,omitempty"`
	ValidForSeconds  int64  `json:"validForSeconds,omitempty"`
	ExcludeRequester bool   `json:"excludeRequester,omitempty"`
}

ObligationResult is one obligation and whether the request satisfies it. An unmet approval carries what an approval request needs to be opened for it.

Its JSON names are part of the recorded evidence (an authorization's detail), so they are spelled out rather than left to the field names.

type Policy

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

Policy is one published policy compiled for evaluation. It is immutable and safe for concurrent use.

func CompilePolicy

func CompilePolicy(ctx context.Context, doc Document, version int) (*Policy, []string, error)

CompilePolicy validates and compiles one policy. Everything that can be checked without a request is checked here — the structure, every FEEL condition, the DMN model — so nothing is parsed or compiled when a decision is asked for (invariant I5). It returns warnings for what is legal but unsafe to rely on.

func (*Policy) ID

func (p *Policy) ID() string

ID and Version name the policy as it was published.

func (*Policy) Version

func (p *Policy) Version() int

type Published

type Published struct {
	Document    Document
	Version     int
	PublishedAt int64
	PublishedBy string
}

Published is one policy version as the store holds it: immutable once published.

type Request

type Request struct {
	Subject  Subject
	Actor    Actor
	Action   Action
	Resource Resource
	Context  Context
}

Request is everything a decision may depend on. Every field is filled by the server from its own records; nothing in it comes from a BPMN model's claims, a process variable or a Worker Instance's report.

type Resource

type Resource struct {
	Type string
	ID   string
}

Resource is what the action touches, in its canonical spelling ("sharepoint:site=…;list=…;path=…").

type RuleDoc

type RuleDoc struct {
	ID string `json:"id"`
	// Effect is "Permit" or "Deny". Exactly one of Effect and Decision is set.
	Effect string `json:"effect,omitempty"`
	// Decision names a decision of the policy's DMN model; its outputs "effect" and
	// "reasonCode" are the rule's answer.
	Decision   string `json:"decision,omitempty"`
	ReasonCode string `json:"reasonCode,omitempty"`
	When       Match  `json:"when,omitempty"`
	// Condition is a FEEL boolean over subject, actor, action, resource and context.
	Condition   string          `json:"condition,omitempty"`
	Obligations []ObligationDoc `json:"obligations,omitempty"`
}

RuleDoc is one rule: a static effect under conditions, or a DMN decision.

type Set

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

Set is the compiled, published policy set. It is immutable: publishing builds a new one, and a reader holding the old one keeps deciding with it.

func CompileSet

func CompileSet(ctx context.Context, published []Published) (*Set, error)

CompileSet compiles every published policy into one set, ordered by priority and then id so the order of the input never changes an answer.

func (*Set) Evaluate

func (s *Set) Evaluate(ctx context.Context, r *Request) Decision

Evaluate decides one request. A nil set is a set that could not be loaded, and is Indeterminate: "there are no policies" and "the policies are unreadable" must never be confused, because the first denies by default while the second would deny for a reason nobody can fix by writing a policy.

func (*Set) Policies

func (s *Set) Policies() []*Policy

Policies lists the set's policies in evaluation order.

type Step

type Step struct {
	PolicyID      string
	PolicyVersion int
	RuleID        string // the rule that answered; empty when none did
	Effect        Effect
	Reason        string
	Note          string // why an answer was Indeterminate
}

Step is one policy's answer.

type Subject

type Subject struct {
	// ID is the stable principal id ("usr_…"); empty when there is none.
	ID string
	// Known says ID was found in the user store; Disabled that the account is
	// deactivated. Both are read at decision time — current state decides.
	Known    bool
	Disabled bool
	// Roles and Groups are the principal's current roles and group ids.
	Roles  []string
	Groups []string
}

Subject is the Atlas principal the action is executed for.

type Target

type Target struct {
	WorkerTypes   []string `json:"workerTypes,omitempty"`
	Workers       []string `json:"workers,omitempty"`
	Operations    []string `json:"operations,omitempty"`
	IdentityModes []string `json:"identityModes,omitempty"`
}

Target selects the requests a policy speaks to. Every list that is set must contain the request's value; an empty target applies to every governed action.

Jump to

Keyboard shortcuts

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