Skip to content

Latest commit

 

History

History
364 lines (320 loc) · 19 KB

File metadata and controls

364 lines (320 loc) · 19 KB

CLI Configuration File (AICRConfig)

AICRConfig is a Kubernetes-style YAML/JSON document that captures the inputs to the five workflow commands — aicr snapshot, aicr recipe, aicr bundle, aicr validate, and aicr verify — so an end-to-end run version-controls as a single file instead of a shell script full of flags. Each command accepts it through the same --config flag:

aicr snapshot --config aicr-config.yaml
aicr recipe   --config aicr-config.yaml
aicr bundle   --config aicr-config.yaml
aicr validate --config aicr-config.yaml
aicr verify   ./my-bundle --config aicr-config.yaml   # bundle dir is positional

The first four are the producer pipeline; spec.verify is the consumer side, so one document can carry both how an artifact is built and the trust floor a downstream consumer enforces against it.

This page documents the complete document schema in one place. The CLI Reference shows per-command usage in its Snapshot, Recipe, Validate, Bundle, and Verify config-file-mode sections. The schema's source of truth is pkg/config.

Document Envelope

kind: AICRConfig               # required, exactly this value
apiVersion: aicr.run/v1alpha2  # required; v1beta1 also accepted, see below
metadata:
  name: gke-h100-training      # optional, identifying only
spec:
  snapshot: {}                 # each section optional —
  recipe: {}                   # at least ONE must be present
  bundle: {}
  validate: {}
  verify: {}

Each spec.* section is optional and each command reads only its own section, so a file may carry just one section or any combination. A document with none of the five sections is rejected.

AICRConfig is an authored file, so its apiVersion is yours to set. v0.21 writes and documents aicr.run/v1alpha2 and the loader also accepts the target aicr.run/v1beta1; empty and unknown values are rejected. v0.22 switches the documented value to the target and v0.23 stops accepting aicr.run/v1alpha2, so edit your config before upgrading to v0.23. The full release-by-release table is in Catalog and binary compatibility; the policy behind it is ADR-022.

Loading, Precedence, and Secrets

Sources. --config accepts a local file path or an HTTP/HTTPS URL (format detected from the extension; fetches are timeout- and size-bounded). ConfigMap cm:// URIs are intentionally rejected — extract the data with kubectl and pass the resulting file.

Precedence. A CLI flag always wins over the matching config field. For slice and map fields (tolerations, selectors, --set), a flag given on the command line replaces the file's value; it does not append.

Nil vs. empty. For agent selectors and tolerations, omitting the field entirely (nil) inherits the compiled-in defaults (tolerations defaults to tolerate all taints), while an explicit empty value ({} / []) clears the default. Several booleans are tri-state for the same reason: absent means "inherit the CLI default", an explicit false is an opt-out (spec.validate.execution.failOnError, failFast, spec.snapshot.execution.privileged, spec.recipe.criteriaStrict, spec.validate.evidence.*).

Secrets are never part of the schema. The cosign OIDC identity token used by attestation and evidence push is deliberately absent — supply it via the COSIGN_IDENTITY_TOKEN environment variable or the --identity-token flag.

Complete Example

kind: AICRConfig
apiVersion: aicr.run/v1alpha2
metadata:
  name: eks-h100-training
spec:
  snapshot:
    output:
      path: snapshot.yaml            # same shape as -o
      format: yaml                   # yaml | json | table
      template: ""                   # optional Go template path
    agent:                           # in-cluster snapshot Job pod
      namespace: aicr-validation
      image: ""                      # default: ghcr.io/nvidia/aicr:latest
      imagePullSecrets: []
      jobName: aicr
      serviceAccountName: aicr
      nodeSelector:
        nodeGroup: gpu-worker
      tolerations:
        - dedicated=gpu-workload:NoSchedule
      requireGpu: false
      runtimeClassName: ""           # mutually exclusive with requireGpu
      os: ""                         # ubuntu | rhel | cos | amazonlinux | ol | talos
      requests: ""                   # "cpu=500m,memory=1Gi"
      limits: ""
    execution:
      timeout: 5m
      noCleanup: false
      privileged: true               # false for PSS-restricted namespaces
      maxNodesPerEntry: 0            # 0 = unlimited topology entries

  recipe:
    criteria:                        # mutually exclusive with input.snapshot
      service: eks
      accelerator: h100
      intent: training
      os: ubuntu
      platform: kubeflow
      nodes: 2
    profile: ""                      # optional name=value; empty uses the declared default
    # configuration:                 # typed desired-state inputs (not matched on)
    #   slurm:                       # only valid when the resolved recipe platform is slurm
    #     accounting:
    #       mode: disabled           # disabled | customer-managed | aicr-provided
    # input:
    #   snapshot: snapshot.yaml      # derive criteria from a snapshot instead
    output:
      path: recipe.yaml
      format: yaml                   # yaml | json | table
    data: ""                         # optional data-overlay dir/archive
    criteriaStrict: false            # reject criteria outside the embedded catalog

  bundle:
    input:
      recipe: recipe.yaml            # must match recipe.output.path when both set
    output:
      target: ./bundles              # local dir or oci:// URI
      imageRefs: ""                  # external digest file; OCI output only
    deployment:
      deployer: helmfile             # helm | helmfile | argocd | argocd-helm | flux | ...
      repo: ""
      set: []                        # value overrides, "key:path=value"
      dynamic: []
      vendorCharts: false
      appName: ""                    # argocd parent Application name override
    scheduling:
      systemNodeSelector: {}
      systemNodeTolerations: []
      acceleratedNodeSelector:
        nodeGroup: gpu-worker
      acceleratedNodeTolerations:
        - nvidia.com/gpu=present:NoSchedule
      draEvictionNodeLabel: nvidia.com/dra-kubelet-plugin=true
      workloadGate: ""
      workloadSelector: {}
      nodes: 2
      storageClass: ""
      sharedStorageClass: ""          # RWX class for opt-in shared filesystems
    attestation:
      enabled: false
      certificateIdentityRegexp: ""
      oidcDeviceFlow: false
      fulcioURL: ""                  # private Sigstore overrides; empty = public good
      rekorURL: ""
      signingKey: ""                 # KMS key ref (awskms:// | gcpkms:// | ...); empty = keyless OIDC
    registry:                        # OCI transport for oci:// push
      insecureTLS: false
      plainHTTP: false

  validate:
    input:
      recipe: recipe.yaml
      snapshot: snapshot.yaml
    agent:                           # same nil-vs-empty semantics as snapshot.agent
      namespace: aicr-validation
      image: ""
      imagePullSecrets: []
      jobName: aicr
      serviceAccountName: aicr
      nodeSelector:
        nodeGroup: gpu-worker
      tolerations:
        - nvidia.com/gpu=present:NoSchedule
      requireGpu: false
    execution:
      phases: [deployment, conformance, performance]
      failOnError: true              # tri-state; absent = CLI default (true)
      failFast: false
      noCluster: false
      noCleanup: false
      timeout: 40m
    evidence:
      cncf:                          # CNCF AI Conformance markdown
        dir: ./evidence
        cncfSubmission: false        # requires dir
        features: []                 # empty = all features
      attestation:                   # recipe-evidence bundle (ADR-007)
        out: evidence-result.json    # setting this enables the path
        bom: ""
        push: ""                     # OCI ref to push the signed bundle
        plainHTTP: false
        insecureTLS: false
  verify:                            # consumer side: policy for `aicr verify`
    policy:                          # assertions checked after verification
      minTrustLevel: verified        # unknown | unverified | attested | verified | max
      requireCreator: ci@myorg.example.com
      cliVersionConstraint: ">= 0.16.0"
    trust:                           # material verification runs against
      certificateIdentityRegexp: ""  # when set, must BEGIN with https://github.com/NVIDIA/aicr/
      key: ""                        # KMS URI or local PEM public-key path
      trustRoot: ""                  # private Sigstore trusted_root.json

Field Reference

spec.snapshot

Inputs to aicr snapshot. There is no input section — the snapshot is produced from the live cluster.

Field Type Notes
output.path string Output file path (same as -o)
output.format string yaml | json | table
output.template string Optional Go template path
agent.* object In-cluster capture Job pod: namespace, image, imagePullSecrets, jobName, serviceAccountName, nodeSelector, tolerations, requireGpu, runtimeClassName (mutually exclusive with requireGpu), os, requests, limits. Mirrors spec.validate.agent so one file pins matching placement for both
execution.timeout duration string e.g. 5m
execution.noCleanup bool Keep the capture Job after completion
execution.privileged bool (tri-state) Set false for PSS-restricted namespaces
execution.maxNodesPerEntry int 0 = unlimited topology entries

spec.recipe

Inputs to aicr recipe. criteria and input.snapshot are mutually exclusive — query by criteria or derive from a snapshot, not both.

Field Type Notes
criteria.service / .accelerator / .intent / .os / .platform string Same names and values as the CLI flags
criteria.nodes int Target GPU node count
profile string Optional configuration profile selection in name=value form. Empty applies the resolved declaration's default.
configuration.slurm.accounting.mode string Slurm accounting ownership: disabled (default) | customer-managed | aicr-provided; mirrors --slurm-accounting-mode. Only valid when the resolved recipe platform is slurm (whether from criteria.platform, a snapshot, or --platform) — an explicit mode (even disabled) on any other platform is rejected with INVALID_REQUEST
input.snapshot string Snapshot path to derive the recipe from
output.path string Recipe output path
output.format string yaml | json | table
data string Data-overlay directory/archive (same as --data)
criteriaStrict bool (tri-state) Reject criteria values outside the embedded catalog; mirrors --criteria-strict / AICR_CRITERIA_STRICT (any of the three enables it)

spec.bundle

Inputs to aicr bundle.

Field Type Notes
input.recipe string Recipe to bundle
output.target string Local directory or oci:// URI
output.imageRefs string Optional external image-reference output file for an OCI output.target only. Local output is rejected. Its parent must be an existing real directory, and the target must be outside and not aliased to the planned or completed bundle.
deployment.deployer string Deployer choice (same values as --deployer)
deployment.repo string GitOps repo for repo-shaped deployers
deployment.set / .dynamic []string Value overrides, key:path=value
deployment.vendorCharts bool Vendor charts into the bundle
deployment.appName string Argo CD parent Application name override (multi-bundle installs sharing a namespace)
scheduling.* object systemNodeSelector/Tolerations, acceleratedNodeSelector/Tolerations, draEvictionNodeLabel, workloadGate, workloadSelector, nodes, storageClass, sharedStorageClass. Selectors are YAML maps; tolerations use the CLI's key=value:effect strings. draEvictionNodeLabel accepts one key=value label and defaults to nvidia.com/dra-kubelet-plugin=true; AICR applies it only when DRA and GPU Operator are both enabled.
attestation.enabled bool Enable bundle attestation (signing); keyless OIDC by default, KMS-backed when signingKey is set
attestation.certificateIdentityRegexp string Expected signer identity
attestation.oidcDeviceFlow bool Device-code flow for headless signing
attestation.fulcioURL / .rekorURL string Private Sigstore endpoints; empty = public-good defaults
attestation.signingKey string KMS key reference for key-based signing (awskms:// | gcpkms:// | azurekms:// | hashivault://); empty = keyless OIDC. Mutually exclusive with the keyless-only inputs (oidcDeviceFlow, fulcioURL, --identity-token)
registry.insecureTLS / .plainHTTP bool OCI transport options for push

When output.imageRefs is set, AICR writes the published OCI digest through a mode-0600 temporary file and an anchored same-directory rename. The target may be absent or an existing retained regular file; directories, symlinks, other non-regular files, and bundle aliases are rejected. The final validation and rename are ordered but are not one atomic identity-conditioned filesystem operation, so no other process should mutate the target directory while the bundle command runs.

spec.validate

Inputs to aicr validate.

Field Type Notes
input.recipe / .snapshot string Recipe + snapshot to validate
agent.* object In-cluster validation Job pod; same fields and nil-vs-empty semantics as spec.snapshot.agent (minus runtimeClassName/os/requests/limits)
execution.phases []string e.g. [deployment, conformance, performance]
execution.failOnError bool (tri-state) Absent = CLI default (true); explicit false opts out
execution.failFast bool (tri-state) Stop after the first failed phase
execution.noCluster bool Test mode: no cluster access, constraints evaluated inline
execution.noCleanup bool Keep validation Jobs after completion
execution.timeout duration string e.g. 40m
evidence.cncf.dir string CNCF AI Conformance evidence directory (--evidence-dir)
evidence.cncf.cncfSubmission bool (tri-state) Emit submission layout; requires dir
evidence.cncf.features []string Empty = all features; honored only with cncfSubmission
evidence.attestation.out string Recipe-evidence result path (v1 for unprofiled recipes, v2 for profiled ones) — setting it enables the attestation path
evidence.attestation.bom / .push string BOM input; OCI ref for the signed bundle push
evidence.attestation.plainHTTP / .insecureTLS bool (tri-state) Push transport options

spec.verify

Verification policy for aicr verify, the one consumer-side section. The two sub-sections mirror how the command consumes them: policy holds assertions checked after verification runs, trust holds the material it verifies against.

Field Type Notes
policy.minTrustLevel string unknown | unverified | attested | verified, or max (the CLI default) to auto-detect the highest level the bundle can reach
policy.requireCreator string Pins the OIDC identity in the bundle attestation's signing certificate
policy.cliVersionConstraint string Constrains the aicr version in the attestation predicate; supports >=, >, <=, <, ==, !=, and a bare version means >=
trust.certificateIdentityRegexp string Certificate identity pattern for binary attestation verification; must begin with https://github.com/NVIDIA/aicr/ (leading ^ allowed) and must not use top-level alternation, so it stays confined to the repository
trust.key string KMS key URI (awskms:// | gcpkms:// | azurekms:// | hashivault://) or local PEM public-key path; the verify counterpart to spec.bundle.attestation.signingKey
trust.trustRoot string Path to a private Sigstore trusted_root.json, additive to the built-in public-good root

policy.minTrustLevel sets operator policy, not an org-enforced guardrail. A committed value lowers the effective floor as readily as it raises it (unknown makes the trust check a no-op, since every level meets it), so treat it as a reviewable choice rather than a control that cannot be relaxed.

A lowered floor admits any bundle whose actual trust level reaches it, which is broader than unsigned bundles. It also covers chains that legitimately degraded: an attested bundle whose binary attestation is absent, or one carrying external --data, both report attested against a verified maximum, so the default max rejects them while a lowered floor does not.

What no policy value can wave through: checksum failures, and attestations that are present but fail verification. Those are rejected regardless of the floor.

aicr verify logs the floor at INFO when config is what supplies it: that is, when --min-trust-level is absent and the configured value is anything other than max. An explicit flag takes precedence instead, and that override is logged separately by the flag-precedence path.

Every field is a durable, non-secret reference or policy value; no private key material is part of the schema. Three aicr verify flags are deliberately excluded: the bundle directory (a positional argument), --format (presentation, not policy), and --insecure-ignore-tlog, which weakens the trust floor and so stays command-line-only rather than something a committed file can silently enable. It still composes with a config-supplied trust.key.

Cross-Section Rules

  • At least one of the five spec.* sections must be present.
  • spec.recipe.criteria and spec.recipe.input.snapshot are mutually exclusive.
  • When both spec.recipe.output.path and spec.bundle.input.recipe are set, they must reference the same file (compared after filepath.Clean; mixing absolute and relative forms is rejected). Mismatched paths in a workflow file are almost always a typo, so the loader fails up-front.
  • Enum-valued fields (criteria.*, output formats, phases) are validated with the same parsers the CLI flags use, so error messages match the CLI's.

See Also

  • CLI Reference — per-command flags and config-file-mode examples
  • Validation — validation phases and evidence workflow
  • Bundling — deployers and bundle outputs