Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse equal-preference cipher groups #6461

Merged
merged 1 commit into from
May 24, 2024
Merged
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
1 change: 1 addition & 0 deletions .codespell.ignorewords
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ wit
aks
immediatedly
te
NotIn
31 changes: 17 additions & 14 deletions apis/projectcontour/v1alpha1/ciphersuites.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ package v1alpha1
// - most of the clients that might need to use the commented ciphers are
// unable to connect without TLS 1.0, which contour never enables.
//
// Ciphers are listed in order of preference.
// [cipher1|cipher2|...] defines an equal-preference group of ciphers.
//
// This list is ignored if the client and server negotiate TLS 1.3.
//
// The commented ciphers are left in place to simplify updating this list for future
Expand All @@ -41,18 +44,18 @@ var DefaultTLSCiphers = []string{
// See: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters
// Note: This list is a superset of what is valid for stock Envoy builds and those using BoringSSL FIPS.
var ValidTLSCiphers = map[string]struct{}{
"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]": {},
"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]": {},
"ECDHE-ECDSA-AES128-GCM-SHA256": {},
"ECDHE-RSA-AES128-GCM-SHA256": {},
"ECDHE-ECDSA-AES128-SHA": {},
"ECDHE-RSA-AES128-SHA": {},
"AES128-GCM-SHA256": {},
"AES128-SHA": {},
"ECDHE-ECDSA-AES256-GCM-SHA384": {},
"ECDHE-RSA-AES256-GCM-SHA384": {},
"ECDHE-ECDSA-AES256-SHA": {},
"ECDHE-RSA-AES256-SHA": {},
"AES256-GCM-SHA384": {},
"AES256-SHA": {},
"ECDHE-ECDSA-CHACHA20-POLY1305": {},
"ECDHE-RSA-CHACHA20-POLY1305": {},
"ECDHE-ECDSA-AES128-GCM-SHA256": {},
"ECDHE-RSA-AES128-GCM-SHA256": {},
"ECDHE-ECDSA-AES128-SHA": {},
"ECDHE-RSA-AES128-SHA": {},
"AES128-GCM-SHA256": {},
"AES128-SHA": {},
"ECDHE-ECDSA-AES256-GCM-SHA384": {},
"ECDHE-RSA-AES256-GCM-SHA384": {},
"ECDHE-ECDSA-AES256-SHA": {},
"ECDHE-RSA-AES256-SHA": {},
"AES256-GCM-SHA384": {},
"AES256-SHA": {},
}
23 changes: 22 additions & 1 deletion apis/projectcontour/v1alpha1/contourconfig_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,27 @@ func ValidateTLSProtocolVersions(min, max string) error {
return nil
}

// isValidTLSCipher parses a cipher string and returns true if it is valid.
// We do not support the full syntax defined in the BoringSSL documentation,
// see https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#Cipher-suite-configuration
func isValidTLSCipher(cipherSpec string) bool {
// Equal-preference group: [cipher1|cipher2|...]
if strings.HasPrefix(cipherSpec, "[") && strings.HasSuffix(cipherSpec, "]") {
for _, cipher := range strings.Split(strings.Trim(cipherSpec, "[]"), "|") {
if _, ok := ValidTLSCiphers[cipher]; !ok {
return false
}
}
return true
}

if _, ok := ValidTLSCiphers[cipherSpec]; !ok {
return false
}

return true
}

// Validate ensures EnvoyTLS configuration is valid.
func (e *EnvoyTLS) Validate() error {
if err := ValidateTLSProtocolVersions(e.MinimumProtocolVersion, e.MaximumProtocolVersion); err != nil {
Expand All @@ -193,7 +214,7 @@ func (e *EnvoyTLS) Validate() error {

var invalidCipherSuites []string
for _, c := range e.CipherSuites {
if _, ok := ValidTLSCiphers[c]; !ok {
if !isValidTLSCipher(c) {
invalidCipherSuites = append(invalidCipherSuites, c)
}
}
Expand Down
16 changes: 16 additions & 0 deletions apis/projectcontour/v1alpha1/contourconfig_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,10 @@ func TestContourConfigurationSpecValidate(t *testing.T) {
c.Envoy.Listener.TLS.CipherSuites = []string{
"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]",
"ECDHE-ECDSA-AES128-GCM-SHA256",
"ECDHE-ECDSA-CHACHA20-POLY1305",
"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]",
"ECDHE-RSA-AES128-GCM-SHA256",
"ECDHE-RSA-CHACHA20-POLY1305",
"ECDHE-ECDSA-AES128-SHA",
"AES128-GCM-SHA256",
"AES128-SHA",
Expand All @@ -161,6 +163,20 @@ func TestContourConfigurationSpecValidate(t *testing.T) {
"AES128-GCM-SHA256",
}
require.Error(t, c.Validate())

// Equal-preference group with invalid cipher.
c.Envoy.Listener.TLS.CipherSuites = []string{
"[ECDHE-ECDSA-AES128-GCM-SHA256|NOTAVALIDCIPHER]",
"ECDHE-ECDSA-AES128-GCM-SHA256",
}
require.Error(t, c.Validate())

// Unmatched brackets.
c.Envoy.Listener.TLS.CipherSuites = []string{
"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305",
"ECDHE-ECDSA-AES128-GCM-SHA256",
}
require.Error(t, c.Validate())
})

t.Run("gateway validation", func(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions changelogs/unreleased/6461-tsaarni-small.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for defining equal-preference cipher groups ([cipher1|cipher2|...]) and permit `ECDHE-ECDSA-CHACHA20-POLY1305` and `ECDHE-RSA-CHACHA20-POLY1305` to be used separately.
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ func TestDesiredDeploymentWhenSettingDisabledFeature(t *testing.T) {
disabledFeatures []contour_v1.Feature
}{
{
description: "disable 2 featuers",
description: "disable 2 features",
disabledFeatures: []contour_v1.Feature{"tlsroutes", "grpcroutes"},
},
{
Expand Down