Files
git.stella-ops.org/docs/operations/rekor-policy.md

6.2 KiB

Rekor Transparency Log Budget Policy

Last Updated: 2025-12-20 Owner: Attestor Team Sprint: SPRINT_3500_0003_0003


Overview

This document defines the budget policy for Rekor transparency log submissions. The policy balances transparency requirements with rate limits and cost considerations.


Submission Tiers

Tier 1: Graph-Level Attestations (Default)

Scope: One DSSE envelope per scan containing the call graph digest.

Frequency:

  • Submitted automatically for every completed scan
  • Includes: CallGraphSnapshot.GraphDigest, scan metadata, scanner version

Payload Size: ~2-5 KB per submission

Rate Budget:

  • Default: 100 submissions/hour per tenant
  • Burst: 200 submissions/hour (10-minute window)

Configuration:

attestor:
  rekor:
    enabled: true
    tier: graph-only
    budget:
      hourlyLimit: 100
      burstLimit: 200
      burstWindow: "00:10:00"

Tier 2: Edge Bundle Attestations (On Escalation)

Scope: Detailed edge bundles submitted for escalated findings.

Triggers:

  • CVE with CVSS >= 9.0 and reachable status
  • Security team escalation request
  • Policy engine gate failure with require_proof: true

Frequency:

  • Only on explicit escalation
  • Subject to daily budget cap

Payload Size: ~10-50 KB per bundle (varies with graph size)

Rate Budget:

  • Default: 50 bundles/day per tenant
  • No burst allowance

Configuration:

attestor:
  rekor:
    edgeBundles:
      enabled: true
      dailyLimit: 50
      triggers:
        - cvssThreshold: 9.0
        - policyGate: require_proof
        - manualEscalation: true

Budget Enforcement

Rate Limiting

The Attestor module enforces rate limits via the RekorSubmissionQueue:

  1. Admission: Requests exceeding budget are queued with backpressure
  2. Retry: Failed submissions retry with exponential backoff
  3. Overflow: Excess requests are stored locally for later submission

Quota Tracking

Quotas are tracked per tenant in attestor.rekor_quotas:

CREATE TABLE attestor.rekor_quotas (
    tenant_id UUID PRIMARY KEY,
    hourly_count INT NOT NULL DEFAULT 0,
    daily_bundle_count INT NOT NULL DEFAULT 0,
    last_reset_hour TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    last_reset_day DATE NOT NULL DEFAULT CURRENT_DATE
);

Alerts

Metric Threshold Action
attestor_rekor_queue_depth > 1000 Page on-call
attestor_rekor_submissions_rejected > 100/hour Investigate quota abuse
attestor_rekor_budget_utilization > 80% Notify tenant admin

Air-Gap Considerations

In air-gapped deployments, Rekor submissions are:

  1. Queued Locally: Stored in attestor.rekor_offline_queue
  2. Bundled on Export: Included in offline kit as pending attestations
  3. Submitted on Connect: When connectivity restored, queue drains

Offline Queue Schema

CREATE TABLE attestor.rekor_offline_queue (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    tier TEXT NOT NULL CHECK (tier IN ('graph', 'edge')),
    payload BYTEA NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    priority INT NOT NULL DEFAULT 0
);

Monitoring

Key Metrics

Metric Description Labels
attestor_rekor_submissions_total Total Rekor submissions tier, status
attestor_rekor_submission_latency_seconds Submission latency histogram tier
attestor_rekor_queue_depth Current queue depth tier
attestor_rekor_budget_remaining Remaining hourly budget tenant

Grafana Dashboard

Import dashboard ID: stellaops-attestor-rekor from the StellaOps dashboard gallery.


Troubleshooting

Common Issues

Q: Submissions are being rejected with 429

  • Check attestor_rekor_budget_remaining metric
  • Review tenant's hourly submission rate
  • Consider increasing budget if legitimate spike

Q: Offline queue growing unbounded

  • Verify network connectivity to Rekor
  • Check attestor_rekor_submission_errors for root cause
  • Consider manual drain if transient issue resolved

Q: Edge bundles not being submitted

  • Verify escalation triggers are configured
  • Check policy engine gate configuration
  • Review attestor_rekor_edge_bundle_triggers logs

Configuration Reference

Full Configuration Schema

attestor:
  rekor:
    # Enable Rekor integration
    enabled: true

    # Rekor server URL (default: public Sigstore Rekor)
    serverUrl: "https://rekor.sigstore.dev"

    # Log version: Auto, V1, or V2 (V2 uses tile-based Sunlight format)
    version: Auto

    # Log ID for multi-log environments (hex-encoded SHA-256)
    logId: "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"

    # Tile base URL for V2 (optional, defaults to {serverUrl}/tile/)
    tileBaseUrl: ""

    # Prefer tile proofs when version is Auto
    preferTileProofs: false

    # Submission tier: graph-only | with-edges
    tier: graph-only

    # Budget configuration
    budget:
      # Hourly limit for graph attestations
      hourlyLimit: 100

      # Burst allowance
      burstLimit: 200
      burstWindow: "00:10:00"

      # Daily limit for edge bundles
      edgeBundleDailyLimit: 50

    # Retry configuration
    retry:
      maxAttempts: 3
      initialDelay: "00:00:05"
      maxDelay: "00:05:00"
      backoffMultiplier: 2.0

    # Offline mode
    offline:
      queueEnabled: true
      maxQueueSize: 10000
      drainOnConnect: true

    # Edge bundle triggers
    edgeBundles:
      enabled: true
      triggers:
        - cvssThreshold: 9.0
        - policyGate: require_proof
        - manualEscalation: true