Skip to content

WIP: CNTRLPLANE-2012: Add configurable PKI support for installer-generated signer certificates#10396

Open
hasbro17 wants to merge 4 commits intoopenshift:mainfrom
hasbro17:install-config-pki
Open

WIP: CNTRLPLANE-2012: Add configurable PKI support for installer-generated signer certificates#10396
hasbro17 wants to merge 4 commits intoopenshift:mainfrom
hasbro17:install-config-pki

Conversation

@hasbro17
Copy link
Contributor

See PKI config enhancement openshift/enhancements#1882 for background

Overview:
Currently, the OpenShift installer hard-codes all signer certificates to use RSA 2048-bit keys.
This PR adds configurable PKI support to the installer, allowing users to specify cryptographic parameters for the 10 installer-generated signer certificates via a new pki field in the InstallConfig. The
feature is gated behind ConfigurablePKI (TechPreviewNoUpgrade/DevPreviewNoUpgrade).

Example usage in install-config.yaml:

  featureSet: TechPreviewNoUpgrade
  pki:
    signerCertificates:
      key:
        algorithm: ECDSA
        ecdsa:
          curve: P384

Key changes:

  • Add PKI *configv1alpha1.PKIProfile field to InstallConfig, using the official type from openshift/api (PR CNTRLPLANE-1752: Add PKI API to config.openshift.io/v1alpha1 api#2645)
  • Register ConfigurablePKI feature gate check in GatedFeatures()
  • Validate PKI config (algorithm/params matching, key size range, curve validity) via ValidatePKIProfile()
  • Refactor pkg/asset/tls/ to support both RSA and ECDSA key generation with algorithm-appropriate KeyUsage flags
  • Update SelfSignedCertKey.Generate() to accept a pkiProfile parameter
  • Update PemToPrivateKey()/PrivateKeyToPem() to handle both RSA and ECDSA key formats
  • All 10 signer certificate assets now depend on InstallConfig and pass PKI config to key generation
  • Leaf certificates (signed by these CAs) continue using RSA 2048 — unaffected by PKI config

TODO:

  • Day-2 PKI Resource: Create cluster PKI resource that persists the effective config specified in the InstallConfig
  • Validate with e2e test in origin/release that installs a cluster with ConfigurablePKI featuregate enabled and verifies the signer certs and PKI resource

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Mar 16, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 16, 2026

@hasbro17: This pull request references CNTRLPLANE-2012 which is a valid jira issue.

Details

In response to this:

See PKI config enhancement openshift/enhancements#1882 for background

Overview:
Currently, the OpenShift installer hard-codes all signer certificates to use RSA 2048-bit keys.
This PR adds configurable PKI support to the installer, allowing users to specify cryptographic parameters for the 10 installer-generated signer certificates via a new pki field in the InstallConfig. The
feature is gated behind ConfigurablePKI (TechPreviewNoUpgrade/DevPreviewNoUpgrade).

Example usage in install-config.yaml:

 featureSet: TechPreviewNoUpgrade
 pki:
   signerCertificates:
     key:
       algorithm: ECDSA
       ecdsa:
         curve: P384

Key changes:

  • Add PKI *configv1alpha1.PKIProfile field to InstallConfig, using the official type from openshift/api (PR CNTRLPLANE-1752: Add PKI API to config.openshift.io/v1alpha1 api#2645)
  • Register ConfigurablePKI feature gate check in GatedFeatures()
  • Validate PKI config (algorithm/params matching, key size range, curve validity) via ValidatePKIProfile()
  • Refactor pkg/asset/tls/ to support both RSA and ECDSA key generation with algorithm-appropriate KeyUsage flags
  • Update SelfSignedCertKey.Generate() to accept a pkiProfile parameter
  • Update PemToPrivateKey()/PrivateKeyToPem() to handle both RSA and ECDSA key formats
  • All 10 signer certificate assets now depend on InstallConfig and pass PKI config to key generation
  • Leaf certificates (signed by these CAs) continue using RSA 2048 — unaffected by PKI config

TODO:

  • Day-2 PKI Resource: Create cluster PKI resource that persists the effective config specified in the InstallConfig
  • Validate with e2e test in origin/release that installs a cluster with ConfigurablePKI featuregate enabled and verifies the signer certs and PKI resource

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.

@hasbro17 hasbro17 changed the title CNTRLPLANE-2012: Add configurable PKI support for installer-generated signer certificates WIP: CNTRLPLANE-2012: Add configurable PKI support for installer-generated signer certificates Mar 16, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 16, 2026

Important

Review skipped

Auto reviews are limited based on label configuration.

🚫 Excluded labels (none allowed) (1)
  • do-not-merge/work-in-progress

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 44cceb98-bb36-405b-b42c-90e68e3d230d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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

Tip

CodeRabbit can use OpenGrep to find security vulnerabilities and bugs across 17+ programming languages.

OpenGrep is compatible with Semgrep configurations. Add an opengrep.yml or semgrep.yml configuration file to your project to enable OpenGrep analysis.

@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 Mar 16, 2026
@openshift-ci openshift-ci bot requested review from andfasano and tthvo March 16, 2026 20:15
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 16, 2026

[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 dtantsur 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

@hasbro17
Copy link
Contributor Author

The unit tests cover the following areas but add quite a bit of volume to this PR:

  • PKI helpers
  • PKI validation (valid/invalid RSA, ECDSA, mismatches)
  • Key generation (RSA/ECDSA), KeyUsage flags, signature algorithm auto-detection
  • PEM encode/decode roundtrip (RSA + ECDSA)
  • Validation integration in ValidateInstallConfig
  • ConfigurablePKI feature gate (TechPreview, CustomNoUpgrade, disabled)
  • SelfSignedCertKey.Generate() with PKI profiles
  • Cross-algorithm signing (ECDSA CA → RSA leaf, cert chain verification)

I've split most of the unit tests into their own commit, and looking at the actual PKI integration and TLS changes commit-wise would make it easier to review

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (1)
pkg/asset/tls/utils_test.go (1)

57-89: Add a PKCS#8 case for the new parser branch.

PemToPrivateKey now has a "PRIVATE KEY" path in pkg/asset/tls/utils.go, but this suite still only exercises PKCS#1 and EC blocks. One PKCS#8 RSA/ECDSA case would keep that branch from regressing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/asset/tls/utils_test.go` around lines 57 - 89, Test suite is missing a
PKCS#8 ("PRIVATE KEY") case for the new PemToPrivateKey branch; add a subtest
that takes an RSA or ECDSA private key (use GenerateRSAPrivateKey or
GenerateECDSAPrivateKey), marshal it with x509.MarshalPKCS8PrivateKey to produce
PKCS#8 bytes, wrap those bytes in a PEM block labeled "PRIVATE KEY" (similar to
PrivateKeyToPem), feed that PEM to PemToPrivateKey and assert no error and that
the returned value is the expected *rsa.PrivateKey or *ecdsa.PrivateKey type so
the PKCS#8 branch is exercised.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@data/data/install.openshift.io_installconfigs.yaml`:
- Around line 4898-4899: The schema currently requires pki.defaults but the spec
states it is auto-populated; update the YAML schema so pki.defaults is optional
(remove it from any required[] lists or mark it nullable/optional in the pki
object definition) and ensure the pki object still allows a signerCertificates
override without defaults present; apply the same change where pki.defaults is
similarly enforced (the other occurrence referenced) and update the pki.defaults
description to note it is auto-populated when omitted.
- Around line 4902-5152: The schema exposes clientCertificates,
servingCertificates, and defaults as general PKI overrides but the installer
only applies them to installer-generated signer certs—remove or hide these
fields (clientCertificates, servingCertificates, defaults) from the
InstallConfig schema in install.openshift.io_installconfigs.yaml so the API does
not promise unsupported overrides; alternatively, if you must keep them for
compatibility, update their descriptions to explicitly state they only affect
installer-generated signer certificates and add a schema marker (e.g.,
x-kubernetes-hidden or a clear deprecation note) so callers are not misled.
Ensure you update the definitions and any x-kubernetes-validations that
reference these symbols (clientCertificates, servingCertificates, defaults) so
the schema and documentation consistently reflect the limited scope.

In `@docs/user/customization.md`:
- Around line 57-66: The docs currently mention that `defaults` is
auto-populated but never documents `defaults.key`, causing confusion about
whether `defaults.key` is a user-supplied field or internal-only; update the
`pki` section to either (A) document `defaults.key` under `signerCertificates`
(describe its shape and allowed subfields `key.algorithm`, `key.rsa.keySize`,
`key.ecdsa.curve`, valid values and whether it may be provided by users), or (B)
remove/clarify the statement that `defaults` is auto-populated and stop
referring to `defaults.key` as if it were user-configurable; reference `pki`,
`signerCertificates`, and `defaults.key` when making the change.

In `@pkg/asset/tls/tls.go`:
- Around line 266-273: The current code clobbers any caller-set cfg.KeyUsages by
replacing adjustedCfg.KeyUsages with baseUsage; instead preserve caller bits:
compute baseUsage := keyUsageForAlgorithm(params.Algorithm) and then set
adjustedCfg.KeyUsages = cfg.KeyUsages | baseUsage (and if cfg.IsCA also OR
x509.KeyUsageCertSign) so existing explicit bits on cfg.KeyUsages remain honored
while still applying the algorithm-derived and CA bits.

In `@pkg/asset/tls/utils.go`:
- Around line 86-95: The PKCS#8 branch currently calls x509.ParsePKCS8PrivateKey
which can return key types other than RSA/ECDSA and those will later break
PrivateKeyToPem and generateSubjectKeyID; change the "PRIVATE KEY" case
(x509.ParsePKCS8PrivateKey) to assert the returned key is either *rsa.PrivateKey
or *ecdsa.PrivateKey and return an explicit error for any other types so
unsupported PKCS#8 keys are rejected at decode time (refer to the "PRIVATE KEY"
case, x509.ParsePKCS8PrivateKey, and the downstream uses PrivateKeyToPem and
generateSubjectKeyID).

In `@pkg/types/pki/validation.go`:
- Around line 19-23: The current guard in the signer key validation (using
profile.SignerCertificates.Key.Algorithm != "") lets partial key configs (e.g.,
rsa.keySize or ecdsa.curve) skip validation and be silently ignored; change the
check so ValidateKeyConfig is invoked whenever the Key block is non-empty (i.e.,
any of Key.Algorithm, Key.KeySize, Key.Curve or other key fields are set) rather
than only when Algorithm is set, and make the same non-empty-key detection
change in GetEffectiveSignerKeyConfig so fallback/default merging is validated
correctly; add regression tests covering partial defaults and partial
signerCertificates.key inputs to ensure these are validated.

In `@pkg/types/validation/installconfig.go`:
- Around line 284-286: The PKI profile validation call in ValidatePKIProfile
(invoked from install-config validation when c.PKI != nil) currently only checks
profile.SignerCertificates.Key and therefore misses validating pki.defaults.key;
update pkivalidation.ValidatePKIProfile to explicitly validate the defaults.key
field (and any related key fields under profile.Defaults) using the same key
validation logic as for SignerCertificates.Key so invalid default keys fail fast
during install-config validation rather than later during certificate
generation.

---

Nitpick comments:
In `@pkg/asset/tls/utils_test.go`:
- Around line 57-89: Test suite is missing a PKCS#8 ("PRIVATE KEY") case for the
new PemToPrivateKey branch; add a subtest that takes an RSA or ECDSA private key
(use GenerateRSAPrivateKey or GenerateECDSAPrivateKey), marshal it with
x509.MarshalPKCS8PrivateKey to produce PKCS#8 bytes, wrap those bytes in a PEM
block labeled "PRIVATE KEY" (similar to PrivateKeyToPem), feed that PEM to
PemToPrivateKey and assert no error and that the returned value is the expected
*rsa.PrivateKey or *ecdsa.PrivateKey type so the PKCS#8 branch is exercised.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f0fc8704-7ecb-42db-a25a-ef8fbe0e10af

📥 Commits

Reviewing files that changed from the base of the PR and between 3528292 and dfa87a6.

📒 Files selected for processing (34)
  • data/data/install.openshift.io_installconfigs.yaml
  • docs/user/customization.md
  • pkg/asset/ignition/machine/arbiter_ignition_customizations_test.go
  • pkg/asset/ignition/machine/arbiter_test.go
  • pkg/asset/ignition/machine/master_ignition_customizations_test.go
  • pkg/asset/ignition/machine/master_test.go
  • pkg/asset/ignition/machine/worker_ignition_customizations_test.go
  • pkg/asset/ignition/machine/worker_test.go
  • pkg/asset/tls/adminkubeconfig.go
  • pkg/asset/tls/aggregator.go
  • pkg/asset/tls/apiserver.go
  • pkg/asset/tls/boundsasigningkey.go
  • pkg/asset/tls/certkey.go
  • pkg/asset/tls/certkey_test.go
  • pkg/asset/tls/ironictls.go
  • pkg/asset/tls/kubecontrolplane.go
  • pkg/asset/tls/kubelet.go
  • pkg/asset/tls/root.go
  • pkg/asset/tls/tls.go
  • pkg/asset/tls/tls_test.go
  • pkg/asset/tls/utils.go
  • pkg/asset/tls/utils_test.go
  • pkg/types/defaults/installconfig.go
  • pkg/types/defaults/installconfig_test.go
  • pkg/types/defaults/validation/featuregates.go
  • pkg/types/installconfig.go
  • pkg/types/pki/helpers.go
  • pkg/types/pki/helpers_test.go
  • pkg/types/pki/validation.go
  • pkg/types/pki/validation_test.go
  • pkg/types/validation/featuregate_test.go
  • pkg/types/validation/installconfig.go
  • pkg/types/validation/installconfig_test.go
  • pkg/types/zz_generated.deepcopy.go

Comment on lines +4898 to +4899
When specified, the installer uses signerCertificates to configure the installer-generated
signer certificates. The defaults field is auto-populated if not provided.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Make pki.defaults optional in the schema.

Lines 4898-4899 say defaults is auto-populated when omitted, but Lines 5237-5238 require it. Any schema-based validation will reject the intended defaulting path, including configs that only override signerCertificates.

Also applies to: 5237-5238

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@data/data/install.openshift.io_installconfigs.yaml` around lines 4898 - 4899,
The schema currently requires pki.defaults but the spec states it is
auto-populated; update the YAML schema so pki.defaults is optional (remove it
from any required[] lists or mark it nullable/optional in the pki object
definition) and ensure the pki object still allows a signerCertificates override
without defaults present; apply the same change where pki.defaults is similarly
enforced (the other occurrence referenced) and update the pki.defaults
description to note it is auto-populated when omitted.

Comment on lines +4902 to +5152
clientCertificates:
description: |-
clientCertificates optionally overrides certificate parameters for
client authentication certificates used to authenticate to servers.
When set, these parameters take precedence over defaults for all client certificates.
When omitted, the defaults are used for client certificates.
minProperties: 1
properties:
key:
description: |-
key specifies the cryptographic parameters for the certificate's key pair.
Currently this is the only configurable parameter. When omitted in an
overrides entry, the key configuration from defaults is used.
properties:
algorithm:
description: |-
algorithm specifies the key generation algorithm.
Valid values are "RSA" and "ECDSA".

When set to RSA, the rsa field must be specified and the generated key
will be an RSA key with the configured key size.

When set to ECDSA, the ecdsa field must be specified and the generated key
will be an ECDSA key using the configured elliptic curve.
enum:
- RSA
- ECDSA
type: string
ecdsa:
description: |-
ecdsa specifies ECDSA key parameters.
Required when algorithm is ECDSA, and forbidden otherwise.
properties:
curve:
description: |-
curve specifies the NIST elliptic curve for ECDSA keys.
Valid values are "P256", "P384", and "P521".

When set to P256, the NIST P-256 curve (also known as secp256r1) is used,
providing 128-bit security.

When set to P384, the NIST P-384 curve (also known as secp384r1) is used,
providing 192-bit security.

When set to P521, the NIST P-521 curve (also known as secp521r1) is used,
providing 256-bit security.
enum:
- P256
- P384
- P521
type: string
required:
- curve
type: object
rsa:
description: |-
rsa specifies RSA key parameters.
Required when algorithm is RSA, and forbidden otherwise.
properties:
keySize:
description: |-
keySize specifies the size of RSA keys in bits.
Valid values are multiples of 1024 from 2048 to 8192.
format: int32
maximum: 8192
minimum: 2048
multipleOf: 1024
type: integer
required:
- keySize
type: object
required:
- algorithm
type: object
x-kubernetes-validations:
- message: rsa is required when algorithm is RSA, and forbidden
otherwise
rule: 'has(self.algorithm) && self.algorithm == ''RSA'' ? has(self.rsa)
: !has(self.rsa)'
- message: ecdsa is required when algorithm is ECDSA, and forbidden
otherwise
rule: 'has(self.algorithm) && self.algorithm == ''ECDSA'' ? has(self.ecdsa)
: !has(self.ecdsa)'
type: object
defaults:
description: |-
defaults specifies the default certificate configuration that applies
to all certificates unless overridden by a category override.
properties:
key:
description: |-
key specifies the cryptographic parameters for the certificate's key pair.
This field is required in defaults to ensure all certificates have a
well-defined key configuration.
properties:
algorithm:
description: |-
algorithm specifies the key generation algorithm.
Valid values are "RSA" and "ECDSA".

When set to RSA, the rsa field must be specified and the generated key
will be an RSA key with the configured key size.

When set to ECDSA, the ecdsa field must be specified and the generated key
will be an ECDSA key using the configured elliptic curve.
enum:
- RSA
- ECDSA
type: string
ecdsa:
description: |-
ecdsa specifies ECDSA key parameters.
Required when algorithm is ECDSA, and forbidden otherwise.
properties:
curve:
description: |-
curve specifies the NIST elliptic curve for ECDSA keys.
Valid values are "P256", "P384", and "P521".

When set to P256, the NIST P-256 curve (also known as secp256r1) is used,
providing 128-bit security.

When set to P384, the NIST P-384 curve (also known as secp384r1) is used,
providing 192-bit security.

When set to P521, the NIST P-521 curve (also known as secp521r1) is used,
providing 256-bit security.
enum:
- P256
- P384
- P521
type: string
required:
- curve
type: object
rsa:
description: |-
rsa specifies RSA key parameters.
Required when algorithm is RSA, and forbidden otherwise.
properties:
keySize:
description: |-
keySize specifies the size of RSA keys in bits.
Valid values are multiples of 1024 from 2048 to 8192.
format: int32
maximum: 8192
minimum: 2048
multipleOf: 1024
type: integer
required:
- keySize
type: object
required:
- algorithm
type: object
x-kubernetes-validations:
- message: rsa is required when algorithm is RSA, and forbidden
otherwise
rule: 'has(self.algorithm) && self.algorithm == ''RSA'' ? has(self.rsa)
: !has(self.rsa)'
- message: ecdsa is required when algorithm is ECDSA, and forbidden
otherwise
rule: 'has(self.algorithm) && self.algorithm == ''ECDSA'' ? has(self.ecdsa)
: !has(self.ecdsa)'
required:
- key
type: object
servingCertificates:
description: |-
servingCertificates optionally overrides certificate parameters for
TLS server certificates used to serve HTTPS endpoints.
When set, these parameters take precedence over defaults for all serving certificates.
When omitted, the defaults are used for serving certificates.
minProperties: 1
properties:
key:
description: |-
key specifies the cryptographic parameters for the certificate's key pair.
Currently this is the only configurable parameter. When omitted in an
overrides entry, the key configuration from defaults is used.
properties:
algorithm:
description: |-
algorithm specifies the key generation algorithm.
Valid values are "RSA" and "ECDSA".

When set to RSA, the rsa field must be specified and the generated key
will be an RSA key with the configured key size.

When set to ECDSA, the ecdsa field must be specified and the generated key
will be an ECDSA key using the configured elliptic curve.
enum:
- RSA
- ECDSA
type: string
ecdsa:
description: |-
ecdsa specifies ECDSA key parameters.
Required when algorithm is ECDSA, and forbidden otherwise.
properties:
curve:
description: |-
curve specifies the NIST elliptic curve for ECDSA keys.
Valid values are "P256", "P384", and "P521".

When set to P256, the NIST P-256 curve (also known as secp256r1) is used,
providing 128-bit security.

When set to P384, the NIST P-384 curve (also known as secp384r1) is used,
providing 192-bit security.

When set to P521, the NIST P-521 curve (also known as secp521r1) is used,
providing 256-bit security.
enum:
- P256
- P384
- P521
type: string
required:
- curve
type: object
rsa:
description: |-
rsa specifies RSA key parameters.
Required when algorithm is RSA, and forbidden otherwise.
properties:
keySize:
description: |-
keySize specifies the size of RSA keys in bits.
Valid values are multiples of 1024 from 2048 to 8192.
format: int32
maximum: 8192
minimum: 2048
multipleOf: 1024
type: integer
required:
- keySize
type: object
required:
- algorithm
type: object
x-kubernetes-validations:
- message: rsa is required when algorithm is RSA, and forbidden
otherwise
rule: 'has(self.algorithm) && self.algorithm == ''RSA'' ? has(self.rsa)
: !has(self.rsa)'
- message: ecdsa is required when algorithm is ECDSA, and forbidden
otherwise
rule: 'has(self.algorithm) && self.algorithm == ''ECDSA'' ? has(self.ecdsa)
: !has(self.ecdsa)'
type: object
Copy link

@coderabbitai coderabbitai bot Mar 16, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don't expose PKI overrides the installer does not honor.

This feature currently applies PKI settings only to installer-generated signer certs. Exposing clientCertificates, servingCertificates, and defaults as if they affect all certificates makes the InstallConfig API promise knobs that will not change generated leaf certs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@data/data/install.openshift.io_installconfigs.yaml` around lines 4902 - 5152,
The schema exposes clientCertificates, servingCertificates, and defaults as
general PKI overrides but the installer only applies them to installer-generated
signer certs—remove or hide these fields (clientCertificates,
servingCertificates, defaults) from the InstallConfig schema in
install.openshift.io_installconfigs.yaml so the API does not promise unsupported
overrides; alternatively, if you must keep them for compatibility, update their
descriptions to explicitly state they only affect installer-generated signer
certificates and add a schema marker (e.g., x-kubernetes-hidden or a clear
deprecation note) so callers are not misled. Ensure you update the definitions
and any x-kubernetes-validations that reference these symbols
(clientCertificates, servingCertificates, defaults) so the schema and
documentation consistently reflect the limited scope.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@sanchezl The enhancement mentions we will only support Day-1 (installer) support for signer certificate configuration.

I've currently embedded the PKIProfile type into the InstallConfig to stay aligned with the official API and keep the door open for supporting other fields.

So right now in the API type PKIProfile: Defaults is +required but we make it effectively optional in the installer by auto-populating it in SetInstallConfigDefaults()

So the happy path from the enhancement works where we don't have to specify Defaults:

pki:
  signerCertificates:
    key:
      algorithm: RSA
      rsa:
        keySize: 4096

But you could also do defaults only:

pki:
  defaults:
    key:
      algorithm: RSA
      rsa:
        keySize: 4096

Since no signerCertificates override is specified, signer certs fall back to defaults and use RSA 4096. Currently only signers consume this, but eventually this could extend to servingCertificates/clientCertificates overrides.

And you could even do Custom defaults + signer override:

pki:
  defaults:
    key:
      algorithm: RSA
      rsa:
        keySize: 4096
  signerCertificates:
    key:
      algorithm: ECDSA
      ecdsa:
        curve: P521

Here Signer certs use ECDSA P-521 (override takes precedence) so the defaults field is redundant until we support leaf cert customization as well.

So my question is whether we should allow fields other than signerCertificates in the InstallConfig today with the anticipation that we would support them before GA?
Or should we hide everything else and wait until we do decide to support them.

Copy link

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Precedence summary for signers as it is right now

  ┌────────────────────────────────────┬──────────────────────────────────────────────────────────────────┐
  │               Config               │                    Effective signer algorithm                    │
  ├────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
  │ No pki field                       │ RSA 2048 (hardcoded default)                                     │
  ├────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
  │ pki: {}                            │ RSA 2048 (auto-populated defaults)                               │
  ├────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
  │ pki.defaults only                  │ Uses defaults.key                                                │
  ├────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
  │ pki.signerCertificates only        │ Uses signerCertificates.key (defaults auto-populated but unused) │
  ├────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
  │ Both defaults + signerCertificates │ signerCertificates wins for signers                              │
  └────────────────────────────────────┴──────────────────────────────────────────────────────────────────┘

Copy link
Contributor

Choose a reason for hiding this comment

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

The installer team will be very weary of adding too much config to the install-config.yaml. As such we limited it to only signerCertificates.

We should define our own PKI type with only signerCertificates. This way:

  • The CRD schema only shows what users can actually configure
  • The installer team controls when/if new fields are adopted
  • No risk of upstream API changes silently exposing unsupported config

For the Day-2 PKI resource creation, we should:

  1. Start with library-go/pkg/pki.DefaultPKIProfile() as the base (or a similar local copy until library-go PR merges)
  2. Merge the user's signerCertificates config on top and create the Day-2 PKI resource from the merged result

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I was leaning that way as well but wasn't sure. Will strip out the unneccessary config for now and keep it to signerCertificates

Comment on lines +57 to +66
* `pki` (optional object): Configures cryptographic parameters for installer-generated signer certificates.
Requires the `ConfigurablePKI` feature gate (set `featureSet: TechPreviewNoUpgrade` or use `CustomNoUpgrade` with `featureGates`).
When omitted, all signer certificates use RSA 2048 (existing default behavior).
* `signerCertificates` (optional object): Overrides key parameters for all signer certificates.
* `key` (optional object): Key generation parameters.
* `algorithm` (required string): The key algorithm. Valid values are `RSA` and `ECDSA`.
* `rsa` (optional object): RSA-specific parameters. Required when `algorithm` is `RSA`.
* `keySize` (required integer): Key size in bits. Valid values are multiples of 1024 from 2048 to 8192.
* `ecdsa` (optional object): ECDSA-specific parameters. Required when `algorithm` is `ECDSA`.
* `curve` (required string): The elliptic curve. Valid values are `P256`, `P384`, and `P521`.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Document defaults.key or stop referring to it.

Line 304 says defaults is auto-populated, but the field list here only describes signerCertificates. As written, users can’t tell whether defaults.key is supported input or just internal defaulting behavior.

Also applies to: 304-304

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/user/customization.md` around lines 57 - 66, The docs currently mention
that `defaults` is auto-populated but never documents `defaults.key`, causing
confusion about whether `defaults.key` is a user-supplied field or
internal-only; update the `pki` section to either (A) document `defaults.key`
under `signerCertificates` (describe its shape and allowed subfields
`key.algorithm`, `key.rsa.keySize`, `key.ecdsa.curve`, valid values and whether
it may be provided by users), or (B) remove/clarify the statement that
`defaults` is auto-populated and stop referring to `defaults.key` as if it were
user-configurable; reference `pki`, `signerCertificates`, and `defaults.key`
when making the change.

Comment on lines +266 to +273
// Set KeyUsage based on algorithm — ECDSA keys cannot perform key encipherment
adjustedCfg := *cfg
baseUsage := keyUsageForAlgorithm(params.Algorithm)
if cfg.IsCA {
adjustedCfg.KeyUsages = baseUsage | x509.KeyUsageCertSign
} else {
adjustedCfg.KeyUsages = baseUsage
}
Copy link

@coderabbitai coderabbitai bot Mar 16, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Preserve caller-specified KeyUsages here.

These lines rebuild adjustedCfg.KeyUsages from scratch, so any explicit bits on cfg.KeyUsages disappear. That’s broader than the ECDSA KeyEncipherment fix and changes the semantics of CertCfg.KeyUsages.

Suggested fix
-	// Set KeyUsage based on algorithm — ECDSA keys cannot perform key encipherment
-	adjustedCfg := *cfg
-	baseUsage := keyUsageForAlgorithm(params.Algorithm)
-	if cfg.IsCA {
-		adjustedCfg.KeyUsages = baseUsage | x509.KeyUsageCertSign
-	} else {
-		adjustedCfg.KeyUsages = baseUsage
-	}
+	// Default KeyUsage when unset, but otherwise preserve caller intent and
+	// only remove bits that are incompatible with the selected algorithm.
+	adjustedCfg := *cfg
+	if adjustedCfg.KeyUsages == 0 {
+		adjustedCfg.KeyUsages = keyUsageForAlgorithm(params.Algorithm)
+	}
+	if params.Algorithm == configv1alpha1.KeyAlgorithmECDSA {
+		adjustedCfg.KeyUsages &^= x509.KeyUsageKeyEncipherment
+	}
+	if cfg.IsCA {
+		adjustedCfg.KeyUsages |= x509.KeyUsageCertSign
+	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Set KeyUsage based on algorithm — ECDSA keys cannot perform key encipherment
adjustedCfg := *cfg
baseUsage := keyUsageForAlgorithm(params.Algorithm)
if cfg.IsCA {
adjustedCfg.KeyUsages = baseUsage | x509.KeyUsageCertSign
} else {
adjustedCfg.KeyUsages = baseUsage
}
// Default KeyUsage when unset, but otherwise preserve caller intent and
// only remove bits that are incompatible with the selected algorithm.
adjustedCfg := *cfg
if adjustedCfg.KeyUsages == 0 {
adjustedCfg.KeyUsages = keyUsageForAlgorithm(params.Algorithm)
}
if params.Algorithm == configv1alpha1.KeyAlgorithmECDSA {
adjustedCfg.KeyUsages &^= x509.KeyUsageKeyEncipherment
}
if cfg.IsCA {
adjustedCfg.KeyUsages |= x509.KeyUsageCertSign
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/asset/tls/tls.go` around lines 266 - 273, The current code clobbers any
caller-set cfg.KeyUsages by replacing adjustedCfg.KeyUsages with baseUsage;
instead preserve caller bits: compute baseUsage :=
keyUsageForAlgorithm(params.Algorithm) and then set adjustedCfg.KeyUsages =
cfg.KeyUsages | baseUsage (and if cfg.IsCA also OR x509.KeyUsageCertSign) so
existing explicit bits on cfg.KeyUsages remain honored while still applying the
algorithm-derived and CA bits.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The caller-set KeyUsages are wrong for ECDSA anyway.
OR-ing caller bits would be incorrect because the existing callers all hardcoded the RSA pattern (KeyEncipherment | DigitalSignature | CertSign), which would re-introduce KeyEncipherment on ECDSA certs.

That's exactly what we need to prevent.

However I'll remove KeyUsages from all 10 signer asset CertCfgs entirely. Callers will no longer set a value that gets unconditionally discarded.
GenerateSelfSignedCertificate is the sole owner of KeyUsages for self-signed certs, setting it based on the key algorithm.

Copy link

Choose a reason for hiding this comment

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

@hasbro17, that makes sense — centralising ownership of KeyUsages in GenerateSelfSignedCertificate is cleaner than trying to mask individual incompatible bits from callers that already carry RSA-centric defaults. Removing the field from all 10 CertCfg sites is the right call here.


📝 Learnings were identified and not saved (knowledge base disabled). Enable

Comment on lines +86 to +95
switch block.Type {
case "RSA PRIVATE KEY":
return x509.ParsePKCS1PrivateKey(block.Bytes)
case "EC PRIVATE KEY":
return x509.ParseECPrivateKey(block.Bytes)
case "PRIVATE KEY":
return x509.ParsePKCS8PrivateKey(block.Bytes)
default:
return nil, fmt.Errorf("unsupported PEM block type: %s", block.Type)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'PemToPrivateKey call sites:\n'
rg -n -C2 '\bPemToPrivateKey\s*\('

printf '\nPrivateKeyToPem supported key types:\n'
sed -n '15,39p' pkg/asset/tls/utils.go

printf '\ngenerateSubjectKeyID supported key types:\n'
sed -n '204,219p' pkg/asset/tls/tls.go

Repository: openshift/installer

Length of output: 5134


Reject unsupported PKCS#8 key types at decode time.

x509.ParsePKCS8PrivateKey accepts key types beyond RSA/ECDSA. The rest of this package (PrivateKeyToPem and generateSubjectKeyID) only supports RSA/ECDSA keys, so this branch can admit unsupported keys that will fail later when used with certificate generation paths.

Suggested fix
 	case "PRIVATE KEY":
-		return x509.ParsePKCS8PrivateKey(block.Bytes)
+		key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
+		if err != nil {
+			return nil, err
+		}
+		switch key.(type) {
+		case *rsa.PrivateKey, *ecdsa.PrivateKey:
+			return key, nil
+		default:
+			return nil, fmt.Errorf("unsupported PKCS#8 private key type: %T", key)
+		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/asset/tls/utils.go` around lines 86 - 95, The PKCS#8 branch currently
calls x509.ParsePKCS8PrivateKey which can return key types other than RSA/ECDSA
and those will later break PrivateKeyToPem and generateSubjectKeyID; change the
"PRIVATE KEY" case (x509.ParsePKCS8PrivateKey) to assert the returned key is
either *rsa.PrivateKey or *ecdsa.PrivateKey and return an explicit error for any
other types so unsupported PKCS#8 keys are rejected at decode time (refer to the
"PRIVATE KEY" case, x509.ParsePKCS8PrivateKey, and the downstream uses
PrivateKeyToPem and generateSubjectKeyID).

Comment on lines +19 to +23
// Validate signerCertificates override if Algorithm is set (non-zero value)
if profile.SignerCertificates.Key.Algorithm != "" {
allErrs = append(allErrs, ValidateKeyConfig(profile.SignerCertificates.Key,
fldPath.Child("signerCertificates", "key"), fips)...)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate populated key blocks even when algorithm is omitted.

The guard on Line 20 lets partial configs like rsa.keySize: 4096 or ecdsa.curve: P384 bypass validation entirely. GetEffectiveSignerKeyConfig() in pkg/types/pki/helpers.go then uses the same Algorithm != "" check, so those inputs are silently ignored, and profile.Defaults.Key is never validated before being used as the fallback. That means broken PKI config can pass install-config validation and only fail or change behavior later during cert generation.

Suggested fix
 func ValidatePKIProfile(profile *configv1alpha1.PKIProfile, fldPath *field.Path, fips bool) field.ErrorList {
 	allErrs := field.ErrorList{}

 	if profile == nil {
 		return allErrs
 	}

-	// Validate signerCertificates override if Algorithm is set (non-zero value)
-	if profile.SignerCertificates.Key.Algorithm != "" {
+	if profile.Defaults.Key.Algorithm != "" ||
+		profile.Defaults.Key.RSA.KeySize != 0 ||
+		profile.Defaults.Key.ECDSA.Curve != "" {
+		allErrs = append(allErrs, ValidateKeyConfig(profile.Defaults.Key,
+			fldPath.Child("defaults", "key"), fips)...)
+	}
+
+	if profile.SignerCertificates.Key.Algorithm != "" ||
+		profile.SignerCertificates.Key.RSA.KeySize != 0 ||
+		profile.SignerCertificates.Key.ECDSA.Curve != "" {
 		allErrs = append(allErrs, ValidateKeyConfig(profile.SignerCertificates.Key,
 			fldPath.Child("signerCertificates", "key"), fips)...)
 	}

 	return allErrs
 }

Please add regression cases for partial defaults.key / signerCertificates.key inputs with this change.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Validate signerCertificates override if Algorithm is set (non-zero value)
if profile.SignerCertificates.Key.Algorithm != "" {
allErrs = append(allErrs, ValidateKeyConfig(profile.SignerCertificates.Key,
fldPath.Child("signerCertificates", "key"), fips)...)
}
func ValidatePKIProfile(profile *configv1alpha1.PKIProfile, fldPath *field.Path, fips bool) field.ErrorList {
allErrs := field.ErrorList{}
if profile == nil {
return allErrs
}
if profile.Defaults.Key.Algorithm != "" ||
profile.Defaults.Key.RSA.KeySize != 0 ||
profile.Defaults.Key.ECDSA.Curve != "" {
allErrs = append(allErrs, ValidateKeyConfig(profile.Defaults.Key,
fldPath.Child("defaults", "key"), fips)...)
}
if profile.SignerCertificates.Key.Algorithm != "" ||
profile.SignerCertificates.Key.RSA.KeySize != 0 ||
profile.SignerCertificates.Key.ECDSA.Curve != "" {
allErrs = append(allErrs, ValidateKeyConfig(profile.SignerCertificates.Key,
fldPath.Child("signerCertificates", "key"), fips)...)
}
return allErrs
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/types/pki/validation.go` around lines 19 - 23, The current guard in the
signer key validation (using profile.SignerCertificates.Key.Algorithm != "")
lets partial key configs (e.g., rsa.keySize or ecdsa.curve) skip validation and
be silently ignored; change the check so ValidateKeyConfig is invoked whenever
the Key block is non-empty (i.e., any of Key.Algorithm, Key.KeySize, Key.Curve
or other key fields are set) rather than only when Algorithm is set, and make
the same non-empty-key detection change in GetEffectiveSignerKeyConfig so
fallback/default merging is validated correctly; add regression tests covering
partial defaults and partial signerCertificates.key inputs to ensure these are
validated.

Comment on lines +284 to +286
if c.PKI != nil {
allErrs = append(allErrs, pkivalidation.ValidatePKIProfile(c.PKI, field.NewPath("pki"), c.FIPS)...)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate pki.defaults.key as part of install-config validation.

At Line 285, ValidatePKIProfile is called, but current validator logic (in pkg/types/pki/validation.go) only checks profile.SignerCertificates.Key. Invalid pki.defaults.key can slip through and fail later in certificate generation instead of returning a clean config error.

Proposed fix
--- a/pkg/types/pki/validation.go
+++ b/pkg/types/pki/validation.go
@@
 func ValidatePKIProfile(profile *configv1alpha1.PKIProfile, fldPath *field.Path, fips bool) field.ErrorList {
 	allErrs := field.ErrorList{}
@@
+	// Validate defaults key config if Algorithm is set (non-zero value)
+	if profile.Defaults.Key.Algorithm != "" {
+		allErrs = append(allErrs, ValidateKeyConfig(
+			profile.Defaults.Key,
+			fldPath.Child("defaults", "key"),
+			fips,
+		)...)
+	}
+
 	// Validate signerCertificates override if Algorithm is set (non-zero value)
 	if profile.SignerCertificates.Key.Algorithm != "" {
 		allErrs = append(allErrs, ValidateKeyConfig(profile.SignerCertificates.Key,
 			fldPath.Child("signerCertificates", "key"), fips)...)
 	}

As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/types/validation/installconfig.go` around lines 284 - 286, The PKI
profile validation call in ValidatePKIProfile (invoked from install-config
validation when c.PKI != nil) currently only checks
profile.SignerCertificates.Key and therefore misses validating pki.defaults.key;
update pkivalidation.ValidatePKIProfile to explicitly validate the defaults.key
field (and any related key fields under profile.Defaults) using the same key
validation logic as for SignerCertificates.Key so invalid default keys fail fast
during install-config validation rather than later during certificate
generation.

@hasbro17
Copy link
Contributor Author

Since the flow from specifying the PKI config to signer cert/key generation is a bit long the following flow helps me visualize all the relevant pieces that this PR is modifying.
Config validation

flowchart LR
      A["install-config.yaml<br/><code>pki.signerCertificates</code>"] --> B["SetInstallConfigDefaults()<br/>auto-populate defaults"]
      B --> C["ValidateFeatureSet()<br/>ConfigurablePKI gate"]
      B --> D["ValidatePKIProfile()<br/>algorithm, keySize, curve"]
      C --> E["10 Signer Assets"]
      D --> E

      style A fill:#e1f5fe
      style E fill:#c8e6c9
Loading

Key generation

flowchart LR
      A["SelfSignedCertKey.Generate(pkiProfile)"] --> B["GetEffectiveSignerKeyConfig()<br/>signer override → defaults → RSA 2048"]
      B --> C{"Algorithm?"}
      C -->|RSA| D["GenerateRSAPrivateKey(keySize)<br/>KeyUsage: Sign+Encipher+CertSign"]
      C -->|ECDSA| E["GenerateECDSAPrivateKey(curve)<br/>KeyUsage: Sign+CertSign"]
      D --> F["SelfSignedCertificate(crypto.Signer)<br/>SignatureAlg auto-detected"]
      E --> F
      F --> G["Signer CA cert+key (PEM)"]
      G --> H["SignedCertKey.Generate()<br/>Leaf certs: always RSA 2048"]

      style A fill:#e1f5fe
      style G fill:#c8e6c9
      style H fill:#fff9c4
Loading

@hasbro17
Copy link
Contributor Author

/test ?

@hasbro17
Copy link
Contributor Author

/test e2e-aws-ovn-techpreview
/test e2e-gcp-ovn-techpreview

Add configurable PKI support to InstallConfig behind the ConfigurablePKI
feature gate, allowing users to specify cryptographic parameters for
installer-generated signer certificates.

Key changes:
- Define custom PKIConfig type with only signerCertificates field
- Add PKI *PKIConfig field to InstallConfig
- Add ConfigurablePKI feature gate entry in GatedFeatures()
- Create pkg/types/pki/ with validation functions
- Wire PKI validation into ValidateInstallConfig()
- Require signerCertificates.key when pki is present (pki: {} is invalid)

Assisted-by: Claude Code (Opus 4.6)
Update pkg/asset/tls/ to generate signer certificates with either RSA
or ECDSA keys based on the PKI config from InstallConfig. Leaf
certificates continue to use RSA 2048.

Key changes:
- Add DefaultRSAKeySize/DefaultKeyAlgorithm constants
- Add RSA/ECDSA key generation functions and PEM encode/decode support
- Change SelfSignedCertificate to accept crypto.Signer
- Change SignedCertificate/GenerateSignedCertificate caKey to crypto.PrivateKey
- Add pkiConfig parameter to SelfSignedCertKey.Generate()
- Update PKIConfigToKeyParams to accept *types.PKIConfig
- Set algorithm-appropriate KeyUsage (ECDSA omits KeyEncipherment)
- All signer assets now depend on InstallConfig and pass PKI config
- Add type assertion in BoundSASigningKey.Load() for RSA requirement

Assisted-by: Claude Code (Opus 4.6)
Add tests covering PKI validation, feature gate enforcement,
certificate generation with PKI configs, and cross-algorithm
certificate signing.

Key additions:
- Test ValidatePKIConfig catches invalid configs and empty PKI
- Test ConfigurablePKI feature gate with TechPreview and CustomNoUpgrade
- Test ValidateInstallConfig catches invalid PKI with field paths
- Test SelfSignedCertKey.Generate() with non-nil PKI configs
- Test ECDSA CA signing RSA leaf certificate with chain verification
- Test RSA/ECDSA key generation, KeyUsage flags, signature algorithm detection
- Test PEM encode/decode roundtrip for RSA and ECDSA keys

Assisted-by: Claude Code (Opus 4.6)
Document the configurable PKI feature in docs/user/customization.md,
following the existing inline documentation pattern for install-config
properties.

Key additions:
- Add pki field entry with nested signerCertificates structure
- Add RSA 4096 and ECDSA P-384 install-config example fragments
- Document ConfigurablePKI feature gate requirement
- Note scope: signer certificates only, leaf certs unaffected

Assisted-by: Claude Code (Opus 4.6)
@hasbro17 hasbro17 force-pushed the install-config-pki branch from dfa87a6 to 71dcced Compare March 17, 2026 20:24
@hasbro17
Copy link
Contributor Author

/test e2e-aws-ovn-techpreview
/test e2e-gcp-ovn-techpreview

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 18, 2026

@hasbro17: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/gofmt 71dcced link true /test gofmt
ci/prow/golint 71dcced link true /test golint
ci/prow/e2e-metal-ipi-ovn-ipv6 71dcced link true /test e2e-metal-ipi-ovn-ipv6
ci/prow/e2e-metal-ipi-ovn-dualstack 71dcced link false /test e2e-metal-ipi-ovn-dualstack
ci/prow/e2e-metal-ovn-two-node-fencing 71dcced link false /test e2e-metal-ovn-two-node-fencing

Full PR test history. Your PR dashboard.

Details

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 kubernetes-sigs/prow repository. I understand the commands that are listed here.

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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants