From 10467170e3b7b5582d2f1552239c8e826b760f03 Mon Sep 17 00:00:00 2001 From: Pierangelo Di Pilato Date: Tue, 24 Sep 2024 13:37:48 +0200 Subject: [PATCH] Report error for unsupported PKCS #1 format for the private key Java Kafka clients don't support PKCS #1 format for private keys. Signed-off-by: Pierangelo Di Pilato --- control-plane/pkg/security/secret.go | 22 ++++++++++++++ control-plane/pkg/security/secret_test.go | 29 +++++++++++++++++++ .../pkg/security/testdata/pkcs1_user.key | 27 +++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 control-plane/pkg/security/testdata/pkcs1_user.key diff --git a/control-plane/pkg/security/secret.go b/control-plane/pkg/security/secret.go index 23e4d9ca62..b70962d371 100644 --- a/control-plane/pkg/security/secret.go +++ b/control-plane/pkg/security/secret.go @@ -19,8 +19,10 @@ package security import ( "crypto/tls" "crypto/x509" + "encoding/pem" "fmt" "strconv" + "strings" "github.com/IBM/sarama" @@ -193,6 +195,10 @@ func sslConfig(protocol string, data map[string][]byte) kafka.ConfigOption { if err != nil { return fmt.Errorf("[protocol %s] failed to load x.509 key pair: %w", protocol, err) } + // Java Kafka clients don't support PKCS #1 format for the private key + if isPrivateKeyPKCS1Format(userKeyCert) { + return fmt.Errorf("[protocol %s] unsupported user key format in %s, 'PKCS #1' format is not supported, convert private key to 'PKCS #8'", protocol, UserKey) + } tlsCerts = []tls.Certificate{tlsCert} } } @@ -220,3 +226,19 @@ func skipClientAuthCheck(data map[string][]byte) (bool, error) { } return enabled, nil } + +func isPrivateKeyPKCS1Format(keyPEMBlock []byte) bool { + var keyDERBlock *pem.Block + for { + keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock) + if keyDERBlock == nil { + return false + } + if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") { + break + } + } + + _, err := x509.ParsePKCS1PrivateKey(keyDERBlock.Bytes) + return err == nil +} diff --git a/control-plane/pkg/security/secret_test.go b/control-plane/pkg/security/secret_test.go index 601cafb996..7e27176cb6 100644 --- a/control-plane/pkg/security/secret_test.go +++ b/control-plane/pkg/security/secret_test.go @@ -194,6 +194,22 @@ func TestSSL(t *testing.T) { assert.NotNil(t, config.Net.TLS.Config.RootCAs) } +func TestSSLPKCS1(t *testing.T) { + ca, userKey, userCert := loadPKCS1Certs(t) + + secret := map[string][]byte{ + "protocol": []byte("SSL"), + "user.key": userKey, + "user.crt": userCert, + "ca.crt": ca, + } + config := sarama.NewConfig() + + err := kafka.Options(config, secretData(secret)) + + assert.NotNil(t, err) +} + func TestSSLNoUserKey(t *testing.T) { ca, _, userCert := loadCerts(t) @@ -384,3 +400,16 @@ func loadCerts(t *testing.T) (ca, userKey, userCert []byte) { return ca, userKey, userCert } + +func loadPKCS1Certs(t *testing.T) (ca, userKey, userCert []byte) { + ca, err := os.ReadFile("testdata/ca.crt") + assert.Nil(t, err) + + userKey, err = os.ReadFile("testdata/pkcs1_user.key") + assert.Nil(t, err) + + userCert, err = os.ReadFile("testdata/user.crt") + assert.Nil(t, err) + + return ca, userKey, userCert +} diff --git a/control-plane/pkg/security/testdata/pkcs1_user.key b/control-plane/pkg/security/testdata/pkcs1_user.key new file mode 100644 index 0000000000..6b7a292fac --- /dev/null +++ b/control-plane/pkg/security/testdata/pkcs1_user.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA1c6XoILp78NVhSuzC8KJ1QnSGQ8CisCHkGWeEIkXI0Cuh2k6 +2+vpVIMUuHdehF45/Jxcia54GqIZ6SneN1IpW94+oP+Sls1ZtEZgJpJCyMqe8qBd +jB2M/+CI3px8GyinnumM50TPr/zpp04XsR8I2NzhQq2IQtNAm7FjK7orZtfdqCYe +sk5tARcObVWxKm+WOwjTWDGmlVyxwyWqFGIspV2ymv8Sx8rnOBhUFYIBqB3lefNn +ja0Oh89oZM6ZlRrCupxsnZHXhM3i/c2+AR+tLWQEW0xlqdtle8oARe44E1bnryI1 +mDLmjQ3YuyR4/Kw+yl4Q+DLFMC7pBAZLTFbkIQIDAQABAoIBAE190DTr3e/5gyB+ +Iymq+5vMMGrGpuw1Na0fN3fUyB8NzXPkruGQkoP/8l2dXhNpt2iYH24DXyKACBYb +B6BTVgwm89oUZ0Pi75VIQIcaUbxGu+9CMkWbXERNVC4i11Rcmswc5+XWadPmPaVW +x315uxImlDo/fPiDapJDa6colZxzDRfa+cH2PrjzDw317Q371qEliJOJF2ZFPDRF +vSBiSQlo9gE9vVR6lanuaG1nQFkAnN1wjb4qfjsGjSdSbQfOHkwA+jQ8o4L3csAo +idUq8UlLmGJY7GIStF47m7TiWv/aLcTCOks7sii/gQJx9GEme+wR1Xe/BtHErqnI +N3hUVKUCgYEA7PvaV6AJE/Ht9itRbxuoeK+yAe0Sn9z5mbuy9HQsVJH0LLL/lL5Y +BuyWWy+Tj7IorfCEmHyY9KOq9V7HRRIa6PKzd5rVGn1D8I6yPU/n8FgZboOy4ahN +lkbDNIuHcu27bkqiAZ4Vu2mpRtalr7QQdlS9v7S235GDQWTroDQQyycCgYEA5vaj +mPnvYOR2S2h4pSBTKdz9Ba2fWw0MiLFIKoHmOblazqRZkLOKoN/DbnOKpbvKqyA6 +cwo4r9AF4dRLa0sE3zjmNOBZAV0Uu6fhcaZgvc+1t82P+vrZblP9pXOdFGGoed4S +bskLL/C1oXd6+Q89rCFIkkHJXDJvxRUZNe0BA3cCgYBZ9akGxltr1NTOM9dv5AHp +/lgGXyZIxSuC7juajFcfq2ATb8eRgUgNKNZSuxa635iNntXWxMWTaGXHSzk9wQey +Eh+KcZ4fthmKQcDrgV+8XtUYnKnU+3yoZShI1AaQ3CngTjh9gLMjN5LoryaqMiJl +qPl2wnUBHU3EDzla0Sjm1QKBgQCPxodu6l+OxImzRZScznOWwt+rkjp6NrRPv3R6 +KaUE2BLkQkETKAErRkBlWH290BpIzuYzyPAi2e9fdoWAhBHDV6tOzT368FPAwbBA +zF66qjun8MopZdDGsnhab48gKe7z9j8pQfO54zFeE3+03Tz6EzoW+eb8gtU7LXgl +LqWL3wKBgQC0+0lRsGfnsPgRDaAAwoHCxP6h3DNMcRxNMca1aI78ENJZUXfY3XzG +yOE1i/1/SV1NQD4O1BlEqNTaDlM0yw0UttMvOPrI+ZC9hZIbCxVfXGZ7xKqIL+Vo +nG64GxSZh7M6pQHzUjlqTpsr8JaG6O7ODQtlYPHwNw24j7YGvxfk7A== +-----END RSA PRIVATE KEY-----