Skip to content

Repository files navigation

ocm

Build status OpenSSF Scorecard

A monorepo for OCMv2 components.

Packages cloud-native applications (container images, Helm charts and their configuration) as Open Component Model components and publishes them to ghcr. It builds no application code; images and charts come from their own source repositories.

Warning

OCM v2. The predecessor opendefensecloud/ocm-components is pinned to the legacy v1 CLI and its commands do not work here. Layout and conventions are kept the same so components can move over with little churn.

Components

Component Wraps Docs
opendefense.cloud/dependency-controller controller + webhook images, Helm chart README
opendefense.cloud/quota-controller controller + webhook images, Helm chart README
opendefense.cloud/krop-controller controller image, Helm chart README

Layout

One directory per component, discovered automatically:

<component>/
├── component-constructor.yaml   # OCM descriptor — the only place a version lives
├── values.yaml.tpl              # image localization, rendered by ocm-kit
├── minimal-values.yaml          # dev/test configuration
├── production-values.yaml       # production HA configuration
└── README.md

Everything else is shared: Makefile (all commands), .ocmconfig (credentials and signer), sigstore-verify.yaml (verifier), renovate.json (version bumps), .github/workflows/ (release, Scorecard, commit and workflow linting).

Adding a component

Create a directory with a component-constructor.yaml — the release workflow discovers it, there is no matrix to update. Then follow the conventions above and see CONTRIBUTING.md.

Usage

make setup                       # install the pinned OCM v2 CLI into ./bin
make validate COMPONENT=<name>   # build into a throwaway CTF, publishes nothing
make help                        # every target

Targets take COMPONENT=<name> and REGISTRY=<ref>; OCM_VERSION is derived from the wrapped chart. The Makefile pulls common.mk from dev-kit for repo-settings and update-action-pins.

Publishing model

make publish is descriptor-only: the descriptor is pushed, images and charts stay as references to where they already live in ghcr. Copying them by value would duplicate bytes inside the same registry.

Consumers build their own self-contained bundle when they need one:

ocm transfer component-version \
  ghcr.io/opendefensecloud//opendefense.cloud/dependency-controller:<version> \
  ctf::./bundle --copy-resources --recursive

A dangling reference cannot be published: OCM resolves every external resource at build time to compute its digest, so make validate already fails if a wrapped image or chart is missing. make resolve-check re-validates the whole graph after publishing.

Published paths keep the source image path under the target repository, so the chart lands at <REGISTRY>/opendefensecloud/charts/<component>. The doubled opendefensecloud is expected.

Releasing

A component's version is the version of the artifact it wraps. Chart 0.4.0 means component 0.4.0 read from the helmChart resource (make version). There is no second version line to keep in sync.

Renovate bumps the chart/image → merge to main → published + signed → tagged

Nothing is tagged by hand and there is no release PR. A push to main publishes every component whose version is not in the registry yet, so the workflow is safe to re-run. Pull requests validate but publish nothing.

The tag <component>/v<version> is a convenience — it lets you check out the packaging state of a release. It triggers nothing and is an unsigned ref.

The descriptor is not a substitute: a sources entry is not covered by the signature (measured — two builds differing only in the commit produce an identical signed digest, and OCM warns about exactly this). What does bind the release to a commit is the Sigstore certificate, whose extensions record the workflow run and its revision.

Important

A packaging-only fix has no version of its own and ships with the next upstream release.

Signing

Sigstore keyless. There are no signing secrets: permissions: id-token: write provides an ambient OIDC token that the signing handler forwards to cosign, and Fulcio issues a short-lived certificate bound to the workflow identity — which is also what ties a release to its commit.

The signature is stored inside the component descriptor, not as a separate registry artifact, so GitHub's package page shows no signature badge. Check it with make verify.

Configuration is split across two files, and the split is not obvious:

File Holds
.ocmconfig registry credentials, and the signer
sigstore-verify.yaml the verifier — passed via --verifier-spec

Warning

A verifier: key inside .ocmconfig is silently ignored. ocm verify logs "no verifier specification file given, using default RSASSA-PSS" and then fails on the Sigstore bundle's media type. The verifier must be its own file.

Registry credentials are likewise not optional: without an explicit DockerConfig/v1 entry OCM requests a push token anonymously and ghcr answers 403. A public pull works either way, which makes the omission easy to miss.

Verification pins who may have signed — without both constraints a keyless signature proves only that somebody signed:

# sigstore-verify.yaml
certificateOIDCIssuer: https://token.actions.githubusercontent.com
certificateIdentity: https://github.com/opendefensecloud/ocm/.github/workflows/release.yml@refs/heads/main

Signing does not work offline; locally you need SIGSTORE_ID_TOKEN set.

Resolvers are not configured — no component declares componentReferences.

Migrating from the v1 repositories

OCM v2 changes enough that v1 commands do not carry over — --output crashes on OCI resources, --upload-as defaults the wrong way, --version is gone, and v2 signatures do not verify with v1 tooling. The measured list is in CLAUDE.md.

Licence

The Apache 2.0 LICENSE covers this repository's own content — component constructors, values files, the Makefile, workflows and documentation.

It does not cover the packaged applications. Each wrapped image and Helm chart keeps the licence of the project that produces it; see the component's README.md for which, and that project's repository for the terms.

Publishing here is descriptor-only, so this repository redistributes no third-party artifacts — it references them where they already live. A consumer who builds a by-value bundle (transfer --copy-resources) does redistribute them, and the upstream licences apply to that copy.

About

A monorepo for OCMv2 components

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages