Skip to main content

Command Palette

Search for a command to run...

Open Component Model in Production: Building Software Bills of Delivery for Cloud-Native Supply Chains

How to implement comprehensive software supply chain tracking using the Open Component Model that captures dependencies, deployment artifacts, configurations, and runtime bindings across multi-repository environments.

Updated
8 min read
Open Component Model in Production: Building Software Bills of Delivery for Cloud-Native Supply Chains
M

Senior Freelancer & Technical Lead

Working as a Golang developer since 2020. Working as a mobile developer since 2013.

Focussed on architecture, testability and clean code. Open minded & product driven. Based in Rhede, available world-wide

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.

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 Descriptors

At the heart of OCM is the component descriptor – a machine-readable manifest that describes a deliverable software component. Think of it as a shipping manifest that lists everything needed to successfully deploy and run your software.

apiVersion: ocm.software/v3alpha1
kind: ComponentVersion
metadata:
  name: my-web-app
  version: 1.2.3
  provider: appetizer-labs
spec:
  resources:
  - name: app-image
    type: ociImage
    version: 1.2.3
    access:
      type: ociRegistry
      imageReference: registry.example.com/my-web-app:1.2.3
  - name: helm-chart
    type: helmChart
    version: 1.2.3
    access:
      type: ociRegistry
      imageReference: registry.example.com/charts/my-web-app:1.2.3
  - name: config
    type: yaml
    access:
      type: github
      repository: github.com/appetizer-labs/my-web-app-config
      ref: v1.2.3
  sources:
  - name: app-source
    type: git
    access:
      type: github
      repository: github.com/appetizer-labs/my-web-app
      ref: v1.2.3

This descriptor captures not just what artifacts exist, but where they're stored and how to access them. The sources section maintains traceability back to source code, while resources describes the deliverable artifacts.

Resource Types and Access Methods

OCM supports multiple resource types out of the box:

  • ociImage for container images
  • helmChart for Helm packages
  • yaml for configuration files
  • executable for binaries
  • blob for arbitrary data

Access methods define how to retrieve these resources:

  • ociRegistry for OCI-compliant registries
  • github for Git repositories
  • s3 for object storage
  • localBlob for local files

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

Start by installing the OCM CLI tool:

# Install OCM CLI
curl -L https://github.com/open-component-model/ocm/releases/latest/download/ocm-linux-amd64.tar.gz | tar xz
sudo mv ocm /usr/local/bin/

# Verify installation
ocm version

For multi-repository setups, you'll typically have one repository per microservice plus a central repository for component descriptors. Here's a practical structure:

my-platform/
├── services/
│   ├── user-service/
│   ├── payment-service/
│   └── notification-service/
├── charts/
│   └── platform-chart/
└── components/
    └── platform-component/
        └── component-descriptor.yaml

Creating Component Descriptors for Microservices

Each microservice should generate its own component descriptor during the CI/CD process. Here's how to automate this with GitHub Actions:

name: Build and Package Component
on:
  push:
    tags: ['v*']

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Build container image
      run: |
        docker build -t ${{ github.repository }}:${{ github.ref_name }} .
        docker push ${{ github.repository }}:${{ github.ref_name }}

    - name: Generate component descriptor
      run: |
        ocm create componentversion \
          --provider appetizer-labs \
          --name ${{ github.repository }} \
          --version ${{ github.ref_name }} \
          --resource name=app-image,type=ociImage,version=${{ github.ref_name }},access='{"type":"ociRegistry","imageReference":"${{ github.repository }}:${{ github.ref_name }}"}' \
          --source name=source,type=git,access='{"type":"github","repository":"${{ github.repository }}","ref":"${{ github.ref_name }}"}'

    - name: Push component descriptor
      run: |
        ocm transfer componentversion component-descriptor.yaml \
          ghcr.io/${{ github.repository_owner }}/components

This approach ensures every service build produces a traceable component descriptor that captures the exact artifacts and their sources.

Aggregating Components for Platform Delivery

For platform-level deployments, create aggregate components that reference individual service components:

apiVersion: ocm.software/v3alpha1
kind: ComponentVersion
metadata:
  name: my-platform
  version: 2.1.0
  provider: appetizer-labs
spec:
  componentReferences:
  - name: user-service
    componentName: appetizer-labs/user-service
    version: 1.5.2
  - name: payment-service
    componentName: appetizer-labs/payment-service
    version: 2.3.1
  - name: notification-service
    componentName: appetizer-labs/notification-service
    version: 1.1.0
  resources:
  - name: platform-chart
    type: helmChart
    version: 2.1.0
    access:
      type: ociRegistry
      imageReference: ghcr.io/appetizer-labs/charts/platform:2.1.0

This creates a complete bill of delivery for your entire platform, with precise version tracking for each component.

Tracking Dependencies and Runtime Bindings

Capturing External Dependencies

Modern applications depend on external services, databases, and third-party APIs. OCM can capture these dependencies explicitly:

spec:
  references:
  - name: postgres
    componentName: external/postgresql
    version: "14.9"
    extraIdentity:
      deployment: production
  - name: redis
    componentName: external/redis
    version: "7.0"
    extraIdentity:
      deployment: production
  - name: stripe-api
    componentName: external/stripe
    version: "2023-10-16"
    extraIdentity:
      environment: production

This approach makes external dependencies visible in your supply chain, enabling better security scanning and compliance tracking.

Runtime Configuration Binding

OCM excels at capturing how components are configured for specific environments. Use labels and extra identity fields to track environment-specific bindings:

spec:
  resources:
  - name: app-config
    type: yaml
    version: 1.2.3
    access:
      type: github
      repository: github.com/appetizer-labs/configs
      ref: production/v1.2.3
    labels:
    - name: environment
      value: production
    - name: region
      value: us-west-2
    extraIdentity:
      cluster: prod-us-west-2
      namespace: my-app

This level of detail enables precise tracking of what configuration was deployed where, crucial for incident response and compliance audits.

Implementing Comprehensive Supply Chain Security

Signature Verification

OCM supports cryptographic signing of component descriptors, enabling end-to-end verification of your supply chain:

# Generate signing key
ocm create rsakeypair appetizer-labs-key

# Sign component
ocm sign componentversion \
  --signature appetizer-labs-signature \
  --private-key appetizer-labs-key.priv \
  component-descriptor.yaml

# Verify signature during deployment
ocm verify componentversion \
  --signature appetizer-labs-signature \
  --public-key appetizer-labs-key.pub \
  ghcr.io/appetizer-labs/components//my-platform:2.1.0

Integrate signature verification into your deployment pipelines to ensure only signed components reach production.

Vulnerability Scanning Integration

OCM component descriptors provide the perfect input for comprehensive vulnerability scanning. Here's how to integrate with popular scanning tools:

# Extract all container images from component
ocm download resource \
  --type ociImage \
  --output-format json \
  ghcr.io/appetizer-labs/components//my-platform:2.1.0 | \
  jq -r '.access.imageReference' | \
  xargs -I {} trivy image {}

# Scan Helm charts for misconfigurations
ocm download resource \
  --type helmChart \
  --output helm-chart.tgz \
  ghcr.io/appetizer-labs/components//my-platform:2.1.0
checkov -f helm-chart.tgz

This approach ensures you're scanning the exact artifacts that will be deployed, not just what's in your source repositories.

Policy Enforcement

Use OCM metadata to enforce deployment policies. For example, require all production components to be signed and scanned:

# admission-controller-policy.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: ocm-policy
data:
  policy.rego: |
    package ocm.admission

    deny[msg] {
      input.metadata.labels.environment == "production"
      not input.metadata.annotations["ocm.software/signature"]
      msg := "Production components must be signed"
    }

    deny[msg] {
      input.metadata.labels.environment == "production"
      not input.metadata.annotations["security.scan.passed"]
      msg := "Production components must pass security scans"
    }

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 application deployments:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
  labels:
    ocm.software/component: appetizer-labs/user-service
    ocm.software/version: 1.5.2
    ocm.software/platform-component: appetizer-labs/my-platform
    ocm.software/platform-version: 2.1.0
spec:
  template:
    metadata:
      labels:
        ocm.software/component: appetizer-labs/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="appetizer-labs/user-service"}

Supply Chain Drift Detection

Monitor for unauthorized changes to your supply chain by comparing runtime state with OCM descriptors:

#!/bin/bash
# drift-detection.sh

# Get expected images from OCM
expected_images=$(ocm get resources \
  --type ociImage \
  ghcr.io/appetizer-labs/components//my-platform:2.1.0 | \
  jq -r '.spec.resources[].access.imageReference')

# Get actual running images
actual_images=$(kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}')

# 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 Versioning Strategy

Align OCM component versions with your release strategy. For semantic versioning:

  • 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 in component descriptors:

metadata:
  labels:
  - name: build.commit
    value: a1b2c3d4
  - name: build.timestamp
    value: "2024-01-15T10:30:00Z"
  - name: build.pipeline
    value: github-actions

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 descriptors
└── infrastructure/
    ├── terraform/             # Infrastructure as code
    └── policies/              # Security and compliance policies

Automation and Integration

Automate OCM descriptor generation and validation in your CI/CD pipelines. Never manually create component descriptors – they should be generated from your build process to ensure accuracy and consistency.

Use GitOps principles with OCM by storing component descriptors in Git and using tools like ArgoCD to deploy based on OCM metadata:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-platform
spec:
  source:
    repoURL: ghcr.io/appetizer-labs/components
    targetRevision: 2.1.0
    chart: my-platform
  destination:
    server: https://kubernetes.default.svc
    namespace: production

Looking Forward: OCM in the Cloud-Native Ecosystem

The Open Component Model represents a significant step forward in supply chain security and observability. As the cloud-native ecosystem continues to evolve, OCM provides a foundation for more sophisticated supply chain management.

Key areas where OCM is expanding include integration with policy engines like Open Policy Agent, enhanced support for serverless deployments, and better tooling for multi-cloud scenarios. The specification is actively developed and backed by major cloud providers, ensuring long-term viability.

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, automate descriptor generation, and gradually expand coverage across your entire software portfolio. 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.