Open Component Model in Production: Building Software Bills of Delivery for Cloud-Native Supply Chains
The software supply chain has become a critical attack vector, with incidents like SolarWinds and Log4Shell exposing how vulnerable our interconnected systems really are. Traditional Software Bills of Materials (SBOMs) tell us what components exist, but they don’t capture the full picture of how software actually gets delivered and deployed. Enter the Open Component Model (OCM) – an open standard that goes beyond simple dependency tracking to create comprehensive Software Bills of Delivery (SBOD) for cloud-native environments.
Unlike SBOMs that focus on what’s in your code, OCM describes the complete delivery pipeline – from source repositories to runtime configurations. This matters because modern applications aren’t just code; they’re complex assemblies of container images, Helm charts, configuration files, and deployment manifests spread across multiple repositories and registries.
Note: The OCM project recently launched a next-generation rewrite at open-component-model/open-component-model. The new CLI and Go library are actively developed and marked Work In Progress — expect the API to stabilize over the coming months. All examples in this post use the new CLI.
What Makes OCM Different from Traditional Supply Chain Tools
The Open Component Model specification defines a technology-agnostic format for describing software delivery artifacts. Where SBOMs answer “what libraries am I using?”, OCM answers “what exactly needs to be delivered for this software to run?”
This distinction is crucial in cloud-native environments where your application might consist of:
- Multiple microservices from different repositories
- Container images with specific tags and digests
- Kubernetes manifests with environment-specific configurations
- Helm charts with values files
- External dependencies like databases or message queues
Traditional tools struggle to connect these dots across repository boundaries. OCM creates a unified model that captures not just the artifacts, but their relationships and deployment context.
Core OCM Concepts for Production Implementation
Component Constructor Files
The heart of OCM is the component constructor – a YAML file that describes one or more deliverable software components. It serves as the input to the OCM CLI when creating component versions. Think of it as a shipping manifest listing everything needed to successfully deploy and run your software.
# component-constructor.yaml
components:
- name: github.com/my-org/my-web-app
version: 1.2.3
provider:
name: my-org
resources:
- name: app-image
type: ociImage
version: 1.2.3
access:
type: OCIImage/v1
imageReference: registry.example.com/my-web-app:1.2.3
- name: helm-chart
type: helmChart
version: 1.2.3
access:
type: Helm/v1
helmRepository: registry.example.com
helmChart: my-web-app
version: 1.2.3
sources:
- name: app-source
type: git
access:
type: File/v1alpha1
uri: https://github.com/my-org/my-web-app
Component names follow a DNS-like convention (e.g. github.com/my-org/my-app). The sources section maintains traceability back to source code, while resources describes the deliverable artifacts. You can reference remote artifacts via access or embed local content directly via input.
Resource Types and Access Methods
OCM supports multiple resource types:
ociImagefor container imageshelmChartfor Helm packagesblobfor arbitrary data
Access types define how to retrieve external resources:
OCIImage/v1— OCI-compliant registriesHelm/v1— Helm repositoriesLocalBlob/v1— content stored in the same OCM repositoryFile/v1alpha1— files referenced by URI
For local content, input types let you embed artifacts directly:
File/v1— embed a single fileDir/v1— embed a directory as a tar archiveHelm/v1— embed a local Helm chartUTF8/v1— embed inline text or structured data
This flexibility lets you model complex delivery scenarios where artifacts live in different systems.
Setting Up OCM in Multi-Repository Environments
Installation and Basic Configuration
Install the OCM CLI:
# Install via the official installer script
curl -sfL https://ocm.software/install-cli.sh | bash
# Or use the container image
docker run -t ghcr.io/open-component-model/cli:latest --help
# Verify installation
ocm version
For multi-repository setups, you’ll typically have one component per microservice plus an aggregate platform component. A practical repo structure:
my-platform/
├── services/
│ ├── user-service/
│ ├── payment-service/
│ └── notification-service/
├── charts/
│ └── platform-chart/
└── components/
└── component-constructor.yaml
Creating Component Versions for Microservices
Each microservice generates its own component version during CI/CD. The constructor file supports environment variable substitution via Go template syntax:
# component-constructor.yaml
components:
- name: ${COMPONENT_NAME}
version: ${COMPONENT_VERSION}
provider:
name: ${PROVIDER_NAME}
resources:
- name: app-image
type: ociImage
version: ${COMPONENT_VERSION}
access:
type: OCIImage/v1
imageReference: ${REGISTRY_URL}/${IMAGE_NAME}:${IMAGE_TAG}
sources:
- name: source
type: git
access:
type: File/v1alpha1
uri: https://github.com/${GITHUB_REPOSITORY}
Here’s how to wire this into a GitHub Actions workflow:
name: Build and Package Component
on:
push:
tags: ['v*']
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install OCM CLI
run: curl -sfL https://ocm.software/install-cli.sh | bash
- name: Build container image
run: |
docker build -t ghcr.io/${{ github.repository }}:${{ github.ref_name }} .
docker push ghcr.io/${{ github.repository }}:${{ github.ref_name }}
- name: Add component version to OCM repository
env:
COMPONENT_NAME: github.com/${{ github.repository }}
COMPONENT_VERSION: ${{ github.ref_name }}
PROVIDER_NAME: ${{ github.repository_owner }}
REGISTRY_URL: ghcr.io
IMAGE_NAME: ${{ github.repository }}
IMAGE_TAG: ${{ github.ref_name }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
ocm add component-version \
--repository ghcr.io/${{ github.repository_owner }}/ocm \
--constructor component-constructor.yaml
This ensures every service build produces a traceable component version capturing the exact artifacts and their sources.
Aggregating Components for Platform Delivery
For platform-level deployments, create aggregate components that reference individual service components:
# platform-component-constructor.yaml
components:
- name: github.com/my-org/my-platform
version: 2.1.0
provider:
name: my-org
componentReferences:
- name: user-service
componentName: github.com/my-org/user-service
version: 1.5.2
- name: payment-service
componentName: github.com/my-org/payment-service
version: 2.3.1
- name: notification-service
componentName: github.com/my-org/notification-service
version: 1.1.0
resources:
- name: platform-chart
type: helmChart
version: 2.1.0
access:
type: Helm/v1
helmRepository: ghcr.io/my-org/charts
helmChart: platform
version: 2.1.0
This creates a complete bill of delivery for your entire platform, with precise version tracking for each component.
Implementing Comprehensive Supply Chain Security
Signature Verification
OCM supports cryptographic signing of component versions, enabling end-to-end verification of your supply chain. Keys are configured via .ocmconfig rather than passed as flags:
# ~/.config/ocm/config or .ocmconfig in your project
type: generic.config.ocm.software/v1
configurations:
- type: credentials.config.ocm.software
consumers:
- identity:
type: RSA/v1alpha1
algorithm: RSASSA-PSS
signature: default
credentials:
- type: Credentials/v1
properties:
private_key_pem_file: /path/to/signing.key
public_key_pem_file: /path/to/signing.pub
With credentials configured:
# Sign a component version
ocm sign component-version \
ghcr.io/my-org/ocm//github.com/my-org/my-platform:2.1.0 \
--signature my-org-signature
# Verify signature before deployment
ocm verify component-version \
ghcr.io/my-org/ocm//github.com/my-org/my-platform:2.1.0
# Verify a specific named signature
ocm verify component-version \
ghcr.io/my-org/ocm//github.com/my-org/my-platform:2.1.0 \
--signature my-org-signature
Integrate signature verification into your deployment pipelines to ensure only signed components reach production.
Inspecting and Scanning Component Versions
OCM component versions provide the perfect input for comprehensive vulnerability scanning. Inspect a component version to extract its artifact references:
# Inspect a component version (YAML output)
ocm get component-version \
ghcr.io/my-org/ocm//github.com/my-org/my-platform:2.1.0 \
--output yaml
# Download a specific resource for scanning
ocm download resource \
ghcr.io/my-org/ocm//github.com/my-org/my-platform:2.1.0 \
--identity name=app-image \
--output ./app-image.tar
# Scan the downloaded image
trivy image --input ./app-image.tar
This approach ensures you’re scanning the exact artifacts that will be deployed, not just what’s in your source repositories.
Transferring Components Between Registries
OCM’s transfer capability is central to air-gapped or multi-environment deployments:
# Transfer from a local CTF archive to an OCI registry
ocm transfer component-version \
ctf::./transport-archive//github.com/my-org/my-platform:2.1.0 \
ghcr.io/production-registry/ocm \
--copy-resources
# Recursive transfer (includes all referenced component versions)
ocm transfer component-version \
ghcr.io/my-org/ocm//github.com/my-org/my-platform:2.1.0 \
ghcr.io/production-registry/ocm \
--recursive --copy-resources
Monitoring and Observability for OCM Components
Runtime Correlation
One of OCM’s most powerful features is the ability to correlate runtime behavior with specific component versions. Add OCM metadata to your Kubernetes deployments:
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
labels:
ocm.software/component: github.com/my-org/user-service
ocm.software/version: 1.5.2
ocm.software/platform-component: github.com/my-org/my-platform
ocm.software/platform-version: 2.1.0
spec:
template:
metadata:
labels:
ocm.software/component: github.com/my-org/user-service
ocm.software/version: 1.5.2
This enables powerful queries in your monitoring systems:
# Alert on errors for specific component versions
rate(http_requests_total{code=~"5.."}[5m]) > 0.1
and on(pod)
kube_pod_labels{label_ocm_software_component="github.com/my-org/user-service"}
Supply Chain Drift Detection
Monitor for unauthorized changes to your supply chain by comparing runtime state with OCM component versions:
#!/bin/bash
# drift-detection.sh
# Get expected images from OCM component version
expected_images=$(ocm get component-version \
ghcr.io/my-org/ocm//github.com/my-org/my-platform:2.1.0 \
--output json | jq -r '.resources[].access.imageReference // empty')
# Get actual running images
actual_images=$(kubectl get pods \
-o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n')
# Compare and alert on differences
diff <(echo "$expected_images" | sort) <(echo "$actual_images" | sort) || {
echo "ALERT: Supply chain drift detected!"
exit 1
}
Run this check regularly to catch unauthorized deployments or configuration drift.
Best Practices for Production OCM Implementation
Component Naming and Versioning Strategy
OCM component names follow a DNS-like convention — use your GitHub organization path (e.g. github.com/my-org/my-service) to ensure global uniqueness. For versioning, align with SemVer:
- Patch versions (1.2.1 → 1.2.2): Bug fixes, security patches
- Minor versions (1.2.0 → 1.3.0): New features, backward-compatible changes
- Major versions (1.0.0 → 2.0.0): Breaking changes, architecture updates
Include build metadata as resource labels in your constructor:
resources:
- name: app-image
type: ociImage
version: ${COMPONENT_VERSION}
labels:
- name: build.commit
value: ${GITHUB_SHA}
- name: build.timestamp
value: ${BUILD_TIMESTAMP}
- name: build.pipeline
value: github-actions
access:
type: OCIImage/v1
imageReference: ${REGISTRY_URL}/${IMAGE_NAME}:${IMAGE_TAG}
Repository Organization
Structure your repositories to support OCM workflows:
organization/
├── services/
│ ├── user-service/ # Individual service repos
│ ├── payment-service/
│ └── notification-service/
├── platform/
│ ├── charts/ # Shared Helm charts
│ ├── configs/ # Environment configs
│ └── components/ # Platform component constructors
└── infrastructure/
├── terraform/ # Infrastructure as code
└── policies/ # Security and compliance policies
Automation and Integration
Automate component version creation in your CI/CD pipelines. Never manually create component constructors that reference artifacts you haven’t built — generate them from your build process to ensure accuracy. Use environment variable substitution in constructor files rather than hardcoding versions.
For GitOps workflows, store your aggregate platform constructor in Git and trigger OCM transfers on version bumps. Combined with the OCM Kubernetes controller, you can drive deployments directly from component versions in an OCI registry.
Looking Forward: OCM in the Cloud-Native Ecosystem
The Open Component Model represents a significant step forward in supply chain security and observability. The new-generation implementation at open-component-model/open-component-model is an active rewrite that brings a cleaner library API, a redesigned CLI, and a Kubernetes controller for GitOps-style deployments. It’s backed by SAP and the broader CNCF community.
Key areas of active development include deeper integration with policy engines like Open Policy Agent, enhanced multi-cloud transfer scenarios, and language bindings beyond Go. The project acknowledges the WIP status openly — the CLI command surface and library API will stabilize as the project matures.
For organizations serious about supply chain security, OCM isn’t just another tool – it’s a comprehensive approach to understanding and controlling what gets delivered to production. Start with a pilot project: pick one service, write its component constructor, push it to an OCI registry, and verify you can reproduce the exact delivery from the descriptor alone. The investment in proper supply chain tracking pays dividends when you need to respond quickly to security incidents or compliance audits.
The future of software delivery is traceable, verifiable, and secure. OCM provides the foundation to build that future today.