test: add test cases for Kafka SASL auth mechanisms plain and scram

This commit is contained in:
Kjell Winblad 2022-09-12 20:54:58 +02:00
parent 0c1595be02
commit f0e03086a6
5 changed files with 122 additions and 14 deletions

View File

@ -13,15 +13,24 @@ services:
image: wurstmeister/kafka:2.13-2.7.0 image: wurstmeister/kafka:2.13-2.7.0
ports: ports:
- "9092:9092" - "9092:9092"
- "9093:9093"
container_name: kafka-1.emqx.net container_name: kafka-1.emqx.net
hostname: kafka-1.emqx.net hostname: kafka-1.emqx.net
environment: environment:
KAFKA_BROKER_ID: 1 KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENERS: PLAINTEXT://:9092 KAFKA_LISTENERS: PLAINTEXT://:9092,SASL_PLAINTEXT://:9093
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka-1.emqx.net:9092 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka-1.emqx.net:9092,SASL_PLAINTEXT://kafka-1.emqx.net:9093
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_SASL_ENABLED_MECHANISMS: PLAIN,SCRAM-SHA-256,SCRAM-SHA-512
KAFKA_JMX_OPTS: "-Djava.security.auth.login.config=/etc/kafka/jaas.conf"
KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: true
KAFKA_CREATE_TOPICS: test-topic-one-partition:1:1,test-topic-two-partitions:2:1,test-topic-three-partitions:3:1, KAFKA_CREATE_TOPICS: test-topic-one-partition:1:1,test-topic-two-partitions:2:1,test-topic-three-partitions:3:1,
networks: networks:
emqx_bridge: emqx_bridge:
volumes:
- ./kafka/jaas.conf:/etc/kafka/jaas.conf
- ./kafka/run_add_scram_users.sh:/bin/run_add_scram_users.sh
command: run_add_scram_users.sh

View File

@ -0,0 +1,9 @@
KafkaServer {
org.apache.kafka.common.security.plain.PlainLoginModule required
user_admin="password"
user_emqxuser="password";
org.apache.kafka.common.security.scram.ScramLoginModule required
username="admin"
password="password";
};

View File

@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail
echo "+++++++ Starting Kafka ++++++++"
start-kafka.sh &
SERVER=localhost
PORT1=9092
PORT2=9093
TIMEOUT=60
echo "+++++++ Wait until Kafka ports are up ++++++++"
timeout $TIMEOUT bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' $SERVER $PORT1
timeout $TIMEOUT bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' $SERVER $PORT2
echo "+++++++ Run config commands ++++++++"
kafka-configs.sh --bootstrap-server localhost:9092 --alter --add-config 'SCRAM-SHA-256=[iterations=8192,password=password],SCRAM-SHA-512=[password=password]' --entity-type users --entity-name emqxuser
echo "+++++++ Wait until Kafka ports are down ++++++++"
bash -c 'while printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' $SERVER $PORT1

View File

@ -28,12 +28,7 @@ init_per_suite(Config) ->
end_per_suite(_) -> end_per_suite(_) ->
ok. ok.
t_publish(_CtConfig) -> do_publish(Conf, KafkaTopic) ->
KafkaTopic = "test-topic-one-partition",
Conf = config(#{
"kafka_hosts_string" => kafka_hosts_string(),
"kafka_topic" => KafkaTopic
}),
InstId = <<"InstanceID">>, InstId = <<"InstanceID">>,
Time = erlang:system_time(millisecond), Time = erlang:system_time(millisecond),
BinTime = integer_to_binary(Time), BinTime = integer_to_binary(Time),
@ -51,6 +46,54 @@ t_publish(_CtConfig) ->
ok = ?PRODUCER:on_stop(InstId, State), ok = ?PRODUCER:on_stop(InstId, State),
ok. ok.
t_publish(_CtConfig) ->
KafkaTopic = "test-topic-one-partition",
Conf = config(#{
"authentication" => "none",
"kafka_hosts_string" => kafka_hosts_string(),
"kafka_topic" => KafkaTopic
}),
do_publish(Conf, KafkaTopic).
t_publish_sasl_plain(_CtConfig) ->
KafkaTopic = "test-topic-one-partition",
Conf = config(#{
"authentication" => #{
"mechanism" => "plain",
"username" => "emqxuser",
"password" => "password"
},
"kafka_hosts_string" => kafka_hosts_string_sasl(),
"kafka_topic" => KafkaTopic
}),
do_publish(Conf, KafkaTopic).
t_publish_sasl_scram256(_CtConfig) ->
KafkaTopic = "test-topic-one-partition",
Conf = config(#{
"authentication" => #{
"mechanism" => "scram_sha_256",
"username" => "emqxuser",
"password" => "password"
},
"kafka_hosts_string" => kafka_hosts_string_sasl(),
"kafka_topic" => KafkaTopic
}),
do_publish(Conf, KafkaTopic).
t_publish_sasl_scram512(_CtConfig) ->
KafkaTopic = "test-topic-one-partition",
Conf = config(#{
"authentication" => #{
"mechanism" => "scram_sha_512",
"username" => "emqxuser",
"password" => "password"
},
"kafka_hosts_string" => kafka_hosts_string_sasl(),
"kafka_topic" => KafkaTopic
}),
do_publish(Conf, KafkaTopic).
config(Args) -> config(Args) ->
{ok, Conf} = hocon:binary(hocon_config(Args)), {ok, Conf} = hocon:binary(hocon_config(Args)),
#{config := Parsed} = hocon_tconf:check_plain( #{config := Parsed} = hocon_tconf:check_plain(
@ -61,7 +104,13 @@ config(Args) ->
Parsed#{bridge_name => "testbridge"}. Parsed#{bridge_name => "testbridge"}.
hocon_config(Args) -> hocon_config(Args) ->
Hocon = bbmustache:render(iolist_to_binary(hocon_config_template()), Args), AuthConf = maps:get("authentication", Args),
AuthTemplate = iolist_to_binary(hocon_config_template_authentication(AuthConf)),
AuthConfRendered = bbmustache:render(AuthTemplate, AuthConf),
Hocon = bbmustache:render(
iolist_to_binary(hocon_config_template()),
Args#{"authentication" => AuthConfRendered}
),
Hocon. Hocon.
%% erlfmt-ignore %% erlfmt-ignore
@ -69,7 +118,7 @@ hocon_config_template() ->
""" """
bootstrap_hosts = \"{{ kafka_hosts_string }}\" bootstrap_hosts = \"{{ kafka_hosts_string }}\"
enable = true enable = true
authentication = none authentication = {{{ authentication }}}
producer = { producer = {
mqtt { mqtt {
topic = \"t/#\" topic = \"t/#\"
@ -80,9 +129,24 @@ producer = {
} }
""". """.
%% erlfmt-ignore
hocon_config_template_authentication("none") ->
"none";
hocon_config_template_authentication(#{"mechanism" := _}) ->
"""
{
mechanism = {{ mechanism }}
password = {{ password }}
username = {{ username }}
}
""".
kafka_hosts_string() -> kafka_hosts_string() ->
"kafka-1.emqx.net:9092,". "kafka-1.emqx.net:9092,".
kafka_hosts_string_sasl() ->
"kafka-1.emqx.net:9093,".
kafka_hosts() -> kafka_hosts() ->
kpro:parse_endpoints(kafka_hosts_string()). kpro:parse_endpoints(kafka_hosts_string()).

View File

@ -14,8 +14,8 @@ help() {
echo "--suites SUITE1,SUITE2: Comma separated SUITE names to run. e.g. apps/emqx/test/emqx_SUITE.erl" echo "--suites SUITE1,SUITE2: Comma separated SUITE names to run. e.g. apps/emqx/test/emqx_SUITE.erl"
echo "--console: Start EMQX in console mode" echo "--console: Start EMQX in console mode"
echo "--attach: Attach to the Erlang docker container without running any test case" echo "--attach: Attach to the Erlang docker container without running any test case"
echo "--only-up: Keep the testbed running after CT" echo "--only-up: Only start the testbed but do not run CT"
echo "--keep-up: Only start the testbed but do not run CT" echo "--keep-up: Keep the testbed running after CT"
} }
WHICH_APP='novalue' WHICH_APP='novalue'
@ -151,7 +151,7 @@ elif [ "$CONSOLE" = 'yes' ]; then
docker exec -i $TTY "$ERLANG_CONTAINER" bash -c "make run" docker exec -i $TTY "$ERLANG_CONTAINER" bash -c "make run"
else else
set +e set +e
docker exec -i $TTY -e EMQX_CT_SUITES="$SUITES" "$ERLANG_CONTAINER" bash -c "make ${WHICH_APP}-ct" docker exec -i $TTY -e EMQX_CT_SUITES="$SUITES" "$ERLANG_CONTAINER" bash -c "BUILD_WITHOUT_QUIC=1 make ${WHICH_APP}-ct"
RESULT=$? RESULT=$?
if [ "$KEEP_UP" = 'yes' ]; then if [ "$KEEP_UP" = 'yes' ]; then
exit $RESULT exit $RESULT