← Alle Beiträge

Open Component Model in der Produktion: Software Bills of Delivery für Cloud-Native Supply Chains

Matthias Bruns · · 9 Min. Lesezeit
open-component-model software-supply-chain sbom cloud-native

Die Software-Supply-Chain ist zu einem kritischen Angriffsvektor geworden. Vorfälle wie SolarWinds und Log4Shell haben gezeigt, wie verwundbar unsere vernetzten Systeme wirklich sind. Herkömmliche Software Bills of Materials (SBOMs) zeigen uns, welche Komponenten existieren, erfassen aber nicht das vollständige Bild davon, wie Software tatsächlich ausgeliefert und deployed wird. Hier kommt das Open Component Model (OCM) ins Spiel – ein offener Standard, der über einfache Abhängigkeitsverfolgung hinausgeht und umfassende Software Bills of Delivery (SBOD) für Cloud-Native-Umgebungen erstellt.

Im Gegensatz zu SBOMs, die sich darauf konzentrieren, was in Ihrem Code enthalten ist, beschreibt OCM die komplette Delivery-Pipeline – von Quell-Repositories bis hin zu Runtime-Konfigurationen. Das ist wichtig, weil moderne Anwendungen nicht nur Code sind; sie sind komplexe Zusammenstellungen aus Container-Images, Helm-Charts, Konfigurationsdateien und Deployment-Manifesten, die über mehrere Repositories und Registries verteilt sind.

Hinweis: Das OCM-Projekt hat kürzlich eine Next-Generation-Neuimplementierung unter open-component-model/open-component-model gestartet. Das neue CLI und die Go-Bibliothek werden aktiv entwickelt und sind als Work In Progress markiert – die API wird sich in den kommenden Monaten stabilisieren. Alle Beispiele in diesem Artikel verwenden das neue CLI.

Was OCM von herkömmlichen Supply-Chain-Tools unterscheidet

Die Open Component Model Spezifikation definiert ein technologie-agnostisches Format zur Beschreibung von Software-Delivery-Artefakten. Während SBOMs die Frage „welche Bibliotheken verwende ich?” beantworten, beantwortet OCM „was genau muss ausgeliefert werden, damit diese Software läuft?”

Diese Unterscheidung ist entscheidend in Cloud-Native-Umgebungen, wo Ihre Anwendung bestehen könnte aus:

  • Mehreren Microservices aus verschiedenen Repositories
  • Container-Images mit spezifischen Tags und Digests
  • Kubernetes-Manifesten mit umgebungsspezifischen Konfigurationen
  • Helm-Charts mit Values-Dateien
  • Externen Abhängigkeiten wie Datenbanken oder Message Queues

Herkömmliche Tools haben Schwierigkeiten, diese Punkte über Repository-Grenzen hinweg zu verbinden. OCM erstellt ein einheitliches Modell, das nicht nur die Artefakte erfasst, sondern auch ihre Beziehungen und den Deployment-Kontext.

Zentrale OCM-Konzepte für die Produktionsimplementierung

Component-Constructor-Dateien

Das Herzstück von OCM ist der Component Constructor – eine YAML-Datei, die eine oder mehrere auslieferbare Software-Komponenten beschreibt. Sie dient als Eingabe für das OCM CLI beim Erstellen von Component Versions. Stellen Sie sich ihn als Versandmanifest vor, das alles auflistet, was für ein erfolgreiches Deployment und die Ausführung Ihrer Software benötigt wird.

# 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

Komponentennamen folgen einer DNS-ähnlichen Konvention (z. B. github.com/my-org/my-app). Der sources-Bereich stellt die Nachverfolgbarkeit zurück zum Quellcode sicher, während resources die auslieferbaren Artefakte beschreibt. Sie können externe Artefakte über access referenzieren oder lokale Inhalte direkt über input einbetten.

Ressourcentypen und Zugriffsmethoden

OCM unterstützt mehrere Ressourcentypen:

  • ociImage für Container-Images
  • helmChart für Helm-Pakete
  • blob für beliebige Daten

Access-Typen definieren, wie externe Ressourcen abgerufen werden:

  • OCIImage/v1 — OCI-konforme Registries
  • Helm/v1 — Helm-Repositories
  • LocalBlob/v1 — Inhalte, die im selben OCM-Repository gespeichert sind
  • File/v1alpha1 — Dateien, referenziert über URI

Für lokale Inhalte ermöglichen Input-Typen das direkte Einbetten von Artefakten:

  • File/v1 — einzelne Datei einbetten
  • Dir/v1 — Verzeichnis als Tar-Archiv einbetten
  • Helm/v1 — lokales Helm-Chart einbetten
  • UTF8/v1 — Text oder strukturierte Daten inline einbetten

Diese Flexibilität ermöglicht es Ihnen, komplexe Delivery-Szenarien zu modellieren, bei denen Artefakte in verschiedenen Systemen leben.

OCM in Multi-Repository-Umgebungen einrichten

Installation und Grundkonfiguration

Installieren Sie das OCM CLI:

# Installation über das offizielle Installer-Skript
curl -sfL https://ocm.software/install-cli.sh | bash

# Oder das Container-Image verwenden
docker run -t ghcr.io/open-component-model/cli:latest --help

# Installation überprüfen
ocm version

Für Multi-Repository-Setups haben Sie typischerweise eine Komponente pro Microservice plus eine aggregierte Platform-Komponente. Eine praktische Repository-Struktur:

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

Component Versions für Microservices erstellen

Jeder Microservice erstellt seine eigene Component Version während des CI/CD-Prozesses. Die Constructor-Datei unterstützt Umgebungsvariablen-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}

So wird das in einen GitHub-Actions-Workflow integriert:

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

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

    - name: OCM CLI installieren
      run: curl -sfL https://ocm.software/install-cli.sh | bash

    - name: Container-Image bauen
      run: |
        docker build -t ghcr.io/${{ github.repository }}:${{ github.ref_name }} .
        docker push ghcr.io/${{ github.repository }}:${{ github.ref_name }}

    - name: Component Version zum OCM-Repository hinzufügen
      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

Dieser Ansatz stellt sicher, dass jeder Service-Build eine nachverfolgbare Component Version erstellt, die die exakten Artefakte und ihre Quellen erfasst.

Komponenten für Platform-Delivery aggregieren

Für Platform-Level-Deployments erstellen Sie aggregierte Komponenten, die auf einzelne Service-Komponenten verweisen:

# 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

Das erstellt eine vollständige Bill of Delivery für Ihre gesamte Plattform mit präziser Versionsverfolgung für jede Komponente.

Umfassende Supply-Chain-Sicherheit implementieren

Signaturverifizierung

OCM unterstützt kryptographisches Signieren von Component Versions und ermöglicht End-to-End-Verifizierung Ihrer Supply Chain. Schlüssel werden über .ocmconfig konfiguriert, nicht als CLI-Flags übergeben:

# ~/.config/ocm/config oder .ocmconfig im Projekt
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

Mit konfigurierten Credentials:

# Component Version signieren
ocm sign component-version \
  ghcr.io/my-org/ocm//github.com/my-org/my-platform:2.1.0 \
  --signature my-org-signature

# Signatur vor dem Deployment verifizieren
ocm verify component-version \
  ghcr.io/my-org/ocm//github.com/my-org/my-platform:2.1.0

# Eine bestimmte Signatur verifizieren
ocm verify component-version \
  ghcr.io/my-org/ocm//github.com/my-org/my-platform:2.1.0 \
  --signature my-org-signature

Integrieren Sie Signaturverifizierung in Ihre Deployment-Pipelines, um sicherzustellen, dass nur signierte Komponenten die Produktion erreichen.

Component Versions inspizieren und scannen

OCM Component Versions bieten die perfekte Grundlage für umfassendes Vulnerability-Scanning. Inspizieren Sie eine Component Version, um ihre Artefakt-Referenzen zu extrahieren:

# Component Version inspizieren (YAML-Ausgabe)
ocm get component-version \
  ghcr.io/my-org/ocm//github.com/my-org/my-platform:2.1.0 \
  --output yaml

# Eine bestimmte Ressource für den Scan herunterladen
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

# Heruntergeladenes Image scannen
trivy image --input ./app-image.tar

Dieser Ansatz stellt sicher, dass Sie die exakten Artefakte scannen, die deployed werden, nicht nur das, was in Ihren Quell-Repositories ist.

Komponenten zwischen Registries transferieren

OCMs Transfer-Funktion ist zentral für Air-Gapped- oder Multi-Environment-Deployments:

# Von einem lokalen CTF-Archiv zu einer OCI-Registry transferieren
ocm transfer component-version \
  ctf::./transport-archive//github.com/my-org/my-platform:2.1.0 \
  ghcr.io/production-registry/ocm \
  --copy-resources

# Rekursiver Transfer (inkl. aller referenzierten 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 und Observability für OCM-Komponenten

Runtime-Korrelation

Eine der mächtigsten Funktionen von OCM ist die Fähigkeit, Runtime-Verhalten mit spezifischen Component Versions zu korrelieren. Fügen Sie OCM-Metadaten zu Ihren Kubernetes-Deployments hinzu:

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

Das ermöglicht mächtige Abfragen in Ihren Monitoring-Systemen:

# Alert bei Fehlern für spezifische 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-Erkennung

Überwachen Sie nicht autorisierte Änderungen an Ihrer Supply Chain durch Vergleich des Runtime-Zustands mit OCM Component Versions:

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

# Erwartete Images aus OCM Component Version abrufen
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')

# Tatsächlich laufende Images abrufen
actual_images=$(kubectl get pods \
  -o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n')

# Vergleichen und bei Unterschieden alarmieren
diff <(echo "$expected_images" | sort) <(echo "$actual_images" | sort) || {
  echo "ALARM: Supply-Chain-Drift erkannt!"
  exit 1
}

Führen Sie diese Überprüfung regelmäßig aus, um nicht autorisierte Deployments oder Konfigurationsdrift zu erkennen.

Best Practices für die OCM-Produktionsimplementierung

Komponentenbenennung und Versionsstrategie

OCM-Komponentennamen folgen einer DNS-ähnlichen Konvention – verwenden Sie Ihren GitHub-Organisationspfad (z. B. github.com/my-org/my-service), um globale Eindeutigkeit zu gewährleisten. Richten Sie die Versionierung an SemVer aus:

  • Patch-Versionen (1.2.1 → 1.2.2): Bugfixes, Sicherheitspatches
  • Minor-Versionen (1.2.0 → 1.3.0): Neue Features, rückwärtskompatible Änderungen
  • Major-Versionen (1.0.0 → 2.0.0): Breaking Changes, Architekturupdates

Schließen Sie Build-Metadaten als Labels in Ihren Constructor ein:

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-Organisation

Strukturieren Sie Ihre Repositories zur Unterstützung von OCM-Workflows:

organisation/
├── services/
│   ├── user-service/           # Individuelle Service-Repos
│   ├── payment-service/
│   └── notification-service/
├── platform/
│   ├── charts/                 # Geteilte Helm-Charts
│   ├── configs/               # Umgebungskonfigurationen
│   └── components/            # Platform Component Constructors
└── infrastructure/
    ├── terraform/             # Infrastructure as Code
    └── policies/              # Sicherheits- und Compliance-Richtlinien

Automatisierung und Integration

Automatisieren Sie die Erstellung von Component Versions in Ihren CI/CD-Pipelines. Erstellen Sie niemals manuell Component Constructors, die Artefakte referenzieren, die Sie noch nicht gebaut haben – generieren Sie sie aus Ihrem Build-Prozess, um Genauigkeit sicherzustellen. Verwenden Sie Umgebungsvariablen-Substitution in Constructor-Dateien anstatt Versionen hardzukodieren.

Für GitOps-Workflows speichern Sie Ihren aggregierten Platform-Constructor in Git und triggern OCM-Transfers bei Versions-Bumps. Kombiniert mit dem OCM Kubernetes-Controller können Sie Deployments direkt aus Component Versions in einer OCI-Registry steuern.

Ausblick: OCM im Cloud-Native-Ökosystem

Das Open Component Model stellt einen bedeutenden Schritt nach vorn in Supply-Chain-Sicherheit und Observability dar. Die Next-Generation-Implementierung unter open-component-model/open-component-model ist eine aktive Neuimplementierung, die eine sauberere Library-API, ein neu gestaltetes CLI und einen Kubernetes-Controller für GitOps-basierte Deployments mitbringt. Sie wird von SAP und der breiteren CNCF-Community unterstützt.

Wichtige Bereiche aktiver Entwicklung umfassen tiefere Integration mit Policy-Engines wie Open Policy Agent, verbesserte Multi-Cloud-Transfer-Szenarien und Language Bindings über Go hinaus. Das Projekt kommuniziert den WIP-Status offen – die CLI-Befehlsoberfläche und Library-API werden sich stabilisieren, wenn das Projekt reift.

Für Organisationen, die Supply-Chain-Sicherheit ernst nehmen, ist OCM nicht nur ein weiteres Tool – es ist ein umfassender Ansatz zum Verstehen und Kontrollieren dessen, was in die Produktion ausgeliefert wird. Beginnen Sie mit einem Pilotprojekt: Wählen Sie einen Service, schreiben Sie seinen Component Constructor, pushen Sie ihn zu einer OCI-Registry und überprüfen Sie, ob Sie die exakte Auslieferung aus dem Descriptor allein reproduzieren können. Die Investition in ordnungsgemäße Supply-Chain-Verfolgung zahlt sich aus, wenn Sie schnell auf Sicherheitsvorfälle oder Compliance-Audits reagieren müssen.

Die Zukunft der Softwareauslieferung ist nachverfolgbar, verifizierbar und sicher. OCM bietet die Grundlage, um diese Zukunft heute zu bauen.

Lesebarkeit

Schriftgröße