xk6-kafka
xk6-kafka copied to clipboard
Tests SASL_SCRAM_SHA512 (SASL over TLS)
Hello,
I'm testing your test_sasl_auth.js script with a SCRAM_SHA512 user.
But I have this error:
$ k6 run -v k6-sasl.js
DEBU[0000] Logger format: TEXT
DEBU[0000] k6 version: v0.39.0 ((devel), go1.18.4, linux/amd64)
/\ |‾‾| /‾‾/ /‾‾/
/\ / \ | |/ / / /
/ \/ \ | ( / ‾‾\
/ \ | |\ \ | (‾) |
/ __________ \ |__| \__\ \_____/ .io
DEBU[0000] Resolving and reading test 'k6-sasl.js'...
DEBU[0000] Loading... moduleSpecifier="file:///k6-scripts/k6-sasl.js" originalModuleSpecifier=k6-sasl.js
DEBU[0000] 'k6-sasl.js' resolved to 'file:///k6-scripts/k6-sasl.js' and successfully loaded 3996 bytes!
DEBU[0000] Gathering k6 runtime options...
DEBU[0000] Initializing k6 runner for 'k6-sasl.js' (file:///k6-scripts/k6-sasl.js)...
DEBU[0000] Detecting test type for... test_path="file:///k6-scripts/k6-sasl.js"
DEBU[0000] Trying to load as a JS test... test_path="file:///k6-scripts/k6-sasl.js"
DEBU[0001] Babel: Transformed t=675.613151ms
ERRO[0001] ReferenceError: SASL_SCRAM_SHA512 is not defined
at file:///k6-scripts/k6-sasl.js:38:15(58) hint="script exception"
I use your docker image: mostafamoradian/xk6-kafka:latest
Any explanation ?
The script:
/*
This is a k6 test script that imports the xk6-kafka and
tests Kafka with a 200 JSON messages per iteration. It
also uses SASL authentication.
*/
import { check } from "k6";
import { Writer, Reader, Connection, SASL_PLAIN, TLS_1_2 } from "k6/x/kafka"; // import kafka extension
export const options = {
// This is used for testing purposes. For real-world use, you should use your own options:
// https://k6.io/docs/using-k6/k6-options/
scenarios: {
sasl_auth: {
executor: "constant-vus",
vus: 1,
duration: "10s",
gracefulStop: "1s",
},
},
};
const brokers = ["my-cluster-kafka-bootstrap.diod-mpms-kafka-test.svc:9092"];
const topic = "bench1";
// SASL config is optional
const saslConfig = {
username: "benchuser",
password: "XXXXXXXX",
// Possible values for the algorithm is:
// NONE (default)
// SASL_PLAIN
// SASL_SCRAM_SHA256
// SASL_SCRAM_SHA512
// SASL_SSL (must enable TLS)
algorithm: SASL_SCRAM_SHA512,
};
// TLS config is optional
const tlsConfig = {
// Enable/disable TLS (default: false)
enableTls: false,
// Skip TLS verification if the certificate is invalid or self-signed (default: false)
insecureSkipTlsVerify: false,
// Possible values:
// TLS_1_0
// TLS_1_1
// TLS_1_2 (default)
// TLS_1_3
minVersion: TLS_1_2,
// Only needed if you have a custom or self-signed certificate and keys
// clientCertPem: "/k6-scripts/benchuser.user.crt",
// clientKeyPem: "/k6-scripts/benchuser.user.key",
// serverCaPem: "/k6-scripts/benchuser.ca.crt",
};
const offset = 0;
// partition and groupID are mutually exclusive
const partition = 0;
const numPartitions = 1;
const replicationFactor = 1;
const groupID = "benchusergroup";
const writer = new Writer({
brokers: brokers,
topic: topic,
sasl: saslConfig,
tls: tlsConfig,
});
const reader = new Reader({
brokers: brokers,
topic: topic,
// partition: partition,
groupID: groupID,
offset: offset,
sasl: saslConfig,
tls: tlsConfig,
});
const connection = new Connection({
address: brokers[0],
sasl: saslConfig,
tls: tlsConfig,
});
if (__VU == 0) {
connection.createTopic({
topic: topic,
numPartitions: numPartitions,
replicationFactor: replicationFactor,
});
console.log("Existing topics: ", connection.listTopics(saslConfig, tlsConfig));
}
export default function () {
for (let index = 0; index < 100; index++) {
let messages = [
{
key: JSON.stringify({
correlationId: "test-id-abc-" + index,
}),
value: JSON.stringify({
name: "xk6-kafka",
version: "0.2.1",
author: "Mostafa Moradian",
description:
"k6 extension to load test Apache Kafka with support for Avro messages",
index: index,
}),
},
{
key: JSON.stringify({
correlationId: "test-id-def-" + index,
}),
value: JSON.stringify({
name: "xk6-kafka",
version: "0.2.1",
author: "Mostafa Moradian",
description:
"k6 extension to load test Apache Kafka with support for Avro messages",
index: index,
}),
},
];
writer.produce({ messages: messages });
}
// Read 10 messages only
let messages = reader.consume({ limit: 10 });
check(messages, {
"10 messages returned": (msgs) => msgs.length == 10,
});
}
export function teardown(data) {
if (__VU == 0) {
// Delete the topic
connection.deleteTopic(topic);
}
writer.close();
reader.close();
connection.close();
}
Rgds.
Hey @blezoray,
You need to import the constant at the top:
// import kafka extension and constants
import { Writer, Reader, Connection, SASL_SCRAM_SHA512, TLS_1_2 } from "k6/x/kafka";
I'll close this ticket, but feel free to re-open it if you have other questions.
With this import, it's better:
import { Writer, Reader, Connection, SASL_PLAIN, SASL_SCRAM_SHA512, TLS_1_2 } from "k6/x/kafka"; // import kafka extension
Thanks
Now, I'm trying to test a listerner with SASL over TLS. I configure the tlsConfig.serverCaPem with the path of my CA file.
// TLS config is optional
const tlsConfig = {
// Enable/disable TLS (default: false)
enableTls: true,
// Skip TLS verification if the certificate is invalid or self-signed (default: false)
insecureSkipTlsVerify: false,
// Possible values:
// TLS_1_0
// TLS_1_1
// TLS_1_2 (default)
// TLS_1_3
minVersion: TLS_1_2,
// Only needed if you have a custom or self-signed certificate and keys
// clientCertPem: "/k6-scripts/benchuser.user.crt",
// clientKeyPem: "/k6-scripts/benchuser.user.key",
serverCaPem: "/k6-scripts/benchuser.ca.crt",
};
But I have this error:
ERRO[0001] Cannot process TLS config error="File not found: , OriginalError: %!w(*fs.PathError=&{stat 2})"
ERRO[0001] Cannot process TLS config error="File not found: , OriginalError: %!w(*fs.PathError=&{stat 2})"
ERRO[0001] Cannot process TLS config error="File not found: , OriginalError: %!w(*fs.PathError=&{stat 2})"
ERRO[0001] Failed to create dialer., OriginalError: %!w(*fmt.wrapError=&{could not successfully authenticate to my-cluster-kafka-bootstrap.diod-mpms-kafka-test.svc:9093 with SASL: SASL handshake failed: EOF 0xc0015d8e00}) error="Failed to create dialer., OriginalError: %!w(*fmt.wrapError=&{could not successfully authenticate to my-cluster-kafka-bootstrap.diod-mpms-kafka-test.svc:9093 with SASL: SASL handshake failed: EOF 0xc0015d8e00})"
ERRO[0001] Failed to create dialer., OriginalError: %!w(*fmt.wrapError=&{could not successfully authenticate to my-cluster-kafka-bootstrap.diod-mpms-kafka-test.svc:9093 with SASL: SASL handshake failed: EOF 0xc0015d8e00})
at file:///tmp/k6-sasl-tls.js:84:19(124) hint="script exception"
It seems to open 3 files ???
It works fine when I remove the serverCaPem and I set insecureSkipTlsVerify to true.
Any reason ?
@blezoray
You need to provide all three files to be able to test over TLS. Also, if you pass insecureSkipTlsVerify, it'll completely bypass validation.
But if my listerner does SASL authentication over TLS, I have only the CA. With CA, user cert & key, it is TLS authentication and not SASL authentication.
@blezoray What do you mean? Can you elaborate?
I suppose @oscar067 has managed to make SASL/SSL auth work.
Here, you have an explanation of the difference between TLS 1 way and TLS 2 way. https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/
In your case, when you do SASL over TLS, you establish a TLS 1way session to the server and then SASL challenges the client to be authenticated with its user/password.
When you do TLS 2 ways, your client is authenticated inside the TLS session with its private key/cert and the server doesn't need to do SASL challenge.
Is it clear ?
Hi
I was able to make work the SSL TLS 2 way, as @mostafa describe, but is true I did not tried SASL over TLS
export const writerCommsHub = new Writer({
// WriterConfig object
brokers: bootstrap,
topic: kafkaTopic,
tls: {
enableTls: true,
insecureSkipTlsVerify: false,
clientCertPem: "/certs/cert.pem",
clientKeyPem: "/certs/server.key",
serverCaPem: "/certs/Corporate_Root_CA_G3_.cer",
},
});
@oscar067 Thanks for letting us know. @blezoray Then this is something I need to investigate more.
Hi @mostafa , I found this video which explains the difference between TLS and SASL over TLS. https://www.youtube.com/watch?v=_PmEs8xEz8g
Rgds.
@blezoray Awesome! Thanks for the pointer.
I'll try to see if I can fix it. In the meantime, I'd be happy to see contributions. SASL and TLS are handled in the auth.go file.
@blezoray Created #169 to fix this issue.
@blezoray Fixed in #170. Feel free to reopen the issue if it problem persists.
Hi,
Sorry for the delay to answer. I tested SASL auth, SASL auth over TLS, and TLS auth. All works fine. Thanks a lot.
Rgds.