github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/lorry/engines/kafka/metadata_test.go (about)

     1  /*
     2  Copyright 2021 The Dapr Authors
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6      http://www.apache.org/licenses/LICENSE-2.0
     7  Unless required by applicable law or agreed to in writing, software
     8  distributed under the License is distributed on an "AS IS" BASIS,
     9  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  See the License for the specific language governing permissions and
    11  limitations under the License.
    12  */
    13  
    14  package kafka
    15  
    16  import (
    17  	"fmt"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/go-logr/zapr"
    22  	"go.uber.org/zap"
    23  
    24  	"github.com/Shopify/sarama"
    25  	"github.com/stretchr/testify/require"
    26  )
    27  
    28  var (
    29  	clientCertPemMock = `-----BEGIN CERTIFICATE-----
    30  Y2xpZW50Q2VydA==
    31  -----END CERTIFICATE-----`
    32  	clientKeyMock = `-----BEGIN RSA PRIVATE KEY-----
    33  Y2xpZW50S2V5
    34  -----END RSA PRIVATE KEY-----`
    35  	caCertMock = `-----BEGIN CERTIFICATE-----
    36  Y2FDZXJ0
    37  -----END CERTIFICATE-----`
    38  )
    39  
    40  func getKafka() *Kafka {
    41  	development, _ := zap.NewDevelopment()
    42  	return &Kafka{logger: zapr.NewLogger(development)}
    43  }
    44  
    45  func getBaseMetadata() map[string]string {
    46  	return map[string]string{"consumerGroup": "a", "clientID": "a", "brokers": "a", "disableTls": "true", "authType": mtlsAuthType, "maxMessageBytes": "2048", "initialOffset": "newest"}
    47  }
    48  
    49  func getCompleteMetadata() map[string]string {
    50  	return map[string]string{
    51  		"consumerGroup": "a", "clientID": "a", "brokers": "a", "authType": mtlsAuthType, "maxMessageBytes": "2048",
    52  		skipVerify: "true", clientCert: clientCertPemMock, clientKey: clientKeyMock, caCert: caCertMock,
    53  		"consumeRetryInterval": "200", "initialOffset": "newest",
    54  	}
    55  }
    56  
    57  func TestParseMetadata(t *testing.T) {
    58  	k := getKafka()
    59  	t.Run("default kafka version", func(t *testing.T) {
    60  		m := getCompleteMetadata()
    61  		meta, err := k.getKafkaMetadata(m)
    62  		require.NoError(t, err)
    63  		require.NotNil(t, meta)
    64  		assertMetadata(t, meta)
    65  		require.Equal(t, sarama.V2_0_0_0, meta.Version) //nolint:nosnakecase
    66  	})
    67  
    68  	t.Run("specific kafka version", func(t *testing.T) {
    69  		m := getCompleteMetadata()
    70  		m["version"] = "0.10.2.0"
    71  		meta, err := k.getKafkaMetadata(m)
    72  		require.NoError(t, err)
    73  		require.NotNil(t, meta)
    74  		assertMetadata(t, meta)
    75  		require.Equal(t, sarama.V0_10_2_0, meta.Version) //nolint:nosnakecase
    76  	})
    77  
    78  	t.Run("invalid kafka version", func(t *testing.T) {
    79  		m := getCompleteMetadata()
    80  		m["version"] = "not_valid_version"
    81  		meta, err := k.getKafkaMetadata(m)
    82  		require.Error(t, err)
    83  		require.Nil(t, meta)
    84  		require.Equal(t, "kafka error: invalid kafka version", err.Error())
    85  	})
    86  }
    87  
    88  func assertMetadata(t *testing.T, meta *kafkaMetadata) {
    89  	require.Equal(t, "a", meta.Brokers[0])
    90  	require.Equal(t, "a", meta.ConsumerGroup)
    91  	require.Equal(t, "a", meta.ClientID)
    92  	require.Equal(t, 2048, meta.MaxMessageBytes)
    93  	require.Equal(t, true, meta.TLSSkipVerify)
    94  	require.Equal(t, clientCertPemMock, meta.TLSClientCert)
    95  	require.Equal(t, clientKeyMock, meta.TLSClientKey)
    96  	require.Equal(t, caCertMock, meta.TLSCaCert)
    97  	require.Equal(t, 200*time.Millisecond, meta.ConsumeRetryInterval)
    98  }
    99  
   100  func TestMissingBrokers(t *testing.T) {
   101  	m := map[string]string{"initialOffset": "newest"}
   102  	k := getKafka()
   103  	meta, err := k.getKafkaMetadata(m)
   104  	require.Error(t, err)
   105  	require.Nil(t, meta)
   106  
   107  	require.Equal(t, "kafka error: missing 'brokers' attribute", err.Error())
   108  }
   109  
   110  func TestMissingAuthType(t *testing.T) {
   111  	m := map[string]string{"brokers": "kafka.com:9092", "initialOffset": "newest"}
   112  	k := getKafka()
   113  	meta, err := k.getKafkaMetadata(m)
   114  	require.Error(t, err)
   115  	require.Nil(t, meta)
   116  
   117  	require.Equal(t, "kafka error: missing 'authType' attribute", err.Error())
   118  }
   119  
   120  func TestMetadataUpgradeNoAuth(t *testing.T) {
   121  	m := map[string]string{"brokers": "akfak.com:9092", "initialOffset": "newest", "authRequired": "false"}
   122  	k := getKafka()
   123  	upgraded, err := k.upgradeMetadata(m)
   124  	require.Nil(t, err)
   125  	require.Equal(t, noAuthType, upgraded["authType"])
   126  }
   127  
   128  func TestMetadataUpgradePasswordAuth(t *testing.T) {
   129  	k := getKafka()
   130  	m := map[string]string{"brokers": "akfak.com:9092", "initialOffset": "newest", "authRequired": "true", "saslPassword": "sassapass"}
   131  	upgraded, err := k.upgradeMetadata(m)
   132  	require.Nil(t, err)
   133  	require.Equal(t, passwordAuthType, upgraded["authType"])
   134  }
   135  
   136  func TestMetadataUpgradePasswordMTLSAuth(t *testing.T) {
   137  	k := getKafka()
   138  	m := map[string]string{"brokers": "akfak.com:9092", "initialOffset": "newest", "authRequired": "true"}
   139  	upgraded, err := k.upgradeMetadata(m)
   140  	require.Nil(t, err)
   141  	require.Equal(t, mtlsAuthType, upgraded["authType"])
   142  }
   143  
   144  func TestMissingSaslValues(t *testing.T) {
   145  	k := getKafka()
   146  	m := map[string]string{"brokers": "akfak.com:9092", "initialOffset": "newest", "authType": "password"}
   147  	meta, err := k.getKafkaMetadata(m)
   148  	require.Error(t, err)
   149  	require.Nil(t, meta)
   150  
   151  	require.Equal(t, fmt.Sprintf("kafka error: missing SASL Username for authType '%s'", passwordAuthType), err.Error())
   152  
   153  	m["saslUsername"] = "sassafras"
   154  
   155  	meta, err = k.getKafkaMetadata(m)
   156  	require.Error(t, err)
   157  	require.Nil(t, meta)
   158  
   159  	require.Equal(t, fmt.Sprintf("kafka error: missing SASL Password for authType '%s'", passwordAuthType), err.Error())
   160  }
   161  
   162  func TestMissingSaslValuesOnUpgrade(t *testing.T) {
   163  	k := getKafka()
   164  	m := map[string]string{"brokers": "akfak.com:9092", "initialOffset": "newest", "authRequired": "true", "saslPassword": "sassapass"}
   165  	upgraded, err := k.upgradeMetadata(m)
   166  	require.Nil(t, err)
   167  	meta, err := k.getKafkaMetadata(upgraded)
   168  	require.Error(t, err)
   169  	require.Nil(t, meta)
   170  
   171  	require.Equal(t, fmt.Sprintf("kafka error: missing SASL Username for authType '%s'", passwordAuthType), err.Error())
   172  }
   173  
   174  func TestMissingOidcValues(t *testing.T) {
   175  	k := getKafka()
   176  	m := map[string]string{"brokers": "akfak.com:9092", "initialOffset": "newest", "authType": oidcAuthType}
   177  	meta, err := k.getKafkaMetadata(m)
   178  	require.Error(t, err)
   179  	require.Nil(t, meta)
   180  	require.Equal(t, fmt.Sprintf("kafka error: missing OIDC Token Endpoint for authType '%s'", oidcAuthType), err.Error())
   181  
   182  	m["oidcTokenEndpoint"] = "https://sassa.fra/"
   183  	meta, err = k.getKafkaMetadata(m)
   184  	require.Error(t, err)
   185  	require.Nil(t, meta)
   186  	require.Equal(t, fmt.Sprintf("kafka error: missing OIDC Client ID for authType '%s'", oidcAuthType), err.Error())
   187  
   188  	m["oidcClientID"] = "sassafras"
   189  	meta, err = k.getKafkaMetadata(m)
   190  	require.Error(t, err)
   191  	require.Nil(t, meta)
   192  	require.Equal(t, fmt.Sprintf("kafka error: missing OIDC Client Secret for authType '%s'", oidcAuthType), err.Error())
   193  
   194  	// Check if missing scopes causes the default 'openid' to be used.
   195  	m["oidcClientSecret"] = "sassapass"
   196  	meta, err = k.getKafkaMetadata(m)
   197  	require.Nil(t, err)
   198  	require.Contains(t, meta.OidcScopes, "openid")
   199  }
   200  
   201  func TestPresentSaslValues(t *testing.T) {
   202  	k := getKafka()
   203  	m := map[string]string{
   204  		"brokers":       "akfak.com:9092",
   205  		"authType":      passwordAuthType,
   206  		"saslUsername":  "sassafras",
   207  		"saslPassword":  "sassapass",
   208  		"initialOffset": "newest",
   209  	}
   210  	meta, err := k.getKafkaMetadata(m)
   211  	require.NoError(t, err)
   212  	require.NotNil(t, meta)
   213  
   214  	require.Equal(t, "sassafras", meta.SaslUsername)
   215  	require.Equal(t, "sassapass", meta.SaslPassword)
   216  }
   217  
   218  func TestPresentOidcValues(t *testing.T) {
   219  	k := getKafka()
   220  	m := map[string]string{
   221  		"brokers":           "akfak.com:9092",
   222  		"authType":          oidcAuthType,
   223  		"oidcTokenEndpoint": "https://sassa.fras",
   224  		"oidcClientID":      "sassafras",
   225  		"oidcClientSecret":  "sassapass",
   226  		"oidcScopes":        "akfak",
   227  		"initialOffset":     "newest",
   228  	}
   229  	meta, err := k.getKafkaMetadata(m)
   230  	require.NoError(t, err)
   231  	require.NotNil(t, meta)
   232  
   233  	require.Equal(t, "https://sassa.fras", meta.OidcTokenEndpoint)
   234  	require.Equal(t, "sassafras", meta.OidcClientID)
   235  	require.Equal(t, "sassapass", meta.OidcClientSecret)
   236  	require.Contains(t, meta.OidcScopes, "akfak")
   237  }
   238  
   239  func TestInvalidAuthRequiredFlag(t *testing.T) {
   240  	m := map[string]string{"brokers": "akfak.com:9092", "authRequired": "maybe?????????????"}
   241  	k := getKafka()
   242  	_, err := k.upgradeMetadata(m)
   243  	require.Error(t, err)
   244  
   245  	require.Equal(t, "kafka error: invalid value for 'authRequired' attribute", err.Error())
   246  }
   247  
   248  func TestInitialOffset(t *testing.T) {
   249  	m := map[string]string{"consumerGroup": "a", "brokers": "a", "authRequired": "false", "initialOffset": "oldest"}
   250  	k := getKafka()
   251  	upgraded, err := k.upgradeMetadata(m)
   252  	require.NoError(t, err)
   253  	meta, err := k.getKafkaMetadata(upgraded)
   254  	require.NoError(t, err)
   255  	require.Equal(t, sarama.OffsetOldest, meta.InitialOffset)
   256  	m["initialOffset"] = "newest"
   257  	meta, err = k.getKafkaMetadata(m)
   258  	require.NoError(t, err)
   259  	require.Equal(t, sarama.OffsetNewest, meta.InitialOffset)
   260  }
   261  
   262  func TestTls(t *testing.T) {
   263  	k := getKafka()
   264  
   265  	t.Run("disable tls", func(t *testing.T) {
   266  		m := getBaseMetadata()
   267  		meta, err := k.getKafkaMetadata(m)
   268  		require.NoError(t, err)
   269  		require.NotNil(t, meta)
   270  		c := &sarama.Config{}
   271  		err = updateTLSConfig(c, meta)
   272  		require.NoError(t, err)
   273  		require.Equal(t, false, c.Net.TLS.Enable)
   274  	})
   275  
   276  	t.Run("wrong client cert format", func(t *testing.T) {
   277  		m := getBaseMetadata()
   278  		m[clientCert] = "clientCert"
   279  		meta, err := k.getKafkaMetadata(m)
   280  		require.Error(t, err)
   281  		require.Nil(t, meta)
   282  
   283  		require.Equal(t, "kafka error: invalid client certificate", err.Error())
   284  	})
   285  
   286  	t.Run("wrong client key format", func(t *testing.T) {
   287  		m := getBaseMetadata()
   288  		m[clientKey] = "clientKey"
   289  		meta, err := k.getKafkaMetadata(m)
   290  		require.Error(t, err)
   291  		require.Nil(t, meta)
   292  
   293  		require.Equal(t, "kafka error: invalid client key", err.Error())
   294  	})
   295  
   296  	t.Run("miss client key", func(t *testing.T) {
   297  		m := getBaseMetadata()
   298  		m[clientCert] = clientCertPemMock
   299  		meta, err := k.getKafkaMetadata(m)
   300  		require.Error(t, err)
   301  		require.Nil(t, meta)
   302  
   303  		require.Equal(t, "kafka error: clientKey or clientCert is missing", err.Error())
   304  	})
   305  
   306  	t.Run("miss client cert", func(t *testing.T) {
   307  		m := getBaseMetadata()
   308  		m[clientKey] = clientKeyMock
   309  		meta, err := k.getKafkaMetadata(m)
   310  		require.Error(t, err)
   311  		require.Nil(t, meta)
   312  
   313  		require.Equal(t, "kafka error: clientKey or clientCert is missing", err.Error())
   314  	})
   315  
   316  	t.Run("wrong ca cert format", func(t *testing.T) {
   317  		m := getBaseMetadata()
   318  		m[caCert] = "caCert"
   319  		meta, err := k.getKafkaMetadata(m)
   320  		require.Error(t, err)
   321  		require.Nil(t, meta)
   322  
   323  		require.Equal(t, "kafka error: invalid ca certificate", err.Error())
   324  	})
   325  }