Add Geo replication support for SupplyChain::Attestation

What does this MR do and why?

This MR implements Geo replication and verification support for Supply Chain Attestations—signed text files which represent build provenance, SBOM, etc. These are generated in the Rails backend, typically triggered by a pipeline.

What this MR does:

  1. Adds Geo replication infrastructure for SupplyChain::Attestation:
    • Creates Geo::PackagesNugetSymbolRegistry to track replication state
    • Creates Geo::PackagesNugetSymbolState to track verification state
    • Implements Geo::PackagesNugetSymbolReplicator using the blob replication strategy
  2. Enables verification of attestations:
    • Adds checksum calculation and verification for symbol files
    • Tracks verification state (pending, succeeded, failed)
    • Supports both local and object storage locations
  3. Supports selective sync:
    • Symbols can be selectively synced by namespace (group/project)
    • Symbols can be selectively synced by storage shard
    • Respects object storage sync settings
  4. Feature flags for safe rollout:
    • geo_supply_chain_attestation_replication - Controls replication functionality
    • geo_supply_chain_attestation_checksumming - Controls verification on primary

How to set up and validate locally

Prerequisites

  1. Set up a local Geo environment with a primary and secondary node. Follow the Geo development setup guide.

Testing Replication

On the Primary Node:

  1. Enable the feature flags in Rails console:

    Feature.enable(:geo_supply_chain_attestation_replication)
    Feature.enable(:geo_supply_chain_attestation_force_primary_checksumming)
  2. Create an attestation file:

    attestation = SupplyChain::Attestation.new(
      project: Project.find(1),
      build: Ci::Build.where(project_id: 1).take,
      predicate_kind: :provenance,
      predicate_type: "https://slsa.dev/provenance/v1",
      subject_digest: "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
      file: File.open("/path/to/file.txt")
    )
    attestation.save!
  3. Verify the symbol was created and verification started:

    attestation.reload
    attestation.supply_chain_attestation_state
    # Should show verification_state as 'pending' or 'verification_succeeded'

On the Secondary Node:

  1. Check that the registry entry was created:

    Geo::SupplyChainAttestationRegistry.count
    # Should be > 0
    
    registry = Geo::SupplyChainAttestationRegistry.last
    registry.supply_chain_attestation_id
    # Should match the symbol ID from primary
  2. Trigger replication:

    Geo::SupplyChainAttestationReplicator.new(model_record_id: attestation.id).execute
  3. Verify the attestation file was replicated:

    registry.reload
    registry.state
    # Should be 'synced'
    
    registry.verification_state
    # Should be 'verification_succeeded'

Related to #571772

Edited by Aaron Huntsman

Merge request reports

Loading