feat(cli): Add full PEM encoding support for signing and verifying component versions#2147
Conversation
…nt versions Signed-off-by: Jakob Möller <contact@jakob-moeller.com>
📝 WalkthroughWalkthroughThis pull request updates CLI help text and reference documentation for sign and verify component-version commands to distinguish between Plain (default) and PEM signature encoding policies. It includes credential configuration examples for each encoding type, updates the RSA bindings dependency version, and adds an integration test for PEM-encoded certificate chain signing. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
cli/cmd/sign/component-version/cmd.go (1)
136-154:⚠️ Potential issue | 🟡 MinorClarify the defaulting semantics for user-supplied signer specs.
loadSignerSpecinjects Plain only when the--signer-specflag is omitted entirely. When a signer spec file is provided, the raw config passes through unchanged. The binding's code default is also Plain, yet the help textsignatureEncodingPolicy: Plain (default) | PEMreads like a field-level default that applies regardless of context.✏️ Suggested wording
-# signatureEncodingPolicy: Plain (default) | PEM +# signatureEncodingPolicy: Plain | PEM +# +# If you omit the entire --signer-spec flag, the CLI defaults to Plain encoding. +# If you provide a signer spec file, set signatureEncodingPolicy explicitly.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cli/cmd/sign/component-version/cmd.go` around lines 136 - 154, The help text is ambiguous about when the Plain default applies; update the documentation string to clarify that signatureEncodingPolicy's "Plain (default)" is applied only when no --signer-spec is provided (handled by loadSignerSpec) or by the binding's own default, and that if a user-supplied signer spec file is provided the field is passed through unchanged. Reference loadSignerSpec and the --signer-spec flag in the wording and explicitly state that field-level defaults in the binding may also be Plain, so users must set signatureEncodingPolicy: PEM in their signer-spec file to override.
🧹 Nitpick comments (1)
cli/integration/signing_integration_test.go (1)
165-169: Add a negative PEM-chain case next to the happy path.This locks in the root-only success path, but the new help text also depends on rejecting an embedded self-signed root and on using only the supplied trust anchor. A second case with
[leaf, intermediate, root]or an unrelatedpublic_key_pem_filewould keep that boundary under regression coverage.Also applies to: 205-289
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cli/integration/signing_integration_test.go` around lines 165 - 169, Add a negative PEM-chain test case alongside the existing happy-path by writing a chain file that includes the root (e.g., call writePEMCertFile(t, dir, "chain_with_root.pem", leaf, interm, root) or a chain with an unrelated public key) and then assert the verifier rejects it — mirror the happy-path flow but expect failure when using that chainPath (and similarly add the same negative case for the other ranges mentioned around signing_integration_test.go lines 205-289); ensure you reference the same helpers (writePEMCertFile) and variables (chainPath/rootCAPath) so the test verifies that only the supplied trust anchor (rootCAPath) is accepted and embedded self-signed roots are rejected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@cli/cmd/sign/component-version/cmd.go`:
- Around line 136-154: The help text is ambiguous about when the Plain default
applies; update the documentation string to clarify that
signatureEncodingPolicy's "Plain (default)" is applied only when no
--signer-spec is provided (handled by loadSignerSpec) or by the binding's own
default, and that if a user-supplied signer spec file is provided the field is
passed through unchanged. Reference loadSignerSpec and the --signer-spec flag in
the wording and explicitly state that field-level defaults in the binding may
also be Plain, so users must set signatureEncodingPolicy: PEM in their
signer-spec file to override.
---
Nitpick comments:
In `@cli/integration/signing_integration_test.go`:
- Around line 165-169: Add a negative PEM-chain test case alongside the existing
happy-path by writing a chain file that includes the root (e.g., call
writePEMCertFile(t, dir, "chain_with_root.pem", leaf, interm, root) or a chain
with an unrelated public key) and then assert the verifier rejects it — mirror
the happy-path flow but expect failure when using that chainPath (and similarly
add the same negative case for the other ranges mentioned around
signing_integration_test.go lines 205-289); ensure you reference the same
helpers (writePEMCertFile) and variables (chainPath/rootCAPath) so the test
verifies that only the supplied trust anchor (rootCAPath) is accepted and
embedded self-signed roots are rejected.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 19572e86-1987-49d4-8abe-0833902a4a9c
⛔ Files ignored due to path filters (2)
cli/go.sumis excluded by!**/*.sumcli/integration/go.sumis excluded by!**/*.sum
📒 Files selected for processing (7)
cli/cmd/sign/component-version/cmd.gocli/cmd/verify/component-version/cmd.gocli/docs/reference/ocm_sign_component-version.mdcli/docs/reference/ocm_verify_component-version.mdcli/go.modcli/integration/go.modcli/integration/signing_integration_test.go
…mponent versions (open-component-model#2147) <!-- markdownlint-disable MD041 --> #### What this PR does / why we need it Adds end-to-end CLI support and documentation for the **PEM signature encoding policy** (`signatureEncodingPolicy: PEM`), which embeds an X.509 certificate chain directly in the signature value and validates it against a verifier-supplied trust anchor. **Changes:** - `cli/cmd/sign/component-version/cmd.go` — extends the `--signer-spec` flag description and `Example` block with a second credential config showing PEM signing (`private_key_pem_file` + `public_key_pem_file` for a leaf+intermediate chain) and a second signer spec snippet for `signatureEncodingPolicy: PEM` - `cli/cmd/verify/component-version/cmd.go` — extends the `Example` block with a PEM verification credential config (root CA as trust anchor via `public_key_pem_file`), explains trust anchor isolation, and fixes two copy-paste bugs where examples said `sign` instead of `verify` - `cli/docs/reference/ocm_sign_component-version.md` / `ocm_verify_component-version.md` — regenerated from the above - `cli/integration/signing_integration_test.go` — adds `Test_Integration_Signing_PEM`: an end-to-end integration test that builds a 3-tier certificate chain (root → intermediate → leaf) at runtime, signs a component version with PEM encoding via the CLI, and verifies it using only the root CA as an isolated trust anchor #### Which issue(s) this PR fixes part of open-component-model/ocm-project#1000 <!-- Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. --> #### Testing ##### How to test the changes Generate a certificate chain and two config files, then sign and verify a component version: ```bash # Generate chain mkdir -p /tmp/ocm-pem-test && cd /tmp/ocm-pem-test openssl genrsa -out root.key 2048 openssl req -x509 -new -nodes -key root.key -sha256 -days 365 -subj "/CN=test-root" -out root.crt openssl genrsa -out leaf.key 2048 openssl req -new -key leaf.key -subj "/CN=test-leaf" -out leaf.csr openssl x509 -req -in leaf.csr -CA root.crt -CAkey root.key -CAcreateserial -sha256 -days 90 -out leaf.crt cp leaf.crt chain.pem ``` **`sign.ocmconfig`** ```yaml 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: /tmp/ocm-pem-test/leaf.key public_key_pem_file: /tmp/ocm-pem-test/chain.pem ``` **`verify.ocmconfig`** ```yaml 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: public_key_pem_file: /tmp/ocm-pem-test/root.crt ``` **`pem-signer.yaml`** ```yaml type: RSASigningConfiguration/v1alpha1 signatureAlgorithm: RSASSA-PSS signatureEncodingPolicy: PEM ``` ```bash # Sign ocm sign cv --config sign.ocmconfig --signer-spec pem-signer.yaml --dry-run <repo>//<component>:<version> ocm sign cv --config sign.ocmconfig --signer-spec pem-signer.yaml <repo>//<component>:<version> # Verify ocm verify cv --config verify.ocmconfig <repo>//<component>:<version> ``` Run the new integration test directly (requires Docker for the OCI registry): ```bash cd cli/integration && go test -run Test_Integration_Signing_PEM -v -timeout 120s ``` ##### Verification - [x] I have tested the changes locally by running `ocm` Signed-off-by: Jakob Möller <contact@jakob-moeller.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
…mponent versions (open-component-model#2147) <!-- markdownlint-disable MD041 --> #### What this PR does / why we need it Adds end-to-end CLI support and documentation for the **PEM signature encoding policy** (`signatureEncodingPolicy: PEM`), which embeds an X.509 certificate chain directly in the signature value and validates it against a verifier-supplied trust anchor. **Changes:** - `cli/cmd/sign/component-version/cmd.go` — extends the `--signer-spec` flag description and `Example` block with a second credential config showing PEM signing (`private_key_pem_file` + `public_key_pem_file` for a leaf+intermediate chain) and a second signer spec snippet for `signatureEncodingPolicy: PEM` - `cli/cmd/verify/component-version/cmd.go` — extends the `Example` block with a PEM verification credential config (root CA as trust anchor via `public_key_pem_file`), explains trust anchor isolation, and fixes two copy-paste bugs where examples said `sign` instead of `verify` - `cli/docs/reference/ocm_sign_component-version.md` / `ocm_verify_component-version.md` — regenerated from the above - `cli/integration/signing_integration_test.go` — adds `Test_Integration_Signing_PEM`: an end-to-end integration test that builds a 3-tier certificate chain (root → intermediate → leaf) at runtime, signs a component version with PEM encoding via the CLI, and verifies it using only the root CA as an isolated trust anchor #### Which issue(s) this PR fixes part of open-component-model/ocm-project#1000 <!-- Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. --> #### Testing ##### How to test the changes Generate a certificate chain and two config files, then sign and verify a component version: ```bash # Generate chain mkdir -p /tmp/ocm-pem-test && cd /tmp/ocm-pem-test openssl genrsa -out root.key 2048 openssl req -x509 -new -nodes -key root.key -sha256 -days 365 -subj "/CN=test-root" -out root.crt openssl genrsa -out leaf.key 2048 openssl req -new -key leaf.key -subj "/CN=test-leaf" -out leaf.csr openssl x509 -req -in leaf.csr -CA root.crt -CAkey root.key -CAcreateserial -sha256 -days 90 -out leaf.crt cp leaf.crt chain.pem ``` **`sign.ocmconfig`** ```yaml 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: /tmp/ocm-pem-test/leaf.key public_key_pem_file: /tmp/ocm-pem-test/chain.pem ``` **`verify.ocmconfig`** ```yaml 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: public_key_pem_file: /tmp/ocm-pem-test/root.crt ``` **`pem-signer.yaml`** ```yaml type: RSASigningConfiguration/v1alpha1 signatureAlgorithm: RSASSA-PSS signatureEncodingPolicy: PEM ``` ```bash # Sign ocm sign cv --config sign.ocmconfig --signer-spec pem-signer.yaml --dry-run <repo>//<component>:<version> ocm sign cv --config sign.ocmconfig --signer-spec pem-signer.yaml <repo>//<component>:<version> # Verify ocm verify cv --config verify.ocmconfig <repo>//<component>:<version> ``` Run the new integration test directly (requires Docker for the OCI registry): ```bash cd cli/integration && go test -run Test_Integration_Signing_PEM -v -timeout 120s ``` ##### Verification - [x] I have tested the changes locally by running `ocm` Signed-off-by: Jakob Möller <contact@jakob-moeller.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
What this PR does / why we need it
Adds end-to-end CLI support and documentation for the PEM signature encoding policy (
signatureEncodingPolicy: PEM), which embeds an X.509 certificate chain directly in the signature value and validates it against a verifier-supplied trust anchor.Changes:
cli/cmd/sign/component-version/cmd.go— extends the--signer-specflag description andExampleblock with a second credential config showing PEM signing (private_key_pem_file+public_key_pem_filefor a leaf+intermediate chain) and a second signer spec snippet forsignatureEncodingPolicy: PEMcli/cmd/verify/component-version/cmd.go— extends theExampleblock with a PEM verification credential config (root CA as trust anchor viapublic_key_pem_file), explains trust anchor isolation, and fixes two copy-paste bugs where examples saidsigninstead ofverifycli/docs/reference/ocm_sign_component-version.md/ocm_verify_component-version.md— regenerated from the abovecli/integration/signing_integration_test.go— addsTest_Integration_Signing_PEM: an end-to-end integration test that builds a 3-tier certificate chain (root → intermediate → leaf) at runtime, signs a component version with PEM encoding via the CLI, and verifies it using only the root CA as an isolated trust anchorWhich issue(s) this PR fixes
part of open-component-model/ocm-project#1000
Testing
How to test the changes
Generate a certificate chain and two config files, then sign and verify a component version:
sign.ocmconfigverify.ocmconfigpem-signer.yamlRun the new integration test directly (requires Docker for the OCI registry):
Verification
ocm