Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
80 changes: 80 additions & 0 deletions design/20250716-source-plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Design: Source Plugins

## Summary

trust-manager has always supported a variety of trust sources: Secrets, ConfigMaps, "inLine" PEM data and the public trust bundles are
all sources of trust data today. All of these sources make sense for trust-manager to support directly.

There are other sources which might not make sense for trust-manager to support directly, but which are useful for users to be able to
include in their trust-manager targets. Examples include:

- Files from container images (e.g. `/etc/ssl/certs/ca-certificates.crt` from a Debian image)
- Files sources from an HTTP server (e.g. the Mozilla CA bundle)
- Enterprise trust stores (e.g. Microsoft Active Directory, CyberArk Workload Identity Manager, AWS PrivateCA, etc.)

This document describes a design for a source plugin system which allows users to add sources of trust data such as these to their
trust-manager bundles.

## Goals

- Allow for users to implement a custom source of trust data without interacting with the trust-manager codebase

## Non-Goals

- Changes to existing trust-manager sources (e.g. Secrets, ConfigMaps)

## Proposal

The direction of travel for for the trust-manager API interface is described by [PR#647](https://github.com/cert-manager/trust-manager/pull/647), which changes source types from keys in a map to a free-form "kind" string. This enables the use of arbitrary kinds of sources, including those which are not built-in to trust-manager. Specifically, this enables the use of CRDs to define sources of trust data.

For example, a source plugin for a file in a container image could be implemented as follows:

```yaml
spec:
sources:
- kind: ImageTrustSource
apiVersion: example.io/v1alpha1
name: example
```

In this example, `ImageTrustSource` is a CRD, and trust-manager can query this named resource to retrieve trust data. For example, the
YAML for the `ImageTrustSource` CRD might look like this:

```yaml
apiVersion: example.io/v1alpha1
kind: ImageTrustSource
metadata:
name: example
spec:
image: docker.io/library/debian:bookworm
path: /etc/ssl/certs/ca-certificates.crt
```

Running in the same cluster, a plugin controller would watch for changes to `ImageTrustSource` resources and update the status field of
each resource as appropriate. For example, the controller might download the image, extract the file at the specified path, and add
that file's data to a status field:

```yaml
apiVersion: example.io/v1alpha1
kind: ImageTrustSource
metadata:
name: example
spec:
image: docker.io/library/debian:bookworm
path: /etc/ssl/certs/ca-certificates.crt
status:
bundleData: |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid object size limits I would have the status expose an array of secrets that contain the actual bundle, most implementations would probably only ever need a single secret, but cant hurt to future proof it in the design.

Something like:

status:
  bundleSecrets:
  - name: example-bundle-01
  - name: example-bundle-02

For namespaced sources the secrets would exist in the same namespace as the resource, for cluster sources the secrets would exist in the trust-manager namespace

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If any source exceeds the size limit, the targets will also exceed the size limit. I don't think we need to account for this additional complexity.

Copy link

@ThatsMrTalbot ThatsMrTalbot Jul 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC we have had issues raised in the past about peoples bundles exceeding the size, I would argue that is where a CSI driver could help 🙂

I also wonder if post-quantum will increase CA cert size enough to make hitting the 1mb limit more likely

-----BEGIN CERTIFICATE-----
MIID...
-----END CERTIFICATE-----
```

The bundle data from the source would then be fed into the trust-manager target, in a similar way to how the existing sources are used.

## Open Questions

- If the source plugins need a separate controller, why should that controller not simply write its data into a ConfigMap or Secret, which trust-manager can then consume natively?
- Concretely: What do we gain from having CRDs here?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. If a source produces a bundle larger than 1mb then it will need to shard it across multiple secrets, you would need to know that to include all the shards in your trust bundle. By referencing the CRD you get a single object you can reference
  2. It gives us the option of having cluster scope sources, if you just reference secrets you can never have a namespaced TrustBundle reference anything outside its own namespace. I think cluster scope sources would be a great way for us to ship our "default" CAs with a ClusterImageTrustSource
  3. I think its better UX. If you used secrets then a ImageTrustSource would ether need to produce a deterministic secret name or have a configurable secret name, and IMO the secret is just an implementation detail.

- Does this make setup difficult? Plugin CRDs should be able to be installed before trust-manager.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The controller-runtime uses a dynamic discovery implementation, so CRDs do not need to be installed first.

- Does this require every plugin to bind a role with CRD read permissions to the trust-manager service account?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good point, probably yes

- Does the key from the status field need to be configurable? Most likely it does - how do we configure it?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not have it configurable, I would have a "contract" we have with plugins that says you must have this field to function. That is how ClusterAPI works for example, the providers have their own CRDs that work with ClusterAPI if they fulfil the API contract.