Skip to content

complytime/complypack

Repository files navigation

ComplyPack

CI Go Reference Go Report Card

ComplyPack is a Go library for packing, unpacking, signing, and verifying OCI artifacts containing policy bundles. It provides an evaluator-agnostic format for distributing compliance policies using OCI registries.

Features

  • OCI Artifact Packaging - Pack policy content into OCI Image Manifest v1.1 artifacts
  • Evaluator-Agnostic - Supports any policy language (OPA, CEL, etc.) via evaluator-id dispatch
  • Signing & Verification - Built-in support for keyed and keyless (Sigstore) signing
  • Memory-Safe - 100MB content size limit prevents memory exhaustion attacks
  • Provenance Tracking - Optional Gemara linkage for generated policies
  • Flexible API - Functional options pattern for clean, extensible configuration

Installation

go get github.com/complytime/complypack

Quick Start

Packing a Policy

package main

import (
    "context"
    "strings"

    "github.com/complytime/complypack/pkg/complypack"
    "oras.land/oras-go/v2/content/memory"
)

func main() {
    ctx := context.Background()
    store := memory.New()

    // Configure the artifact
    cfg := complypack.Config{
        EvaluatorID: "io.complytime.opa",
        Version:     "1.0.0",
    }

    // Pack the policy content
    content := strings.NewReader("policy content here")
    desc, err := complypack.Pack(ctx, store, cfg, content)
    if err != nil {
        panic(err)
    }

    // desc.Digest contains the artifact reference
}

Unpacking a Policy

result, err := complypack.Unpack(ctx, store, desc)
if err != nil {
    panic(err)
}
defer result.Content.Close()

// Access configuration
fmt.Printf("Evaluator: %s\n", result.Config.EvaluatorID)

// Read content
content, _ := io.ReadAll(result.Content)

With Signing

// Pack with keyed signing
desc, err := complypack.Pack(ctx, store, cfg, content,
    complypack.WithSigning("/path/to/private.key"))

// Pack with keyless signing (OIDC)
desc, err := complypack.Pack(ctx, store, cfg, content,
    complypack.WithKeylessSigning("user@example.com", "https://accounts.google.com"))

// Unpack with verification
result, err := complypack.Unpack(ctx, store, desc,
    complypack.WithVerification("/path/to/public.key"))

With Provenance

cfg := complypack.Config{
    EvaluatorID: "io.complytime.opa",
    Version:     "1.0.0",
    Source: &complypack.Provenance{
        GemaraContent: "oci://registry/gemara/controls:v1.0.0",
        PolicyID:      "policy-123",
    },
}

Architecture

ComplyPack uses OCI Image Manifest v1.1 with the following structure:

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "artifactType": "application/vnd.complypack.artifact.v1",
  "config": {
    "mediaType": "application/vnd.complypack.config.v1+json",
    "digest": "sha256:...",
    "size": 324
  },
  "layers": [
    {
      "mediaType": "application/vnd.complypack.content.v1.tar+gzip",
      "digest": "sha256:...",
      "size": 1024000
    }
  ]
}

Media Types

Purpose Media Type
Artifact Type application/vnd.complypack.artifact.v1
Config Layer application/vnd.complypack.config.v1+json
Content Layer application/vnd.complypack.content.v1.tar+gzip

Content Layer

The content layer is opaque - the library treats it as raw bytes. For OPA-based policies, this would typically be an OPA bundle tarball. The evaluator-id in the config determines how consumers should interpret the content.

Memory Usage

Pack() loads the entire content into memory for digest calculation. Content size is limited to 100MB to prevent memory exhaustion. For larger artifacts, consider alternative approaches or splitting content.

Error Handling

ComplyPack uses sentinel errors for predictable error checking:

import "errors"

_, err := complypack.Pack(ctx, store, cfg, content)
if errors.Is(err, complypack.ErrEmptyContent) {
    // Handle empty content
}
if errors.Is(err, complypack.ErrContentTooLarge) {
    // Handle content exceeding 100MB limit
}

Available sentinel errors:

  • ErrInvalidConfig - Config validation failed
  • ErrEmptyContent - Content reader returned zero bytes
  • ErrContentTooLarge - Content exceeds 100MB limit
  • ErrSigningFailed - Signing operation failed
  • ErrVerificationFailed - Signature verification failed
  • ErrInvalidMediaType - Unexpected media type in manifest
  • ErrNoContentLayer - Manifest missing content layer

Storage Backends

ComplyPack works with any ORAS-compatible storage backend:

// In-memory (for testing)
store := memory.New()

// Filesystem
store, err := file.New("/tmp/oci-store")
defer store.Close()

// Remote registry (via ORAS)
repo, err := remote.NewRepository("ghcr.io/org/repo")
store := repo

Current Limitations

  • Signing/Verification: Validation logic is implemented, but full sigstore-go integration is pending. Signing/verification options will return "not yet implemented" errors.
  • Content Size: Maximum 100MB per artifact
  • Single Content Layer: Only one content layer per artifact is supported

Contributing

Contributions are welcome! Please see our contributing guidelines.

License

Apache License 2.0 - see LICENSE for details.

Related Projects

About

Assessment logic packaging for complyctl

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors