policy

package module
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Dec 13, 2025 License: Apache-2.0 Imports: 28 Imported by: 0

README

🔴🟡🟢 AMPEL Policy Framework

Go Reference License

The AMPEL Policy Framework provides the data structures, tooling, and libraries for defining, distributing, and managing security policies that evaluate software supply chain attestations.

This framework is used by the AMPEL policy engine to verify that software artifacts meet specific security and compliance requirements based on in-toto attestations.

🚀 Quick Start

Installation
go get github.com/carabiner-dev/policy
Parse and Compile a Policy
package main

import (
    "fmt"
    "github.com/carabiner-dev/policy"
)

func main() {
    // Create a compiler
    compiler := policy.NewCompiler()

    // Compile a policy from a file
    set, pcy, group, err := compiler.CompileFile("my-policy.json")
    if err != nil {
        panic(err)
    }

    if set != nil {
        fmt.Printf("Compiled PolicySet: %s\n", set.GetId())
        fmt.Printf("Contains %d policies\n", len(set.GetPolicies()))
    }
}
Simple Policy Example
{
  "id": "sbom-check",
  "meta": {
    "description": "Verify an SBOM exists"
  },
  "tenets": [
    {
      "id": "has-packages",
      "runtime": "cel@v0",
      "code": "has(sbom.packages) && sbom.packages.size() > 0",
      "predicates": {
        "types": ["https://spdx.dev/Document"]
      },
      "error": {
        "message": "No SBOM found",
        "guidance": "Ensure your build generates an SBOM attestation"
      }
    }
  ]
}

📖 Documentation

New to the AMPEL Policy Framework? Start here:

Technical References:

✨ Key Features

📦 Policy Materials

Define security requirements using three policy material types:

  • Policy: Fundamental evaluation unit containing executable checks (tenets)
  • PolicyGroup: Complex security controls with multiple evaluation strategies
  • PolicySet: Top-level container bringing policies and groups together
🌐 Remote Referencing

Store policies in git repositories or on HTTPS servers, reference them by URI:

{
  "policies": [
    {
      "source": {
        "location": {
          "uri": "git+https://github.com/org/policies@commit-sha#path/to/policy.json"
        }
      }
    }
  ]
}

Features:

  • Centralized policy management
  • Version control with git
  • Content integrity verification
  • Efficient caching
🔄 Flexible Evaluation

Control how policies are evaluated with:

  • Assert Modes: Require ALL checks to pass (AND) or just ONE (OR)
  • Enforce Modes: Block on failures (ON) or warn only (OFF)
  • Mix and match at different levels for sophisticated compliance modeling
🔗 Evidence Chaining

Connect attestations across related artifacts:

{
  "chain": [
    {
      "predicate": {
        "type": "https://slsa.dev/provenance/v1",
        "selector": "materials[0].digest.sha1",
        "runtime": "cel@v0"
      }
    }
  ]
}

Trace from binaries → images → commits → source code.

🎯 Context Values

Parameterize policies for reusability:

{
  "context": {
    "allowed_licenses": {
      "type": "array",
      "required": true,
      "description": "List of approved SPDX license identifiers"
    }
  }
}

Same policy, different parameters per organization/project.

✅ Identity Verification

Specify expected signers for attestations:

  • Sigstore identities: OIDC issuer + identity
  • Key-based: Public key verification
  • Identity references: Reuse common identities
🚄 High Performance
  • Parallel remote resource fetching
  • Intelligent content caching
  • Deduplication by content hash
  • Optimized for large policy sets

🏗️ Architecture

Components

This repository contains:

1. Protocol Buffer Definitions

The policy.proto file defines the structure of:

  • Policy, PolicyGroup, PolicySet
  • Identities, Tenets, Metadata
  • Remote references and chain links

Generated Go code is available in api/v1/.

2. Parser

Reads policy files and converts them to structured protobuf objects:

  • Supports JSON and HJSON formats
  • Handles cryptographic signature envelopes
  • Applies default values
  • Computes content hashes

See Parser Documentation →

3. Compiler

Assembles complete policies by resolving remote references:

  • Fetches remote policies from git/HTTPS
  • Validates and assembles policy structures
  • Manages recursive dependencies
  • Caches fetched content

See Compiler Documentation →

4. Storage Backend

Caching layer for remote content:

  • Indexes by hash, URL, and ID
  • Deduplicates content
  • Optimizes repeated compilations

See Storage Backend Documentation →

Workflow
Policy Files (JSON/HJSON)
         ↓
    [Parser]
         ↓
Policy Objects (Protobuf)
         ↓
    [Compiler] ←→ [Storage Backend]
         ↓           ↑
Remote Fetching -----┘
         ↓
Complete PolicySet
         ↓
  [AMPEL Engine]
         ↓
   Evaluation Results

🧪 Policy Material Elements

Policy

A policy contains one or more tenets (executable checks) evaluated against attestations:

{
  "id": "license-check",
  "meta": {
    "description": "Verify approved licenses",
    "assert_mode": "AND"
  },
  "context": {
    "allowed_licenses": {
      "type": "array",
      "required": true
    }
  },
  "tenets": [
    {
      "id": "check-licenses",
      "runtime": "cel@v0",
      "code": "sbom.packages.all(p, p.license in allowed_licenses)",
      "predicates": {
        "types": ["https://spdx.dev/Document"]
      }
    }
  ]
}

Assert Mode: AND means all tenets must pass, OR means at least one must pass.

Learn more about Policies →

PolicyGroup

Groups policies into blocks with different evaluation strategies:

{
  "id": "build-verification",
  "blocks": [
    {
      "id": "required-checks",
      "meta": {
        "assert_mode": "AND"
      },
      "policies": [
        // ALL of these must pass
      ]
    },
    {
      "id": "alternative-checks",
      "meta": {
        "assert_mode": "OR"
      },
      "policies": [
        // At least ONE must pass
      ]
    }
  ]
}

A PolicyGroup passes when ALL blocks pass, enabling complex security controls.

Learn more about PolicyGroups →

PolicySet

The top-level container combining policies and groups:

{
  "id": "org-policy",
  "meta": {
    "description": "Organizational security policy"
  },
  "common": {
    "identities": [...],
    "context": {...}
  },
  "policies": [...],
  "groups": [...]
}

Includes shared identities and context values used by all policies.

Learn more about PolicySets →

🔧 Usage Examples

Parse a Policy
parser := policy.NewParser()
pcy, err := parser.ParsePolicyFile("policy.json")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Policy: %s\n", pcy.GetId())
fmt.Printf("Tenets: %d\n", len(pcy.GetTenets()))
Compile from Remote Location
compiler := policy.NewCompiler()

uri := "git+https://github.com/org/policies@9a70ca49@abc123#policy.json"
set, pcy, group, err := compiler.CompileLocation(uri)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Compiled: %s\n", set.GetId())
Parse with Signature Verification
import "github.com/carabiner-dev/policy/options"

parser := policy.NewParser()

opts := options.WithVerifySignatures(true)
opts = options.WithIdentityStrings([]string{
    "sigstore:https://token.actions.githubusercontent.com:https://github.com/org/repo/.github/workflows/release.yml@refs/tags/v1.0.0",
})

policySet, verification, err := parser.ParseVerifyPolicySetFile(
    "signed-policy.json",
    opts,
)

if verification != nil && verification.GetSignature().GetVerified() {
    fmt.Println("✓ Signature valid")
}
Compile PolicySet with Remote Policies
compiler := policy.NewCompiler()

// PolicySet references remote policies
set, _, _, err := compiler.CompileFile("policyset.json")
if err != nil {
    log.Fatal(err)
}

// Remote policies are fetched, cached, and assembled
for i, p := range set.GetPolicies() {
    fmt.Printf("Policy %d: %s (from %s)\n",
        i,
        p.GetId(),
        p.GetMeta().GetOrigin().GetUri(),
    )
}

More examples in the tooling documentation →

🔐 Supported Runtimes

Tenets support multiple runtimes for executing policy code:

  • CEL (Common Expression Language): cel@v0 (default, recommended)
  • Rego: rego@v1 (planned)
  • Cedar: cedar@v1 (planned)

CEL is a non-Turing complete expression language designed for safe, fast policy evaluation.

🔗 Supported Remote Locations

Git Repositories (VCS Locators)
git+https://github.com/org/repo@commit-sha#path/to/policy.json
git+ssh://git@github.com/org/repo@commit-sha#path/to/policy.json

Best Practice: Always pin to commit SHAs for reproducibility.

HTTPS URLs
https://policies.example.com/policy.json

Best Practice: Include content digests for integrity verification:

{
  "source": {
    "location": {
      "uri": "https://example.com/policy.json",
      "digest": {
        "sha256": "abc123..."
      }
    }
  }
}

🤝 Integration with AMPEL

This framework provides the policy definitions and tooling. To evaluate policies against attestations, use the AMPEL policy engine.

import (
    "context"
    "github.com/carabiner-dev/policy"
    "github.com/carabiner-dev/ampel/pkg/verifier"
)

// Compile the policy
compiler := policy.NewCompiler()
set, _, _, err := compiler.CompileFile("policy.json")
if err != nil {
    log.Fatal(err)
}

// Create AMPEL verifier
ampel := verifier.New()

// Verify subject against the compiled PolicySet
results, err := ampel.Verify(
    context.Background(),
    &verifier.VerificationOptions{},
    set,  // Can be *Policy, *PolicySet, or *PolicyGroup
    subject,
)
if err != nil {
    log.Fatal(err)
}

// Check results
if results.Passed() {
    fmt.Println("✓ Policy verification passed")
} else {
    fmt.Println("✗ Policy verification failed")
}

The typical workflow is:

  1. Use this framework to compile a PolicySet (resolving remote references, etc.)
  2. Pass the compiled PolicySet to AMPEL's Verify() method
  3. AMPEL executes the policy tenets and returns results

See the AMPEL documentation for details on policy evaluation.

📋 Format and Compatibility

Policies are defined using Protocol Buffers for:

  • Strong typing and validation
  • Cross-language compatibility
  • Efficient serialization
  • Clear schema evolution

The framework is designed to work with the in-toto attestation framework, the industry standard for software supply chain evidence.

🧪 Testing

Run tests:

go test ./...

Run specific test suites:

go test -v -run TestParseLocalPolicies ./...
go test -v -run TestCompileLocalPolicies ./...

🤝 Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes with tests
  4. Submit a pull request

📄 License

This project is Copyright © 2025 by Carabiner Systems, Inc and released under the terms of the Apache 2.0 license.

🙏 Acknowledgments

Built on the in-toto attestation framework and inspired by the need for flexible, powerful software supply chain security policies.

Documentation

Index

Constants

View Source
const (
	AssertModeAND = "AND"
	AssertModeOR  = "OR"

	EnforceOn  = "ON"
	EnforceOff = "OFF"
)

Variables

View Source
var ErrParseInconsistency = errors.New("internal error: fetched reference ID and policy ID mismatch")

This error is thrown if a fetchedRef lists a policy ID not contained in its policy or policy set. If it's ever thrown it is definitely a bug:

View Source
var ErrUnsupportedLocationURI = errors.New("unsupported policy location")

Functions

func PolicyOrSet

func PolicyOrSet(set *api.PolicySet, pcy *api.Policy) any

PolicyOrSet takes a policy or policyset and returns the one that is not nill

func PolicyOrSetOrGroup added in v0.4.0

func PolicyOrSetOrGroup(set *api.PolicySet, pcy *api.Policy, grp *api.PolicyGroup) any

PolicyOrSet takes a policy or policyset and returns the one that is not nill

Types

type Compiler

type Compiler struct {
	Options CompilerOptions
	Store   StorageBackend
	// contains filtered or unexported fields
}

Compiler is the policy compiler

func NewCompiler

func NewCompiler() *Compiler

func (*Compiler) Compile

func (compiler *Compiler) Compile(data []byte, funcs ...options.OptFn) (*api.PolicySet, *api.Policy, *api.PolicyGroup, error)

CompileVerify compiles a policy, while verifying its signature

func (*Compiler) CompileFile

func (compiler *Compiler) CompileFile(path string, funcs ...options.OptFn) (*api.PolicySet, *api.Policy, *api.PolicyGroup, error)

CompileFile reads data from a local file and returns either a policy set or policy.

func (*Compiler) CompileLocation

func (compiler *Compiler) CompileLocation(location string, funcs ...options.OptFn) (*api.PolicySet, *api.Policy, *api.PolicyGroup, error)

func (*Compiler) CompilePolicy

func (compiler *Compiler) CompilePolicy(p *api.Policy, funcs ...options.OptFn) (*api.Policy, error)

Compile builds a policy set fetching any remote pieces as necessary

func (*Compiler) CompilePolicyGroup added in v0.4.0

func (compiler *Compiler) CompilePolicyGroup(grp *api.PolicyGroup, funcs ...options.OptFn) (*api.PolicyGroup, error)

Compile builds a policy set fetching any remote pieces as necessary

func (*Compiler) CompileRemote

func (compiler *Compiler) CompileRemote(uri string, funcs ...options.OptFn) (*api.PolicySet, *api.Policy, *api.PolicyGroup, error)

CompileRemote reads a policy or policy set from a remote location. The location URI can be a git VCS locator using HTTPS or SSH as transport or an HTTPS URL.

func (*Compiler) CompileSet

func (compiler *Compiler) CompileSet(set *api.PolicySet, funcs ...options.OptFn) (*api.PolicySet, error)

Compile builds a policy set fetching any remote pieces as necessary

func (*Compiler) CompileVerify added in v0.2.0

func (compiler *Compiler) CompileVerify(data []byte, funcs ...options.OptFn) (set *api.PolicySet, pcy *api.Policy, grp *api.PolicyGroup, ver attestation.Verification, err error)

CompileVerify is the main method to assemble policies and groups.

Compiling means fetching all the policy references and assembling a policy in memory from the fetched data.

func (*Compiler) CompileVerifyFile added in v0.2.0

func (compiler *Compiler) CompileVerifyFile(path string, funcs ...options.OptFn) (*api.PolicySet, *api.Policy, *api.PolicyGroup, attestation.Verification, error)

CompileFile reads data from a local file and returns either a policy set or policy.

func (*Compiler) CompileVerifyLocation added in v0.2.0

func (compiler *Compiler) CompileVerifyLocation(location string, funcs ...options.OptFn) (set *api.PolicySet, pcy *api.Policy, grp *api.PolicyGroup, ver attestation.Verification, err error)

CompileLocaCompileVerifyLocationtion takes a location string and parses a policy or PolicySet as read from it. The location will be tested, if it is a URL or VCS locator, it will be retrieved remotely. If its a local file, it will be read from disk. Anything else throws an error.

This function variant returns the signature verification.

func (*Compiler) CompileVerifyRemote added in v0.2.0

func (compiler *Compiler) CompileVerifyRemote(uri string, funcs ...options.OptFn) (set *api.PolicySet, pcy *api.Policy, grp *api.PolicyGroup, ver attestation.Verification, err error)

CompileRemote reads a policy or policy set from a remote location. The location URI can be a git VCS locator using HTTPS or SSH as transport or an HTTPS URL.

type CompilerOptions

type CompilerOptions struct {

	// MaxRemoteRecursion captures the maximum recursion level the
	// compiler will do to fetch remote content. Note that this setting
	// causes exponential requests, so be careful when defining a value.
	MaxRemoteRecursion int
}

CompilerOptions are the settings of the compiler itself.

type Fetcher

type Fetcher struct{}

Fetcher is the ampel policy fetcher. It optimizes retrieval of policy data from repositories and source control systems.

func NewFetcher

func NewFetcher() *Fetcher

func (*Fetcher) Get

func (gf *Fetcher) Get(uri string) ([]byte, error)

func (*Fetcher) GetFromGit

func (gf *Fetcher) GetFromGit(locator string) ([]byte, error)

GetFromGit gets data from a git repository at the specified revision

func (*Fetcher) GetFromHTTP

func (gf *Fetcher) GetFromHTTP(url string) ([]byte, error)

GetFromHTTP retrieves data from an http endpoint

func (*Fetcher) GetGroup

func (gf *Fetcher) GetGroup(uris []string) ([][]byte, error)

GetGroup fetches a list of uris that can be HTTP(S) URLs or SPDX VCS locators. The functions uses the vcslocator module and the k8s http agent to fetch in parallel. The returned slice if byte-slices is guarranteed to preserve the URL order. If a request fails, this function returns a single error and discards all data.

Retries are currently not supported but will probably be at a later point once the VCS locator module supports retrying.

type Parser

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

Parser implements methods to read the policy and policy set json files. Note that the parser only deals with decoding json. Use the policy compiler to assemble policies with external/remote references.

func NewParser

func NewParser() *Parser

NewParser creates a new policy parser

func (*Parser) Open

func (p *Parser) Open(location string, funcs ...options.OptFn) (*api.PolicySet, *api.Policy, *api.PolicyGroup, error)

Open opens a Policy or policySet. This function supports remote locations (https URLs or VCS locators) and will eventually verify signatures after reading and parsing data (still under construction).

func (*Parser) OpenVerify added in v0.2.0

func (p *Parser) OpenVerify(location string, funcs ...options.OptFn) (set *api.PolicySet, pcy *api.Policy, grp *api.PolicyGroup, v attestation.Verification, err error)

Open opens a Policy or policySet. This function supports remote locations (https URLs or VCS locators) and will eventually verify signatures after reading and parsing data (still under construction).

func (*Parser) ParsePolicy

func (p *Parser) ParsePolicy(data []byte, funcs ...options.OptFn) (*api.Policy, error)

ParsePolicy parses a policy from its JSON representation or an envelope

func (*Parser) ParsePolicyFile

func (p *Parser) ParsePolicyFile(path string, funcs ...options.OptFn) (*api.Policy, error)

ParsePolicyFile parses a policy from a file

func (*Parser) ParsePolicyGroup added in v0.4.0

func (p *Parser) ParsePolicyGroup(policyGroupData []byte, funcs ...options.OptFn) (*api.PolicyGroup, error)

ParseSet parses a policy set.

func (*Parser) ParsePolicyGroupFile added in v0.4.0

func (p *Parser) ParsePolicyGroupFile(path string, funcs ...options.OptFn) (*api.PolicyGroup, error)

ParsePolicyFile parses a policy from a file

func (*Parser) ParsePolicyOrSet

func (p *Parser) ParsePolicyOrSet(data []byte, funcs ...options.OptFn) (*api.PolicySet, *api.Policy, error)

ParsePolicyOrSet takes json data and tries to parse a policy or a policy set out of it. Returns an error if the JSON data is none.

func (*Parser) ParsePolicySet

func (p *Parser) ParsePolicySet(policySetData []byte, funcs ...options.OptFn) (*api.PolicySet, error)

ParseSet parses a policy set.

func (*Parser) ParsePolicySetFile

func (p *Parser) ParsePolicySetFile(path string, funcs ...options.OptFn) (*api.PolicySet, error)

ParseFile parses a policySet from a file

func (*Parser) ParseVerifyPolicy added in v0.2.0

func (p *Parser) ParseVerifyPolicy(data []byte, funcs ...options.OptFn) (*api.Policy, attestation.Verification, error)

ParsePolicy parses a policy from its JSON representation or an envelope

func (*Parser) ParseVerifyPolicyGroup added in v0.4.0

func (p *Parser) ParseVerifyPolicyGroup(policyGroupData []byte, funcs ...options.OptFn) (*api.PolicyGroup, attestation.Verification, error)

ParseSet parses a policy set.

func (*Parser) ParseVerifyPolicyOrSet added in v0.2.0

func (p *Parser) ParseVerifyPolicyOrSet(data []byte, funcs ...options.OptFn) (set *api.PolicySet, pcy *api.Policy, v attestation.Verification, err error)

deprecated

func (*Parser) ParseVerifyPolicyOrSetOrGroup added in v0.4.0

func (p *Parser) ParseVerifyPolicyOrSetOrGroup(data []byte, funcs ...options.OptFn) (set *api.PolicySet, pcy *api.Policy, grp *api.PolicyGroup, v attestation.Verification, err error)

ParseVerifyPolicyOrSet parses a policy and verifies the signatures. It returns a PolicySet or Policy and the signature verification results object.

func (*Parser) ParseVerifyPolicySet added in v0.2.0

func (p *Parser) ParseVerifyPolicySet(policySetData []byte, funcs ...options.OptFn) (*api.PolicySet, attestation.Verification, error)

ParseSet parses a policy set.

type PolicyFetcher

type PolicyFetcher interface {
	Get(string) ([]byte, error)
	GetGroup(uris []string) ([][]byte, error)
}

type Signer

type Signer struct {
	Options options.SignerOptions
}

Signer is the policy/policy set signer object. Signing is done by wrapping the policies in an in-toto statement and the predicate/* wrappers before passing them to the sigstore signer.

func NewSigner

func NewSigner(funcs ...options.SignerOptFn) *Signer

NewSigner returns a policy signer with the specified options

func (*Signer) SignPolicyData

func (ps *Signer) SignPolicyData(data []byte, w io.Writer, funcs ...options.SignerOptFn) error

SignPolicyData signs raw policy data

func (*Signer) SignPolicyFile

func (ps *Signer) SignPolicyFile(path string, w io.Writer, funcs ...options.SignerOptFn) error

SignBundleToFile signs a policy file and writes it to a filename derived from the original.

type StorageBackend

type StorageBackend interface {
	StoreReference(api.RemoteReference) error
	StoreReferenceWithReturn(api.RemoteReference) (*api.PolicySet, *api.Policy, *api.PolicyGroup, error)
	GetReferencedPolicy(api.RemoteReference) (*api.Policy, error)
	GetReferencedGroup(api.RemoteReference) (*api.PolicyGroup, error)
}

Storage backend is an interface that fronts systems that store and index policies

Directories

Path Synopsis
api
v1

Jump to

Keyboard shortcuts

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