Skip to content

Commit 886f3e1

Browse files
committed
Handle EC parameters before TLS private keys
1 parent be39693 commit 886f3e1

2 files changed

Lines changed: 51 additions & 1 deletion

File tree

internal/gatewayapi/tls.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func parseCertsFromTLSSecretsData(secrets []*corev1.Secret) ([]*corev1.Secret, [
105105

106106
keyData := secret.Data[corev1.TLSPrivateKeyKey]
107107

108-
keyBlock, _ := pem.Decode(keyData)
108+
keyBlock := firstSupportedPrivateKeyBlock(keyData)
109109
if keyBlock == nil {
110110
errs = append(errs, fmt.Errorf("%s/%s must contain valid %s and %s, unable to decode pem data in %s",
111111
secret.Namespace, secret.Name, corev1.TLSCertKey, corev1.TLSPrivateKeyKey, corev1.TLSPrivateKeyKey))
@@ -203,6 +203,25 @@ func parseCertsFromTLSSecretsData(secrets []*corev1.Secret) ([]*corev1.Secret, [
203203
//
204204
// Return a status.ListenerError with InvalidCertificateRef Condition if no valid certificates are found in the provided data,
205205
// Return a status.ListenerError with PartiallyInvalidCertificateRef Condition if some certificates are invalid but also valid certificates exist.
206+
func firstSupportedPrivateKeyBlock(data []byte) *pem.Block {
207+
var firstBlock *pem.Block
208+
for len(data) > 0 {
209+
block, rest := pem.Decode(data)
210+
if block == nil {
211+
return firstBlock
212+
}
213+
if firstBlock == nil {
214+
firstBlock = block
215+
}
216+
switch block.Type {
217+
case "PRIVATE KEY", "RSA PRIVATE KEY", "EC PRIVATE KEY":
218+
return block
219+
}
220+
data = rest
221+
}
222+
return firstBlock
223+
}
224+
206225
func filterValidCertificates(data []byte) ([]byte, status.ListenerError) {
207226
if len(data) == 0 {
208227
return nil, status.NewListenerStatusError(

internal/gatewayapi/tls_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,37 @@ func TestValidateTLSSecretsData(t *testing.T) {
306306
}
307307
}
308308

309+
func TestValidateTLSSecretsDataWithECParameters(t *testing.T) {
310+
const ecParametersPEM = "-----BEGIN EC PARAMETERS-----\nBggqhkjOPQMBBw==\n-----END EC PARAMETERS-----\n"
311+
312+
t.Run("ec-parameters-before-private-key", func(t *testing.T) {
313+
secrets := createTestSecrets(t, []string{"ecdsa-p256-cert.pem"}, []string{"ecdsa-p256.key"})
314+
keyData := append([]byte(nil), secrets[0].Data[corev1.TLSPrivateKeyKey]...)
315+
secrets[0].Data[corev1.TLSPrivateKeyKey] = append([]byte(ecParametersPEM), keyData...)
316+
317+
validSecrets, certs, err := parseCertsFromTLSSecretsData(secrets)
318+
require.NoError(t, err)
319+
require.Len(t, validSecrets, 1)
320+
require.Len(t, certs, 1)
321+
322+
keyBlock, _ := pem.Decode(keyData)
323+
require.NotNil(t, keyBlock)
324+
require.Equal(t, pem.EncodeToMemory(keyBlock), validSecrets[0].Data[corev1.TLSPrivateKeyKey])
325+
})
326+
327+
t.Run("ec-parameters-without-private-key", func(t *testing.T) {
328+
secrets := createTestSecrets(t, []string{"ecdsa-p256-cert.pem"}, []string{"ecdsa-p256.key"})
329+
secrets[0].Data[corev1.TLSPrivateKeyKey] = []byte(ecParametersPEM)
330+
331+
validSecrets, certs, err := parseCertsFromTLSSecretsData(secrets)
332+
require.Error(t, err)
333+
require.Equal(t, "test/secret must contain valid tls.crt and tls.key, EC PARAMETERS key format found in tls.key, supported formats are PKCS1, PKCS8 or EC", err.Error())
334+
require.Equal(t, gwapiv1.ListenerReasonInvalidCertificateRef, err.Reason())
335+
require.Empty(t, validSecrets)
336+
require.Empty(t, certs)
337+
})
338+
}
339+
309340
func TestFilterValidCertificates(t *testing.T) {
310341
type testCase struct {
311342
Name string

0 commit comments

Comments
 (0)