66//
77// Options:
88//
9- // -d Debug logging (implies -v)
10- // -v Verbose - log non-critical errors also
11- // -D http receive only (for debugging; implies -d) with dump to kafka-proxy.dat
9+ // -v Verbose - log non-critical errors also
10+ // -d Debug logging (implies -v)
11+ // -D http receive only (for debugging; implies -d) with dump to kafka-proxy.dat
12+ // -P password Password for use with -D exclusively
1213//
1314// Kafka posts data via http to this proxy. This proxy decodes the traffic and then speaks the
1415// normal Kafka protocol to the broker, forwarding individual messages to it. It is not necessary
2122// non-critical errors), and to stderr with -d.
2223//
2324// With -D, all validated incoming data are appended to kafka-proxy.dat in the proxy's working
24- // directory.
25+ // directory. With -P, the sasl-password field must be set in the control object and must match
26+ // this password or the message is rejected, not dumped.
2527//
2628// # Config file
2729//
@@ -135,7 +137,8 @@ var (
135137 httpListenPort = 8090
136138 debug = flag .Bool ("d" , false , "Debug logging" )
137139 verbose = flag .Bool ("v" , false , "Verbose logging of non-critical errors" )
138- receiveOnly = flag .Bool ("D" , false , "Receive only (for debugging)" )
140+ receiveOnly = flag .Bool ("D" , false , "Receive only (for debugging) + dumping" )
141+ password = flag .String ("P" , "" , "Password (for -D only)" )
139142)
140143
141144var (
@@ -263,6 +266,15 @@ func runDebugDumper(ch <-chan Msg) {
263266 }
264267 msgId := id
265268 id ++
269+ // If no -P then accept everything.
270+ if * password != "" {
271+ if msg .Control .SaslPassword != * password {
272+ if * debug {
273+ log .Printf ("Dropping message, bad password" )
274+ }
275+ continue
276+ }
277+ }
266278 if * debug {
267279 log .Printf (
268280 "Message #%d received: %s %s %s %s %s %d" ,
@@ -296,13 +308,7 @@ func runKafkaSender(ch <-chan Msg) {
296308 msgId , msg .Topic , msg .Key , msg .Client , msg .SaslUser , msg .SaslPassword , msg .DataSize ,
297309 )
298310 }
299- // TODO: Should we launder these even more?
300- saslUser := strings .TrimSpace (msg .SaslUser )
301- saslPassword := strings .TrimSpace (msg .SaslPassword )
302- topic := strings .TrimSpace (msg .Topic )
303- key := strings .TrimSpace (msg .Key )
304- client := strings .TrimSpace (msg .Client )
305- if kafkaRequireSasl && saslUser == "" && saslPassword == "" {
311+ if kafkaRequireSasl && msg .SaslUser == "" && msg .SaslPassword == "" {
306312 if * debug {
307313 log .Printf ("Rejecting message b/c no Sasl credentials" )
308314 }
@@ -312,15 +318,15 @@ func runKafkaSender(ch <-chan Msg) {
312318 // each node that sends us data. So attach client as a header to the record, to
313319 // indicate the originating client.
314320 record := & kgo.Record {
315- Key : []byte (key ),
316- Topic : topic ,
321+ Key : []byte (msg . Key ),
322+ Topic : msg . Topic ,
317323 Value : msg .Data ,
318324 Headers : []kgo.RecordHeader {
319- kgo.RecordHeader {Key : "Originator" , Value : []byte (client )},
325+ kgo.RecordHeader {Key : "Originator" , Value : []byte (msg . Client )},
320326 kgo.RecordHeader {Key : "Id" , Value : []byte (fmt .Sprint (msgId ))},
321327 },
322328 }
323- clientId := saslUser + "|" + saslPassword
329+ clientId := msg . SaslUser + "|" + msg . SaslPassword
324330 cl := clients [clientId ]
325331 if cl == nil {
326332 if len (clients ) == maxCredentials {
@@ -335,10 +341,10 @@ func runKafkaSender(ch <-chan Msg) {
335341 kgo .SeedBrokers (kafkaBrokerAddress ),
336342 kgo .AllowAutoTopicCreation (),
337343 }
338- if saslUser != "" || saslPassword != "" {
344+ if msg . SaslUser != "" || msg . SaslPassword != "" {
339345 opts = append (opts , kgo .SASL (plain.Auth {
340- User : saslUser ,
341- Pass : saslPassword ,
346+ User : msg . SaslUser ,
347+ Pass : msg . SaslPassword ,
342348 }.AsMechanism ()))
343349 }
344350 if kafkaCaCert != nil {
@@ -456,15 +462,27 @@ func parsePayload(ch chan<- Msg, payload []byte) (int, string) {
456462 report (false , "Could not decode a control object: %v\n %s" , err , string (controlObject ))
457463 return 400 , "Malformed control object"
458464 }
465+
459466 // Consume the control object and single newline we know is there, because we found it
460467 ix += loc + 1
468+
461469 // Extract the data, and forward the control object and data to the Kafka thread.
462470 endIx := ix + int (c .DataSize )
463471 if endIx > len (payload ) {
464472 report (false , "Out of bounds data length for %s" , string (controlObject ))
465473 return 400 , "Out of bounds data length"
466474 }
475+
476+ // Launder the control fields.
477+ c .SaslUser = strings .TrimSpace (c .SaslUser )
478+ c .SaslPassword = strings .TrimSpace (c .SaslPassword )
479+ c .Topic = strings .TrimSpace (c .Topic )
480+ c .Key = strings .TrimSpace (c .Key )
481+ c .Client = strings .TrimSpace (c .Client )
482+
483+ // Produce it.
467484 ch <- Msg {Control : c , Data : payload [ix :endIx ]}
485+
468486 // Consume the data
469487 ix = endIx
470488 }
0 commit comments