github.com/crowdsecurity/crowdsec@v1.6.1/pkg/acquisition/modules/kafka/kafka_test.go (about) 1 package kafkaacquisition 2 3 import ( 4 "context" 5 "net" 6 "runtime" 7 "strconv" 8 "testing" 9 "time" 10 11 "github.com/segmentio/kafka-go" 12 log "github.com/sirupsen/logrus" 13 "github.com/stretchr/testify/require" 14 "gopkg.in/tomb.v2" 15 16 "github.com/crowdsecurity/go-cs-lib/cstest" 17 18 "github.com/crowdsecurity/crowdsec/pkg/acquisition/configuration" 19 "github.com/crowdsecurity/crowdsec/pkg/types" 20 ) 21 22 func TestConfigure(t *testing.T) { 23 tests := []struct { 24 config string 25 expectedErr string 26 }{ 27 { 28 config: ` 29 foobar: bla 30 source: kafka`, 31 expectedErr: "line 2: field foobar not found in type kafkaacquisition.KafkaConfiguration", 32 }, 33 { 34 config: `source: kafka`, 35 expectedErr: "cannot create a kafka reader with an empty list of broker addresses", 36 }, 37 { 38 config: ` 39 source: kafka 40 brokers: 41 - bla 42 timeout: 5`, 43 expectedErr: "cannot create a kafka reader with am empty topic", 44 }, 45 { 46 config: ` 47 source: kafka 48 brokers: 49 - bla 50 topic: toto 51 timeout: aa`, 52 expectedErr: "cannot create kafka dialer: strconv.Atoi: parsing \"aa\": invalid syntax", 53 }, 54 { 55 config: ` 56 source: kafka 57 brokers: 58 - localhost:9092 59 topic: crowdsec`, 60 expectedErr: "", 61 }, 62 { 63 config: ` 64 source: kafka 65 brokers: 66 - localhost:9092 67 topic: crowdsec 68 partition: 1 69 group_id: crowdsec`, 70 expectedErr: "cannote create kafka reader: cannot specify both group_id and partition", 71 }, 72 } 73 74 subLogger := log.WithFields(log.Fields{ 75 "type": "kafka", 76 }) 77 for _, test := range tests { 78 k := KafkaSource{} 79 err := k.Configure([]byte(test.config), subLogger, configuration.METRICS_NONE) 80 cstest.AssertErrorContains(t, err, test.expectedErr) 81 } 82 } 83 84 func writeToKafka(w *kafka.Writer, logs []string) { 85 86 for idx, log := range logs { 87 err := w.WriteMessages(context.Background(), kafka.Message{ 88 Key: []byte(strconv.Itoa(idx)), 89 // create an arbitrary message payload for the value 90 Value: []byte(log), 91 }) 92 if err != nil { 93 panic("could not write message " + err.Error()) 94 } 95 } 96 } 97 98 func createTopic(topic string, broker string) { 99 conn, err := kafka.Dial("tcp", broker) 100 if err != nil { 101 panic(err) 102 } 103 defer conn.Close() 104 105 controller, err := conn.Controller() 106 if err != nil { 107 panic(err) 108 } 109 var controllerConn *kafka.Conn 110 controllerConn, err = kafka.Dial("tcp", net.JoinHostPort(controller.Host, strconv.Itoa(controller.Port))) 111 if err != nil { 112 panic(err) 113 } 114 defer controllerConn.Close() 115 116 topicConfigs := []kafka.TopicConfig{ 117 { 118 Topic: topic, 119 NumPartitions: 1, 120 ReplicationFactor: 1, 121 }, 122 } 123 124 err = controllerConn.CreateTopics(topicConfigs...) 125 if err != nil { 126 panic(err) 127 } 128 } 129 130 func TestStreamingAcquisition(t *testing.T) { 131 if runtime.GOOS == "windows" { 132 t.Skip("Skipping test on windows") 133 } 134 tests := []struct { 135 name string 136 logs []string 137 expectedLines int 138 expectedErr string 139 }{ 140 { 141 name: "valid msgs", 142 logs: []string{ 143 "message 1", 144 "message 2", 145 "message 3", 146 }, 147 expectedLines: 3, 148 }, 149 } 150 151 subLogger := log.WithFields(log.Fields{ 152 "type": "kafka", 153 }) 154 155 createTopic("crowdsecplaintext", "localhost:9092") 156 157 w := kafka.NewWriter(kafka.WriterConfig{ 158 Brokers: []string{"localhost:9092"}, 159 Topic: "crowdsecplaintext", 160 }) 161 if w == nil { 162 log.Fatalf("Unable to setup a kafka producer") 163 } 164 165 for _, ts := range tests { 166 ts := ts 167 t.Run(ts.name, func(t *testing.T) { 168 k := KafkaSource{} 169 err := k.Configure([]byte(` 170 source: kafka 171 brokers: 172 - localhost:9092 173 topic: crowdsecplaintext`), subLogger, configuration.METRICS_NONE) 174 if err != nil { 175 t.Fatalf("could not configure kafka source : %s", err) 176 } 177 tomb := tomb.Tomb{} 178 out := make(chan types.Event) 179 err = k.StreamingAcquisition(out, &tomb) 180 cstest.AssertErrorContains(t, err, ts.expectedErr) 181 182 actualLines := 0 183 go writeToKafka(w, ts.logs) 184 READLOOP: 185 for { 186 select { 187 case <-out: 188 actualLines++ 189 case <-time.After(2 * time.Second): 190 break READLOOP 191 } 192 } 193 require.Equal(t, ts.expectedLines, actualLines) 194 tomb.Kill(nil) 195 tomb.Wait() 196 }) 197 } 198 199 } 200 201 func TestStreamingAcquisitionWithSSL(t *testing.T) { 202 if runtime.GOOS == "windows" { 203 t.Skip("Skipping test on windows") 204 } 205 tests := []struct { 206 name string 207 logs []string 208 expectedLines int 209 expectedErr string 210 }{ 211 { 212 name: "valid msgs", 213 logs: []string{ 214 "message 1", 215 "message 2", 216 }, 217 expectedLines: 2, 218 }, 219 } 220 221 subLogger := log.WithFields(log.Fields{ 222 "type": "kafka", 223 }) 224 225 createTopic("crowdsecssl", "localhost:9092") 226 227 w2 := kafka.NewWriter(kafka.WriterConfig{ 228 Brokers: []string{"localhost:9092"}, 229 Topic: "crowdsecssl", 230 }) 231 if w2 == nil { 232 log.Fatalf("Unable to setup a kafka producer") 233 } 234 235 for _, ts := range tests { 236 ts := ts 237 t.Run(ts.name, func(t *testing.T) { 238 k := KafkaSource{} 239 err := k.Configure([]byte(` 240 source: kafka 241 brokers: 242 - localhost:9093 243 topic: crowdsecssl 244 tls: 245 insecure_skip_verify: true 246 client_cert: ./testdata/kafkaClient.certificate.pem 247 client_key: ./testdata/kafkaClient.key 248 ca_cert: ./testdata/snakeoil-ca-1.crt 249 `), subLogger, configuration.METRICS_NONE) 250 if err != nil { 251 t.Fatalf("could not configure kafka source : %s", err) 252 } 253 tomb := tomb.Tomb{} 254 out := make(chan types.Event) 255 err = k.StreamingAcquisition(out, &tomb) 256 cstest.AssertErrorContains(t, err, ts.expectedErr) 257 258 actualLines := 0 259 go writeToKafka(w2, ts.logs) 260 READLOOP: 261 for { 262 select { 263 case <-out: 264 actualLines++ 265 case <-time.After(2 * time.Second): 266 break READLOOP 267 } 268 } 269 require.Equal(t, ts.expectedLines, actualLines) 270 tomb.Kill(nil) 271 tomb.Wait() 272 }) 273 } 274 275 }