From fc3720627bc60d7b077ef4ba910a729fdf7ccbad Mon Sep 17 00:00:00 2001 From: Ilya Averyanov Date: Thu, 17 Aug 2023 19:04:19 +0300 Subject: [PATCH 1/4] chore(ci): fix zookeeper version for hstreamdb --- .ci/docker-compose-file/.env | 2 ++ .ci/docker-compose-file/docker-compose-hstreamdb.yaml | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.ci/docker-compose-file/.env b/.ci/docker-compose-file/.env index e99a6d13f..b7033caae 100644 --- a/.ci/docker-compose-file/.env +++ b/.ci/docker-compose-file/.env @@ -10,6 +10,8 @@ CASSANDRA_TAG=3.11.6 MINIO_TAG=RELEASE.2023-03-20T20-16-18Z OPENTS_TAG=9aa7f88 KINESIS_TAG=2.1 +HSTREAMDB_TAG=v0.15.0 +HSTREAMDB_ZK_TAG=3.8.1 MS_IMAGE_ADDR=mcr.microsoft.com/mssql/server SQLSERVER_TAG=2019-CU19-ubuntu-20.04 diff --git a/.ci/docker-compose-file/docker-compose-hstreamdb.yaml b/.ci/docker-compose-file/docker-compose-hstreamdb.yaml index bf367e408..d42fd9fa2 100644 --- a/.ci/docker-compose-file/docker-compose-hstreamdb.yaml +++ b/.ci/docker-compose-file/docker-compose-hstreamdb.yaml @@ -2,7 +2,7 @@ version: "3.5" services: hserver: - image: hstreamdb/hstream:v0.15.0 + image: hstreamdb/hstream:${HSTREAMDB_TAG} container_name: hstreamdb depends_on: zookeeper: @@ -39,7 +39,7 @@ services: --io-tasks-network emqx_bridge hstore: - image: hstreamdb/hstream:v0.15.0 + image: hstreamdb/hstream:${HSTREAMDB_TAG} networks: - emqx_bridge volumes: @@ -65,7 +65,7 @@ services: start_period: 60s zookeeper: - image: zookeeper + image: zookeeper:${HSTREAMDB_ZK_TAG} expose: - 2181 networks: From 2c458b62f5e9761dbef09ab17faff5e071a0ab1e Mon Sep 17 00:00:00 2001 From: Paulo Zulato Date: Mon, 7 Aug 2023 11:27:30 -0300 Subject: [PATCH 2/4] feat(redis): add support for `username` on AUTH command Fixes https://emqx.atlassian.net/browse/EMQX-9911 --- .../docker-compose-redis-single-tcp.yaml | 7 ++-- .../docker-compose-redis-single-tls.yaml | 12 ++----- .../redis/cluster-tcp/redis.conf | 3 +- .../redis/cluster-tcp/users.acl | 2 ++ .../redis/cluster-tls/redis.conf | 3 +- .../redis/cluster-tls/users.acl | 2 ++ .../redis/sentinel-tcp/master.conf | 2 +- .../redis/sentinel-tcp/slave.conf | 3 +- .../redis/sentinel-tcp/users.acl | 2 ++ .../redis/sentinel-tls/master.conf | 2 +- .../redis/sentinel-tls/slave.conf | 3 +- .../redis/sentinel-tls/users.acl | 2 ++ .../redis/single-tcp/redis.conf | 3 ++ .../redis/single-tcp/users.acl | 2 ++ .../redis/single-tls/redis.conf | 9 +++++ .../redis/single-tls/users.acl | 2 ++ .../src/emqx_bridge_redis.app.src | 2 +- .../test/emqx_bridge_redis_SUITE.erl | 34 +++++++++++++++++++ apps/emqx_redis/rebar.config | 2 +- apps/emqx_redis/src/emqx_redis.app.src | 2 +- apps/emqx_redis/src/emqx_redis.erl | 2 ++ apps/emqx_redis/test/emqx_redis_SUITE.erl | 28 ++++++++++++++- changes/ce/feat-11469.en.md | 1 + 23 files changed, 106 insertions(+), 24 deletions(-) create mode 100644 .ci/docker-compose-file/redis/cluster-tcp/users.acl create mode 100644 .ci/docker-compose-file/redis/cluster-tls/users.acl create mode 100644 .ci/docker-compose-file/redis/sentinel-tcp/users.acl create mode 100644 .ci/docker-compose-file/redis/sentinel-tls/users.acl create mode 100644 .ci/docker-compose-file/redis/single-tcp/redis.conf create mode 100644 .ci/docker-compose-file/redis/single-tcp/users.acl create mode 100644 .ci/docker-compose-file/redis/single-tls/redis.conf create mode 100644 .ci/docker-compose-file/redis/single-tls/users.acl create mode 100644 changes/ce/feat-11469.en.md diff --git a/.ci/docker-compose-file/docker-compose-redis-single-tcp.yaml b/.ci/docker-compose-file/docker-compose-redis-single-tcp.yaml index 6706fe84f..ec7283219 100644 --- a/.ci/docker-compose-file/docker-compose-redis-single-tcp.yaml +++ b/.ci/docker-compose-file/docker-compose-redis-single-tcp.yaml @@ -4,12 +4,11 @@ services: redis_server: container_name: redis image: redis:${REDIS_TAG} + volumes: + - ./redis/single-tcp:/usr/local/etc/redis/ ports: - "6379:6379" - command: - - redis-server - - "--bind 0.0.0.0 ::" - - --requirepass public + command: redis-server /usr/local/etc/redis/redis.conf restart: always networks: - emqx_bridge diff --git a/.ci/docker-compose-file/docker-compose-redis-single-tls.yaml b/.ci/docker-compose-file/docker-compose-redis-single-tls.yaml index 8f59e7a9e..2ea36affd 100644 --- a/.ci/docker-compose-file/docker-compose-redis-single-tls.yaml +++ b/.ci/docker-compose-file/docker-compose-redis-single-tls.yaml @@ -8,18 +8,10 @@ services: - ./certs/server.crt:/etc/certs/redis.crt - ./certs/server.key:/etc/certs/redis.key - ./certs/ca.crt:/etc/certs/ca.crt + - ./redis/single-tls:/usr/local/etc/redis ports: - "6380:6380" - command: - - redis-server - - "--bind 0.0.0.0 ::" - - --requirepass public - - --tls-port 6380 - - --tls-cert-file /etc/certs/redis.crt - - --tls-key-file /etc/certs/redis.key - - --tls-ca-cert-file /etc/certs/ca.crt - - --tls-protocols "TLSv1.3" - - --tls-ciphersuites "TLS_CHACHA20_POLY1305_SHA256" + command: redis-server /usr/local/etc/redis/redis.conf restart: always networks: emqx_bridge: diff --git a/.ci/docker-compose-file/redis/cluster-tcp/redis.conf b/.ci/docker-compose-file/redis/cluster-tcp/redis.conf index 79a0d8a73..6930bde1c 100644 --- a/.ci/docker-compose-file/redis/cluster-tcp/redis.conf +++ b/.ci/docker-compose-file/redis/cluster-tcp/redis.conf @@ -1,10 +1,11 @@ bind :: 0.0.0.0 port 6379 -requirepass public cluster-enabled yes +masteruser default masterauth public +aclfile /usr/local/etc/redis/users.acl protected-mode no daemonize no diff --git a/.ci/docker-compose-file/redis/cluster-tcp/users.acl b/.ci/docker-compose-file/redis/cluster-tcp/users.acl new file mode 100644 index 000000000..5bafe9f6d --- /dev/null +++ b/.ci/docker-compose-file/redis/cluster-tcp/users.acl @@ -0,0 +1,2 @@ +user default on >public ~* &* +@all +user test_user on >test_passwd ~* &* +@all diff --git a/.ci/docker-compose-file/redis/cluster-tls/redis.conf b/.ci/docker-compose-file/redis/cluster-tls/redis.conf index 3020f46a7..5d203de80 100644 --- a/.ci/docker-compose-file/redis/cluster-tls/redis.conf +++ b/.ci/docker-compose-file/redis/cluster-tls/redis.conf @@ -1,10 +1,11 @@ bind :: 0.0.0.0 port 6379 -requirepass public cluster-enabled yes +masteruser default masterauth public +aclfile /usr/local/etc/redis/users.acl tls-port 6389 tls-cert-file /etc/certs/cert.pem diff --git a/.ci/docker-compose-file/redis/cluster-tls/users.acl b/.ci/docker-compose-file/redis/cluster-tls/users.acl new file mode 100644 index 000000000..5bafe9f6d --- /dev/null +++ b/.ci/docker-compose-file/redis/cluster-tls/users.acl @@ -0,0 +1,2 @@ +user default on >public ~* &* +@all +user test_user on >test_passwd ~* &* +@all diff --git a/.ci/docker-compose-file/redis/sentinel-tcp/master.conf b/.ci/docker-compose-file/redis/sentinel-tcp/master.conf index 25940c887..a531d1b40 100644 --- a/.ci/docker-compose-file/redis/sentinel-tcp/master.conf +++ b/.ci/docker-compose-file/redis/sentinel-tcp/master.conf @@ -1,6 +1,6 @@ bind :: 0.0.0.0 port 6379 -requirepass public +aclfile /usr/local/etc/redis/users.acl protected-mode no daemonize no diff --git a/.ci/docker-compose-file/redis/sentinel-tcp/slave.conf b/.ci/docker-compose-file/redis/sentinel-tcp/slave.conf index 2c61aeb6c..4a7e240fc 100644 --- a/.ci/docker-compose-file/redis/sentinel-tcp/slave.conf +++ b/.ci/docker-compose-file/redis/sentinel-tcp/slave.conf @@ -1,9 +1,10 @@ bind :: 0.0.0.0 port 6379 -requirepass public replicaof redis-sentinel-master 6379 +masteruser default masterauth public +aclfile /usr/local/etc/redis/users.acl protected-mode no daemonize no diff --git a/.ci/docker-compose-file/redis/sentinel-tcp/users.acl b/.ci/docker-compose-file/redis/sentinel-tcp/users.acl new file mode 100644 index 000000000..5bafe9f6d --- /dev/null +++ b/.ci/docker-compose-file/redis/sentinel-tcp/users.acl @@ -0,0 +1,2 @@ +user default on >public ~* &* +@all +user test_user on >test_passwd ~* &* +@all diff --git a/.ci/docker-compose-file/redis/sentinel-tls/master.conf b/.ci/docker-compose-file/redis/sentinel-tls/master.conf index f55433f79..68e01f323 100644 --- a/.ci/docker-compose-file/redis/sentinel-tls/master.conf +++ b/.ci/docker-compose-file/redis/sentinel-tls/master.conf @@ -1,6 +1,6 @@ bind :: 0.0.0.0 port 6379 -requirepass public +aclfile /usr/local/etc/redis/users.acl tls-port 6389 tls-cert-file /etc/certs/cert.pem diff --git a/.ci/docker-compose-file/redis/sentinel-tls/slave.conf b/.ci/docker-compose-file/redis/sentinel-tls/slave.conf index d8758da51..25102d5ed 100644 --- a/.ci/docker-compose-file/redis/sentinel-tls/slave.conf +++ b/.ci/docker-compose-file/redis/sentinel-tls/slave.conf @@ -1,9 +1,10 @@ bind :: 0.0.0.0 port 6379 -requirepass public replicaof redis-sentinel-tls-master 6389 +masteruser default masterauth public +aclfile /usr/local/etc/redis/users.acl tls-port 6389 tls-replication yes diff --git a/.ci/docker-compose-file/redis/sentinel-tls/users.acl b/.ci/docker-compose-file/redis/sentinel-tls/users.acl new file mode 100644 index 000000000..5bafe9f6d --- /dev/null +++ b/.ci/docker-compose-file/redis/sentinel-tls/users.acl @@ -0,0 +1,2 @@ +user default on >public ~* &* +@all +user test_user on >test_passwd ~* &* +@all diff --git a/.ci/docker-compose-file/redis/single-tcp/redis.conf b/.ci/docker-compose-file/redis/single-tcp/redis.conf new file mode 100644 index 000000000..1e5f629d2 --- /dev/null +++ b/.ci/docker-compose-file/redis/single-tcp/redis.conf @@ -0,0 +1,3 @@ +bind :: 0.0.0.0 +port 6379 +aclfile /usr/local/etc/redis/users.acl diff --git a/.ci/docker-compose-file/redis/single-tcp/users.acl b/.ci/docker-compose-file/redis/single-tcp/users.acl new file mode 100644 index 000000000..5bafe9f6d --- /dev/null +++ b/.ci/docker-compose-file/redis/single-tcp/users.acl @@ -0,0 +1,2 @@ +user default on >public ~* &* +@all +user test_user on >test_passwd ~* &* +@all diff --git a/.ci/docker-compose-file/redis/single-tls/redis.conf b/.ci/docker-compose-file/redis/single-tls/redis.conf new file mode 100644 index 000000000..e2d40bca6 --- /dev/null +++ b/.ci/docker-compose-file/redis/single-tls/redis.conf @@ -0,0 +1,9 @@ +bind :: 0.0.0.0 +aclfile /usr/local/etc/redis/users.acl + +tls-port 6380 +tls-cert-file /etc/certs/redis.crt +tls-key-file /etc/certs/redis.key +tls-ca-cert-file /etc/certs/ca.crt +tls-protocols "TLSv1.3" +tls-ciphersuites "TLS_CHACHA20_POLY1305_SHA256" diff --git a/.ci/docker-compose-file/redis/single-tls/users.acl b/.ci/docker-compose-file/redis/single-tls/users.acl new file mode 100644 index 000000000..5bafe9f6d --- /dev/null +++ b/.ci/docker-compose-file/redis/single-tls/users.acl @@ -0,0 +1,2 @@ +user default on >public ~* &* +@all +user test_user on >test_passwd ~* &* +@all diff --git a/apps/emqx_bridge_redis/src/emqx_bridge_redis.app.src b/apps/emqx_bridge_redis/src/emqx_bridge_redis.app.src index b380bc86d..5b6163969 100644 --- a/apps/emqx_bridge_redis/src/emqx_bridge_redis.app.src +++ b/apps/emqx_bridge_redis/src/emqx_bridge_redis.app.src @@ -1,6 +1,6 @@ {application, emqx_bridge_redis, [ {description, "EMQX Enterprise Redis Bridge"}, - {vsn, "0.1.2"}, + {vsn, "0.1.3"}, {registered, []}, {applications, [ kernel, diff --git a/apps/emqx_bridge_redis/test/emqx_bridge_redis_SUITE.erl b/apps/emqx_bridge_redis/test/emqx_bridge_redis_SUITE.erl index 6a0248b67..0c17ab775 100644 --- a/apps/emqx_bridge_redis/test/emqx_bridge_redis_SUITE.erl +++ b/apps/emqx_bridge_redis/test/emqx_bridge_redis_SUITE.erl @@ -30,6 +30,11 @@ <<"local_topic">> => <<"local_topic/#">> }). +-define(USERNAME_PASSWORD_AUTH_OPTS, #{ + <<"username">> => <<"test_user">>, + <<"password">> => <<"test_passwd">> +}). + -define(BATCH_SIZE, 5). -define(PROXY_HOST, "toxiproxy"). @@ -319,6 +324,22 @@ t_permanent_error(_Config) -> ), {ok, _} = emqx_bridge:remove(Type, Name). +t_auth_username_password(_Config) -> + Name = <<"mybridge">>, + Type = <<"redis_single">>, + ResourceId = emqx_bridge_resource:resource_id(Type, Name), + BridgeConfig = username_password_redis_bridge_config(), + ?assertMatch( + {ok, _}, + emqx_bridge:create(Type, Name, BridgeConfig) + ), + ?WAIT( + {ok, connected}, + emqx_resource:health_check(ResourceId), + 5 + ), + {ok, _} = emqx_bridge:remove(Type, Name). + t_create_disconnected(Config) -> Name = <<"toxic_bridge">>, Type = <<"redis_single">>, @@ -528,6 +549,19 @@ toxiproxy_redis_bridge_config() -> }, maps:merge(Conf0, ?COMMON_REDIS_OPTS). +username_password_redis_bridge_config() -> + Conf0 = ?REDIS_TOXYPROXY_CONNECT_CONFIG#{ + <<"resource_opts">> => #{ + <<"query_mode">> => <<"sync">>, + <<"worker_pool_size">> => <<"1">>, + <<"batch_size">> => integer_to_binary(?BATCH_SIZE), + <<"health_check_interval">> => <<"1s">>, + <<"start_timeout">> => <<"15s">> + } + }, + Conf1 = maps:merge(Conf0, ?COMMON_REDIS_OPTS), + maps:merge(Conf1, ?USERNAME_PASSWORD_AUTH_OPTS). + invalid_command_bridge_config() -> #{redis_single := #{tcp := Conf0}} = redis_connect_configs(), Conf1 = maps:merge(Conf0, ?COMMON_REDIS_OPTS), diff --git a/apps/emqx_redis/rebar.config b/apps/emqx_redis/rebar.config index c14536384..4e67e0986 100644 --- a/apps/emqx_redis/rebar.config +++ b/apps/emqx_redis/rebar.config @@ -3,7 +3,7 @@ {erl_opts, [debug_info]}. {deps, [ %% NOTE: mind ecpool version when updating eredis_cluster version - {eredis_cluster, {git, "https://github.com/emqx/eredis_cluster", {tag, "0.8.1"}}}, + {eredis_cluster, {git, "https://github.com/emqx/eredis_cluster", {tag, "0.8.2"}}}, {emqx_connector, {path, "../../apps/emqx_connector"}}, {emqx_resource, {path, "../../apps/emqx_resource"}} ]}. diff --git a/apps/emqx_redis/src/emqx_redis.app.src b/apps/emqx_redis/src/emqx_redis.app.src index 294a642f5..23e13bb72 100644 --- a/apps/emqx_redis/src/emqx_redis.app.src +++ b/apps/emqx_redis/src/emqx_redis.app.src @@ -1,6 +1,6 @@ {application, emqx_redis, [ {description, "EMQX Redis Database Connector"}, - {vsn, "0.1.0"}, + {vsn, "0.1.1"}, {registered, []}, {applications, [ kernel, diff --git a/apps/emqx_redis/src/emqx_redis.erl b/apps/emqx_redis/src/emqx_redis.erl index ef89c3931..c76cbdfb4 100644 --- a/apps/emqx_redis/src/emqx_redis.erl +++ b/apps/emqx_redis/src/emqx_redis.erl @@ -146,6 +146,7 @@ on_start( Opts = [ {pool_size, PoolSize}, + {username, maps:get(username, Config, undefined)}, {password, maps:get(password, Config, "")}, {auto_reconnect, ?AUTO_RECONNECT_INTERVAL} ] ++ Database ++ Servers, @@ -292,6 +293,7 @@ connect(Opts) -> redis_fields() -> [ {pool_size, fun emqx_connector_schema_lib:pool_size/1}, + {username, fun emqx_connector_schema_lib:username/1}, {password, fun emqx_connector_schema_lib:password/1}, {database, #{ type => non_neg_integer(), diff --git a/apps/emqx_redis/test/emqx_redis_SUITE.erl b/apps/emqx_redis/test/emqx_redis_SUITE.erl index c425f19d9..e03b05921 100644 --- a/apps/emqx_redis/test/emqx_redis_SUITE.erl +++ b/apps/emqx_redis/test/emqx_redis_SUITE.erl @@ -137,6 +137,31 @@ perform_lifecycle_check(ResourceId, InitialConfig, RedisCommand) -> #{timeout => 500} ) ), + % check authentication methods + ?assertEqual( + {ok, <<"OK">>}, + emqx_resource:query(ResourceId, {cmd, ["AUTH", "public"]}) + ), + ?assertEqual( + {error, <<"WRONGPASS invalid username-password pair or user is disabled.">>}, + emqx_resource:query(ResourceId, {cmd, ["AUTH", "test_passwd"]}) + ), + ?assertEqual( + {ok, <<"OK">>}, + emqx_resource:query(ResourceId, {cmd, ["AUTH", "test_user", "test_passwd"]}) + ), + ?assertEqual( + {error, <<"WRONGPASS invalid username-password pair or user is disabled.">>}, + emqx_resource:query(ResourceId, {cmd, ["AUTH", "test_user", "public"]}) + ), + ?assertEqual( + {error, <<"WRONGPASS invalid username-password pair or user is disabled.">>}, + emqx_resource:query(ResourceId, {cmd, ["AUTH", "wrong_user", "test_passwd"]}) + ), + ?assertEqual( + {error, <<"WRONGPASS invalid username-password pair or user is disabled.">>}, + emqx_resource:query(ResourceId, {cmd, ["AUTH", "wrong_user", "public"]}) + ), ?assertEqual(ok, emqx_resource:stop(ResourceId)), % Resource will be listed still, but state will be changed and healthcheck will fail % as the worker no longer exists. @@ -186,7 +211,8 @@ redis_config_sentinel() -> " redis_type = ~s\n" ++ MaybeSentinel ++ MaybeDatabase ++ - " password = public\n" ++ + " username = test_user\n" ++ + " password = test_passwd\n" ++ " ~s = \"~s:~b\"\n" ++ " " ++ "" diff --git a/changes/ce/feat-11469.en.md b/changes/ce/feat-11469.en.md new file mode 100644 index 000000000..827fe3a87 --- /dev/null +++ b/changes/ce/feat-11469.en.md @@ -0,0 +1 @@ +Added support for specifying username in Redis authentication. From fc35c74eab3d8465bc246ac5397cfdba36ff3f01 Mon Sep 17 00:00:00 2001 From: Paulo Zulato Date: Mon, 14 Aug 2023 21:22:31 -0300 Subject: [PATCH 3/4] fix(redis): use eredis_secret to avoid password leaking --- apps/emqx_redis/src/emqx_redis.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/emqx_redis/src/emqx_redis.erl b/apps/emqx_redis/src/emqx_redis.erl index c76cbdfb4..2779620bf 100644 --- a/apps/emqx_redis/src/emqx_redis.erl +++ b/apps/emqx_redis/src/emqx_redis.erl @@ -147,7 +147,7 @@ on_start( [ {pool_size, PoolSize}, {username, maps:get(username, Config, undefined)}, - {password, maps:get(password, Config, "")}, + {password, eredis_secret:wrap(maps:get(password, Config, ""))}, {auto_reconnect, ?AUTO_RECONNECT_INTERVAL} ] ++ Database ++ Servers, Options = From 05fdf52d8eef1be357992879a983ee55b23f4f92 Mon Sep 17 00:00:00 2001 From: Paulo Zulato Date: Fri, 18 Aug 2023 13:26:31 -0300 Subject: [PATCH 4/4] fix(redis): set bridge as unhealthy on authentication error --- .../src/emqx_bridge_redis_connector.erl | 6 +++ .../test/emqx_bridge_redis_SUITE.erl | 41 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/apps/emqx_bridge_redis/src/emqx_bridge_redis_connector.erl b/apps/emqx_bridge_redis/src/emqx_bridge_redis_connector.erl index 38a80048e..696947726 100644 --- a/apps/emqx_bridge_redis/src/emqx_bridge_redis_connector.erl +++ b/apps/emqx_bridge_redis/src/emqx_bridge_redis_connector.erl @@ -35,6 +35,12 @@ on_start(InstId, #{command_template := CommandTemplate} = Config) -> conn_st => RedisConnSt, command_template => preproc_command_template(CommandTemplate) }}; + {error, {start_pool_failed, _, #{type := authentication_error, reason := Reason}}} = Error -> + ?tp( + redis_bridge_connector_start_error, + #{error => Error} + ), + throw({unhealthy_target, Reason}); {error, _} = Error -> ?tp( redis_bridge_connector_start_error, diff --git a/apps/emqx_bridge_redis/test/emqx_bridge_redis_SUITE.erl b/apps/emqx_bridge_redis/test/emqx_bridge_redis_SUITE.erl index 0c17ab775..c4089323b 100644 --- a/apps/emqx_bridge_redis/test/emqx_bridge_redis_SUITE.erl +++ b/apps/emqx_bridge_redis/test/emqx_bridge_redis_SUITE.erl @@ -340,6 +340,47 @@ t_auth_username_password(_Config) -> ), {ok, _} = emqx_bridge:remove(Type, Name). +t_auth_error_username_password(_Config) -> + Name = <<"mybridge">>, + Type = <<"redis_single">>, + ResourceId = emqx_bridge_resource:resource_id(Type, Name), + BridgeConfig0 = username_password_redis_bridge_config(), + BridgeConfig = maps:merge(BridgeConfig0, #{<<"password">> => <<"wrong_password">>}), + ?assertMatch( + {ok, _}, + emqx_bridge:create(Type, Name, BridgeConfig) + ), + ?WAIT( + {ok, disconnected}, + emqx_resource:health_check(ResourceId), + 5 + ), + ?assertMatch( + {ok, _, #{error := {unhealthy_target, _Msg}}}, + emqx_resource_manager:lookup(ResourceId) + ), + {ok, _} = emqx_bridge:remove(Type, Name). + +t_auth_error_password_only(_Config) -> + Name = <<"mybridge">>, + Type = <<"redis_single">>, + ResourceId = emqx_bridge_resource:resource_id(Type, Name), + BridgeConfig0 = toxiproxy_redis_bridge_config(), + BridgeConfig = maps:merge(BridgeConfig0, #{<<"password">> => <<"wrong_password">>}), + ?assertMatch( + {ok, _}, + emqx_bridge:create(Type, Name, BridgeConfig) + ), + ?assertEqual( + {ok, disconnected}, + emqx_resource:health_check(ResourceId) + ), + ?assertMatch( + {ok, _, #{error := {unhealthy_target, _Msg}}}, + emqx_resource_manager:lookup(ResourceId) + ), + {ok, _} = emqx_bridge:remove(Type, Name). + t_create_disconnected(Config) -> Name = <<"toxic_bridge">>, Type = <<"redis_single">>,