Skip to content

Commit 890c481

Browse files
No bug - Allow data dumping to be filtered by passwd (#519)
1 parent d838ba1 commit 890c481

1 file changed

Lines changed: 37 additions & 19 deletions

File tree

util/kafka-proxy/kprox.go

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
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
@@ -21,7 +22,8 @@
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

141144
var (
@@ -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

Comments
 (0)