Skip to content

WIP: OCPNODE-4791: Raise image policy certificate size limits for ML-DSA - #3078

Draft
harche wants to merge 1 commit into
openshift:masterfrom
harche:mldsa-imagepolicy-size-limits
Draft

harche wants to merge 1 commit into
openshift:masterfrom
harche:mldsa-imagepolicy-size-limits

Conversation

@harche

@harche harche commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Raises the size limit of the certificate fields in ClusterImagePolicy and ImagePolicy so they can hold post-quantum ML-DSA (FIPS 204) certificates. Tracked in OCPNODE-4791, under the ML-DSA sigstore signature validation epic OCPNODE-4638.

Why

ML-DSA certificates are much larger than RSA or ECDSA ones. maxLength applies to the base64 encoding of the PEM data, and these are the sizes measured with OpenSSL 3.6:

Public key One certificate
ML-DSA-44 2480 ~7.2K
ML-DSA-65 3636 ~10K
ML-DSA-87 4796 ~13.5K

With the current limit of 8192 characters, a single ML-DSA-65 or ML-DSA-87 certificate is rejected in a PKI or FulcioCAWithRekor policy. A bundle of two ML-DSA-44 certificates is rejected too. CRI-O 1.38 already verifies ML-DSA sigstore signatures (Go 1.27 crypto/mldsa, sigstore >= v1.11.0), and MCO copies the key and certificate data into policy.json without parsing it. That leaves these limits as the only blocker for ML-DSA PKI and Fulcio roots of trust.

Change

  • caRootsData, caIntermediatesData and fulcioCAData: maxLength 8192 → 32768. That is enough for a root plus an intermediate, or two roots, at ML-DSA-87.
  • keyData and rekorKeyData stay at 8192, which already fits ML-DSA-87 public keys.
  • Field documentation updated to match.

32768 keeps about the same headroom 8192 gave the largest classical certificates: 8192 fits three RSA-4096 certificates, and 32768 fits two ML-DSA-87 certificates (a root and an intermediate, or an old and a new root during rotation). CEL cost isn't a constraint: the most expensive rule (findAll) is estimated at 52,437 against a per-rule limit of 10,000,000. Raising the limit further later is non-breaking.

This only relaxes validation, so every existing object stays valid.

Tests

New cases for both ClusterImagePolicy and ImagePolicy, using real ML-DSA certificates:

  • PKI with an ML-DSA-65 root
  • PKI with an ML-DSA-87 root and intermediate
  • PKI with a bundle of two ML-DSA-87 roots
  • FulcioCAWithRekor with an ML-DSA-87 Fulcio CA and Rekor key
  • caRootsData, caIntermediatesData and fulcioCAData over 32768 characters are rejected

With the previous limit, each of the four positive cases fails, for example:

spec.policy.rootOfTrust.pki.caRootsData: Too long: may not be more than 8192 bytes
spec.policy.rootOfTrust.fulcioCAWithRekor.fulcioCAData: Too long: may not be more than 8192 bytes

With this change, make -C tests test GINKGO_EXTRA_ARGS='--focus=imagepolicies' passes all 74 specs, and make lint reports 0 issues.

Post-quantum ML-DSA (FIPS 204) certificates are much larger than RSA or
ECDSA ones: a single ML-DSA-65 certificate is about 10K characters and
an ML-DSA-87 certificate about 13.5K characters as base64-encoded PEM,
over the 8192 character limit of the certificate fields in
ClusterImagePolicy and ImagePolicy.

Raise the limit of caRootsData, caIntermediatesData and fulcioCAData to
32768 characters, enough for a root and an intermediate, or two roots,
at ML-DSA-87. The public key fields stay at 8192, which already fits
ML-DSA-87 public keys (about 4.8K characters).

This only relaxes validation, so every existing object stays valid.

Add integration tests with real ML-DSA-65/87 certificates that fail
with the previous limit, and tests that reject data over the new limit.
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification

This PR uses the pipeline controller for second-stage tests. Selection and triggering follow the repository configuration.

Use /test ? to list jobs, /pipeline remaining to request missing second-stage tests, or /pipeline required to rerun the selected second-stage set.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Oct 5, 2026
@openshift-ci-robot

openshift-ci-robot commented Oct 5, 2026 •

Copy link
Copy Markdown

@harche: This pull request references OCPNODE-4791 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.1.0" version, but no target version was set.

Details

In response to this:

Raises the size limit of the certificate fields in ClusterImagePolicy and ImagePolicy so they can hold post-quantum ML-DSA (FIPS 204) certificates. Tracked in OCPNODE-4791, under the ML-DSA sigstore signature validation epic OCPNODE-4638.

Why

ML-DSA certificates are much larger than RSA or ECDSA ones. maxLength applies to the base64 encoding of the PEM data, and these are the sizes measured with OpenSSL 3.6:

Public key One certificate
ML-DSA-44 2480 ~7.2K
ML-DSA-65 3636 ~10K
ML-DSA-87 4796 ~13.5K

With the current limit of 8192 characters, a single ML-DSA-65 or ML-DSA-87 certificate is rejected in a PKI or FulcioCAWithRekor policy. A bundle of two ML-DSA-44 certificates is rejected too. CRI-O 1.38 already verifies ML-DSA sigstore signatures (Go 1.27 crypto/mldsa, sigstore >= v1.11.0), and MCO copies the key and certificate data into policy.json without parsing it. That leaves these limits as the only blocker for ML-DSA PKI and Fulcio roots of trust.

Change

  • caRootsData, caIntermediatesData and fulcioCAData: maxLength 8192 → 32768. That is enough for a root plus an intermediate, or two roots, at ML-DSA-87.
  • keyData and rekorKeyData stay at 8192, which already fits ML-DSA-87 public keys.
  • Field documentation updated to match.

This only relaxes validation, so every existing object stays valid. The CEL rules on these fields (startsWith, endsWith, findAll marker counts) still fit the cost budget at the new maxLength: the CRDs install in envtest and all existing tests pass.

Tests

New cases for both ClusterImagePolicy and ImagePolicy, using real ML-DSA certificates:

  • PKI with an ML-DSA-65 root
  • PKI with an ML-DSA-87 root and intermediate
  • PKI with a bundle of two ML-DSA-87 roots
  • FulcioCAWithRekor with an ML-DSA-87 Fulcio CA and Rekor key
  • caRootsData, caIntermediatesData and fulcioCAData over 32768 characters are rejected

With the previous limit, each of the four positive cases fails, for example:

spec.policy.rootOfTrust.pki.caRootsData: Too long: may not be more than 8192 bytes
spec.policy.rootOfTrust.fulcioCAWithRekor.fulcioCAData: Too long: may not be more than 8192 bytes

With this change, make -C tests test GINKGO_EXTRA_ARGS='--focus=imagepolicies' passes all 74 specs, and make lint reports 0 issues.

Open question

This relaxes a stable v1 API without a feature gate, because no gate-aware MaxLength marker exists (only FeatureGateAwareMaxItems, FeatureGateAwareEnum and FeatureGateAwareXValidation). If you'd prefer it gated, it could keep MaxLength=32768 and add a FeatureGateAwareXValidation rule that limits the decoded data to 6144 bytes (exactly 8192 base64 characters) while the gate is off.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 5, 2026
@openshift-ci

openshift-ci Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci

openshift-ci Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Hello @harche! Some important instructions when contributing to openshift/api:
API design plays an important part in the user experience of OpenShift and as such API PRs are subject to a high level of scrutiny to ensure they follow our best practices. If you haven't already done so, please review the OpenShift API Conventions and ensure that your proposed changes are compliant. Following these conventions will help expedite the api review process for your PR.

@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository YAML (base), Central YAML (inherited)
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1f848947-b5df-404b-95a7-779c4dcf50c4
📥 Commits

Reviewing files that changed from the base of the PR and between 18d5eb0 and cbfdfc5.

⛔ Files ignored due to path filters (7)
  • config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_clusterimagepolicies.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_imagepolicies.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • config/v1/zz_generated.featuregated-crd-manifests/clusterimagepolicies.config.openshift.io/AAA_ungated.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • config/v1/zz_generated.featuregated-crd-manifests/imagepolicies.config.openshift.io/AAA_ungated.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • config/v1/zz_generated.swagger_doc_generated.go is excluded by !**/zz_generated*
  • openapi/generated_openapi/zz_generated.openapi.go is excluded by !openapi/**, !**/zz_generated*
  • openapi/openapi.json is excluded by !openapi/**
📒 Files selected for processing (5)
  • config/v1/tests/clusterimagepolicies.config.openshift.io/AAA_ungated.yaml
  • config/v1/tests/imagepolicies.config.openshift.io/AAA_ungated.yaml
  • config/v1/types_image_policy.go
  • payload-manifests/crds/0000_10_config-operator_01_clusterimagepolicies.crd.yaml
  • payload-manifests/crds/0000_10_config-operator_01_imagepolicies.crd.yaml

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.


📝 Walkthrough

Walkthrough

The image policy type and its two CRD schemas increase the maximum length for Fulcio CA data, CA roots, and CA intermediate bundles from 8,192 to 32,768 characters. Their descriptions now state that the limit accommodates post-quantum (ML-DSA) certificates. Other validation rules remain unchanged.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to cbfdf

The larger certificate limit and its tests are consistent across the changed files. No concrete merge-blocking issue was established.

🚥 Pre-merge checks | ✅ 15
✅ Passed checks (15 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed The added test titles are fixed YAML strings, and tests/generator.go passes each testEntry.Name to Ginkgo's Entry (lines 194–205). The new titles describe ML-DSA certificate cases and certificat…
Test Structure And Quality ✅ Passed The PR does not change Ginkgo test code. Its added cases are declarative entries in two YAML test fixtures, and its changed Go files contain API declarations or generated OpenAPI data. The Ginkgo-spec…
Microshift Test Compatibility ✅ Passed The check applies to new Ginkgo e2e tests, and this PR adds none. The only changed test files are two YAML fixtures under config/v1/tests/. They add declarative ClusterImagePolicy and `ImagePolicy…
Single Node Openshift (Sno) Test Compatibility ✅ Passed The SNO check does not apply. The pull request adds no Ginkgo e2e tests or Go test declarations. The added cases are YAML API-object fixtures under config/v1/tests, which exercise ImagePolicy and Clus…
Topology-Aware Scheduling Compatibility ✅ Passed The check is not applicable to this change. The reviewed diff changes image-policy certificate length limits, generated schemas, and test fixtures. It adds no deployment or controller scheduling const…
Ote Binary Stdout Contract ✅ Passed The pull request does not change OTE process-level code. The diff changes image-policy API validation markers and documentation, generated CRD/OpenAPI files, and YAML test fixtures. It adds no main, i…
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The PR adds declarative CRD on-create test cases for ClusterImagePolicy and ImagePolicy, not e2e tests. The test harness submits objects to a local envtest API server and checks stored objects or …
No-Weak-Crypto ✅ Passed The pull-request diff changes certificate field length limits, API documentation, generated schemas, and image-policy test fixtures. It introduces no MD5, SHA1, DES, RC4, 3DES, Blowfish, or ECB usage;…
Container-Privileges ✅ Passed The changed files update image-policy certificate size limits, documentation, generated schemas, and test fixtures. No changed lines introduce privileged settings, host namespaces, SYS_ADMIN, root exe…
No-Sensitive-Data-In-Logs ✅ Passed The PR changes API validation comments and certificate size limits, generated schemas, and test fixtures. The added diff contains no logging calls or log statements, so it introduces no path that logs…
Title check ✅ Passed The title clearly states that the image policy certificate size limits are being raised for ML-DSA.
Description check ✅ Passed The description explains the limit changes, their ML-DSA rationale, and the related tests.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@openshift-ci openshift-ci Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Oct 5, 2026
@openshift-ci

openshift-ci Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign joelspeed for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants