bom

package
v0.18.0-rc1 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package bom builds CycloneDX 1.6 software bills-of-materials describing the container images AICR can deploy.

It exposes the reusable pieces of the BOM pipeline:

  • ExtractImagesFromYAML walks rendered Helm output (or any K8s manifest bundle) and returns the unique sorted set of `image:` scalar values.
  • ParseImageRef splits a container image string into registry, repository, tag, and digest components.
  • BuildBOM assembles a CycloneDX 1.6 document from per-component image surveys, modeling AICR as the root component, each AICR component (gpu-operator, network-operator, ...) as an `application`, and each unique image as a `container`. The dependency graph wires AICR to its components and each component to its images.
  • WriteMarkdown emits a stable human-readable summary suitable for docs.

Two callers are anticipated:

  • tools/bom — the repo-wide image inventory tool driven by recipes/registry.yaml.
  • pkg/bundler (planned) — per-bundle SBOM emitted alongside the Helm install scripts produced by `aicr bundle`.

Index

Constants

View Source
const (
	TypeHelm      = "helm"
	TypeKustomize = "kustomize"
	TypeManifest  = "manifest"
)

ComponentResult.Type identifiers, shared so producers (tools/bom, the attestation builder) and this renderer cannot drift on the string values. Type is compared case-insensitively at render time because the attestation builder supplies the recipe ComponentType enum ("Kustomize") while the standalone generator supplies the lowercase kind ("kustomize").

View Source
const RenderFidelityCatalogParity = "catalog-parity: charts are rendered with the shared " +
	"recipes/components/<name>/values.yaml; per-recipe overlay overrides are not applied"

RenderFidelityCatalogParity documents the uniform rendering limitation of every entry in the catalog BOM (tools/bom) — default and variant alike: charts are templated with the shared per-component values file only. It is caller-supplied via Metadata.RenderFidelity because other BOM producers have a different fidelity story and must not carry a false claim. See issue #1611.

Variables

This section is empty.

Functions

func BuildBOM

func BuildBOM(meta Metadata, results []ComponentResult) *cdx.BOM

BuildBOM constructs a CycloneDX 1.6 BOM from a sorted list of component surveys. The graph is:

metadata.component (Metadata.Name)
  └─ each ComponentResult as an `application` (bom-ref: "<name>/<comp>")
       └─ each unique image as a `container` (bom-ref: "img:<ref>")

Image entries are de-duplicated across components. For a BOM that also carries per-source version variants — with fail-closed bom-ref uniqueness — use BuildBOMWithVariants; this legacy entry point is preserved unchanged for existing importers.

func BuildBOMWithVariants added in v0.17.0

func BuildBOMWithVariants(meta Metadata, results []ComponentResult, variants []VariantResult) (*cdx.BOM, error)

BuildBOMWithVariants is the variant-aware companion to BuildBOM: default component entries are byte-identical to BuildBOM's, variant entries carry version-qualified bom-refs ("<meta.Name>/<comp>@<ver>") with sorted aicr:variant:sources, and — unlike the legacy entry point — every bom-ref claims through a global identity set, so duplicates fail closed with ErrCodeInvalidRequest instead of producing an ambiguous dependency graph.

func ExtractImagesFromYAML

func ExtractImagesFromYAML(data []byte) ([]string, error)

ExtractImagesFromYAML walks every YAML document in data and returns the sorted, de-duplicated set of `image:` scalar values. It skips empty values, `null`, and any value still containing an unrendered Go template directive.

Helm template directives ({{ ... }}) are replaced with a placeholder before parsing, so files mixing YAML with Helm templates (those under recipes/components/*/manifests/ that are processed as chart templates) can still be surveyed for static `image:` values.

func WriteMarkdown

func WriteMarkdown(w io.Writer, meta Metadata, results []ComponentResult) error

WriteMarkdown emits a human-readable summary of a component-level BOM suitable for embedding in docs.

func WriteMarkdownWithVariants added in v0.17.0

func WriteMarkdownWithVariants(w io.Writer, meta Metadata, results []ComponentResult, variants []VariantResult) error

WriteMarkdownWithVariants is the variant-aware companion to WriteMarkdown: variants render as a separate "Version variants" table (distinct column headers, so the Components table and its freshness gate stay intact) plus per-variant image sections; the section is omitted entirely when no variants exist. The legacy WriteMarkdown output is unchanged.

Types

type ComponentResult

type ComponentResult struct {
	Name        string   // component identifier, e.g., "gpu-operator"
	DisplayName string   // human-readable name
	Type        string   // "helm", "kustomize", or "manifest"
	Repository  string   // chart repository URL (helm only)
	Chart       string   // chart name (helm only)
	Version     string   // chart version if pinned
	Namespace   string   // default namespace
	Pinned      bool     // whether the chart version is pinned in the recipe
	Images      []string // sorted, deduplicated image references
	Warnings    []string // non-fatal issues to attach as properties
}

ComponentResult is the per-component image survey input to BuildBOM. It carries the metadata needed to render a CycloneDX `application` component plus the list of image references it deploys.

type ImageRef

type ImageRef struct {
	Raw        string // original string
	Registry   string // host[:port], e.g., "nvcr.io" or "docker.io"
	Repository string // path after registry, e.g., "nvidia/gpu-operator"
	Tag        string // ":tag" portion if present
	Digest     string // "@sha256:..." portion if present
}

ImageRef is a parsed container image reference.

func ParseImageRef

func ParseImageRef(s string) ImageRef

ParseImageRef splits a container image reference into its parts using the standard Docker rules: a leading segment is treated as the registry when it contains a "." or ":" or equals "localhost"; otherwise the registry defaults to "docker.io".

func (ImageRef) PURL

func (r ImageRef) PURL() string

PURL returns the Package URL for the image reference using the OCI type.

Per the purl-spec OCI definition (https://github.com/package-url/purl-spec/blob/main/types-doc/oci-definition.md), the canonical form is:

pkg:oci/<name>@<digest>?repository_url=<registry>/<namespace>/<name>&tag=<tag>

where <name> is the last path segment of the image repository, the repository_url is the FULL artifact path (including the name), and the digest is the canonical version. Tags are mutable and live in qualifiers.

When a digest is not available (the common case for our reference BOM today, since most chart defaults pin only by tag), this function falls back to using the tag in the @<version> position. That deviates from strict spec conformance but preserves the version information consumers need. As soon as we adopt digest pinning end-to-end, the output becomes fully spec-conformant with no callsite changes.

type Metadata

type Metadata struct {
	Name        string // e.g., "aicr" or "recipe-h100-eks-ubuntu-training"
	Version     string // e.g., "v0.12.1" or recipe version
	Description string
	Supplier    string // organization name; defaults to "NVIDIA Corporation"
	ToolName    string // tool that generated the BOM; defaults to "aicr"
	ToolVersion string // version of the generating tool

	// Deterministic suppresses run-specific metadata so the artifact can
	// be diffed across runs. Affects both WriteMarkdown (the "_Generated
	// <timestamp>..._" line is omitted) and BuildBOM (a deterministic
	// SerialNumber is derived from Name+Version and Timestamp is omitted).
	// Use for committed doc artifacts, SLSA-style reproducible builds,
	// and any other bit-for-bit reproducible output path.
	Deterministic bool

	// SerialNumber, if non-empty, overrides the BOM serial number. When
	// empty and Deterministic is false, BuildBOM generates a random UUID.
	// When empty and Deterministic is true, BuildBOM derives a serial
	// from Name+Version. Use to inject a caller-supplied identifier
	// (e.g., commit SHA) without forcing the Deterministic mode.
	SerialNumber string

	// Timestamp, if non-empty, overrides the BOM metadata timestamp
	// (RFC3339). When empty and Deterministic is false, BuildBOM uses
	// time.Now().UTC(). When empty and Deterministic is true, the
	// timestamp is omitted entirely.
	Timestamp string

	// NoTitle suppresses the H1 title line in WriteMarkdown so the body
	// can be embedded as a section of a larger document (e.g., the
	// auto-generated middle of docs/user/container-images.md, where the
	// title and surrounding prose are hand-edited).
	NoTitle bool

	// RenderFidelity, when non-empty, is stated in the Markdown header and
	// attached to the CycloneDX metadata as an aicr:render:fidelity
	// property. Producers set it to describe HOW image sets were obtained
	// (tools/bom sets RenderFidelityCatalogParity); producers with a
	// different story leave it empty rather than stamp a false claim.
	RenderFidelity string
}

Metadata identifies the artifact the BOM describes (e.g., the AICR repo itself, or a specific recipe bundle).

type VariantResult added in v0.17.0

type VariantResult struct {
	Name       string   // component identifier, e.g., "kube-prometheus-stack"
	Version    string   // the divergent pinned chart version
	Sources    []string // sorted base/overlay/mixin metadata.names declaring the pin
	Repository string   // chart repository URL (registry coordinates)
	Chart      string   // chart name (registry coordinates)
	Namespace  string   // default namespace
	Images     []string // sorted, deduplicated image references at this version
	Warnings   []string // non-fatal issues to attach as properties
}

VariantResult is a per-source version variant of a registry component: an explicit base/overlay/mixin Helm componentRef.version pin that differs from the component's registry defaultVersion. Variants are derived from recipe data (the declared pins themselves), aggregated by (Name, Version), and rendered at catalog parity with the REGISTRY chart coordinates. See issue #1611 — coordinate or type divergence and effective-inheritance resolution are explicit non-goals of the variants model.

Jump to

Keyboard shortcuts

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