require that secret is a valid PEM

Co-authored-by: Jared Rodriguez <jared@blacknode.net>
This commit is contained in:
Romain
2021-12-10 17:16:04 +01:00
committed by GitHub
parent c309b3b006
commit 0528af1e66
4 changed files with 117 additions and 12 deletions
@@ -38,3 +38,22 @@ spec:
servicePort: 80
tls:
- secretName: myUndefinedSecret
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/frontend-entry-points: ep3
name: badSecretIng
namespace: testing
spec:
rules:
- host: example.fail
http:
paths:
- backend:
serviceName: example-fail
servicePort: 80
tls:
- secretName: badSecret
@@ -6,3 +6,13 @@ kind: Secret
metadata:
name: myTlsSecret
namespace: testing
---
apiVersion: v1
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXG5ceDAwXHgwMFx4MDAtLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tXG4=
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
kind: Secret
metadata:
name: badSecret
namespace: testing
+28
View File
@@ -3,6 +3,7 @@ package kubernetes
import (
"bufio"
"bytes"
"encoding/pem"
"errors"
"flag"
"fmt"
@@ -835,6 +836,19 @@ func getCertificateBlocks(secret *corev1.Secret, namespace, secretName string) (
namespace, secretName, strings.Join(missingEntries, ", "))
}
if !isPem(tlsCrtData) {
missingEntries = append(missingEntries, "tls.crt")
}
if !isPem(tlsKeyData) {
missingEntries = append(missingEntries, "tls.key")
}
if len(missingEntries) > 0 {
return "", "", fmt.Errorf("secret %s/%s does not contain PEM formatted TLS data entries: %s",
namespace, secretName, strings.Join(missingEntries, ","))
}
return cert, key, nil
}
@@ -1269,3 +1283,17 @@ func templateSafeString(value string) error {
_, err := strconv.Unquote(`"` + value + `"`)
return err
}
func isPem(data []byte) bool {
for {
block, rest := pem.Decode(data)
if block == nil {
return false
}
if len(rest) == 0 {
break
}
data = rest
}
return true
}
+60 -12
View File
@@ -1915,8 +1915,8 @@ func TestGetTLS(t *testing.T) {
Namespace: "testing",
},
Data: map[string][]byte{
"tls.crt": []byte("tls-crt"),
"tls.key": []byte("tls-key"),
"tls.crt": []byte("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n"),
"tls.key": []byte("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----\n"),
},
},
{
@@ -1925,8 +1925,8 @@ func TestGetTLS(t *testing.T) {
Namespace: "testing",
},
Data: map[string][]byte{
"tls.crt": []byte("tls-crt"),
"tls.key": []byte("tls-key"),
"tls.crt": []byte("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n"),
"tls.key": []byte("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----\n"),
},
},
},
@@ -1934,14 +1934,14 @@ func TestGetTLS(t *testing.T) {
result: map[string]*tls.Configuration{
"testing/test-secret": {
Certificate: &tls.Certificate{
CertFile: tls.FileOrContent("tls-crt"),
KeyFile: tls.FileOrContent("tls-key"),
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n"),
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----\n"),
},
},
"testing/test-secret2": {
Certificate: &tls.Certificate{
CertFile: tls.FileOrContent("tls-crt"),
KeyFile: tls.FileOrContent("tls-key"),
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n"),
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----\n"),
},
},
},
@@ -1968,8 +1968,8 @@ func TestGetTLS(t *testing.T) {
Namespace: "testing",
},
Data: map[string][]byte{
"tls.crt": []byte("tls-crt"),
"tls.key": []byte("tls-key"),
"tls.crt": []byte("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n"),
"tls.key": []byte("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----\n"),
},
},
},
@@ -1978,12 +1978,60 @@ func TestGetTLS(t *testing.T) {
"testing/test-secret": {
EntryPoints: []string{"api-secure", "https"},
Certificate: &tls.Certificate{
CertFile: tls.FileOrContent("tls-crt"),
KeyFile: tls.FileOrContent("tls-key"),
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n"),
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----\n"),
},
},
},
},
{
desc: "load bad certificate",
ingress: buildIngress(
iNamespace("testing"),
iAnnotation(annotationKubernetesFrontendEntryPoints, "https,api-secure"),
iRules(iRule(iHost("example.com"))),
iTLSes(iTLS("test-secret")),
),
client: clientMock{
secrets: []*corev1.Secret{
{
ObjectMeta: metav1.ObjectMeta{
Name: "test-secret",
Namespace: "testing",
},
Data: map[string][]byte{
"tls.crt": []byte("invalid"),
"tls.key": []byte("invalid"),
},
},
},
},
errResult: "secret testing/test-secret does not contain PEM formatted TLS data entries: tls.crt,tls.key",
},
{
desc: "load nested bad certificate",
ingress: buildIngress(
iNamespace("testing"),
iAnnotation(annotationKubernetesFrontendEntryPoints, "https,api-secure"),
iRules(iRule(iHost("example.com"))),
iTLSes(iTLS("test-secret")),
),
client: clientMock{
secrets: []*corev1.Secret{
{
ObjectMeta: metav1.ObjectMeta{
Name: "test-secret",
Namespace: "testing",
},
Data: map[string][]byte{
"tls.crt": []byte("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n\x00\x00\x00-----END CERTIFICATE-----\n"),
"tls.key": []byte("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"),
},
},
},
},
errResult: "secret testing/test-secret does not contain PEM formatted TLS data entries: tls.crt",
},
}
for _, test := range testCases {