Skip to content
Open
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
75 changes: 75 additions & 0 deletions config/v1/types_tlssecurityprofile.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,31 @@ const (
TLSProfileCustomType TLSProfileType = "Custom"
)

// TLSCurve is a named curve identifier that can be used in TLSProfile.Curves.
// There is a one-to-one mapping between these names and the curve IDs defined
// in crypto/tls package based on IANA's "TLS Supported Groups" registry:
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8

Choose a reason for hiding this comment

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

Looking at cryto/tls, I see the following values.

type CurveID uint16

const (
	CurveP256          CurveID = 23
	CurveP384          CurveID = 24
	CurveP521          CurveID = 25
	X25519             CurveID = 29
	X25519MLKEM768     CurveID = 4588
	SecP256r1MLKEM768  CurveID = 4587
	SecP384r1MLKEM1024 CurveID = 4589
)

Why are we not including all the values?

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

Ok so I think we can align to those values the available curve supported

//
// +kubebuilder:validation:Enum=X25519;P-256;P-384;P-521;X25519MLKEM768
type TLSCurve string

const (
// TLSCurveX25519 represents X25519.
TLSCurveX25519 TLSCurve = "X25519"
// TLSCurveP256 represents P-256 (secp256r1).
TLSCurveP256 TLSCurve = "P-256"
// TLSCurveP384 represents P-384 (secp384r1).
TLSCurveP384 TLSCurve = "P-384"
// TLSCurveP521 represents P-521 (secp521r1).
TLSCurveP521 TLSCurve = "P-521"
// TLSCurveX25519MLKEM768 represents X25519MLKEM768.
TLSCurveX25519MLKEM768 TLSCurve = "X25519MLKEM768"
// TLSCurveP256r1MLKEM1024 represents P256r1MLKEM1024 (secp256r1MLKEM1024).
TLSCurveP256r1MLKEM768 TLSCurve = "P256r1MLKEM768"
Comment on lines +224 to +225
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

Comment typo: says "MLKEM1024" but constant is "MLKEM768".

The comment states P256r1MLKEM1024 but the constant name and value use P256r1MLKEM768.

🔎 Proposed fix
-	// TLSCurveP256r1MLKEM1024 represents P256r1MLKEM1024 (secp256r1MLKEM1024).
+	// TLSCurveP256r1MLKEM768 represents P256r1MLKEM768 (secp256r1MLKEM768).
 	TLSCurveP256r1MLKEM768 TLSCurve = "P256r1MLKEM768"
📝 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
// TLSCurveP256r1MLKEM1024 represents P256r1MLKEM1024 (secp256r1MLKEM1024).
TLSCurveP256r1MLKEM768 TLSCurve = "P256r1MLKEM768"
// TLSCurveP256r1MLKEM768 represents P256r1MLKEM768 (secp256r1MLKEM768).
TLSCurveP256r1MLKEM768 TLSCurve = "P256r1MLKEM768"
🤖 Prompt for AI Agents
In config/v1/types_tlssecurityprofile.go around lines 224-225, the comment for
the TLSCurve constant mismatches the constant name/value: it says
"P256r1MLKEM1024" while the constant is named and set to "P256r1MLKEM768";
update the comment to correctly state "P256r1MLKEM768" so it matches the
constant name and value, keeping the descriptive text consistent (e.g.,
"TLSCurveP256r1MLKEM768 represents P256r1MLKEM768 (secp256r1MLKEM768)").

// TLSCurveP384r1MLKEM1024 represents P384r1MLKEM1024 (secp384r1MLKEM1024).
TLSCurveP384r1MLKEM1024 TLSCurve = "P384r1MLKEM1024"
)
Comment on lines +210 to +228
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:

cat -n config/v1/types_tlssecurityprofile.go | sed -n '210,228p'

Repository: openshift/api

Length of output: 973


🏁 Script executed:

# Check the exact kubebuilder annotation
rg -n "kubebuilder:validation:Enum" config/v1/types_tlssecurityprofile.go -A 1

# Check all TLSCurve constants
rg -n "TLSCurve\w+\s+TLSCurve\s*=" config/v1/types_tlssecurityprofile.go -B 1

Repository: openshift/api

Length of output: 1120


🏁 Script executed:

# Check if P256r1MLKEM768 and P384r1MLKEM1024 are used elsewhere
rg "P256r1MLKEM768|P384r1MLKEM1024" --type go -i

Repository: openshift/api

Length of output: 3577


Add P256r1MLKEM768 and P384r1MLKEM1024 to the kubebuilder enum validation.

The constants TLSCurveP256r1MLKEM768 and TLSCurveP384r1MLKEM1024 are defined at lines 225 and 227, but the kubebuilder validation enum at line 210 only allows X25519;P-256;P-384;P-521;X25519MLKEM768. These curves cannot be configured via the API since they fail CRD validation. Documentation indicates these curves should be available for TLS profiles, so they must be added to the enum.

🤖 Prompt for AI Agents
In config/v1/types_tlssecurityprofile.go around lines 210 to 228, the
kubebuilder validation enum on the TLSCurve type doesn't include the newly
defined constants TLSCurveP256r1MLKEM768 and TLSCurveP384r1MLKEM1024, preventing
those values from being accepted by CRD validation; update the kubebuilder tag
on the TLSCurve type to include "P256r1MLKEM768" and "P384r1MLKEM1024" (matching
the constant string values) so the CRD allows those curve names, then regenerate
CRDs if applicable.


// TLSProfileSpec is the desired behavior of a TLSSecurityProfile.
type TLSProfileSpec struct {
// ciphers is used to specify the cipher algorithms that are negotiated
Expand All @@ -213,6 +238,38 @@ type TLSProfileSpec struct {
//
// +listType=atomic
Ciphers []string `json:"ciphers"`
// curves is used to specify the elliptic curves that are used during
// the TLS handshake. Operators may remove entries their operands do
// not support.
//
// TLSProfiles Old, Intermediate, Modern are including by default the following
// curves: X25519, P-256, P-384, P-521, X25519MLKEM768, SecP256r1MLKEM1024, SecP384r1MLKEM1024.
Comment on lines +245 to +246
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

Documentation lists curves not present in actual defaults.

The comment states Old/Intermediate/Modern profiles include P-521, X25519MLKEM768, SecP256r1MLKEM1024, SecP384r1MLKEM1024, but the actual TLSProfiles defaults (lines 343-384) only include:

  • TLSCurveX25519
  • TLSCurveP256
  • TLSCurveP384
  • TLSCurveX25519MLKEM768

Notably missing from the actual defaults: P-521. This discrepancy will confuse users and operators.

🔎 Proposed fix - align documentation with actual defaults
-	// TLSProfiles Old, Intermediate, Modern are including by default the following
-	// curves: X25519, P-256, P-384, P-521, X25519MLKEM768, SecP256r1MLKEM1024, SecP384r1MLKEM1024.
+	// TLSProfiles Old, Intermediate, Modern are including by default the following
+	// curves: X25519, P-256, P-384, X25519MLKEM768.

Or, update the defaults to match the documentation by adding the missing curves.

📝 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
// TLSProfiles Old, Intermediate, Modern are including by default the following
// curves: X25519, P-256, P-384, P-521, X25519MLKEM768, SecP256r1MLKEM1024, SecP384r1MLKEM1024.
// TLSProfiles Old, Intermediate, Modern are including by default the following
// curves: X25519, P-256, P-384, X25519MLKEM768.
🤖 Prompt for AI Agents
config/v1/types_tlssecurityprofile.go around lines 245-246: the comment claims
Old/Intermediate/Modern include P-521, SecP256r1MLKEM1024 and SecP384r1MLKEM1024
but the actual TLSProfiles defaults at lines 343-384 only include
TLSCurveX25519, TLSCurveP256, TLSCurveP384 and TLSCurveX25519MLKEM768; either
update this comment to list the actual default curves exactly (remove P-521 and
the MLKEM curves not present) or, if the documentation is correct, add the
missing curve constants (e.g., P-521 and the appropriate MLKEM entries) into the
TLSProfiles defaults block so the code and comment match, and ensure the comment
wording matches the final default set.

// TLSProfiles Custom do not include any curves by default.
// NOTE: since this field is optional, if no curves are specified, the default curves
// used by the underlying TLS library will be used.
//
// For example, to use X25519 and P-256 (yaml):
//
// # Example: Force PQC-only encryption
// apiVersion: config.openshift.io/v1
// kind: APIServer
// spec:
// tlsSecurityProfile:
// type: Custom
// custom:
// ciphers:
// - TLS_AES_128_GCM_SHA256
// - TLS_AES_256_GCM_SHA384
// - TLS_CHACHA20_POLY1305_SHA256
// curves:
// - X25519MLKEM768 # PQC-only: only hybrid quantum-resistant curve
// minTLSVersion: VersionTLS13
Comment on lines +253 to +266
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this render all right in the oc explain output?

Copy link
Contributor

Choose a reason for hiding this comment

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

Good question, we generally don't have cross-field examples, but I guess in this case, you cannot specify arbitrary curves that the ciphers you have don't support?

Would anything validate that the curves list is correct for the ciphers you have? Or are all curves supported by all ciphers? Would there ever be a need to say, specify a subset of curves per cipher?

(This might be completely invalid, but as an example, you would want X25519MLKEM768 for TLS_CHACHA20_POLY1305_SHA256, and P-384 for TLS_AES_256_GCM_SHA384, and only those combinations)

Choose a reason for hiding this comment

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

IMO the user facing docs call out that the custom TLS profile "can cause some problems" if misconfigured which is a good hint to the administrator that they should:

  1. Know what they are doing
  2. Validate their config before using the profile in a production environment

I think the best approach here is to offer reasonable valid defaults while keeping custom profiles as a "power user" option.

//
// +optional
Copy link
Contributor

Choose a reason for hiding this comment

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

optional fields should have godoc around what happens if the field is not set (i.e. what is the default behaviour)

Copy link
Author

Choose a reason for hiding this comment

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

I added a note to address this case. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Technically you don't need the NOTE: since this field is optional, in the godoc, since it will be explained as an optional field, but up to you if you want to highlight that. Otherwise looks fine to me

// +listType=set
// +kubebuilder:validation:MaxItems=5
// +openshift:enable:FeatureGate=TLSCurvesConfiguration
Curves []TLSCurve `json:"curves,omitempty"`
// minTLSVersion is used to specify the minimal version of the TLS protocol
// that is negotiated during the TLS handshake. For example, to use TLS
// versions 1.1, 1.2 and 1.3 (yaml):
Expand Down Expand Up @@ -283,6 +340,12 @@ var TLSProfiles = map[TLSProfileType]*TLSProfileSpec{
"AES256-SHA",
"DES-CBC3-SHA",
},
Curves: []TLSCurve{
TLSCurveX25519,
TLSCurveP256,
TLSCurveP384,
TLSCurveX25519MLKEM768,
},
MinTLSVersion: VersionTLS10,
},
TLSProfileIntermediateType: {
Expand All @@ -299,6 +362,12 @@ var TLSProfiles = map[TLSProfileType]*TLSProfileSpec{
"DHE-RSA-AES128-GCM-SHA256",
"DHE-RSA-AES256-GCM-SHA384",
},
Curves: []TLSCurve{
TLSCurveX25519,
TLSCurveP256,
TLSCurveP384,
TLSCurveX25519MLKEM768,
},
MinTLSVersion: VersionTLS12,
},
TLSProfileModernType: {
Expand All @@ -307,6 +376,12 @@ var TLSProfiles = map[TLSProfileType]*TLSProfileSpec{
"TLS_AES_256_GCM_SHA384",
"TLS_CHACHA20_POLY1305_SHA256",
},
Curves: []TLSCurve{
TLSCurveX25519,
TLSCurveP256,
TLSCurveP384,
TLSCurveX25519MLKEM768,
},
MinTLSVersion: VersionTLS13,
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,39 @@ spec:
type: string
type: array
x-kubernetes-list-type: atomic
curves:
description: "curves is used to specify the elliptic curves
that are used during\nthe TLS handshake. Operators may
remove entries their operands do\nnot support.\n\nTLSProfiles
Old, Intermediate, Modern are including by default the following\ncurves:
X25519, P-256, P-384, P-521, X25519MLKEM768, SecP256r1MLKEM1024,
SecP384r1MLKEM1024.\nTLSProfiles Custom do not include any
curves by default.\nNOTE: since this field is optional,
if no curves are specified, the default curves\nused by
the underlying TLS library will be used.\n\nFor example,
to use X25519 and P-256 (yaml):\n\n# Example: Force PQC-only
encryption\napiVersion: config.openshift.io/v1\nkind: APIServer\nspec:\n
\ tlsSecurityProfile:\n type: Custom\n custom:\n ciphers:\n\t
\ - TLS_AES_128_GCM_SHA256\n - TLS_AES_256_GCM_SHA384\n
\ - TLS_CHACHA20_POLY1305_SHA256\n curves:\n
\ - X25519MLKEM768 # PQC-only: only hybrid quantum-resistant
curve\n minTLSVersion: VersionTLS13"
items:
description: |-
TLSCurve is a named curve identifier that can be used in TLSProfile.Curves.
There is a one-to-one mapping between these names and the curve IDs defined
in crypto/tls package based on IANA's "TLS Supported Groups" registry:
https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
enum:
- X25519
- P-256
- P-384
- P-521
- X25519MLKEM768
type: string
maxItems: 5
type: array
x-kubernetes-list-type: set
Comment on lines +333 to +365
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

Mismatch between description and enum values for curves

The description states that Old/Intermediate/Modern profiles include 7 curves by default:

X25519, P-256, P-384, P-521, X25519MLKEM768, SecP256r1MLKEM1024, SecP384r1MLKEM1024

However, the enum (lines 356-361) only defines 5 values:

  • X25519, P-256, P-384, P-521, X25519MLKEM768

Missing from enum: SecP256r1MLKEM1024, SecP384r1MLKEM1024

Additionally, maxItems: 5 (line 363) would prevent users from specifying all 7 curves mentioned in the description.

Please either update the enum and maxItems to include all mentioned curves, or correct the description to match the actual supported values.

🤖 Prompt for AI Agents
In
config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-CustomNoUpgrade.crd.yaml
around lines 333-365, the `curves` description lists 7 curves but the enum only
defines 5 and maxItems is 5; update the enum to include SecP256r1MLKEM1024 and
SecP384r1MLKEM1024 and change maxItems to 7 so the schema matches the
description (alternatively, if those two curves are not supported, edit the
descriptive text to list only the five supported curves and keep maxItems at 5).
Ensure the enum entries exactly match the names in the description and adjust
maxItems accordingly.

minTLSVersion:
description: |-
minTLSVersion is used to specify the minimal version of the TLS protocol
Expand Down
5 changes: 5 additions & 0 deletions config/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions config/v1/zz_generated.featuregated-crd-manifests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ apiservers.config.openshift.io:
Category: ""
FeatureGates:
- KMSEncryptionProvider
- TLSCurvesConfiguration
FilenameOperatorName: config-operator
FilenameOperatorOrdering: "01"
FilenameRunLevel: "0000_10"
Expand Down
Loading