diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index e2631f3ac..ff4dcf632 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,3 +1,6 @@
+## Default
+* @emqx/emqx-review-board
+
## MQTT & Core
/src/ @qzhuyan
/include/ @qzhuyan
@@ -5,13 +8,13 @@
/test/ @qzhuyan
## CI
-/.github/ @id
-/.ci/ @id
-/scripts/ @id
-/build @id
-/deploy/ @id
+/.github/ @emqx/emqx-review-board @id
+/.ci/ @emqx/emqx-review-board @id
+/scripts/ @emqx/emqx-review-board @id
+/build @emqx/emqx-review-board @id
+/deploy/ @emqx/emqx-review-board @id
-## Authenticatio & ACL
+## Authentication & ACL
/apps/emqx_auth_*/ @savonarola
/apps/emqx_psk_file/ @savonarola
/apps/emqx_retainer/ @savonarola
@@ -31,13 +34,6 @@
/apps/emqx_prometheus/ @zhongwencool
/apps/emqx_recon/ @zhongwencool
-
## Data integration
/apps/emqx_rule_engine/ @thalesmg
/apps/emqx_web_hook/ @thalesmg
-
-## External Plugins
-/lib-extra/ @zmstone
-
-## Default
-* @zmstone
diff --git a/.github/workflows/apps_version_check.yaml b/.github/workflows/apps_version_check.yaml
index 80759fc56..be34593f9 100644
--- a/.github/workflows/apps_version_check.yaml
+++ b/.github/workflows/apps_version_check.yaml
@@ -13,7 +13,7 @@ jobs:
os:
- ubuntu20.04
- container: ghcr.io/emqx/emqx-builder/4.4-23:${{ matrix.erl_otp }}-${{ matrix.os }}
+ container: ghcr.io/emqx/emqx-builder/4.4-24:${{ matrix.erl_otp }}-${{ matrix.os }}
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/build_packages.yaml b/.github/workflows/build_packages.yaml
index cc4f59438..bb7cd82cf 100644
--- a/.github/workflows/build_packages.yaml
+++ b/.github/workflows/build_packages.yaml
@@ -157,6 +157,7 @@ jobs:
- amd64
- arm64
os:
+ - ubuntu22.04
- ubuntu20.04
- ubuntu18.04
- ubuntu16.04
@@ -195,7 +196,7 @@ jobs:
--profile "${PROFILE}" \
--pkgtype "${PACKAGE}" \
--arch "${ARCH}" \
- --builder "ghcr.io/emqx/emqx-builder/4.4-23:${OTP}-${SYSTEM}"
+ --builder "ghcr.io/emqx/emqx-builder/4.4-24:${OTP}-${SYSTEM}"
- uses: actions/upload-artifact@v3
with:
name: ${{ matrix.profile }}
@@ -271,7 +272,7 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
- BUILD_FROM=ghcr.io/emqx/emqx-builder/4.4-23:${{ matrix.otp }}-alpine3.15.1
+ BUILD_FROM=ghcr.io/emqx/emqx-builder/4.4-24:${{ matrix.otp }}-alpine3.15.1
RUN_FROM=alpine:3.15.1
EMQX_NAME=${{ matrix.profile }}
file: source/deploy/docker/Dockerfile
@@ -287,7 +288,7 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
- BUILD_FROM=ghcr.io/emqx/emqx-builder/4.4-23:${{ matrix.otp }}-alpine3.15.1
+ BUILD_FROM=ghcr.io/emqx/emqx-builder/4.4-24:${{ matrix.otp }}-alpine3.15.1
RUN_FROM=alpine:3.15.1
EMQX_NAME=${{ matrix.profile }}
file: source/deploy/docker/Dockerfile.enterprise
diff --git a/.github/workflows/build_slim_packages.yaml b/.github/workflows/build_slim_packages.yaml
index 355128e32..bb1fca468 100644
--- a/.github/workflows/build_slim_packages.yaml
+++ b/.github/workflows/build_slim_packages.yaml
@@ -19,6 +19,7 @@ jobs:
otp:
- 24.3.4.2-1
os:
+ - ubuntu22.04
- ubuntu20.04
- el7
runs-on:
@@ -32,7 +33,7 @@ jobs:
- runs-on: aws-amd64
use-self-hosted: false
- container: ghcr.io/emqx/emqx-builder/4.4-23:${{ matrix.otp }}-${{ matrix.os }}
+ container: ghcr.io/emqx/emqx-builder/4.4-24:${{ matrix.otp }}-${{ matrix.os }}
steps:
- uses: AutoModality/action-clean@v1
diff --git a/.github/workflows/check_deps_integrity.yaml b/.github/workflows/check_deps_integrity.yaml
index 8c478e265..3b97b5d47 100644
--- a/.github/workflows/check_deps_integrity.yaml
+++ b/.github/workflows/check_deps_integrity.yaml
@@ -5,7 +5,7 @@ on: [pull_request]
jobs:
check_deps_integrity:
runs-on: ubuntu-20.04
- container: ghcr.io/emqx/emqx-builder/4.4-23:24.3.4.2-1-ubuntu20.04
+ container: ghcr.io/emqx/emqx-builder/4.4-24:24.3.4.2-1-ubuntu20.04
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index cd163888d..20661aee9 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -7,7 +7,7 @@ on:
jobs:
prepare:
runs-on: ubuntu-20.04
- container: ghcr.io/emqx/emqx-builder/4.4-23:24.3.4.2-1-ubuntu20.04
+ container: ghcr.io/emqx/emqx-builder/4.4-24:24.3.4.2-1-ubuntu20.04
outputs:
profiles: ${{ steps.detect-profiles.outputs.profiles}}
diff --git a/.github/workflows/run_acl_migration_tests.yaml b/.github/workflows/run_acl_migration_tests.yaml
index 8545faa0f..230e208ae 100644
--- a/.github/workflows/run_acl_migration_tests.yaml
+++ b/.github/workflows/run_acl_migration_tests.yaml
@@ -5,7 +5,7 @@ on: workflow_dispatch
jobs:
test:
runs-on: ubuntu-20.04
- container: ghcr.io/emqx/emqx-builder/4.4-23:24.3.4.2-1-ubuntu20.04
+ container: ghcr.io/emqx/emqx-builder/4.4-24:24.3.4.2-1-ubuntu20.04
strategy:
fail-fast: true
env:
diff --git a/.github/workflows/run_fvt_tests.yaml b/.github/workflows/run_fvt_tests.yaml
index 8f9825600..b0545045f 100644
--- a/.github/workflows/run_fvt_tests.yaml
+++ b/.github/workflows/run_fvt_tests.yaml
@@ -200,7 +200,7 @@ jobs:
relup_test_plan:
runs-on: ubuntu-20.04
- container: ghcr.io/emqx/emqx-builder/4.4-23:24.3.4.2-1-ubuntu20.04
+ container: ghcr.io/emqx/emqx-builder/4.4-24:24.3.4.2-1-ubuntu20.04
outputs:
profile: ${{ steps.profile-and-versions.outputs.profile }}
vsn: ${{ steps.profile-and-versions.outputs.vsn }}
@@ -251,7 +251,7 @@ jobs:
otp:
- 24.3.4.2-1
runs-on: ubuntu-20.04
- container: ghcr.io/emqx/emqx-builder/4.4-23:24.3.4.2-1-ubuntu20.04
+ container: ghcr.io/emqx/emqx-builder/4.4-24:24.3.4.2-1-ubuntu20.04
defaults:
run:
shell: bash
@@ -288,7 +288,7 @@ jobs:
- relup_test_plan
- relup_test_build
runs-on: ubuntu-20.04
- container: ghcr.io/emqx/emqx-builder/4.4-23:24.3.4.2-1-ubuntu20.04
+ container: ghcr.io/emqx/emqx-builder/4.4-24:24.3.4.2-1-ubuntu20.04
strategy:
fail-fast: false
matrix:
diff --git a/.github/workflows/run_test_cases.yaml b/.github/workflows/run_test_cases.yaml
index 5612562a6..38cd2f9bb 100644
--- a/.github/workflows/run_test_cases.yaml
+++ b/.github/workflows/run_test_cases.yaml
@@ -12,7 +12,7 @@ on:
jobs:
prepare:
runs-on: aws-amd64
- container: ghcr.io/emqx/emqx-builder/4.4-23:24.3.4.2-1-ubuntu20.04
+ container: ghcr.io/emqx/emqx-builder/4.4-24:24.3.4.2-1-ubuntu20.04
outputs:
fast_ct_apps: ${{ steps.run_find_apps.outputs.fast_ct_apps }}
docker_ct_apps: ${{ steps.run_find_apps.outputs.docker_ct_apps }}
@@ -58,7 +58,7 @@ jobs:
eunit_and_proper:
needs: prepare
runs-on: aws-amd64
- container: ghcr.io/emqx/emqx-builder/4.4-23:24.3.4.2-1-ubuntu20.04
+ container: ghcr.io/emqx/emqx-builder/4.4-24:24.3.4.2-1-ubuntu20.04
strategy:
fail-fast: false
matrix:
@@ -86,7 +86,7 @@ jobs:
fast_ct:
needs: prepare
runs-on: ${{ matrix.runs-on }}
- container: ghcr.io/emqx/emqx-builder/4.4-23:24.3.4.2-1-ubuntu20.04
+ container: ghcr.io/emqx/emqx-builder/4.4-24:24.3.4.2-1-ubuntu20.04
strategy:
fail-fast: false
matrix:
@@ -249,7 +249,7 @@ jobs:
- fast_ct
- docker_ct
runs-on: aws-amd64
- container: ghcr.io/emqx/emqx-builder/4.4-23:24.3.4.2-1-ubuntu20.04
+ container: ghcr.io/emqx/emqx-builder/4.4-24:24.3.4.2-1-ubuntu20.04
steps:
- uses: AutoModality/action-clean@v1
- uses: actions/download-artifact@v3
diff --git a/apps/emqx_auth_http/src/emqx_acl_http.erl b/apps/emqx_auth_http/src/emqx_acl_http.erl
index 3decdbf6d..e18527179 100644
--- a/apps/emqx_auth_http/src/emqx_acl_http.erl
+++ b/apps/emqx_auth_http/src/emqx_acl_http.erl
@@ -44,7 +44,10 @@ check_acl(ClientInfo, PubSub, Topic, _AclResult, #{acl := ACLParams = #{path :=
Username = maps:get(username, ClientInfo1, undefined),
case check_acl_request(ACLParams, ClientInfo1) of
{ok, 200, <<"ignore">>} -> ok;
- {ok, 200, _Body} -> {stop, allow};
+ {ok, 200, _Body} ->
+ ?LOG(debug, "Allow ~s to topic ~ts, username: ~ts",
+ [PubSub, Topic, Username]),
+ {stop, allow};
{ok, Code, _Body} ->
?LOG(warning, "Deny ~s to topic ~ts, username: ~ts, http response code: ~p",
[PubSub, Topic, Username, Code]),
@@ -74,4 +77,3 @@ check_acl_request(ACLParams =
access(subscribe) -> 1;
access(publish) -> 2.
-
diff --git a/apps/emqx_auth_http/src/emqx_auth_http.app.src b/apps/emqx_auth_http/src/emqx_auth_http.app.src
index 7f05e6c7e..a870575ce 100644
--- a/apps/emqx_auth_http/src/emqx_auth_http.app.src
+++ b/apps/emqx_auth_http/src/emqx_auth_http.app.src
@@ -1,6 +1,6 @@
{application, emqx_auth_http,
[{description, "EMQ X Authentication/ACL with HTTP API"},
- {vsn, "4.3.10"}, % strict semver, bump manually!
+ {vsn, "4.3.11"}, % strict semver, bump manually!
{modules, []},
{registered, [emqx_auth_http_sup]},
{applications, [kernel,stdlib,ehttpc]},
diff --git a/apps/emqx_auth_http/src/emqx_auth_http.appup.src b/apps/emqx_auth_http/src/emqx_auth_http.appup.src
index 6de6453d8..3f167d768 100644
--- a/apps/emqx_auth_http/src/emqx_auth_http.appup.src
+++ b/apps/emqx_auth_http/src/emqx_auth_http.appup.src
@@ -1,7 +1,13 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.3.9",[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]}]},
+ [{"4.3.10",
+ [{load_module,emqx_auth_http,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_http,brutal_purge,soft_purge,[]}]},
+ {"4.3.9",
+ [{load_module,emqx_auth_http,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_http,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]}]},
{"4.3.8",
[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http,brutal_purge,soft_purge,[]},
@@ -39,7 +45,13 @@
{load_module,emqx_auth_http_cli,brutal_purge,soft_purge,[]}]},
{<<"4.3.[0-1]">>,[{restart_application,emqx_auth_http}]},
{<<".*">>,[]}],
- [{"4.3.9",[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]}]},
+ [{"4.3.10",
+ [{load_module,emqx_auth_http,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_http,brutal_purge,soft_purge,[]}]},
+ {"4.3.9",
+ [{load_module,emqx_auth_http,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_http,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]}]},
{"4.3.8",
[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http,brutal_purge,soft_purge,[]},
diff --git a/apps/emqx_auth_http/src/emqx_auth_http.erl b/apps/emqx_auth_http/src/emqx_auth_http.erl
index aad08e7b6..c7710ae94 100644
--- a/apps/emqx_auth_http/src/emqx_auth_http.erl
+++ b/apps/emqx_auth_http/src/emqx_auth_http.erl
@@ -41,19 +41,20 @@ check(ClientInfo, AuthResult, #{auth := AuthParms = #{path := Path},
{ok, 200, <<"ignore">>} ->
ok;
{ok, 200, Body} ->
+ ?LOG(debug, "Auth succeeded from path: ~ts, username: ~ts", [Path, Username]),
IsSuperuser = is_superuser(SuperParams, ClientInfo),
{stop, AuthResult#{is_superuser => IsSuperuser,
auth_result => success,
anonymous => false,
mountpoint => mountpoint(Body, ClientInfo)}};
{ok, Code, _Body} ->
- ?LOG(warning, "Deny connection from path: ~s, username: ~ts, http "
+ ?LOG(warning, "Deny connection from path: ~ts, username: ~ts, http "
"response code: ~p",
[Path, Username, Code]),
{stop, AuthResult#{auth_result => http_to_connack_error(Code),
anonymous => false}};
{error, Error} ->
- ?LOG_SENSITIVE(warning, "Deny connection from path: ~s, username: ~ts, due to "
+ ?LOG_SENSITIVE(warning, "Deny connection from path: ~ts, username: ~ts, due to "
"request http-server failed: ~0p", [Path, Username, Error]),
%%FIXME later: server_unavailable is not right.
{stop, AuthResult#{auth_result => server_unavailable,
diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src b/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src
index 8b66965b1..ab6dd53e7 100644
--- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src
+++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src
@@ -1,6 +1,6 @@
{application, emqx_auth_jwt,
[{description, "EMQ X Authentication with JWT"},
- {vsn, "4.4.8"}, % strict semver, bump manually!
+ {vsn, "4.4.9"}, % strict semver, bump manually!
{modules, []},
{registered, [emqx_auth_jwt_sup]},
{applications, [kernel,stdlib,jose]},
diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src b/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src
index 0c2c0e58f..1407592b0 100644
--- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src
+++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src
@@ -1,38 +1,18 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.4.7",[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]},
- {"4.4.6",
- [{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]},
- {load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]},
- {"4.4.5",
+ [{"4.4.8",
[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
- {"4.4.4",
- [{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]},
- {load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]},
- {"4.4.3",
- [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]},
- {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
- {"4.4.2",
+ {<<"4\\.4\\.[2-7]">>,
[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]},
{<<"4\\.4\\.[0-1]">>,[{restart_application,emqx_auth_jwt}]},
{<<".*">>,[]}],
- [{"4.4.7",[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]},
- {"4.4.6",
- [{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]},
- {load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]},
- {"4.4.5",
+ [{"4.4.8",
[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
- {"4.4.4",
- [{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]},
- {load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]},
- {"4.4.3",
- [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]},
- {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
- {"4.4.2",
+ {<<"4\\.4\\.[2-7]">>,
[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]},
{<<"4\\.4\\.[0-1]">>,[{restart_application,emqx_auth_jwt}]},
diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl
index 63a59b5ec..dd3b2dbc9 100644
--- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl
+++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl
@@ -51,8 +51,14 @@ check_auth(ClientInfo, AuthResult, #{from := From, checklists := Checklists}) ->
{error, not_token} ->
ok;
{error, Reason} ->
+ ?LOG_SENSITIVE(debug,
+ "Auth from JWT failed, Client: ~p, Reason: ~p",
+ [ClientInfo, Reason]),
{stop, AuthResult#{auth_result => Reason, anonymous => false}};
{ok, Claims} ->
+ ?LOG_SENSITIVE(debug,
+ "Auth from JWT succeeded, Client: ~p",
+ [ClientInfo]),
{stop, maps:merge(AuthResult, verify_claims(Checklists, Claims, ClientInfo))}
end
end.
diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl
index 3713e74f3..30a3fa19d 100644
--- a/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl
+++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl
@@ -99,13 +99,13 @@ handle_cast(_Msg, State) ->
{noreply, State}.
handle_info({timeout, _TRef, refresh}, State = #state{addr = Addr}) ->
- NState = try
- true = ets:insert(?TAB, {remote, request_jwks(Addr)}),
- State
- catch _:_ ->
- State
- end,
- {noreply, reset_timer(NState)};
+ try
+ true = ets:insert(?TAB, {remote, request_jwks(Addr)})
+ catch Err:Reason ->
+ ?LOG_SENSITIVE(warning, "Request JWKS failed, jwks_addr: ~p, reason: ~p",
+ [Addr, {Err, Reason}])
+ end,
+ {noreply, reset_timer(State)};
handle_info({request_jwks, Options}, State) ->
Remote = key2jwt_value(jwks_addr, fun request_jwks/1, Options),
diff --git a/apps/emqx_auth_ldap/src/emqx_acl_ldap.erl b/apps/emqx_auth_ldap/src/emqx_acl_ldap.erl
index d01eace21..8faeed913 100644
--- a/apps/emqx_auth_ldap/src/emqx_acl_ldap.erl
+++ b/apps/emqx_auth_ldap/src/emqx_acl_ldap.erl
@@ -29,8 +29,16 @@
check_acl(ClientInfo, PubSub, Topic, NoMatchAction, State) ->
case do_check_acl(ClientInfo, PubSub, Topic, NoMatchAction, State) of
ok -> ok;
- {stop, allow} -> {stop, allow};
- {stop, deny} -> {stop, deny}
+ {stop, allow} ->
+ ?LOG_SENSITIVE(debug,
+ "[LDAP] Allow Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
+ {stop, allow};
+ {stop, deny} ->
+ ?LOG_SENSITIVE(debug,
+ "[LDAP] Deny Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
+ {stop, deny}
end.
do_check_acl(#{username := <<$$, _/binary>>}, _PubSub, _Topic, _NoMatchAction, _State) ->
diff --git a/apps/emqx_auth_ldap/src/emqx_auth_ldap.app.src b/apps/emqx_auth_ldap/src/emqx_auth_ldap.app.src
index 48dc39bc9..4bee1aefa 100644
--- a/apps/emqx_auth_ldap/src/emqx_auth_ldap.app.src
+++ b/apps/emqx_auth_ldap/src/emqx_auth_ldap.app.src
@@ -1,6 +1,6 @@
{application, emqx_auth_ldap,
[{description, "EMQ X Authentication/ACL with LDAP"},
- {vsn, "4.3.6"}, % strict semver, bump manually!
+ {vsn, "4.3.7"}, % strict semver, bump manually!
{modules, []},
{registered, [emqx_auth_ldap_sup]},
{applications, [kernel,stdlib,eldap2,ecpool]},
diff --git a/apps/emqx_auth_ldap/src/emqx_auth_ldap.appup.src b/apps/emqx_auth_ldap/src/emqx_auth_ldap.appup.src
index 632067873..01b29895f 100644
--- a/apps/emqx_auth_ldap/src/emqx_auth_ldap.appup.src
+++ b/apps/emqx_auth_ldap/src/emqx_auth_ldap.appup.src
@@ -1,7 +1,10 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.3.5",
+ [{"4.3.6",
+ [{load_module,emqx_acl_ldap,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]}]},
+ {"4.3.5",
[{load_module,emqx_acl_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_ldap_cli,brutal_purge,soft_purge,[]}]},
@@ -21,7 +24,10 @@
{load_module,emqx_acl_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_ldap_cli,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
- [{"4.3.5",
+ [{"4.3.6",
+ [{load_module,emqx_acl_ldap,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]}]},
+ {"4.3.5",
[{load_module,emqx_acl_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_ldap_cli,brutal_purge,soft_purge,[]}]},
diff --git a/apps/emqx_auth_ldap/src/emqx_auth_ldap.erl b/apps/emqx_auth_ldap/src/emqx_auth_ldap.erl
index 33fa91618..d1d73784d 100644
--- a/apps/emqx_auth_ldap/src/emqx_auth_ldap.erl
+++ b/apps/emqx_auth_ldap/src/emqx_auth_ldap.erl
@@ -58,6 +58,9 @@ check(ClientInfo = #{username := Username, password := Password}, AuthResult,
end,
case CheckResult of
ok ->
+ ?LOG_SENSITIVE(debug,
+ "[LDAP] Auth from ldap succeeded, Client: ~p",
+ [ClientInfo]),
{stop, AuthResult#{auth_result => success, anonymous => false}};
{error, not_found} ->
ok;
diff --git a/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.erl b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.erl
index 576977ec1..928dcc608 100644
--- a/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.erl
+++ b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.erl
@@ -17,6 +17,7 @@
-module(emqx_acl_mnesia).
-include("emqx_auth_mnesia.hrl").
+-include_lib("emqx/include/logger.hrl").
%% ACL Callbacks
-export([ init/0
@@ -43,8 +44,14 @@ check_acl(ClientInfo = #{ clientid := Clientid }, PubSub, Topic, _NoMatchAction,
case match(ClientInfo, PubSub, Topic, Acls) of
allow ->
+ ?LOG_SENSITIVE(debug,
+ "[Mnesia] Allow Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
{stop, allow};
deny ->
+ ?LOG_SENSITIVE(debug,
+ "[Mnesia] Deny Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
{stop, deny};
_ ->
ok
diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src
index 3bce055f6..c8298c146 100644
--- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src
+++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src
@@ -1,6 +1,6 @@
{application, emqx_auth_mnesia,
[{description, "EMQ X Authentication with Mnesia"},
- {vsn, "4.3.10"}, % strict semver, bump manually
+ {vsn, "4.3.11"}, % strict semver, bump manually
{modules, []},
{registered, []},
{applications, [kernel,stdlib,mnesia]},
diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src
index 82bff332d..36e4437fd 100644
--- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src
+++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src
@@ -1,13 +1,25 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.3.9",[{load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
- {"4.3.8",[{load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
+ [{"4.3.10",
+ [{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]}]},
+ {"4.3.9",
+ [{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
+ {"4.3.8",
+ [{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
{"4.3.7",
- [{load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[5-6]">>,
- [{load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mnesia_db,brutal_purge,soft_purge,[]},
@@ -35,13 +47,25 @@
{load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
- [{"4.3.9",[{load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
- {"4.3.8",[{load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
+ [{"4.3.10",
+ [{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]}]},
+ {"4.3.9",
+ [{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
+ {"4.3.8",
+ [{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
{"4.3.7",
- [{load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[5-6]">>,
- [{load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mnesia_db,brutal_purge,soft_purge,[]},
diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl
index 5a36be59b..35bea5fde 100644
--- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl
+++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl
@@ -70,6 +70,9 @@ check(ClientInfo = #{ clientid := Clientid
?LOG(info, "[Mnesia] Auth from mnesia failed: ~p", [Info]),
{stop, AuthResult#{anonymous => false, auth_result => password_error}};
_ ->
+ ?LOG_SENSITIVE(debug,
+ "[Mnesia] Auth from mnesia succeeded, Client: ~p",
+ [ClientInfo]),
{stop, AuthResult#{anonymous => false, auth_result => success}}
end
end.
diff --git a/apps/emqx_auth_mongo/src/emqx_acl_mongo.erl b/apps/emqx_auth_mongo/src/emqx_acl_mongo.erl
index a7487dd07..2f069478b 100644
--- a/apps/emqx_auth_mongo/src/emqx_acl_mongo.erl
+++ b/apps/emqx_auth_mongo/src/emqx_acl_mongo.erl
@@ -38,8 +38,16 @@ check_acl(ClientInfo, PubSub, Topic, _AclResult, Env = #{aclquery := AclQuery})
[] -> ok;
Rows ->
try match(ClientInfo, Topic, topics(PubSub, Rows)) of
- matched -> {stop, allow};
- nomatch -> {stop, deny}
+ matched ->
+ ?LOG_SENSITIVE(debug,
+ "[MongoDB] Allow Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
+ {stop, allow};
+ nomatch ->
+ ?LOG_SENSITIVE(debug,
+ "[MongoDB] Deny Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
+ {stop, deny}
catch
_Err:Reason->
?LOG(error, "[MongoDB] Check mongo ~p ACL failed, got ACL config: ~p, error: :~p",
diff --git a/apps/emqx_auth_mongo/src/emqx_auth_mongo.app.src b/apps/emqx_auth_mongo/src/emqx_auth_mongo.app.src
index 2849fe0a8..0677f118b 100644
--- a/apps/emqx_auth_mongo/src/emqx_auth_mongo.app.src
+++ b/apps/emqx_auth_mongo/src/emqx_auth_mongo.app.src
@@ -1,6 +1,6 @@
{application, emqx_auth_mongo,
[{description, "EMQ X Authentication/ACL with MongoDB"},
- {vsn, "4.4.5"}, % strict semver, bump manually!
+ {vsn, "4.4.6"}, % strict semver, bump manually!
{modules, []},
{registered, [emqx_auth_mongo_sup]},
{applications, [kernel,stdlib,mongodb,ecpool]},
diff --git a/apps/emqx_auth_mongo/src/emqx_auth_mongo.appup.src b/apps/emqx_auth_mongo/src/emqx_auth_mongo.appup.src
index eb62a4a57..b3c2b92ef 100644
--- a/apps/emqx_auth_mongo/src/emqx_auth_mongo.appup.src
+++ b/apps/emqx_auth_mongo/src/emqx_auth_mongo.appup.src
@@ -1,12 +1,19 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.4.4",[{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
+ [{"4.4.5",
+ [{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
+ {"4.4.4",
+ [{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{<<"4\\.4\\.[2-3]">>,
- [{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.4.1",
- [{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.4.0",
@@ -15,12 +22,19 @@
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
- [{"4.4.4",[{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
- {<<"4\\.4\\.[2-3]">>,
- [{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
+ [{"4.4.5",
+ [{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
+ {"4.4.4",
+ [{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
+ {<<"4\\.4\\.[2-3]">>,
+ [{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.4.1",
- [{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.4.0",
diff --git a/apps/emqx_auth_mongo/src/emqx_auth_mongo.erl b/apps/emqx_auth_mongo/src/emqx_auth_mongo.erl
index 1c8c18ce3..9ca272c65 100644
--- a/apps/emqx_auth_mongo/src/emqx_auth_mongo.erl
+++ b/apps/emqx_auth_mongo/src/emqx_auth_mongo.erl
@@ -68,6 +68,9 @@ check(ClientInfo = #{password := Password}, AuthResult,
case Result of
ok ->
?tp(emqx_auth_mongo_superuser_check_authn_ok, #{}),
+ ?LOG_SENSITIVE(debug,
+ "[MongoDB] Auth from mongo succeeded, Client: ~p",
+ [ClientInfo]),
{stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo),
anonymous => false,
auth_result => success}};
diff --git a/apps/emqx_auth_mysql/rebar.config b/apps/emqx_auth_mysql/rebar.config
index b86500e8f..99456c76d 100644
--- a/apps/emqx_auth_mysql/rebar.config
+++ b/apps/emqx_auth_mysql/rebar.config
@@ -1,7 +1,4 @@
-{deps,
- [
- {mysql, {git, "https://github.com/emqx/mysql-otp", {tag, "1.7.1"}}}
- ]}.
+{deps, []}.
{edoc_opts, [{preprocess, true}]}.
{erl_opts, [warn_unused_vars,
diff --git a/apps/emqx_auth_mysql/src/emqx_acl_mysql.erl b/apps/emqx_auth_mysql/src/emqx_acl_mysql.erl
index 436c69d5f..a5b0f86b2 100644
--- a/apps/emqx_auth_mysql/src/emqx_acl_mysql.erl
+++ b/apps/emqx_auth_mysql/src/emqx_acl_mysql.erl
@@ -29,8 +29,16 @@
check_acl(ClientInfo, PubSub, Topic, NoMatchAction, #{pool := Pool} = State) ->
case do_check_acl(Pool, ClientInfo, PubSub, Topic, NoMatchAction, State) of
ok -> ok;
- {stop, allow} -> {stop, allow};
- {stop, deny} -> {stop, deny}
+ {stop, allow} ->
+ ?LOG_SENSITIVE(debug,
+ "[MySQL] Allow Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
+ {stop, allow};
+ {stop, deny} ->
+ ?LOG_SENSITIVE(debug,
+ "[MySQL] Allow Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
+ {stop, deny}
end.
do_check_acl(_Pool, #{username := <<$$, _/binary>>}, _PubSub, _Topic, _NoMatchAction, _State) ->
diff --git a/apps/emqx_auth_mysql/src/emqx_auth_mysql.app.src b/apps/emqx_auth_mysql/src/emqx_auth_mysql.app.src
index b6d1ef811..abfa86c5f 100644
--- a/apps/emqx_auth_mysql/src/emqx_auth_mysql.app.src
+++ b/apps/emqx_auth_mysql/src/emqx_auth_mysql.app.src
@@ -1,6 +1,6 @@
{application, emqx_auth_mysql,
[{description, "EMQ X Authentication/ACL with MySQL"},
- {vsn, "4.3.4"}, % strict semver, bump manually!
+ {vsn, "4.3.5"}, % strict semver, bump manually!
{modules, []},
{registered, [emqx_auth_mysql_sup]},
{applications, [kernel,stdlib,mysql,ecpool]},
diff --git a/apps/emqx_auth_mysql/src/emqx_auth_mysql.appup.src b/apps/emqx_auth_mysql/src/emqx_auth_mysql.appup.src
index 5cc4fbc7b..a0a6b036d 100644
--- a/apps/emqx_auth_mysql/src/emqx_auth_mysql.appup.src
+++ b/apps/emqx_auth_mysql/src/emqx_auth_mysql.appup.src
@@ -1,10 +1,17 @@
%% -*- mode: erlang -*-
+%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.3.3",
+ [{"4.3.4",
[{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mysql_cli,brutal_purge,soft_purge,[]}]},
+ {"4.3.3",
+ [{load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[1-2]">>,
- [{load_module,emqx_auth_mysql_cli,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mysql_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]}]},
{"4.3.0",
@@ -13,11 +20,17 @@
{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
- [{"4.3.3",
+ [{"4.3.4",
[{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mysql_cli,brutal_purge,soft_purge,[]}]},
+ {"4.3.3",
+ [{load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[1-2]">>,
- [{load_module,emqx_auth_mysql_cli,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_mysql_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]}]},
{"4.3.0",
@@ -25,5 +38,4 @@
{load_module,emqx_auth_mysql_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]}]},
- {<<".*">>,[]}]
-}.
+ {<<".*">>,[]}]}.
diff --git a/apps/emqx_auth_mysql/src/emqx_auth_mysql.erl b/apps/emqx_auth_mysql/src/emqx_auth_mysql.erl
index ac35e6ce6..94045e1ad 100644
--- a/apps/emqx_auth_mysql/src/emqx_auth_mysql.erl
+++ b/apps/emqx_auth_mysql/src/emqx_auth_mysql.erl
@@ -46,6 +46,9 @@ check(ClientInfo = #{password := Password}, AuthResult,
end,
case CheckPass of
ok ->
+ ?LOG_SENSITIVE(debug,
+ "[MySQL] Auth from mysql succeeded, Client: ~p",
+ [ClientInfo]),
{stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo),
anonymous => false,
auth_result => success}};
diff --git a/apps/emqx_auth_pgsql/src/emqx_acl_pgsql.erl b/apps/emqx_auth_pgsql/src/emqx_acl_pgsql.erl
index ee385cd16..1afb93975 100644
--- a/apps/emqx_auth_pgsql/src/emqx_acl_pgsql.erl
+++ b/apps/emqx_auth_pgsql/src/emqx_acl_pgsql.erl
@@ -36,9 +36,17 @@ do_check_acl(Pool, ClientInfo, PubSub, Topic, _NoMatchAction, #{acl_query := {Ac
{ok, _, Rows} ->
Rules = filter(PubSub, compile(Rows)),
case match(ClientInfo, Topic, Rules) of
- {matched, allow} -> {stop, allow};
- {matched, deny} -> {stop, deny};
- nomatch -> ok
+ {matched, allow} ->
+ ?LOG_SENSITIVE(debug,
+ "[Postgres] Allow Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
+ {stop, allow};
+ {matched, deny} ->
+ ?LOG_SENSITIVE(debug,
+ "[Postgres] Deny Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
+ {stop, deny};
+ nomatch -> ok
end;
{error, Reason} ->
?LOG(error, "[Postgres] do_check_acl error: ~p~n", [Reason]),
@@ -105,4 +113,3 @@ empty(null) -> true;
empty("") -> true;
empty(<<>>) -> true;
empty(_) -> false.
-
diff --git a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.app.src b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.app.src
index 47929bc65..96a810d7c 100644
--- a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.app.src
+++ b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.app.src
@@ -1,6 +1,6 @@
{application, emqx_auth_pgsql,
[{description, "EMQ X Authentication/ACL with PostgreSQL"},
- {vsn, "4.4.4"}, % strict semver, bump manually!
+ {vsn, "4.4.5"}, % strict semver, bump manually!
{modules, []},
{registered, [emqx_auth_pgsql_sup]},
{applications, [kernel,stdlib,epgsql,ecpool]},
diff --git a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src
index d5a641a66..98826f918 100644
--- a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src
+++ b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src
@@ -1,20 +1,29 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.4.3",
- [{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
+ [{"4.4.4",
+ [{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]}]},
+ {"4.4.3",
+ [{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]}]},
{<<"4\\.4\\.[0-2]">>,
- [{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
- [{"4.4.3",
- [{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
+ [{"4.4.4",
+ [{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]}]},
+ {"4.4.3",
+ [{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]}]},
{<<"4\\.4\\.[0-2]">>,
- [{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}]}.
-
diff --git a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.erl b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.erl
index 6bdc53941..8f75c1279 100644
--- a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.erl
+++ b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.erl
@@ -45,6 +45,9 @@ check(ClientInfo = #{password := Password}, AuthResult,
end,
case CheckPass of
ok ->
+ ?LOG_SENSITIVE(debug,
+ "[Postgres] Auth from pgsql succeeded, Client: ~p",
+ [ClientInfo]),
{stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo),
anonymous => false,
auth_result => success}};
diff --git a/apps/emqx_auth_redis/src/emqx_acl_redis.erl b/apps/emqx_auth_redis/src/emqx_acl_redis.erl
index 2fcdb9592..74a68905c 100644
--- a/apps/emqx_auth_redis/src/emqx_acl_redis.erl
+++ b/apps/emqx_auth_redis/src/emqx_acl_redis.erl
@@ -33,8 +33,16 @@ check_acl(ClientInfo, PubSub, Topic, _AclResult,
{ok, []} -> ok;
{ok, Rules} ->
case match(ClientInfo, PubSub, Topic, Rules) of
- allow -> {stop, allow};
- nomatch -> {stop, deny}
+ allow ->
+ ?LOG_SENSITIVE(debug,
+ "[Redis] Allow Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
+ {stop, allow};
+ nomatch ->
+ ?LOG_SENSITIVE(debug,
+ "[Redis] Deny Topic: ~p, Action: ~p for Client: ~p",
+ [Topic, PubSub, ClientInfo]),
+ {stop, deny}
end;
{error, Reason} ->
?LOG(error, "[Redis] do_check_acl error: ~p", [Reason]),
@@ -71,4 +79,3 @@ feed_var(Str, Var, Val) ->
b2i(Bin) -> list_to_integer(binary_to_list(Bin)).
description() -> "Redis ACL Module".
-
diff --git a/apps/emqx_auth_redis/src/emqx_auth_redis.app.src b/apps/emqx_auth_redis/src/emqx_auth_redis.app.src
index 80827507b..0fb0ecaff 100644
--- a/apps/emqx_auth_redis/src/emqx_auth_redis.app.src
+++ b/apps/emqx_auth_redis/src/emqx_auth_redis.app.src
@@ -1,6 +1,6 @@
{application, emqx_auth_redis,
[{description, "EMQ X Authentication/ACL with Redis"},
- {vsn, "4.3.4"}, % strict semver, bump manually!
+ {vsn, "4.3.5"}, % strict semver, bump manually!
{modules, []},
{registered, [emqx_auth_redis_sup]},
{applications, [kernel,stdlib,eredis,eredis_cluster,ecpool]},
diff --git a/apps/emqx_auth_redis/src/emqx_auth_redis.appup.src b/apps/emqx_auth_redis/src/emqx_auth_redis.appup.src
index 8ce75dbeb..c3c25571a 100644
--- a/apps/emqx_auth_redis/src/emqx_auth_redis.appup.src
+++ b/apps/emqx_auth_redis/src/emqx_auth_redis.appup.src
@@ -1,11 +1,15 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.3.3",
- [{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]},
+ [{"4.3.4",
+ [{load_module,emqx_acl_redis,brutal_purge,soft_purge,[]}]},
+ {"4.3.3",
+ [{load_module,emqx_acl_redis,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_redis,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_redis_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[1-2]">>,
- [{load_module,emqx_auth_redis_cli,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_acl_redis,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_redis_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_redis_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]}]},
{"4.3.0",
@@ -14,11 +18,15 @@
{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_redis,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
- [{"4.3.3",
- [{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]},
+ [{"4.3.4",
+ [{load_module,emqx_acl_redis,brutal_purge,soft_purge,[]}]},
+ {"4.3.3",
+ [{load_module,emqx_acl_redis,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_redis,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_redis_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[1-2]">>,
- [{load_module,emqx_auth_redis_cli,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_acl_redis,brutal_purge,soft_purge,[]},
+ {load_module,emqx_auth_redis_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_redis_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]}]},
{"4.3.0",
diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.app.src b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.app.src
index a3bf1e914..b58be5d2e 100644
--- a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.app.src
+++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.app.src
@@ -1,6 +1,6 @@
{application, emqx_bridge_mqtt,
[{description, "EMQ X Bridge to MQTT Broker"},
- {vsn, "4.3.7"}, % strict semver, bump manually!
+ {vsn, "4.3.8"}, % strict semver, bump manually!
{modules, []},
{registered, []},
{applications, [kernel,stdlib,replayq,emqtt]},
diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.appup.src b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.appup.src
index a6ca580f1..013371592 100644
--- a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.appup.src
+++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.appup.src
@@ -1,7 +1,9 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.3.6",
+ [{"4.3.7",
+ [{load_module,emqx_bridge_mqtt_actions,brutal_purge,soft_purge,[]}]},
+ {"4.3.6",
[{load_module,emqx_bridge_connect,brutal_purge,soft_purge,[]},
{load_module,emqx_bridge_mqtt_actions,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[4-5]">>,
@@ -21,7 +23,9 @@
{load_module,emqx_bridge_worker,brutal_purge,soft_purge,[]},
{load_module,emqx_bridge_mqtt_actions,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
- [{"4.3.6",
+ [{"4.3.7",
+ [{load_module,emqx_bridge_mqtt_actions,brutal_purge,soft_purge,[]}]},
+ {"4.3.6",
[{load_module,emqx_bridge_connect,brutal_purge,soft_purge,[]},
{load_module,emqx_bridge_mqtt_actions,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[4-5]">>,
diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_actions.erl b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_actions.erl
index b5d43f5f4..b43d44eac 100644
--- a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_actions.erl
+++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_actions.erl
@@ -111,11 +111,11 @@
zh => <<"桥接挂载点"/utf8>>},
description => #{
en => <<"MountPoint for bridge topic:
"
- "Example: The topic of messages sent to `topic1` on local node "
- "will be transformed to `bridge/aws/${node}/topic1`">>,
+ "Example: The topic of messages sent to topic1
on local node "
+ "will be transformed to bridge/aws/${node}/topic1
">>,
zh => <<"桥接主题的挂载点:
"
- "示例: 本地节点向 `topic1` 发消息,远程桥接节点的主题"
- "会变换为 `bridge/aws/${node}/topic1`"/utf8>>
+ "示例: 本地节点向 topic1
发消息,远程桥接节点的主题"
+ "会变换为 bridge/aws/${node}/topic1
"/utf8>>
}
},
disk_cache => #{
@@ -267,10 +267,10 @@
type => string,
required => true,
default => <<"emqx2@127.0.0.1">>,
- title => #{en => <<"EMQ X Node Name">>,
- zh => <<"EMQ X 节点名称"/utf8>>},
- description => #{en => <<"EMQ X Remote Node Name">>,
- zh => <<"远程 EMQ X 节点名称 "/utf8>>}
+ title => #{en => <<"EMQX Node Name">>,
+ zh => <<"EMQX 节点名称"/utf8>>},
+ description => #{en => <<"EMQX Remote Node Name">>,
+ zh => <<"远程 EMQX 节点名称 "/utf8>>}
},
mountpoint => #{
order => 2,
@@ -280,11 +280,11 @@
title => #{en => <<"Bridge MountPoint">>,
zh => <<"桥接挂载点"/utf8>>},
description => #{en => <<"MountPoint for bridge topic
"
- "Example: The topic of messages sent to `topic1` on local node "
- "will be transformed to `bridge/aws/${node}/topic1`">>,
+ "Example: The topic of messages sent to topic1
on local node "
+ "will be transformed to bridge/emqx/${node}/topic1
">>,
zh => <<"桥接主题的挂载点
"
- "示例: 本地节点向 `topic1` 发消息,远程桥接节点的主题"
- "会变换为 `bridge/aws/${node}/topic1`"/utf8>>}
+ "示例: 本地节点向 topic1
发消息,远程桥接节点的主题"
+ "会变换为 bridge/emqx/${node}/topic1
"/utf8>>}
},
pool_size => #{
order => 3,
@@ -358,7 +358,7 @@
destroy => on_resource_destroy,
params => ?RESOURCE_CONFIG_SPEC_RPC,
title => #{en => <<"EMQX Bridge">>, zh => <<"EMQX Bridge"/utf8>>},
- description => #{en => <<"EMQ X RPC Bridge">>, zh => <<"EMQ X RPC 消息桥接"/utf8>>}
+ description => #{en => <<"EMQX RPC Bridge">>, zh => <<"EMQX RPC 消息桥接"/utf8>>}
}).
-rule_action(#{
diff --git a/apps/emqx_coap/rebar.config b/apps/emqx_coap/rebar.config
index e1da2c197..3ec4e9fdb 100644
--- a/apps/emqx_coap/rebar.config
+++ b/apps/emqx_coap/rebar.config
@@ -1,4 +1,4 @@
{deps,
[
- {gen_coap, {git, "https://github.com/emqx/gen_coap", {tag, "v0.4.2"}}}
+ {gen_coap, {git, "https://github.com/emqx/gen_coap", {tag, "v0.4.3"}}}
]}.
diff --git a/apps/emqx_management/priv/emqx_management.schema b/apps/emqx_management/priv/emqx_management.schema
index 0b91509f1..42f63b7bf 100644
--- a/apps/emqx_management/priv/emqx_management.schema
+++ b/apps/emqx_management/priv/emqx_management.schema
@@ -90,6 +90,11 @@
{datatype, {enum, [true, false]}}
]}.
+{mapping, "management.listener.http.proxy_header", "emqx_management.listeners", [
+ {default, false},
+ {datatype, {enum, [true, false]}}
+]}.
+
{mapping, "management.listener.https", "emqx_management.listeners", [
{datatype, [integer, ip]}
]}.
@@ -186,6 +191,11 @@
{datatype, {enum, [true, false]}}
]}.
+{mapping, "management.listener.https.proxy_header", "emqx_management.listeners", [
+ {default, false},
+ {datatype, {enum, [true, false]}}
+]}.
+
{translation, "emqx_management.application", fun(Conf) ->
Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
Opts = fun(Prefix) ->
@@ -202,7 +212,9 @@ end}.
Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
Opts = fun(Prefix) ->
Filter([{num_acceptors, cuttlefish:conf_get(Prefix ++ ".acceptors", Conf)},
- {max_connections, cuttlefish:conf_get(Prefix ++ ".max_clients", Conf)}])
+ {max_connections, cuttlefish:conf_get(Prefix ++ ".max_clients", Conf)},
+ {proxy_header, cuttlefish:conf_get(Prefix ++ ".proxy_header", Conf)}
+ ])
end,
TcpOpts = fun(Prefix) ->
Filter([{backlog, cuttlefish:conf_get(Prefix ++ ".backlog", Conf, undefined)},
diff --git a/apps/emqx_management/src/emqx_management.app.src b/apps/emqx_management/src/emqx_management.app.src
index fe927c097..b505e2c69 100644
--- a/apps/emqx_management/src/emqx_management.app.src
+++ b/apps/emqx_management/src/emqx_management.app.src
@@ -1,6 +1,6 @@
{application, emqx_management,
[{description, "EMQ X Management API and CLI"},
- {vsn, "4.4.12"}, % strict semver, bump manually!
+ {vsn, "4.4.13"}, % strict semver, bump manually!
{modules, []},
{registered, [emqx_management_sup]},
{applications, [kernel,stdlib,emqx_plugin_libs,minirest]},
diff --git a/apps/emqx_management/src/emqx_mgmt_api.erl b/apps/emqx_management/src/emqx_mgmt_api.erl
index b9f8aeab1..99d8f8172 100644
--- a/apps/emqx_management/src/emqx_mgmt_api.erl
+++ b/apps/emqx_management/src/emqx_mgmt_api.erl
@@ -167,7 +167,7 @@ cluster_query(Params, {Tab, QsSchema}, QueryFun) ->
Start = if Page > 1 -> (Page-1) * Limit;
true -> 0
end,
- Nodes = ekka_mnesia:running_nodes(),
+ Nodes = lists:sort(ekka_mnesia:running_nodes()),
Rows = do_cluster_query(Nodes, Qs, QueryFun, Start, Limit+1, []),
Meta = #{page => Page, limit => Limit},
NMeta = case CodCnt =:= 0 of
diff --git a/apps/emqx_management/src/emqx_mgmt_http.erl b/apps/emqx_management/src/emqx_mgmt_http.erl
index 444e0ce25..7f571ee70 100644
--- a/apps/emqx_management/src/emqx_mgmt_http.erl
+++ b/apps/emqx_management/src/emqx_mgmt_http.erl
@@ -52,12 +52,12 @@ stop_listeners() ->
start_listener({Proto, Port, Options}) when Proto == http ->
Dispatch = [{"/status", emqx_mgmt_http, []},
{"/api/v4/[...]", minirest, http_handlers()}],
- minirest:start_http(listener_name(Proto), ranch_opts(Port, Options), Dispatch);
+ minirest:start_http(listener_name(Proto), ranch_opts(Port, Options), Dispatch, proto_opts(Options));
start_listener({Proto, Port, Options}) when Proto == https ->
Dispatch = [{"/status", emqx_mgmt_http, []},
{"/api/v4/[...]", minirest, http_handlers()}],
- minirest:start_https(listener_name(Proto), ranch_opts(Port, Options), Dispatch).
+ minirest:start_https(listener_name(Proto), ranch_opts(Port, Options), Dispatch, proto_opts(Options)).
ranch_opts(Port, Options0) ->
NumAcceptors = proplists:get_value(num_acceptors, Options0, 4),
@@ -68,6 +68,7 @@ ranch_opts(Port, Options0) ->
({inet6, false}, Acc) -> Acc;
({ipv6_v6only, true}, Acc) -> [{ipv6_v6only, true} | Acc];
({ipv6_v6only, false}, Acc) -> Acc;
+ ({proxy_header, _}, Acc) -> Acc;
({K, V}, Acc)->
[{K, V} | Acc]
end, [], Options0),
@@ -77,6 +78,9 @@ ranch_opts(Port, Options0) ->
socket_opts => [{port, Port} | Options]},
Res.
+proto_opts(Options) ->
+ maps:with([proxy_header], maps:from_list(Options)).
+
stop_listener({Proto, Port, _}) ->
io:format("Stop http:management listener on ~s successfully.~n",[format(Port)]),
minirest:stop_http(listener_name(Proto)).
diff --git a/apps/emqx_management/test/emqx_mgmt_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_api_SUITE.erl
index 1e315f8d0..57ab5d0f5 100644
--- a/apps/emqx_management/test/emqx_mgmt_api_SUITE.erl
+++ b/apps/emqx_management/test/emqx_mgmt_api_SUITE.erl
@@ -794,13 +794,7 @@ t_keepalive(_Config) ->
Path = api_path(["clients", ClientId, "keepalive"]),
{ok, NotFound} = request_api(put, Path, "interval=5", AuthHeader, [#{}]),
?assertEqual("{\"message\":\"not_found\",\"code\":112}", NotFound),
- {ok, C1} = emqtt:start_link(#{username => Username, clientid => ClientId}),
- {ok, _} = emqtt:connect(C1),
- {ok, Ok} = request_api(put, Path, "interval=5", AuthHeader, [#{}]),
- ?assertEqual("{\"code\":0}", Ok),
- [Pid] = emqx_cm:lookup_channels(list_to_binary(ClientId)),
- #{conninfo := #{keepalive := Keepalive}} = emqx_connection:info(Pid),
- ?assertEqual(5, Keepalive),
+ C1 = keepalive_ok(61, 0, Username, ClientId, Path, AuthHeader),
{ok, Error1} = request_api(put, Path, "interval=-1", AuthHeader, [#{}]),
{ok, Error2} = request_api(put, Path, "interval=65536", AuthHeader, [#{}]),
ErrMsg = #{<<"code">> => 102,
@@ -808,9 +802,26 @@ t_keepalive(_Config) ->
?assertEqual(ErrMsg, jiffy:decode(Error1, [return_maps])),
?assertEqual(Error1, Error2),
emqtt:disconnect(C1),
+ %% test change keepalive from 0 to 60
+ C2 = keepalive_ok(0, 60, Username, ClientId, Path, AuthHeader),
+ emqtt:disconnect(C2),
+ %% test change keepalive from 60 to 0
+ C3 = keepalive_ok(60, 0, Username, ClientId, Path, AuthHeader),
+ emqtt:disconnect(C3),
application:stop(emqx_dashboard),
ok.
+keepalive_ok(InitSec, UpdateSec, Username, ClientId, Path, AuthHeader) ->
+ {ok, C1} = emqtt:start_link(#{username => Username, clientid => ClientId, keepalive => InitSec}),
+ {ok, _} = emqtt:connect(C1),
+ Qs = "interval=" ++ integer_to_list(UpdateSec),
+ {ok, Ok} = request_api(put, Path, Qs, AuthHeader, [#{}]),
+ ?assertEqual("{\"code\":0}", Ok),
+ [Pid] = emqx_cm:lookup_channels(list_to_binary(ClientId)),
+ #{conninfo := #{keepalive := Keepalive}} = emqx_connection:info(Pid),
+ ?assertEqual(UpdateSec, Keepalive),
+ C1.
+
t_status_ok(_Config) ->
{ok, #{ body := Resp
, status_code := StatusCode
diff --git a/apps/emqx_prometheus/src/emqx_prometheus.app.src b/apps/emqx_prometheus/src/emqx_prometheus.app.src
index ded1bf46d..6e7d7400f 100644
--- a/apps/emqx_prometheus/src/emqx_prometheus.app.src
+++ b/apps/emqx_prometheus/src/emqx_prometheus.app.src
@@ -1,6 +1,6 @@
{application, emqx_prometheus,
[{description, "Prometheus for EMQ X"},
- {vsn, "4.3.1"}, % strict semver, bump manually!
+ {vsn, "4.3.2"}, % strict semver, bump manually!
{modules, []},
{registered, [emqx_prometheus_sup]},
{applications, [kernel,stdlib,prometheus]},
diff --git a/apps/emqx_prometheus/src/emqx_prometheus.appup.src b/apps/emqx_prometheus/src/emqx_prometheus.appup.src
index a06d65fe1..1234d5395 100644
--- a/apps/emqx_prometheus/src/emqx_prometheus.appup.src
+++ b/apps/emqx_prometheus/src/emqx_prometheus.appup.src
@@ -1,9 +1,9 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.3.0",
- [{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
+ [{"4.3.1",[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
+ {"4.3.0",[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
- [{"4.3.0",
- [{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
+ [{"4.3.1",[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
+ {"4.3.0",[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}]}.
diff --git a/apps/emqx_prometheus/src/emqx_prometheus.erl b/apps/emqx_prometheus/src/emqx_prometheus.erl
index b58c4cc5f..5342a6d71 100644
--- a/apps/emqx_prometheus/src/emqx_prometheus.erl
+++ b/apps/emqx_prometheus/src/emqx_prometheus.erl
@@ -185,6 +185,10 @@ emqx_collect(emqx_connections_count, Stats) ->
gauge_metric(?C('connections.count', Stats));
emqx_collect(emqx_connections_max, Stats) ->
gauge_metric(?C('connections.max', Stats));
+emqx_collect(emqx_live_connections_count, Stats) ->
+ gauge_metric(?C('live_connections.count', Stats));
+emqx_collect(emqx_live_connections_max, Stats) ->
+ gauge_metric(?C('live_connections.max', Stats));
%% sessions
emqx_collect(emqx_sessions_count, Stats) ->
@@ -471,6 +475,8 @@ emqx_collect(emqx_cluster_nodes_stopped, ClusterData) ->
emqx_stats() ->
[ emqx_connections_count
, emqx_connections_max
+ , emqx_live_connections_count
+ , emqx_live_connections_max
, emqx_sessions_count
, emqx_sessions_max
, emqx_topics_count
diff --git a/apps/emqx_retainer/src/emqx_retainer.app.src b/apps/emqx_retainer/src/emqx_retainer.app.src
index 27baf5e88..941038d73 100644
--- a/apps/emqx_retainer/src/emqx_retainer.app.src
+++ b/apps/emqx_retainer/src/emqx_retainer.app.src
@@ -1,6 +1,6 @@
{application, emqx_retainer,
[{description, "EMQ X Retainer"},
- {vsn, "4.4.3"}, % strict semver, bump manually!
+ {vsn, "4.4.4"}, % strict semver, bump manually!
{modules, []},
{registered, [emqx_retainer_sup]},
{applications, [kernel,stdlib]},
diff --git a/apps/emqx_retainer/src/emqx_retainer.appup.src b/apps/emqx_retainer/src/emqx_retainer.appup.src
index 045afb570..54413bfa2 100644
--- a/apps/emqx_retainer/src/emqx_retainer.appup.src
+++ b/apps/emqx_retainer/src/emqx_retainer.appup.src
@@ -1,15 +1,27 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.4.2",[{load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}]},
- {"4.4.1",[{load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}]},
+ [{"4.4.3",[{load_module,emqx_retainer,brutal_purge,soft_purge,[]}]},
+ {"4.4.2",[{load_module,emqx_retainer,brutal_purge,soft_purge,[]},
+ {load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}
+ ]},
+ {"4.4.1",[{load_module,emqx_retainer,brutal_purge,soft_purge,[]},
+ {load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}
+ ]},
{"4.4.0",
- [{load_module,emqx_retainer_cli,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_retainer,brutal_purge,soft_purge,[]},
+ {load_module,emqx_retainer_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
- [{"4.4.2",[{load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}]},
- {"4.4.1",[{load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}]},
+ [{"4.4.3",[{load_module,emqx_retainer,brutal_purge,soft_purge,[]}]},
+ {"4.4.2",[{load_module,emqx_retainer,brutal_purge,soft_purge,[]},
+ {load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}
+ ]},
+ {"4.4.1",[{load_module,emqx_retainer,brutal_purge,soft_purge,[]},
+ {load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}
+ ]},
{"4.4.0",
- [{load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]},
- {load_module,emqx_retainer_cli,brutal_purge,soft_purge,[]}]},
+ [{load_module,emqx_retainer,brutal_purge,soft_purge,[]},
+ {load_module,emqx_retainer_cli,brutal_purge,soft_purge,[]},
+ {load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}]}.
diff --git a/apps/emqx_retainer/src/emqx_retainer.erl b/apps/emqx_retainer/src/emqx_retainer.erl
index 3bafc6a1d..84e49c5be 100644
--- a/apps/emqx_retainer/src/emqx_retainer.erl
+++ b/apps/emqx_retainer/src/emqx_retainer.erl
@@ -22,6 +22,7 @@
-include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/logger.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
+-include_lib("snabbkaffe/include/snabbkaffe.hrl").
-logger_header("[Retainer]").
@@ -74,11 +75,12 @@ on_session_subscribed(_, Topic, #{rh := Rh, is_new := IsNew}) ->
%% @private
dispatch(Pid, Topic) ->
- Msgs = case emqx_topic:wildcard(Topic) of
- false -> read_messages(Topic);
- true -> match_messages(Topic)
- end,
+ MsgsT = case emqx_topic:wildcard(Topic) of
+ false -> read_messages(Topic);
+ true -> match_messages(Topic)
+ end,
Now = erlang:system_time(millisecond),
+ Msgs = drop_banned_messages(MsgsT),
[Pid ! {deliver, Topic, refresh_timestamp_expiry(Msg, Now)} || Msg <- sort_retained(Msgs)].
%% RETAIN flag set to 1 and payload containing zero bytes
@@ -332,3 +334,21 @@ refresh_timestamp_expiry(Msg = #message{headers =
refresh_timestamp_expiry(Msg, Now) ->
Msg#message{timestamp = Now}.
+
+drop_banned_messages(Msgs) ->
+ lists:filter(fun(Msg) ->
+ case emqx_banned:look_up({clientid, Msg#message.from}) of
+ [] ->
+ true;
+ _ ->
+ ?tp(
+ notice,
+ ignore_retained_message_deliver,
+ #{
+ reason => "client is banned",
+ clientid => Msg#message.from
+ }
+ ),
+ false
+ end
+ end, Msgs).
diff --git a/apps/emqx_retainer/test/emqx_retainer_SUITE.erl b/apps/emqx_retainer/test/emqx_retainer_SUITE.erl
index 787c49bcb..6e2f7b1ca 100644
--- a/apps/emqx_retainer/test/emqx_retainer_SUITE.erl
+++ b/apps/emqx_retainer/test/emqx_retainer_SUITE.erl
@@ -23,6 +23,7 @@
-include_lib("eunit/include/eunit.hrl").
-include_lib("common_test/include/ct.hrl").
+-include_lib("snabbkaffe/include/snabbkaffe.hrl").
all() -> emqx_ct:all(?MODULE).
@@ -189,6 +190,53 @@ t_stop_publish_clear_msg(_) ->
ok = emqtt:disconnect(C1).
+t_deliver_when_banned(_) ->
+ Client1 = <<"c1">>,
+ Client2 = <<"c2">>,
+
+ {ok, C1} = emqtt:start_link([{clientid, Client1}, {clean_start, true}, {proto_ver, v5}]),
+ {ok, _} = emqtt:connect(C1),
+
+ lists:foreach(
+ fun(I) ->
+ Topic = erlang:list_to_binary(io_lib:format("retained/~p", [I])),
+ Msg = emqx_message:make(Client2, 0, Topic, <<"this is a retained message">>),
+ Msg2 = emqx_message:set_flag(retain, Msg),
+ emqx:publish(Msg2)
+ end,
+ lists:seq(1, 3)
+ ),
+
+ Now = erlang:system_time(second),
+ Who = {clientid, Client2},
+
+ emqx_banned:create(#{
+ who => Who,
+ by => <<"test">>,
+ reason => <<"test">>,
+ at => Now,
+ until => Now + 120
+ }),
+ timer:sleep(100),
+
+ snabbkaffe:start_trace(),
+
+ {ok, SubRef} =
+ snabbkaffe_collector:subscribe(?match_event(#{?snk_kind := ignore_retained_message_deliver}),
+ _NEvents = 3,
+ _Timeout = 10000,
+ 0),
+
+ {ok, #{}, [0]} = emqtt:subscribe(C1, <<"retained/+">>, [{qos, 0}, {rh, 0}]),
+ {ok, Trace} = snabbkaffe_collector:receive_events(SubRef),
+ ?assertEqual(3, length(?of_kind(ignore_retained_message_deliver, Trace))),
+
+ snabbkaffe:stop(),
+
+ emqx_banned:delete(Who),
+ {ok, #{}, [0]} = emqtt:unsubscribe(C1, <<"retained/+">>),
+ ok = emqtt:disconnect(C1).
+
%%--------------------------------------------------------------------
%% Helper functions
%%--------------------------------------------------------------------
diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src b/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src
index e9578168d..cdf8fb959 100644
--- a/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src
+++ b/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src
@@ -1,22 +1,32 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.4.14",[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]},
- {"4.4.13",[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]},
+ [{<<"4\\.4\\.1[3-4]">>,
+ [{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_events,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_monitor,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}
+ ]},
{"4.4.12",
[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_events,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_monitor,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]},
{update,emqx_rule_engine_jwt_sup,supervisor},
{load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]}]},
{"4.4.11",
[{load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_events,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_monitor,brutal_purge,soft_purge,[]},
{update,emqx_rule_engine_jwt_sup,supervisor},
{load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_engine_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]},
{apply,{emqx_rule_engine_sup,ensure_api_delegator_started,[]}},
- {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}]},
+ {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}
+ ]},
{"4.4.10",
[{add_module,emqx_rule_engine_jwt},
{add_module,emqx_rule_engine_jwt_worker},
@@ -222,15 +232,24 @@
{load_module,emqx_rule_engine,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
- [{"4.4.14",[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]},
- {"4.4.13",[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]},
+ [{<<"4\\.4\\.1[3-4]">>,
+ [{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_events,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_monitor,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}
+ ]},
{"4.4.12",
[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_events,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_monitor,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]},
{update,emqx_rule_engine_jwt_sup,supervisor},
{load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]}]},
{"4.4.11",
[{load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_events,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_monitor,brutal_purge,soft_purge,[]},
{update,emqx_rule_engine_jwt_sup,supervisor},
{load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.erl b/apps/emqx_rule_engine/src/emqx_rule_engine.erl
index 8f7e6bdbb..b7467a81f 100644
--- a/apps/emqx_rule_engine/src/emqx_rule_engine.erl
+++ b/apps/emqx_rule_engine/src/emqx_rule_engine.erl
@@ -36,6 +36,7 @@
, create_resource/1
, test_resource/1
, start_resource/1
+ , start_all_resources_of_type/1
, get_resource_status/1
, is_resource_alive/1
, is_resource_alive/2
@@ -354,19 +355,27 @@ do_check_and_update_resource(#{id := Id, type := Type, description := NewDescrip
-spec(start_resource(resource_id()) -> ok | {error, Reason :: term()}).
start_resource(ResId) ->
case emqx_rule_registry:find_resource(ResId) of
- {ok, #resource{type = ResType, config = Config}} ->
- {ok, #resource_type{on_create = {Mod, Create}}}
- = emqx_rule_registry:find_resource_type(ResType),
- try
- init_resource_with_retrier(Mod, Create, ResId, Config),
- refresh_actions_of_a_resource(ResId)
- catch
- throw:Reason -> {error, Reason}
- end;
+ {ok, Res} ->
+ do_start_resource(Res);
not_found ->
{error, {resource_not_found, ResId}}
end.
+do_start_resource(#resource{id = ResId, type = ResType, config = Config}) ->
+ {ok, #resource_type{on_create = {Mod, Create}}}
+ = emqx_rule_registry:find_resource_type(ResType),
+ try
+ init_resource_with_retrier(Mod, Create, ResId, Config),
+ refresh_actions_of_a_resource(ResId)
+ catch
+ throw:Reason -> {error, Reason}
+ end.
+
+-spec(start_all_resources_of_type(resource_type_name()) -> [{resource_id(), ok | {error, term()}}]).
+start_all_resources_of_type(Type) ->
+ [{ResId, do_start_resource(Res)}
+ || #resource{id = ResId} = Res <- emqx_rule_registry:get_resources_by_type(Type)].
+
-spec(test_resource(#{type := _, config := _, _ => _}) -> ok | {error, Reason :: term()}).
test_resource(#{type := Type} = Params) ->
case emqx_rule_registry:find_resource_type(Type) of
@@ -520,19 +529,27 @@ refresh_resource(#resource{id = ResId, type = Type, config = Config}) ->
refresh_rules_when_boot() ->
lists:foreach(fun
(#rule{enabled = true} = Rule) ->
- try refresh_rule(Rule)
- catch _:_ ->
- %% We set the enable = false when rule init failed to avoid bad rules running
- %% without actions created properly.
- %% The init failure might be caused by a disconnected resource, in this case the
- %% actions can not be created, so the rules won't work.
- %% After the user fixed the problem he can enable it manually,
- %% doing so will also recreate the actions.
- emqx_rule_registry:add_rule(Rule#rule{enabled = false, state = refresh_failed_at_bootup})
- end;
- (_) -> ok
+ ensure_rule_retrier(Rule);
+ (#rule{enabled = false, state = refresh_failed_at_bootup} = Rule) ->
+ %% the rule was previously disabled by emqx so we need to retry it
+ ensure_rule_retrier(Rule);
+ (#rule{enabled = false, id = RuleId}) ->
+ ?LOG(warning, "rule ~s was disabled by the user, won't re-enable it", [RuleId])
end, emqx_rule_registry:get_rules()).
+ensure_rule_retrier(#rule{id = RuleId} = Rule) ->
+ try refresh_rule(Rule)
+ catch _:_ ->
+ %% We set the enable = false when rule init failed to avoid bad rules running
+ %% without actions created properly.
+ %% The init failure might be caused by a disconnected resource, in this case the
+ %% actions can not be created, so the rules won't work.
+ %% After the user fixed the problem he can enable it manually,
+ %% doing so will also recreate the actions.
+ emqx_rule_registry:add_rule(Rule#rule{enabled = false, state = refresh_failed_at_bootup}),
+ emqx_rule_monitor:ensure_rule_retrier(RuleId)
+ end.
+
refresh_rule(#rule{id = RuleId, for = Topics, actions = Actions}) ->
ok = emqx_rule_metrics:create_rule_metrics(RuleId),
lists:foreach(fun emqx_rule_events:load/1, Topics),
diff --git a/apps/emqx_rule_engine/src/emqx_rule_events.erl b/apps/emqx_rule_engine/src/emqx_rule_events.erl
index f64e389d0..5406845d8 100644
--- a/apps/emqx_rule_engine/src/emqx_rule_events.erl
+++ b/apps/emqx_rule_engine/src/emqx_rule_events.erl
@@ -853,9 +853,25 @@ printable_maps(Headers) ->
value => Value
} || {Key, Value} <- V0]
};
+ (K, V, AccIn) when is_map(V) ->
+ AccIn#{K => printable_maps(V)};
+ (K, V, AccIn) when is_list(V) ->
+ AccIn#{K => printable_list(V)};
(_K, V, AccIn) when is_tuple(V) ->
- %% internal header
+ %% internal header, remove it
AccIn;
(K, V, AccIn) ->
AccIn#{K => V}
end, #{}, Headers).
+
+printable_list(L) ->
+ lists:filtermap(fun printable_element/1, L).
+
+printable_element(E) when is_map(E) ->
+ {true, printable_maps(E)};
+printable_element(E) when is_tuple(E) ->
+ false;
+printable_element(E) when is_list(E) ->
+ {true, printable_list(E)};
+printable_element(E) ->
+ {true, E}.
diff --git a/apps/emqx_rule_engine/src/emqx_rule_monitor.erl b/apps/emqx_rule_engine/src/emqx_rule_monitor.erl
index f45684053..4e4d4ebe1 100644
--- a/apps/emqx_rule_engine/src/emqx_rule_monitor.erl
+++ b/apps/emqx_rule_engine/src/emqx_rule_monitor.erl
@@ -33,16 +33,21 @@
, stop/0
, async_refresh_resources_rules/0
, ensure_resource_retrier/1
+ , ensure_rule_retrier/1
+ , retry_loop/2
, retry_loop/3
]).
-%% fot test
--export([ put_retry_interval/1
- , get_retry_interval/0
- , erase_retry_interval/0
+-export([ put_resource_retry_interval/1
+ , put_rule_retry_interval/1
+ , get_resource_retry_interval/0
+ , get_rule_retry_interval/0
+ , erase_resource_retry_interval/0
+ , erase_rule_retry_interval/0
]).
--define(T_RETRY, 60000).
+-define(T_RESOURCE_RETRY, 15000).
+-define(T_RULE_RETRY, 20000).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
@@ -54,23 +59,33 @@ init([]) ->
_ = erlang:process_flag(trap_exit, true),
{ok, #{retryers => #{}}}.
-put_retry_interval(I) when is_integer(I) andalso I >= 10 ->
+put_resource_retry_interval(I) when is_integer(I) andalso I >= 10 ->
_ = persistent_term:put({?MODULE, resource_restart_interval}, I),
ok.
-
-erase_retry_interval() ->
- _ = persistent_term:erase({?MODULE, resource_restart_interval}),
+put_rule_retry_interval(I) when is_integer(I) andalso I >= 10 ->
+ _ = persistent_term:put({?MODULE, rule_restart_interval}, I),
ok.
-get_retry_interval() ->
- persistent_term:get({?MODULE, resource_restart_interval}, ?T_RETRY).
+erase_resource_retry_interval() ->
+ _ = persistent_term:erase({?MODULE, resource_restart_interval}),
+ ok.
+erase_rule_retry_interval() ->
+ _ = persistent_term:erase({?MODULE, rule_restart_interval}),
+ ok.
+
+get_resource_retry_interval() ->
+ persistent_term:get({?MODULE, resource_restart_interval}, ?T_RESOURCE_RETRY).
+get_rule_retry_interval() ->
+ persistent_term:get({?MODULE, rule_restart_interval}, ?T_RULE_RETRY).
async_refresh_resources_rules() ->
gen_server:cast(?MODULE, async_refresh).
ensure_resource_retrier(ResId) ->
- Interval = get_retry_interval(),
- gen_server:cast(?MODULE, {create_restart_handler, resource, ResId, Interval}).
+ gen_server:cast(?MODULE, {create_restart_handler, resource, ResId}).
+
+ensure_rule_retrier(RuleId) ->
+ gen_server:cast(?MODULE, {create_restart_handler, rule, RuleId}).
handle_call(_Msg, _From, State) ->
{reply, ok, State}.
@@ -82,12 +97,12 @@ handle_cast(async_refresh, State) ->
Pid = spawn_link(fun do_async_refresh/0),
{noreply, State#{boot_refresh_pid => Pid}};
-handle_cast({create_restart_handler, Tag, Obj, Interval}, State) ->
+handle_cast({create_restart_handler, Tag, Obj}, State) ->
Objects = maps:get(Tag, State, #{}),
NewState = case maps:find(Obj, Objects) of
error ->
update_object(Tag, Obj,
- create_restart_handler(Tag, Obj, Interval), State);
+ create_restart_handler(Tag, Obj), State);
{ok, _Pid} ->
State
end,
@@ -130,13 +145,17 @@ update_object(Tag, Obj, Retryer, State) ->
retryers => Retryers#{Retryer => {Tag, Obj}}
}.
-create_restart_handler(Tag, Obj, Interval) ->
- ?LOG(info, "starting_a_retry_loop for ~p ~p, with delay interval: ~p", [Tag, Obj, Interval]),
+create_restart_handler(Tag, Obj) ->
+ ?LOG(warning, "starting_a_retry_loop for ~p ~p", [Tag, Obj]),
%% spawn a dedicated process to handle the restarting asynchronously
- spawn_link(?MODULE, retry_loop, [Tag, Obj, Interval]).
+ spawn_link(?MODULE, retry_loop, [Tag, Obj]).
-retry_loop(resource, ResId, Interval) ->
- timer:sleep(Interval),
+%% retry_loop/3 is to avoid crashes during relup
+retry_loop(Tag, ResId, _Interval) ->
+ retry_loop(Tag, ResId).
+
+retry_loop(resource, ResId) ->
+ timer:sleep(get_resource_retry_interval()),
case emqx_rule_registry:find_resource(ResId) of
{ok, #resource{type = Type, config = Config}} ->
try
@@ -154,10 +173,30 @@ retry_loop(resource, ResId, Interval) ->
end,
?LOG_SENSITIVE(warning, "init_resource_retry_failed ~p, ~0p", [ResId, LogContext]),
%% keep looping
- ?MODULE:retry_loop(resource, ResId, Interval)
+ ?MODULE:retry_loop(resource, ResId)
end;
not_found ->
ok
+ end;
+
+retry_loop(rule, RuleId) ->
+ timer:sleep(get_rule_retry_interval()),
+ case emqx_rule_registry:get_rule(RuleId) of
+ {ok, #rule{enabled = false, state = refresh_failed_at_bootup} = Rule} ->
+ try
+ emqx_rule_engine:refresh_rule(Rule),
+ emqx_rule_registry:add_rule(Rule#rule{enabled = true, state = normal}),
+ ?LOG(warning, "rule ~s has been refreshed and re-enabled", [RuleId])
+ catch
+ Err:Reason:ST ->
+ ?LOG(warning, "init_rule failed: ~p, ~0p",
+ [{Err, Reason}, ST]),
+ ?MODULE:retry_loop(rule, RuleId)
+ end;
+ {ok, #rule{enabled = false, state = State}} when State =/= refresh_failed_at_bootup ->
+ ?LOG(warning, "rule ~s was disabled by the user, won't re-enable it", [RuleId]);
+ _ ->
+ ok
end.
do_async_refresh() ->
@@ -171,6 +210,6 @@ refresh_and_enable_rules_of_resource(ResId) ->
fun (#rule{id = Id, enabled = false, state = refresh_failed_at_bootup} = Rule) ->
emqx_rule_engine:refresh_rule(Rule),
emqx_rule_registry:add_rule(Rule#rule{enabled = true, state = normal}),
- ?LOG(info, "rule ~s is refreshed and re-enabled", [Id]);
+ ?LOG(warning, "rule ~s is refreshed and re-enabled", [Id]);
(_) -> ok
end, emqx_rule_registry:find_rules_depends_on_resource(ResId)).
diff --git a/apps/emqx_rule_engine/test/emqx_rule_events_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_events_SUITE.erl
index 14376c91d..ec9fccab2 100644
--- a/apps/emqx_rule_engine/test/emqx_rule_events_SUITE.erl
+++ b/apps/emqx_rule_engine/test/emqx_rule_events_SUITE.erl
@@ -36,18 +36,44 @@ t_mod_hook_fun(_) ->
]].
t_printable_maps(_) ->
- Headers = #{peerhost => {127,0,0,1},
- peername => {{127,0,0,1}, 9980},
- sockname => {{127,0,0,1}, 1883},
- redispatch_to => {<<"group">>, <<"sub/topic/+">>},
- shared_dispatch_ack => {self(), ref}
- },
+ TestMap = #{
+ peerhost => {127,0,0,1},
+ peername => {{127,0,0,1}, 9980},
+ sockname => {{127,0,0,1}, 1883},
+ redispatch_to => {<<"group">>, <<"sub/topic/+">>},
+ shared_dispatch_ack => {self(), ref},
+ string => <<"abc">>,
+ atom => abc,
+ integer => 1,
+ float => 1.0,
+ simple_list => [1, 1.0, a, "abc", <<"abc">>, {a,b}]
+ },
+ Headers = TestMap#{
+ map => TestMap,
+ map_list => [
+ TestMap#{
+ map => TestMap
+ }
+ ]
+ },
Converted = emqx_rule_events:printable_maps(Headers),
- ?assertMatch(
- #{peerhost := <<"127.0.0.1">>,
- peername := <<"127.0.0.1:9980">>,
- sockname := <<"127.0.0.1:1883">>
- }, Converted),
- ?assertNot(maps:is_key(redispatch_to, Converted)),
- ?assertNot(maps:is_key(shared_dispatch_ack, Converted)),
+ Verify = fun(Result) ->
+ ?assertMatch(
+ #{peerhost := <<"127.0.0.1">>,
+ peername := <<"127.0.0.1:9980">>,
+ sockname := <<"127.0.0.1:1883">>,
+ string := <<"abc">>,
+ atom := abc,
+ integer := 1,
+ float := 1.0,
+ simple_list := [1, 1.0, a, "abc", <<"abc">>] %% {a,b} is removed
+ }, Result),
+ ?assertNot(maps:is_key(redispatch_to, Result)),
+ ?assertNot(maps:is_key(shared_dispatch_ack, Result)),
+ %% make sure the result is jsonable
+ _ = emqx_json:encode(Result)
+ end,
+ Verify(maps:get(map, Converted)),
+ Verify(maps:get(map, lists:nth(1, maps:get(map_list, Converted)))),
+ Verify(Converted),
ok.
diff --git a/apps/emqx_rule_engine/test/emqx_rule_monitor_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_monitor_SUITE.erl
index 2bab6c4d8..646f2644f 100644
--- a/apps/emqx_rule_engine/test/emqx_rule_monitor_SUITE.erl
+++ b/apps/emqx_rule_engine/test/emqx_rule_monitor_SUITE.erl
@@ -48,7 +48,7 @@ end_per_suite(_Config) ->
ok.
init_per_testcase(t_restart_resource, Config) ->
- emqx_rule_monitor:put_retry_interval(100),
+ emqx_rule_monitor:put_resource_retry_interval(100),
Opts = [public, named_table, set, {read_concurrency, true}],
_ = ets:new(?RES_PARAMS_TAB, [{keypos, #resource_params.id}|Opts]),
ets:new(t_restart_resource, [named_table, public]),
@@ -90,12 +90,13 @@ end_per_testcase(_, Config) ->
common_init_per_testcase() ->
AlarmOpts = [{actions, [log, publish]}, {size_limit, 1000}, {validity_period, 86400}],
+ _ = emqx_alarm:mnesia(boot),
{ok, _} = emqx_alarm:start_link(AlarmOpts),
{ok, _} = emqx_rule_monitor:start_link().
common_end_per_testcases() ->
ok = emqx_alarm:stop(),
- emqx_rule_monitor:erase_retry_interval(),
+ emqx_rule_monitor:erase_resource_retry_interval(),
emqx_rule_monitor:stop().
t_restart_resource(_) ->
diff --git a/apps/emqx_sn/rebar.config b/apps/emqx_sn/rebar.config
index 295751b23..4cb27511d 100644
--- a/apps/emqx_sn/rebar.config
+++ b/apps/emqx_sn/rebar.config
@@ -2,8 +2,7 @@
{plugins, [rebar3_proper]}.
{deps,
- [{esockd, {git, "https://github.com/emqx/esockd", {tag, "5.8.7"}}},
- {cuttlefish, {git, "https://github.com/emqx/cuttlefish", {tag, "v3.0.0"}}}
+ [{cuttlefish, {git, "https://github.com/emqx/cuttlefish", {tag, "v3.0.0"}}}
]}.
{edoc_opts, [{preprocess, true}]}.
diff --git a/build b/build
index 9cc68e531..59a237c46 100755
--- a/build
+++ b/build
@@ -205,6 +205,14 @@ make_zip() {
;;
esac
;;
+ ubuntu22)
+ case "$PKG_VSN" in
+ 4.4.15*)
+ # this is the first version for amzn2, no relup
+ has_relup='no'
+ ;;
+ esac
+ ;;
macos*)
case "$PKG_VSN" in
4.4.12*)
diff --git a/changes/v4.4.15-en.md b/changes/v4.4.15-en.md
index a5f438a9a..9502639e3 100644
--- a/changes/v4.4.15-en.md
+++ b/changes/v4.4.15-en.md
@@ -1,7 +1,53 @@
-
# v4.4.15
## Enhancements
+
- The MongoDB library has been upgraded to support MongoDB version 5.1 and greater.
+- Support HAProxy protocol for dashboard API [9803](https://github.com/emqx/emqx/pull/9803).
+
+- Added Ubuntu 22.04 package release [#9831](https://github.com/emqx/emqx/pull/9831).
+
+- Improve the integration of the `banned` and the `delayed` feature [#9790](https://github.com/emqx/emqx/pull/9790).
+ Now when publishing a delayed message will check first if its source client is banned, if true, this publish will be ignored.
+
+- Security enhancement for retained messages [#9790](https://github.com/emqx/emqx/pull/9790).
+ The retained messages will not be published if the publisher client is banned.
+
+- Now the corresponding session will be kicked when client is banned by `clientid` [#9904](https://github.com/emqx/emqx/pull/9904).
+
+- Add more debug logs for authentication and ACL [#9943](https://github.com/emqx/emqx/pull/9943).
+
+- Expose the stats `live_connections.count` and `live_connections.max` to Prometheus [#9929](https://github.com/emqx/emqx/pull/9929).
+
## Bug fixes
+
+- Fixed an error when forward MQTT messages with User-Property using the `republish` action [#9942](https://github.com/emqx/emqx/pull/9942).
+
+- fix some issues in descriptions of the actions, resources amd emqx-modules [#9931](https://github.com/emqx/emqx/pull/9931).
+
+- fix there's no error logs when query the JWKS server failed [#9931](https://github.com/emqx/emqx/pull/9931).
+
+- The returned client lists of HTTP query `GET /api/v4/clients?_page=2&_limit=20` to different nodes might be inconsistent [#9926](https://github.com/emqx/emqx/pull/9926).
+
+- Fix the problem that new MQTT TLS connections failed to establish after release hot upgrade [#9810](https://github.com/emqx/emqx/pull/9810).
+ For more detailed information please see: [emqx/esockd#170](https://github.com/emqx/esockd/pull/170).
+
+- Fix a problem in the log message format of MQTT packets [#9858](https://github.com/emqx/emqx/pull/9858).
+ Before this fix, a comma was missing between the flags (DUP) of the fixed header
+ and the fields (ClientId) of the variable header:
+ ```
+ 2023-01-29T13:40:36.567692+08:00 [debug] 127.0.0.1:50393 [MQTT] RECV CONNECT(Q0, R0, D0ClientId=test_client, ... Password=undefined)
+ ```
+
+- Avoid crash logs in CoAP gateway when receiving liveness checking packets from Load Balancer [#9869](https://github.com/emqx/emqx/pull/9869).
+
+- Fix the exclusive topics aren't removed when the session has already been cleaned [#9868](https://github.com/emqx/emqx/pull/9868).
+
+- fix the emqx reports `{case_clause,{error,closed}}` error log message when websocket connections interrupted [emqx/cowboy#8](https://github.com/emqx/cowboy/pull/8).
+
+- fix sometimes the rules cannot be enabled automatically after emqx is restarted [#9911](https://github.com/emqx/emqx/pull/9911).
+
+- fix the `{badarg,[{ets,lookup,[gproc,{shared, ...` error logs during shutdown [#9919](https://github.com/emqx/emqx/pull/9919).
+
+- Fix crash when updating a client's keepalive via the HTTP API if it connects with keepalive disabled [#9933](https://github.com/emqx/emqx/pull/9933).
diff --git a/changes/v4.4.15-zh.md b/changes/v4.4.15-zh.md
index b97382510..1fab3657b 100644
--- a/changes/v4.4.15-zh.md
+++ b/changes/v4.4.15-zh.md
@@ -2,6 +2,53 @@
## 增强
-- MongoDB库已升级至支持MongoDB 5.1及以上版本[#9707](https://github.com/emqx/emqx/pull/9707)。
+## 修复
+
+- MongoDB 库已升级至支持 MongoDB 5.1 及以上版本[#9707](https://github.com/emqx/emqx/pull/9707)。
+
+- 现在 dashboard 支持 `HAProxy` 协议了 [9803](https://github.com/emqx/emqx/pull/9803)。
+
+- 发布 Ubuntu 22.04 安装包 [#9831](https://github.com/emqx/emqx/pull/9831)。
+
+- 增强 `封禁` 和 `延迟消息` 这两个功能的集成性 [#9790](https://github.com/emqx/emqx/pull/9790)。
+ 现在发送延迟消息前,会先检查消息的来源客户端是否被封禁了,如果是,这条延迟消息将会被忽略。
+
+- 增强 `保留消息` 的安全性 [#9790](https://github.com/emqx/emqx/pull/9790)。
+ 现在投递保留消息前,会先过滤掉来源客户端被封禁了的那些消息。
+
+- 现在客户端通过 `clientid` 被封禁时将会踢掉对应的会话 [#9904](https://github.com/emqx/emqx/pull/9904)。
+
+- 为认证和授权添加了更多调试日志 [#9943](https://github.com/emqx/emqx/pull/9943)。
+
+- 将统计数据 `live_connections.count` 和 `live_connections.max` 公开给 Prometheus [#9929](https://github.com/emqx/emqx/pull/9929).
## 修复
+
+- 修复使用 `消息重发布` 动作转发带 User-Property 的 MQTT 消息时出错的问题 [#9942](https://github.com/emqx/emqx/pull/9942)。
+
+- 修复资源、动作以及模块里的一些描述错误 [#9931](https://github.com/emqx/emqx/pull/9931)。
+
+- 修复请求 JWKS 服务失败的时候,没有日志打印的问题 [#9931](https://github.com/emqx/emqx/pull/9931)。
+
+- 使用 HTTP API `GET /api/v4/clients?_page=2&_limit=20` 请求客户端列表时,请求发送到不同的 emqx 节点,返回的客户端列表可能不一致 [#9926](https://github.com/emqx/emqx/pull/9926)。
+
+- 修复版本热升级之后,新的 MQTT TLS 连接建立失败的问题 [#9810](https://github.com/emqx/emqx/pull/9810)。
+ 详情见:[emqx/esockd#170](https://github.com/emqx/esockd/pull/170)
+
+- 修复 MQTT 报文的日志打印格式的问题 [#9858](https://github.com/emqx/emqx/pull/9858)。
+ 在此修复之前,固定报文头的标志位(DUP)和后面的可变报文头的字段(ClientId)之间漏掉了一个逗号做分隔:
+ ```
+ 2023-01-29T13:40:36.567692+08:00 [debug] 127.0.0.1:50393 [MQTT] RECV CONNECT(Q0, R0, D0ClientId=test_client, ... Password=undefined)
+ ```
+
+- 修复 CoAP 网关在收到负载均衡的心跳检查报文时产生的崩溃日志 [#9869](https://github.com/emqx/emqx/pull/9869)。
+
+- 修复会话关闭后,其持有的排他订阅主题没有被释放的问题 [#9868](https://github.com/emqx/emqx/pull/9868)。
+
+- 修复 Websocket 连接中断时日志报 `{case_clause,{error,closed}}` 错误的问题 [emqx/cowboy#8](https://github.com/emqx/cowboy/pull/8)。
+
+- 修复某些情况下,重启 emqx 后规则无法自动启用的问题 [#9911](https://github.com/emqx/emqx/pull/9911)。
+
+- 修复停止 emqx 的时候,日志出现 `{badarg,[{ets,lookup,[gproc,{shared, ...` 错误的问题 [#9919](https://github.com/emqx/emqx/pull/9919)。
+
+- 修复当客户端连接禁用 keepalive时, 通过 HTTP API 更新其 keepalive 会崩溃的问题 [#9933](https://github.com/emqx/emqx/pull/9933)。
diff --git a/deploy/charts/emqx/README.md b/deploy/charts/emqx/README.md
index 2882f9e0d..89b06616a 100644
--- a/deploy/charts/emqx/README.md
+++ b/deploy/charts/emqx/README.md
@@ -40,6 +40,9 @@ Parameter | Description | Default Value
`image.pullPolicy` | The image pull policy | `IfNotPresent`
`image.pullSecrets ` | The image pull secrets (does not add image pull secrets to deployed pods) |``[]``
`recreatePods` | Forces the recreation of pods during upgrades, which can be useful to always apply the most recent configuration. | `false`
+`serviceAccount.create` | If `true`, create a new service account | `true`
+`serviceAccount.name` | Service account to be used. If not set and `serviceAccount.create` is `true`, a name is generated using the fullname template |
+`serviceAccount.annotations` | Annotations to add to the service account |
`podAnnotations ` | Annotations for pod | `{}`
`podManagementPolicy`| To redeploy a chart with existing PVC(s), the value must be set to Parallel to avoid deadlock | `Parallel`
`persistence.enabled` | Enable EMQX persistence using PVC | `false`
diff --git a/deploy/charts/emqx/templates/StatefulSet.yaml b/deploy/charts/emqx/templates/StatefulSet.yaml
index 3234fb85a..91f93d2c5 100644
--- a/deploy/charts/emqx/templates/StatefulSet.yaml
+++ b/deploy/charts/emqx/templates/StatefulSet.yaml
@@ -64,6 +64,7 @@ spec:
checksum/config: {{ $configData | sha256sum | quote }}
{{- end }}
spec:
+ serviceAccountName: {{ include "emqx.serviceAccountName" . }}
volumes:
{{- if .Values.emqxLoadedPlugins }}
- name: emqx-loaded-plugins
@@ -107,9 +108,6 @@ spec:
secret:
secretName: {{ $licenseSecretName }}
{{- end }}
- {{- if eq (.Values.emqxConfig.EMQX_CLUSTER__DISCOVERY | default "k8s") "k8s" }}
- serviceAccountName: {{ include "emqx.fullname" . }}
- {{- end }}
{{- if .Values.podSecurityContext.enabled }}
securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }}
{{- end }}
diff --git a/deploy/charts/emqx/templates/_helpers.tpl b/deploy/charts/emqx/templates/_helpers.tpl
index ad01d5862..3f6d055e4 100644
--- a/deploy/charts/emqx/templates/_helpers.tpl
+++ b/deploy/charts/emqx/templates/_helpers.tpl
@@ -30,3 +30,14 @@ Create chart name and version as used by the chart label.
{{- define "emqx.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "emqx.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "emqx.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/deploy/charts/emqx/templates/rbac.yaml b/deploy/charts/emqx/templates/rbac.yaml
index cbd3b4f7b..b35666f44 100644
--- a/deploy/charts/emqx/templates/rbac.yaml
+++ b/deploy/charts/emqx/templates/rbac.yaml
@@ -1,10 +1,23 @@
-{{- if eq (.Values.emqxConfig.EMQX_CLUSTER__DISCOVERY | default "k8s") "k8s" }}
+{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: {{ .Release.Namespace }}
- name: {{ include "emqx.fullname" . }}
+ name: {{ include "emqx.serviceAccountName" . }}
+ labels:
+ app.kubernetes.io/name: {{ include "emqx.name" . }}
+ helm.sh/chart: {{ include "emqx.chart" . }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/managed-by: {{ .Release.Service }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
+
---
+{{- if .Values.serviceAccount.create }}
+{{- if eq (.Values.emqxConfig.EMQX_CLUSTER__DISCOVERY | default "k8s") "k8s" }}
kind: Role
{{- if semverCompare ">=1.17-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: rbac.authorization.k8s.io/v1
@@ -23,7 +36,12 @@ rules:
- get
- watch
- list
+{{- end }}
+{{- end }}
+
---
+{{- if .Values.serviceAccount.create }}
+{{- if eq (.Values.emqxConfig.EMQX_CLUSTER__DISCOVERY | default "k8s") "k8s" }}
kind: RoleBinding
{{- if semverCompare ">=1.17-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: rbac.authorization.k8s.io/v1
@@ -35,10 +53,11 @@ metadata:
name: {{ include "emqx.fullname" . }}
subjects:
- kind: ServiceAccount
- name: {{ include "emqx.fullname" . }}
+ name: {{ include "emqx.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: Role
name: {{ include "emqx.fullname" . }}
apiGroup: rbac.authorization.k8s.io
{{- end }}
+{{- end }}
diff --git a/deploy/charts/emqx/values.yaml b/deploy/charts/emqx/values.yaml
index 1df94e42d..64a74cff5 100644
--- a/deploy/charts/emqx/values.yaml
+++ b/deploy/charts/emqx/values.yaml
@@ -14,6 +14,16 @@ image:
# pullSecrets:
# - myRegistryKeySecretName
+serviceAccount:
+ # Specifies whether a service account should be created
+ # If set false, means you need create service account by yourself
+ create: true
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: ""
+ # Annotations to add to the service account
+ annotations: {}
+
## Forces the recreation of pods during helm upgrades. This can be useful to update configuration values even if the container image did not change.
recreatePods: false
diff --git a/lib-ce/emqx_modules/src/emqx_mod_acl_internal.erl b/lib-ce/emqx_modules/src/emqx_mod_acl_internal.erl
index 044a4e80d..e36b056f9 100644
--- a/lib-ce/emqx_modules/src/emqx_mod_acl_internal.erl
+++ b/lib-ce/emqx_modules/src/emqx_mod_acl_internal.erl
@@ -57,7 +57,7 @@ reload(Env) ->
unload(Env), load(Env).
description() ->
- "EMQ X Internal ACL Module".
+ "EMQX Internal ACL Module".
%%--------------------------------------------------------------------
%% ACL callbacks
%%--------------------------------------------------------------------
diff --git a/lib-ce/emqx_modules/src/emqx_mod_delayed.erl b/lib-ce/emqx_modules/src/emqx_mod_delayed.erl
index 14d91f4b3..62c0c5132 100644
--- a/lib-ce/emqx_modules/src/emqx_mod_delayed.erl
+++ b/lib-ce/emqx_modules/src/emqx_mod_delayed.erl
@@ -21,6 +21,7 @@
-include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/logger.hrl").
+-include_lib("snabbkaffe/include/snabbkaffe.hrl").
-logger_header("[Delayed]").
@@ -94,7 +95,7 @@ unload(_Env) ->
emqx_mod_sup:stop_child(?MODULE).
description() ->
- "EMQ X Delayed Publish Module".
+ "EMQX Delayed Publish Module".
%%--------------------------------------------------------------------
%% Hooks
%%--------------------------------------------------------------------
@@ -228,7 +229,20 @@ do_publish(Key = {Ts, _Id}, Now, Acc) when Ts =< Now ->
case mnesia:dirty_read(?TAB, Key) of
[] -> ok;
[#delayed_message{msg = Msg}] ->
- emqx_pool:async_submit(fun emqx:publish/1, [Msg])
+ case emqx_banned:look_up({clientid, Msg#message.from}) of
+ [] ->
+ emqx_pool:async_submit(fun emqx:publish/1, [Msg]);
+ _ ->
+ ?tp(
+ notice,
+ ignore_delayed_message_publish,
+ #{
+ reason => "client is banned",
+ clienid => Msg#message.from
+ }
+ ),
+ ok
+ end
end,
do_publish(mnesia:dirty_next(?TAB, Key), Now, [Key|Acc]).
diff --git a/lib-ce/emqx_modules/src/emqx_mod_presence.erl b/lib-ce/emqx_modules/src/emqx_mod_presence.erl
index eb1019a76..b73a2b8d1 100644
--- a/lib-ce/emqx_modules/src/emqx_mod_presence.erl
+++ b/lib-ce/emqx_modules/src/emqx_mod_presence.erl
@@ -46,7 +46,7 @@ unload(_Env) ->
emqx_hooks:del('client.disconnected', {?MODULE, on_client_disconnected}).
description() ->
- "EMQ X Presence Module".
+ "EMQX Presence Module".
%%--------------------------------------------------------------------
%% Callbacks
%%--------------------------------------------------------------------
diff --git a/lib-ce/emqx_modules/src/emqx_mod_rewrite.erl b/lib-ce/emqx_modules/src/emqx_mod_rewrite.erl
index e40c1f3b9..c21211d78 100644
--- a/lib-ce/emqx_modules/src/emqx_mod_rewrite.erl
+++ b/lib-ce/emqx_modules/src/emqx_mod_rewrite.erl
@@ -71,7 +71,7 @@ unload(_) ->
emqx_hooks:del('message.publish', {?MODULE, rewrite_publish}).
description() ->
- "EMQ X Topic Rewrite Module".
+ "EMQX Topic Rewrite Module".
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
diff --git a/lib-ce/emqx_modules/src/emqx_mod_slow_subs.erl b/lib-ce/emqx_modules/src/emqx_mod_slow_subs.erl
index 199f130f0..cb6d55509 100644
--- a/lib-ce/emqx_modules/src/emqx_mod_slow_subs.erl
+++ b/lib-ce/emqx_modules/src/emqx_mod_slow_subs.erl
@@ -46,4 +46,4 @@ unload(_Env) ->
ok.
description() ->
- "EMQ X Slow Subscribers Statistics Module".
+ "EMQX Slow Subscribers Statistics Module".
diff --git a/lib-ce/emqx_modules/src/emqx_mod_subscription.erl b/lib-ce/emqx_modules/src/emqx_mod_subscription.erl
index 8b8851ea9..2fc5048a5 100644
--- a/lib-ce/emqx_modules/src/emqx_mod_subscription.erl
+++ b/lib-ce/emqx_modules/src/emqx_mod_subscription.erl
@@ -71,7 +71,7 @@ unload(_) ->
emqx_hooks:del('client.connected', {?MODULE, on_client_connected}).
description() ->
- "EMQ X Subscription Module".
+ "EMQX Subscription Module".
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
diff --git a/lib-ce/emqx_modules/src/emqx_mod_topic_metrics.erl b/lib-ce/emqx_modules/src/emqx_mod_topic_metrics.erl
index f28b9bce0..71ad1cb80 100644
--- a/lib-ce/emqx_modules/src/emqx_mod_topic_metrics.erl
+++ b/lib-ce/emqx_modules/src/emqx_mod_topic_metrics.erl
@@ -113,7 +113,7 @@ unload(_Env) ->
emqx_mod_sup:stop_child(?MODULE).
description() ->
- "EMQ X Topic Metrics Module".
+ "EMQX Topic Metrics Module".
on_message_publish(#message{topic = Topic, qos = QoS}) ->
case is_registered(Topic) of
diff --git a/lib-ce/emqx_modules/src/emqx_mod_trace.erl b/lib-ce/emqx_modules/src/emqx_mod_trace.erl
index d57296136..012dc9e73 100644
--- a/lib-ce/emqx_modules/src/emqx_mod_trace.erl
+++ b/lib-ce/emqx_modules/src/emqx_mod_trace.erl
@@ -28,7 +28,7 @@
-spec description() -> string().
description() ->
- "EMQ X Trace Module".
+ "EMQX Trace Module".
-spec load(any()) -> ok.
load(_Env) ->
diff --git a/lib-ce/emqx_modules/src/emqx_modules.app.src b/lib-ce/emqx_modules/src/emqx_modules.app.src
index 05c9a73ec..a2694a5e6 100644
--- a/lib-ce/emqx_modules/src/emqx_modules.app.src
+++ b/lib-ce/emqx_modules/src/emqx_modules.app.src
@@ -1,6 +1,6 @@
{application, emqx_modules,
[{description, "EMQ X Module Management"},
- {vsn, "4.4.8"},
+ {vsn, "4.4.9"},
{modules, []},
{applications, [kernel,stdlib]},
{mod, {emqx_modules_app, []}},
diff --git a/lib-ce/emqx_modules/src/emqx_modules.appup.src b/lib-ce/emqx_modules/src/emqx_modules.appup.src
index 0abd3a3e9..3e1f7fb5d 100644
--- a/lib-ce/emqx_modules/src/emqx_modules.appup.src
+++ b/lib-ce/emqx_modules/src/emqx_modules.appup.src
@@ -1,81 +1,75 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
- [{"4.4.7",[{load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]}]},
- {"4.4.6",
- [{load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]}]},
- {"4.4.5",
- [{load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]}]},
- {"4.4.4",
- [{load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]}]},
- {"4.4.3",
- [{load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]}]},
- {"4.4.2",
- [{load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]}]},
- {"4.4.1",
- [{load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_subscription,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]}]},
- {"4.4.0",
- [{load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_subscription,brutal_purge,soft_purge,[]},
+ [{<<"4\\.4\\.[6-8]">>,
+ [{load_module,emqx_mod_acl_internal,brutal_purge,soft_purge,[]},
{load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
{load_module,emqx_mod_presence,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_sup,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]}]},
+ {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_slow_subs,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_subscription,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_topic_metrics,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_trace,brutal_purge,soft_purge,[]}
+ ]},
+ {<<"4\\.4\\.[1-5]">>,
+ [{load_module,emqx_mod_acl_internal,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_presence,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_slow_subs,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_subscription,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_topic_metrics,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_trace,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]},
+ {load_module,emqx_modules,brutal_purge,soft_purge,[]}
+ ]},
+ {"4.4.0",
+ [{load_module,emqx_mod_acl_internal,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_presence,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_slow_subs,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_subscription,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_topic_metrics,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_trace,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]},
+ {load_module,emqx_modules,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_sup,brutal_purge,soft_purge,[]}
+ ]},
{<<".*">>,[]}],
- [{"4.4.7",[{load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]}]},
- {"4.4.6",
- [{load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]}]},
- {"4.4.5",
- [{load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]}]},
- {"4.4.4",
- [{load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]}]},
- {"4.4.3",
- [{load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]}]},
- {"4.4.2",
- [{load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]}]},
- {"4.4.1",
- [{load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_subscription,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]}]},
- {"4.4.0",
- [{load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
- {load_module,emqx_modules,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_subscription,brutal_purge,soft_purge,[]},
+ [{<<"4\\.4\\.[6-8]">>,
+ [{load_module,emqx_mod_acl_internal,brutal_purge,soft_purge,[]},
{load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
{load_module,emqx_mod_presence,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_sup,brutal_purge,soft_purge,[]},
- {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]}]},
+ {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_slow_subs,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_subscription,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_topic_metrics,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_trace,brutal_purge,soft_purge,[]}
+ ]},
+ {<<"4\\.4\\.[1-5]">>,
+ [{load_module,emqx_mod_acl_internal,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_presence,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_slow_subs,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_subscription,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_topic_metrics,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_trace,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]},
+ {load_module,emqx_modules,brutal_purge,soft_purge,[]}
+ ]},
+ {"4.4.0",
+ [{load_module,emqx_mod_acl_internal,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_delayed,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_presence,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_slow_subs,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_subscription,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_topic_metrics,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_trace,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_trace_api,brutal_purge,soft_purge,[]},
+ {load_module,emqx_modules,brutal_purge,soft_purge,[]},
+ {load_module,emqx_mod_sup,brutal_purge,soft_purge,[]}
+ ]},
{<<".*">>,[]}]}.
diff --git a/lib-ce/emqx_modules/test/emqx_mod_delayed_SUITE.erl b/lib-ce/emqx_modules/test/emqx_mod_delayed_SUITE.erl
index 306a1a03d..715e541f0 100644
--- a/lib-ce/emqx_modules/test/emqx_mod_delayed_SUITE.erl
+++ b/lib-ce/emqx_modules/test/emqx_mod_delayed_SUITE.erl
@@ -26,6 +26,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
-include_lib("emqx/include/emqx.hrl").
+-include_lib("snabbkaffe/include/snabbkaffe.hrl").
%%--------------------------------------------------------------------
%% Setups
@@ -78,3 +79,46 @@ t_delayed_message(_) ->
EmptyKey = mnesia:dirty_all_keys(emqx_mod_delayed),
?assertEqual([], EmptyKey),
ok = emqx_mod_delayed:unload([]).
+
+t_banned_delayed(_) ->
+ ok = emqx_mod_delayed:load([]),
+ ClientId1 = <<"bc1">>,
+ ClientId2 = <<"bc2">>,
+
+ Now = erlang:system_time(second),
+ Who = {clientid, ClientId2},
+ emqx_banned:create(#{
+ who => Who,
+ by => <<"test">>,
+ reason => <<"test">>,
+ at => Now,
+ until => Now + 120
+ }),
+
+ snabbkaffe:start_trace(),
+
+ {ok, SubRef} =
+ snabbkaffe_collector:subscribe(?match_event(#{?snk_kind := ignore_delayed_message_publish}),
+ _NEvents = 2,
+ _Timeout = 10000,
+ 0),
+
+ lists:foreach(
+ fun(ClientId) ->
+ Msg = emqx_message:make(ClientId, <<"$delayed/1/bc">>, <<"payload">>),
+ emqx_mod_delayed:on_message_publish(Msg)
+ end,
+ [ClientId1, ClientId1, ClientId1, ClientId2, ClientId2]
+ ),
+
+ ?assertMatch({ok, [#{?snk_kind := ignore_delayed_message_publish},
+ #{?snk_kind := ignore_delayed_message_publish}
+ ]},
+ snabbkaffe_collector:receive_events(SubRef)),
+
+ snabbkaffe:stop(),
+
+ emqx_banned:delete(Who),
+ EmptyKey = mnesia:dirty_all_keys(emqx_mod_delayed),
+ ?assertEqual([], EmptyKey),
+ ok = emqx_mod_delayed:unload([]).
diff --git a/rebar.config b/rebar.config
index d4e83da4d..f79883957 100644
--- a/rebar.config
+++ b/rebar.config
@@ -41,19 +41,19 @@
[ {gpb, "4.11.2"} %% gpb only used to build, but not for release, pin it here to avoid fetching a wrong version due to rebar plugins scattered in all the deps
, {redbug, "2.0.7"}
, {covertool, {git, "https://github.com/zmstone/covertool", {tag, "2.0.4.1"}}}
- , {ehttpc, {git, "https://github.com/emqx/ehttpc", {tag, "0.4.2"}}}
+ , {ehttpc, {git, "https://github.com/emqx/ehttpc", {tag, "0.4.4"}}}
, {gun, {git, "https://github.com/emqx/gun", {tag, "1.3.8"}}}
, {eredis_cluster, {git, "https://github.com/emqx/eredis_cluster", {tag, "0.7.4"}}}
, {gproc, {git, "https://github.com/uwiger/gproc", {tag, "0.9.0"}}}
, {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.5"}}}
- , {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.9.0"}}}
- , {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.8.7"}}}
+ , {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.9.1"}}}
+ , {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.8.8"}}}
, {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.8.1.11"}}}
, {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "3.0.1"}}}
, {cuttlefish, {git, "https://github.com/emqx/cuttlefish", {tag, "v3.3.6"}}}
- , {minirest, {git, "https://github.com/emqx/minirest", {tag, "0.3.10"}}}
+ , {minirest, {git, "https://github.com/emqx/minirest", {tag, "0.3.11"}}}
, {ecpool, {git, "https://github.com/emqx/ecpool", {tag, "0.5.2"}}}
- , {replayq, {git, "https://github.com/emqx/replayq", {tag, "0.3.4"}}}
+ , {replayq, {git, "https://github.com/emqx/replayq", {tag, "0.3.5"}}}
, {pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {branch, "2.0.4"}}}
, {emqtt, {git, "https://github.com/emqx/emqtt", {tag, "1.2.3.1"}}}
, {rulesql, {git, "https://github.com/emqx/rulesql", {tag, "0.1.5"}}}
@@ -63,6 +63,7 @@
, {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "1.0.3"}}}
, {lc, {git, "https://github.com/emqx/lc.git", {tag, "0.3.2"}}}
, {mongodb, {git,"https://github.com/emqx/mongodb-erlang", {tag, "v3.0.19"}}}
+ , {mysql, {git, "https://github.com/emqx/mysql-otp", {tag, "1.7.2"}}}
, {epgsql, {git, "https://github.com/emqx/epgsql.git", {tag, "4.6.0"}}}
, {grpc, {git, "https://github.com/emqx/grpc-erl", {tag, "0.6.7"}}}
]}.
diff --git a/scripts/relup-base-vsns.escript b/scripts/relup-base-vsns.escript
index e99c88a9f..5a4a0483d 100755
--- a/scripts/relup-base-vsns.escript
+++ b/scripts/relup-base-vsns.escript
@@ -176,6 +176,11 @@ filter_froms(Froms0, AvailableVersionsIndex) ->
{"amzn2", _} ->
Excluded = [list_to_binary(["4.4.", integer_to_list(X)]) || X <- lists:seq(0,11)],
lists:filter(fun(Vsn) -> not lists:member(Vsn, Excluded) end, Froms0);
+ %% ubuntu22.04 is introduced since v4.4.15 and e4.4.15
+ %% exclude tags before them
+ {"ubuntu22.04", _} ->
+ Excluded = [list_to_binary(["4.4.", integer_to_list(X)]) || X <- lists:seq(0,14)],
+ lists:filter(fun(Vsn) -> not lists:member(Vsn, Excluded) end, Froms0);
%% macos arm64 (M1/M2) packages are introduced since v4.4.12 and e4.4.12
%% exclude tags before them
{"macos" ++ _, "aarch64" ++ _} ->
diff --git a/src/emqx.appup.src b/src/emqx.appup.src
index ebb567dbd..3711c84d5 100644
--- a/src/emqx.appup.src
+++ b/src/emqx.appup.src
@@ -2,23 +2,57 @@
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
[{"4.4.14",
- [{load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ {load_module,emqx_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_ws_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
+ {load_module,emqx,brutal_purge,soft_purge,[]},
+ {load_module,emqx_relup,brutal_purge,soft_purge,[]},
+ {load_module,emqx_app,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]}]},
{"4.4.13",
- [{load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ {load_module,emqx_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_ws_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_cm,brutal_purge,soft_purge,[]},
+ {load_module,emqx,brutal_purge,soft_purge,[]},
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}]},
{"4.4.12",
- [{load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ {load_module,emqx_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_ws_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_cm,brutal_purge,soft_purge,[]},
+ {load_module,emqx,brutal_purge,soft_purge,[]},
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}]},
{"4.4.11",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_ws_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
+ {load_module,emqx,brutal_purge,soft_purge,[]},
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_misc,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]},
@@ -26,7 +60,12 @@
{load_module,emqx_session,brutal_purge,soft_purge,[]},
{load_module,emqx_channel,brutal_purge,soft_purge,[]}]},
{"4.4.10",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
{add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache},
@@ -47,7 +86,12 @@
{apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.9",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
{add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache},
@@ -74,7 +118,12 @@
{apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.8",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
{add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache},
@@ -102,7 +151,12 @@
{apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.7",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
{add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache},
@@ -130,7 +184,12 @@
{apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.6",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
{add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache},
@@ -158,7 +217,12 @@
{apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.5",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
{add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache},
@@ -188,7 +252,11 @@
{apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.4",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
{add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache},
@@ -225,7 +293,10 @@
{apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.3",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
{add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache},
@@ -269,7 +340,10 @@
{apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.2",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
{add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache},
@@ -314,7 +388,9 @@
{apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.1",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
{add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache},
@@ -364,7 +440,9 @@
{apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.0",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{add_module,emqx_cover},
{add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache},
@@ -417,22 +495,56 @@
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{<<".*">>,[]}],
[{"4.4.14",
- [{load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ {load_module,emqx_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_ws_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
+ {load_module,emqx,brutal_purge,soft_purge,[]},
+ {load_module,emqx_relup,brutal_purge,soft_purge,[]},
+ {load_module,emqx_app,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]}]},
{"4.4.13",
- [{load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ {load_module,emqx_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_ws_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_cm,brutal_purge,soft_purge,[]},
+ {load_module,emqx,brutal_purge,soft_purge,[]},
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}]},
{"4.4.12",
- [{load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_misc,brutal_purge,soft_purge,[]},
+ {load_module,emqx_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_ws_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_cm,brutal_purge,soft_purge,[]},
+ {load_module,emqx,brutal_purge,soft_purge,[]},
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}]},
{"4.4.11",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_ws_connection,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
+ {load_module,emqx,brutal_purge,soft_purge,[]},
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]},
{load_module,emqx_misc,brutal_purge,soft_purge,[]},
@@ -441,7 +553,12 @@
{load_module,emqx_session,brutal_purge,soft_purge,[]},
{delete_module,emqx_cover}]},
{"4.4.10",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{load_module,emqx_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,brutal_purge,soft_purge,[]},
@@ -459,7 +576,12 @@
{delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]},
{"4.4.9",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{load_module,emqx_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,brutal_purge,soft_purge,[]},
@@ -482,7 +604,12 @@
{delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]},
{"4.4.8",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{load_module,emqx_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,brutal_purge,soft_purge,[]},
@@ -506,7 +633,12 @@
{delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]},
{"4.4.7",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{load_module,emqx_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,brutal_purge,soft_purge,[]},
@@ -530,7 +662,12 @@
{delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]},
{"4.4.6",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{load_module,emqx_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,brutal_purge,soft_purge,[]},
@@ -554,7 +691,12 @@
{delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]},
{"4.4.5",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_broker,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{load_module,emqx_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,brutal_purge,soft_purge,[]},
@@ -580,7 +722,11 @@
{delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]},
{"4.4.4",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ {load_module,emqx_packet,brutal_purge,soft_purge,[]},
{load_module,emqx_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_hooks,brutal_purge,soft_purge,[]},
@@ -613,7 +759,10 @@
{delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]},
{"4.4.3",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_hooks,brutal_purge,soft_purge,[]},
@@ -652,7 +801,10 @@
{delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]},
{"4.4.2",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_banned,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_router_helper,brutal_purge,soft_purge,[]},
@@ -692,7 +844,9 @@
{delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]},
{"4.4.1",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_router_helper,brutal_purge,soft_purge,[]},
{load_module,emqx_ws_connection,brutal_purge,soft_purge,[]},
@@ -737,7 +891,9 @@
{delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]},
{"4.4.0",
- [{load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
+ [{load_module,emqx_vm,brutal_purge,soft_purge,[]},
+ {load_module,emqx_keepalive,brutal_purge,soft_purge,[]},
+ {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_router_helper,brutal_purge,soft_purge,[]},
{load_module,emqx_router,brutal_purge,soft_purge,[]},
diff --git a/src/emqx.erl b/src/emqx.erl
index a9a378080..85d154023 100644
--- a/src/emqx.erl
+++ b/src/emqx.erl
@@ -65,6 +65,8 @@
%% Troubleshooting
-export([ set_debug_secret/1
+ , default_started_applications/0
+ , expand_apps/1
]).
-define(APP, ?MODULE).
@@ -252,14 +254,6 @@ is_application_running(App) ->
StartedApps = proplists:get_value(started, application:info()),
proplists:is_defined(App, StartedApps).
--ifdef(EMQX_ENTERPRISE).
-default_started_applications() ->
- [gproc, esockd, ranch, cowboy, ekka, emqx].
--else.
-default_started_applications() ->
- [gproc, esockd, ranch, cowboy, ekka, emqx, emqx_modules].
--endif.
-
-ifdef(EMQX_ENTERPRISE).
on_reboot() ->
try
@@ -290,6 +284,54 @@ on_shutdown(_) ->
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
+-ifdef(EMQX_ENTERPRISE).
+applications_need_restart() ->
+ [gproc, esockd, ranch, cowboy, ekka, emqx].
+-else.
+applications_need_restart() ->
+ [gproc, esockd, ranch, cowboy, ekka, emqx, emqx_modules].
+-endif.
+
+-define(PK_START_APPS, {?MODULE, default_started_applications}).
+default_started_applications() ->
+ case persistent_term:get(?PK_START_APPS, undefined) of
+ undefined ->
+ AppNames = expand_apps(applications_need_restart()),
+ ok = persistent_term:put(?PK_START_APPS, AppNames),
+ AppNames;
+ AppNames ->
+ AppNames
+ end.
+
+%% expand the application list with dependent apps.
+expand_apps(AppNames) ->
+ AllApps = application:which_applications(),
+ remove_duplicated(
+ lists:flatmap(fun(AppName) ->
+ expand_an_app(AppName, AllApps)
+ end, AppNames)).
+
+expand_an_app(AppNameA, AllApps) ->
+ expand_an_app(AppNameA, AllApps, [AppNameA]).
+
+expand_an_app(_AppNameA, [], Acc) ->
+ Acc;
+expand_an_app(AppNameA, [{AppNameB, _Descr, _Vsn} | AllApps], Acc) ->
+ {ok, DepAppNames} = application:get_key(AppNameB, applications),
+ case lists:member(AppNameA, DepAppNames) of
+ true -> %% AppNameB depends on AppNameA
+ NewAcc = Acc ++ expand_an_app(AppNameB, AllApps),
+ expand_an_app(AppNameA, AllApps, NewAcc);
+ false ->
+ expand_an_app(AppNameA, AllApps, Acc)
+ end.
+
+remove_duplicated([]) -> [];
+remove_duplicated([E | Elems]) ->
+ case lists:member(E, Elems) of
+ true -> remove_duplicated(Elems);
+ false -> [E] ++ remove_duplicated(Elems)
+ end.
reload_config(ConfFile) ->
{ok, [Conf]} = file:consult(ConfFile),
diff --git a/src/emqx_banned.erl b/src/emqx_banned.erl
index 6cc1580be..ce5c9c2be 100644
--- a/src/emqx_banned.erl
+++ b/src/emqx_banned.erl
@@ -21,6 +21,7 @@
-include("emqx.hrl").
-include("logger.hrl").
-include("types.hrl").
+-include_lib("snabbkaffe/include/snabbkaffe.hrl").
-logger_header("[Banned]").
@@ -36,6 +37,7 @@
, create/1
, delete/1
, info/1
+ , look_up/1
]).
%% gen_server callbacks
@@ -94,13 +96,15 @@ create(#{who := Who,
reason := Reason,
at := At,
until := Until}) ->
- mnesia:dirty_write(?BANNED_TAB, #banned{who = Who,
- by = By,
- reason = Reason,
- at = At,
- until = Until});
+ insert_banned(#banned{
+ who = Who,
+ by = By,
+ reason = Reason,
+ at = At,
+ until = Until
+ });
create(Banned) when is_record(Banned, banned) ->
- mnesia:dirty_write(?BANNED_TAB, Banned).
+ insert_banned(Banned).
-spec(delete({clientid, emqx_types:clientid()}
| {username, emqx_types:username()}
@@ -111,6 +115,9 @@ delete(Who) ->
info(InfoKey) ->
mnesia:table_info(?BANNED_TAB, InfoKey).
+look_up(Who) ->
+ mnesia:dirty_read(?BANNED_TAB, Who).
+
%%--------------------------------------------------------------------
%% gen_server callbacks
%%--------------------------------------------------------------------
@@ -159,3 +166,20 @@ expire_banned_items(Now) ->
(_, _Acc) -> ok
end, ok, ?BANNED_TAB).
+insert_banned(Banned) ->
+ mnesia:dirty_write(?BANNED_TAB, Banned),
+ on_banned(Banned).
+
+on_banned(#banned{who = {clientid, ClientId}}) ->
+ %% kick the session if the client is banned by clientid
+ ?tp(
+ warning,
+ kick_session_due_to_banned,
+ #{
+ clientid => ClientId
+ }
+ ),
+ emqx_cm:kick_session(ClientId),
+ ok;
+on_banned(_) ->
+ ok.
diff --git a/src/emqx_broker.erl b/src/emqx_broker.erl
index 0fc9975cc..76e0997a1 100644
--- a/src/emqx_broker.erl
+++ b/src/emqx_broker.erl
@@ -183,8 +183,7 @@ do_unsubscribe(Topic, SubPid, SubOpts) ->
true = ets:delete(?SUBOPTION, {SubPid, Topic}),
true = ets:delete_object(?SUBSCRIPTION, {SubPid, Topic}),
Group = maps:get(share, SubOpts, undefined),
- do_unsubscribe(Group, Topic, SubPid, SubOpts),
- emqx_exclusive_subscription:unsubscribe(Topic, SubOpts).
+ do_unsubscribe(Group, Topic, SubPid, SubOpts).
do_unsubscribe(undefined, Topic, SubPid, SubOpts) ->
clean_subscribe(SubOpts, Topic, SubPid);
@@ -344,9 +343,12 @@ subscriber_down(SubPid) ->
clean_subscribe(SubOpts, Topic, SubPid) ->
case maps:get(shard, SubOpts, 0) of
- 0 -> true = ets:delete_object(?SUBSCRIBER, {Topic, SubPid}),
+ 0 ->
+ true = ets:delete_object(?SUBSCRIBER, {Topic, SubPid}),
+ ok = emqx_exclusive_subscription:unsubscribe(Topic, SubOpts),
ok = cast(pick(Topic), {unsubscribed, Topic});
- I -> true = ets:delete_object(?SUBSCRIBER, {{shard, Topic, I}, SubPid}),
+ I ->
+ true = ets:delete_object(?SUBSCRIBER, {{shard, Topic, I}, SubPid}),
ok = cast(pick({Topic, I}), {unsubscribed, Topic, I})
end.
diff --git a/src/emqx_connection.erl b/src/emqx_connection.erl
index f31be4310..35ae98331 100644
--- a/src/emqx_connection.erl
+++ b/src/emqx_connection.erl
@@ -434,7 +434,7 @@ handle_msg({'$gen_cast', Req}, State) ->
{ok, NewState};
handle_msg({Inet, _Sock, Data}, State) when Inet == tcp; Inet == ssl ->
- ?LOG(debug, "RECV ~0p", [Data]),
+ ?LOG(debug, "RECV ~w", [Data]),
Oct = iolist_size(Data),
inc_counter(incoming_bytes, Oct),
ok = emqx_metrics:inc('bytes.received', Oct),
diff --git a/src/emqx_crl_cache.erl b/src/emqx_crl_cache.erl
index fec62ffbc..885d69a9a 100644
--- a/src/emqx_crl_cache.erl
+++ b/src/emqx_crl_cache.erl
@@ -147,6 +147,7 @@ handle_info({timeout, TRef, {refresh, URL}},
{noreply, ensure_timer(URL, State, ?RETRY_TIMEOUT)};
{ok, _CRLs} ->
?LOG(debug, "fetched crl response for ~p", [URL]),
+ ?tp(crl_refresh_timer_done, #{url => URL}),
{noreply, ensure_timer(URL, State)}
end;
_ ->
diff --git a/src/emqx_keepalive.erl b/src/emqx_keepalive.erl
index 69ae5d699..d8a63e60f 100644
--- a/src/emqx_keepalive.erl
+++ b/src/emqx_keepalive.erl
@@ -73,6 +73,7 @@ check(NewVal, KeepAlive = #keepalive{statval = OldVal,
true -> {error, timeout}
end.
+-define(IS_KEEPALIVE(Interval), Interval >= 0 andalso Interval =< 65535000).
%% from mqtt-v3.1.1 specific
%% A Keep Alive value of zero (0) has the effect of turning off the keep alive mechanism.
%% This means that, in this case, the Server is not required
@@ -85,7 +86,10 @@ check(NewVal, KeepAlive = #keepalive{statval = OldVal,
%% typically this is a few minutes.
%% The maximum value is (65535s) 18 hours 12 minutes and 15 seconds.
-%% @doc Update keepalive's interval
--spec(set(interval, non_neg_integer(), keepalive()) -> keepalive()).
-set(interval, Interval, KeepAlive) when Interval >= 0 andalso Interval =< 65535000 ->
+%% @doc Update keepalive interval
+%% The keepalive() is undefined when connecting via keepalive=0.
+-spec(set(interval, non_neg_integer(), keepalive() | undefined) -> keepalive()).
+set(interval, Interval, undefined) when ?IS_KEEPALIVE(Interval) ->
+ init(Interval);
+set(interval, Interval, KeepAlive) when ?IS_KEEPALIVE(Interval) ->
KeepAlive#keepalive{interval = Interval}.
diff --git a/src/emqx_packet.erl b/src/emqx_packet.erl
index 080126e5d..d91ac6f44 100644
--- a/src/emqx_packet.erl
+++ b/src/emqx_packet.erl
@@ -430,7 +430,7 @@ format_header(#mqtt_packet_header{type = Type,
Header = io_lib:format("~s(Q~p, R~p, D~p", [type_name(Type), QoS, i(Retain), i(Dup)]),
case S == undefined of
true -> [Header, ")"];
- false -> [Header, S, ")"]
+ false -> [Header, ", ", S, ")"]
end.
format_variable(undefined, _) ->
diff --git a/src/emqx_relup.erl b/src/emqx_relup.erl
index b26129828..dc453e7ff 100644
--- a/src/emqx_relup.erl
+++ b/src/emqx_relup.erl
@@ -32,6 +32,7 @@ post_release_upgrade(FromRelVsn, _) ->
{_, CurrRelVsn} = ?EMQX_RELEASE,
?INFO("emqx has been upgraded from ~s to ~s!", [FromRelVsn, CurrRelVsn]),
maybe_refresh_jwt_module(FromRelVsn),
+ _ = maybe_restart_oracle_resources(FromRelVsn),
reload_components().
%% What to do after downgraded to an old release vsn.
@@ -93,3 +94,27 @@ maybe_refresh_jwt_module(_) ->
ok.
-endif.
+
+
+-ifdef(EMQX_ENTERPRISE).
+maybe_restart_oracle_resources("4.4." ++ PatchVsn0) ->
+ try
+ case list_to_integer(PatchVsn0) of
+ PatchVsn when PatchVsn =< 14 ->
+ emqx_rule_engine:start_all_resources_of_type(backend_oracle);
+ _ -> ok
+ end
+ catch
+ Err:Reason:ST ->
+ ?INFO("maybe_restart_oracle_resources failed: ~p", [{Err, Reason, ST}]),
+ ok
+ end;
+maybe_restart_oracle_resources(_) ->
+ ok.
+
+-else.
+
+maybe_restart_oracle_resources(_) ->
+ ok.
+
+-endif.
diff --git a/src/emqx_vm.erl b/src/emqx_vm.erl
index 9d5558370..b62dba96a 100644
--- a/src/emqx_vm.erl
+++ b/src/emqx_vm.erl
@@ -380,14 +380,19 @@ read_otp_version() ->
Filename = filename:join([ReleasesDir, emqx_app:get_release(), "BUILT_ON"]),
case file:read_file(Filename) of
{ok, BuiltOn} ->
- %% running on EQM X release
+ %% running on EQMX release
BuiltOn;
{error, enoent} ->
- %% running tests etc.
OtpMajor = erlang:system_info(otp_release),
OtpVsnFile = filename:join([ReleasesDir, OtpMajor, "OTP_VERSION"]),
- {ok, Vsn} = file:read_file(OtpVsnFile),
- Vsn
+ case file:read_file(OtpVsnFile) of
+ {ok, Vsn} ->
+ %% this happens when running in test where system's OTP is in use
+ Vsn;
+ _ ->
+ %% when the code is cover-compiled
+ iolist_to_binary(OtpMajor)
+ end
end.
parse_built_on(BuiltOn) ->
diff --git a/src/emqx_ws_connection.erl b/src/emqx_ws_connection.erl
index 4696b37d9..1597c9b71 100644
--- a/src/emqx_ws_connection.erl
+++ b/src/emqx_ws_connection.erl
@@ -336,7 +336,7 @@ websocket_handle({binary, Data}, State) when is_list(Data) ->
websocket_handle({binary, iolist_to_binary(Data)}, State);
websocket_handle({binary, Data}, State) ->
- ?LOG(debug, "RECV ~0p", [Data]),
+ ?LOG(debug, "RECV ~w", [Data]),
ok = inc_recv_stats(1, iolist_size(Data)),
NState = ensure_stats_timer(State),
return(parse_incoming(Data, NState));
diff --git a/test/emqx_banned_SUITE.erl b/test/emqx_banned_SUITE.erl
index 3630b7516..f409b1f96 100644
--- a/test/emqx_banned_SUITE.erl
+++ b/test/emqx_banned_SUITE.erl
@@ -21,11 +21,12 @@
-include_lib("emqx/include/emqx.hrl").
-include_lib("eunit/include/eunit.hrl").
+-include_lib("snabbkaffe/include/snabbkaffe.hrl").
all() -> emqx_ct:all(?MODULE).
init_per_suite(Config) ->
- application:load(emqx),
+ emqx_ct_helpers:start_apps([]),
ok = ekka:start(),
%% for coverage
ok = emqx_banned:mnesia(copy),
@@ -34,7 +35,8 @@ init_per_suite(Config) ->
end_per_suite(_Config) ->
ekka:stop(),
ekka_mnesia:ensure_stopped(),
- ekka_mnesia:delete_schema().
+ ekka_mnesia:delete_schema(),
+ emqx_ct_helpers:stop_apps([]).
t_add_delete(_) ->
Banned = #banned{who = {clientid, <<"TestClient">>},
@@ -84,7 +86,10 @@ t_check(_) ->
?assertEqual(0, emqx_banned:info(size)).
t_unused(_) ->
- {ok, Banned} = emqx_banned:start_link(),
+ Banned = case emqx_banned:start_link() of
+ {ok, Pid} -> Pid;
+ {error, {already_started, Pid}} -> Pid
+ end,
ok = emqx_banned:create(#banned{who = {clientid, <<"BannedClient">>},
until = erlang:system_time(second)}),
?assertEqual(ignored, gen_server:call(Banned, unexpected_req)),
@@ -93,3 +98,22 @@ t_unused(_) ->
timer:sleep(500), %% expiry timer
ok = emqx_banned:stop().
+t_kick(_) ->
+ ClientId = <<"client">>,
+ snabbkaffe:start_trace(),
+
+ Now = erlang:system_time(second),
+ Who = {clientid, ClientId},
+
+ emqx_banned:create(#{
+ who => Who,
+ by => <<"test">>,
+ reason => <<"test">>,
+ at => Now,
+ until => Now + 120
+ }),
+
+ Trace = snabbkaffe:collect_trace(),
+ snabbkaffe:stop(),
+ emqx_banned:delete(Who),
+ ?assertEqual(1, length(?of_kind(kick_session_due_to_banned, Trace))).
diff --git a/test/emqx_crl_cache_SUITE.erl b/test/emqx_crl_cache_SUITE.erl
index 8c9f9456c..a054ca1e7 100644
--- a/test/emqx_crl_cache_SUITE.erl
+++ b/test/emqx_crl_cache_SUITE.erl
@@ -43,7 +43,7 @@ init_per_testcase(TestCase, Config)
TestCase =:= t_filled_cache;
TestCase =:= t_revoked ->
DataDir = ?config(data_dir, Config),
- CRLFile = filename:join([DataDir, "crl.pem"]),
+ CRLFile = filename:join([DataDir, "intermediate-revoked.crl.pem"]),
{ok, CRLPem} = file:read_file(CRLFile),
[{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem),
ServerPid = start_crl_server(CRLPem),
@@ -53,9 +53,44 @@ init_per_testcase(TestCase, Config)
, {crl_der, CRLDer}
, {http_server, ServerPid}
| Config];
+init_per_testcase(t_revoke_then_refresh, Config) ->
+ DataDir = ?config(data_dir, Config),
+ CRLFileNotRevoked = filename:join([DataDir, "intermediate-not-revoked.crl.pem"]),
+ {ok, CRLPemNotRevoked} = file:read_file(CRLFileNotRevoked),
+ [{'CertificateList', CRLDerNotRevoked, not_encrypted}] = public_key:pem_decode(CRLPemNotRevoked),
+ CRLFileRevoked = filename:join([DataDir, "intermediate-revoked.crl.pem"]),
+ {ok, CRLPemRevoked} = file:read_file(CRLFileRevoked),
+ [{'CertificateList', CRLDerRevoked, not_encrypted}] = public_key:pem_decode(CRLPemRevoked),
+ ServerPid = start_crl_server(CRLPemNotRevoked),
+ OldListeners = emqx:get_env(listeners),
+ OldRefreshInterval = emqx:get_env(crl_cache_refresh_interval),
+ NewRefreshInterval = timer:seconds(10),
+ ExtraHandler =
+ fun(emqx) ->
+ application:set_env(emqx, crl_cache_refresh_interval, NewRefreshInterval),
+ ok;
+ (_) ->
+ ok
+ end,
+ ok = setup_crl_options(Config, #{is_cached => true, extra_handler => ExtraHandler}),
+ ok = snabbkaffe:start_trace(),
+ {ok, {ok, _}} =
+ ?wait_async_action(
+ emqx_crl_cache:refresh_config(),
+ #{?snk_kind := crl_cache_refresh_config},
+ _Timeout = 10_000),
+ [ {crl_pem_not_revoked, CRLPemNotRevoked}
+ , {crl_der_not_revoked, CRLDerNotRevoked}
+ , {crl_pem_revoked, CRLPemRevoked}
+ , {crl_der_revoked, CRLDerRevoked}
+ , {http_server, ServerPid}
+ , {old_configs, [ {listeners, OldListeners}
+ , {crl_cache_refresh_interval, OldRefreshInterval}
+ ]}
+ | Config];
init_per_testcase(t_not_cached_and_unreachable, Config) ->
DataDir = ?config(data_dir, Config),
- CRLFile = filename:join([DataDir, "crl.pem"]),
+ CRLFile = filename:join([DataDir, "intermediate-revoked.crl.pem"]),
{ok, CRLPem} = file:read_file(CRLFile),
[{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem),
application:stop(cowboy),
@@ -65,7 +100,7 @@ init_per_testcase(t_not_cached_and_unreachable, Config) ->
| Config];
init_per_testcase(t_refresh_config, Config) ->
DataDir = ?config(data_dir, Config),
- CRLFile = filename:join([DataDir, "crl.pem"]),
+ CRLFile = filename:join([DataDir, "intermediate-revoked.crl.pem"]),
{ok, CRLPem} = file:read_file(CRLFile),
[{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem),
TestPid = self(),
@@ -88,7 +123,7 @@ init_per_testcase(t_refresh_config, Config) ->
| Config];
init_per_testcase(_TestCase, Config) ->
DataDir = ?config(data_dir, Config),
- CRLFile = filename:join([DataDir, "crl.pem"]),
+ CRLFile = filename:join([DataDir, "intermediate-revoked.crl.pem"]),
{ok, CRLPem} = file:read_file(CRLFile),
[{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem),
TestPid = self(),
@@ -118,6 +153,30 @@ end_per_testcase(TestCase, Config)
clear_crl_cache(),
ok = snabbkaffe:stop(),
ok;
+end_per_testcase(t_revoke_then_refresh, Config) ->
+ ServerPid = ?config(http_server, Config),
+ emqx_crl_cache_http_server:stop(ServerPid),
+ emqx_ct_helpers:stop_apps([]),
+ OldConfigs = ?config(old_configs, Config),
+ clear_crl_cache(),
+ emqx_ct_helpers:stop_apps([]),
+ emqx_ct_helpers:change_emqx_opts(
+ ssl_twoway, [ {crl_options, [ {crl_check_enabled, false}
+ , {crl_cache_urls, []}
+ ]}
+ ]),
+ clear_crl_cache(),
+ lists:foreach(
+ fun({Key, MValue}) ->
+ case MValue of
+ undefined -> ok;
+ Value -> application:set_env(emqx, Key, Value)
+ end
+ end,
+ OldConfigs),
+ application:stop(cowboy),
+ ok = snabbkaffe:stop(),
+ ok;
end_per_testcase(t_not_cached_and_unreachable, _Config) ->
emqx_ct_helpers:stop_apps([]),
emqx_ct_helpers:change_emqx_opts(
@@ -229,7 +288,7 @@ force_cacertfile(Cacertfile) ->
application:set_env(emqx, listeners, SSLListeners ++ OtherListeners),
ok.
-setup_crl_options(Config, #{is_cached := IsCached}) ->
+setup_crl_options(Config, Opts = #{is_cached := IsCached}) ->
DataDir = ?config(data_dir, Config),
Cacertfile = filename:join(DataDir, "ca-chain.cert.pem"),
Certfile = filename:join(DataDir, "server.cert.pem"),
@@ -238,6 +297,7 @@ setup_crl_options(Config, #{is_cached := IsCached}) ->
false -> [];
true -> ["http://localhost:9878/intermediate.crl.pem"]
end,
+ ExtraHandler = maps:get(extra_handler, Opts, fun(_) -> ok end),
Handler =
fun(emqx) ->
emqx_ct_helpers:change_emqx_opts(
@@ -255,8 +315,10 @@ setup_crl_options(Config, #{is_cached := IsCached}) ->
]),
%% emqx_ct_helpers:change_emqx_opts has cacertfile hardcoded....
ok = force_cacertfile(Cacertfile),
+ ExtraHandler(emqx),
ok;
- (_) ->
+ (App) ->
+ ExtraHandler(App),
ok
end,
emqx_ct_helpers:start_apps([], Handler),
@@ -546,3 +608,39 @@ t_revoked(Config) ->
process_flag(trap_exit, true),
?assertMatch({error, {{shutdown, {tls_alert, {certificate_revoked, _}}}, _}}, emqtt:connect(C)),
ok.
+
+t_revoke_then_refresh(Config) ->
+ DataDir = ?config(data_dir, Config),
+ CRLPemRevoked = ?config(crl_pem_revoked, Config),
+ ClientCert = filename:join(DataDir, "client-revoked.cert.pem"),
+ ClientKey = filename:join(DataDir, "client-revoked.key.pem"),
+ {ok, C0} = emqtt:start_link([ {ssl, true}
+ , {ssl_opts, [ {certfile, ClientCert}
+ , {keyfile, ClientKey}
+ ]}
+ , {port, 8883}
+ ]),
+ %% At first, the CRL contains no revoked entries, so the client
+ %% should be allowed connection.
+ ?assertMatch({ok, _}, emqtt:connect(C0)),
+ emqtt:stop(C0),
+
+ %% Now we update the CRL on the server and wait for the cache to
+ %% be refreshed.
+ ok = snabbkaffe:start_trace(),
+ {true, {ok, _}} =
+ ?wait_async_action(
+ emqx_crl_cache_http_server:set_crl(CRLPemRevoked),
+ #{?snk_kind := crl_refresh_timer_done},
+ 70_000),
+
+ %% The *same client* should now be denied connection.
+ {ok, C1} = emqtt:start_link([ {ssl, true}
+ , {ssl_opts, [ {certfile, ClientCert}
+ , {keyfile, ClientKey}
+ ]}
+ , {port, 8883}
+ ]),
+ process_flag(trap_exit, true),
+ ?assertMatch({error, {{shutdown, {tls_alert, {certificate_revoked, _}}}, _}}, emqtt:connect(C1)),
+ ok.
diff --git a/test/emqx_crl_cache_SUITE_data/ca-chain.cert.pem b/test/emqx_crl_cache_SUITE_data/ca-chain.cert.pem
index 7fed6be59..eaabd2445 100644
--- a/test/emqx_crl_cache_SUITE_data/ca-chain.cert.pem
+++ b/test/emqx_crl_cache_SUITE_data/ca-chain.cert.pem
@@ -2,67 +2,67 @@
MIIF+zCCA+OgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwbzELMAkGA1UEBhMCU0Ux
EjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMRIwEAYDVQQK
DAlNeU9yZ05hbWUxETAPBgNVBAsMCE15Um9vdENBMREwDwYDVQQDDAhNeVJvb3RD
-QTAeFw0yMjA2MTMxMjQyMDVaFw0zMjA2MTAxMjQyMDVaMGsxCzAJBgNVBAYTAlNF
+QTAeFw0yMzAxMTIxMzA4MTZaFw0zMzAxMDkxMzA4MTZaMGsxCzAJBgNVBAYTAlNF
MRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAoMCU15T3JnTmFtZTEZMBcGA1UE
CwwQTXlJbnRlcm1lZGlhdGVDQTEZMBcGA1UEAwwQTXlJbnRlcm1lZGlhdGVDQTCC
-AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAN32wUPOGrLjVHY37ICI4sWH
-2GBEYgGtoKyZTfLKqK8W965uxHxMKKeKC7Ro93ScT4giR2GdsCvMyLP4Dlv7FxL7
-rWEHc7vbP22uT4NQQ0hgfl4ch8rTiSl/5FfynOuvMHnKh58z+lGyQ/uqKqAzc6OD
-6FypzSQO2R6JpA+kxKlbTYmOcsLiLFKjCjxyA1ibeozUaRHjPRM7VLHVxYfmpGm/
-86NJxtHrw4hwoKIM9bfURboxfn9R1YM14mZYA6Uw2pScS1+j79tNy74NQNYu1t9E
-cyPQk+AJdp2BsbR5KPYr1SMVLHlTwnzjk1IVW4wUUdX2h56ygmRNo9ui74ODfyud
-4cclg45SeRdOT0w5e3g20ZvfLZpIkhXk19EIIU/YbG6GpL8gLvBHkz6vvidE7L/2
-h2//alJBeWCvyOloIWYNYnwnHGeXR2c5pzNxHipkBSuMeBaLJOO7X9oqKVanu+xq
-nVagFhEYnd+T0PsPa5IVA73KiWMWWeFgJI0pRUydyp0/FhXEhkMWZNJHiscbxcdn
-hTdNCAbMfV/4fMar+d/QKY/GMWUVQ4OlXUoo3WjjRi4T8NJEjZGfLdKw5x81WM4A
-yqDV3OVVCBf1XrHH4IbvbUDgeG1OEGSV9pdvKX4Sm7226vdOc3HPfRnVyf/N1Pv7
-lzPbUlCheKbTW6Oeq97VAgMBAAGjgaQwgaEwHQYDVR0OBBYEFCuv1TkzC1fSgTfz
-E1m1u5pRCJsVMB8GA1UdIwQYMBaAFErA8sZMX6obhoo3XvUpaTy6Z4uhMBIGA1Ud
+AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALQG7dMeU/y9HDNHzhydR0bm
+wN9UGplqJOJPwqJRaZZcrn9umgJ9SU2il2ceEVxMDwzBWCRKJO5/H9A9k13SqsXM
+2c2c9xXfIF1kb820lCm1Uow5hZ/auDjxliNk9kNJDigCRi3QoIs/dVeWzFsgEC2l
+gxRqauN2eNFb6/yXY788YALHBsCRV2NFOFXxtPsvLXpD9Q/8EqYsSMuLARRdHVNU
+ryaEF5lhShpcuz0TlIuTy2TiuXJUtJ+p7a4Z7friZ6JsrmQWsVQBj44F8TJRHWzW
+C7vm9c+dzEX9eqbr5iPL+L4ctMW9Lz6ePcYfIXne6CElusRUf8G+xM1uwovF9bpV
++9IqY7tAu9G1iY9iNtJgNNDKOCcOGKcZCx6Cg1XYOEKReNnUMazvYeqRrrjV5WQ0
+vOcD5zcBRNTXCddCLa7U0guXP9mQrfuk4NTH1Bt77JieTJ8cfDXHwtaKf6aGbmZP
+wl1Xi/GuXNUP/xeog78RKyFwBmjt2JKwvWzMpfmH4mEkG9moh2alva+aEz6LIJuP
+16g6s0Q6c793/OvUtpNcewHw4Vjn39LD9o6VLp854G4n8dVpUWSbWS+sXD1ZE69H
+g/sMNMyq+09ufkbewY8xoCm/rQ1pqDZAVMWsstJEaYu7b/eb7R+RGOj1YECCV/Yp
+EZPdDotbSNRkIi2d/a1NAgMBAAGjgaQwgaEwHQYDVR0OBBYEFExwhjsVUom6tQ+S
+qq6xMUETvnPzMB8GA1UdIwQYMBaAFD90kfU5pc5l48THu0Ayj9SNpHuhMBIGA1Ud
EwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMDsGA1UdHwQ0MDIwMKAuoCyG
Kmh0dHA6Ly9sb2NhbGhvc3Q6OTg3OC9pbnRlcm1lZGlhdGUuY3JsLnBlbTANBgkq
-hkiG9w0BAQsFAAOCAgEAtn/u/ZfmioZyh5DNETRNAftXWvxOyi2MK8soNEsaSbmq
-2ajkQwJ1MZ0+C5HuzsoEEoqStYtD3JG34ydPzQbMPwkTDg48+guu8ji30jYXGIfI
-RQQfseEj1hN8wTLEDAJGl17kJA+js6dcHkJp93qocOCoOwa5MAYB8ZZq/uRJlzVt
-ol6dvhBvhoxkKvJfrhg5dNISVBgIXrs5YOMyXqh6W3YMmepNjs05e5bcLYADyHCd
-f4TK9pgyys4OIVHiRZo0+hlaChKo4vDK7acgZOds7qxS/sxrwKe49FTIrAWWP6fG
-Ij2RHF91fLhi+10oVVSWtCyWRJOaSM4cenbLN36OUg1JswacsqojTCUylMAa8sAB
-RggZ+tt8LlARj3/pdz6IWrccabC+AGZQa1kOKl97hjsE0qy9V5WOiueJ+78u+BY5
-NXIoIyuPG0WCItb76jyn7UDjiCsJt7rfJ5t5rRVLpm8YRG43KuMWjXih/bT07YdE
-tA3X5Bk/XLQBqQbRKpR5+CKFhvXbNmKnuAdFbiG8UTFQdo/HGyBR7zzkF4vTqu8s
-2pMl4xFAMNnGsWQYce6YioQfYL3apgx9PIqgHr+IzXae6/NIpoIs9ShymEZP1jT5
-9DqKzmUQz3czc7RNXLUZbWxoWRtivrDJGPgbSHyMqVu4h2yLINftHSGegC+ZEgc=
+hkiG9w0BAQsFAAOCAgEAK6NgdWQYtPNKQNBGjsgtgqTRh+k30iqSO6Y3yE1KGABO
+EuQdVqkC2qUIbCB0M0qoV0ab50KNLfU6cbshggW4LDpcMpoQpI05fukNh1jm3ZuZ
+0xsB7vlmlsv00tpqmfIl/zykPDynHKOmFh/hJP/KetMy4+wDv4/+xP31UdEj5XvG
+HvMtuqOS23A+H6WPU7ol7KzKBnU2zz/xekvPbUD3JqV+ynP5bgbIZHAndd0o9T8e
+NFX23Us4cTenU2/ZlOq694bRzGaK+n3Ksz995Nbtzv5fbUgqmf7Mcq4iHGRVtV11
+MRyBrsXZp2vbF63c4hrf2Zd6SWRoaDKRhP2DMhajpH9zZASSTlfejg/ZRO2s+Clh
+YrSTkeMAdnRt6i/q4QRcOTCfsX75RFM5v67njvTXsSaSTnAwaPi78tRtf+WSh0EP
+VVPzy++BszBVlJ1VAf7soWZHCjZxZ8ZPqVTy5okoHwWQ09WmYe8GfulDh1oj0wbK
+3FjN7bODWHJN+bFf5aQfK+tumYKoPG8RXL6QxpEzjFWjxhIMJHHMKfDWnAV1o1+7
+/1/aDzq7MzEYBbrgQR7oE5ZHtyqhCf9LUgw0Kr7/8QWuNAdeDCJzjXRROU0hJczp
+dOyfRlLbHmLLmGOnROlx6LsGNQ17zuz6SPi7ei8/ylhykawDOAGkM1+xFakmQhM=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-MIIFzzCCA7egAwIBAgIUVYtdlrTMH1BoMy9JpiiL/FXv5NMwDQYJKoZIhvcNAQEL
+MIIFzzCCA7egAwIBAgIUYjc7hD7/UJ0/VPADfNfp/WpOwRowDQYJKoZIhvcNAQEL
BQAwbzELMAkGA1UEBhMCU0UxEjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJ
U3RvY2tob2xtMRIwEAYDVQQKDAlNeU9yZ05hbWUxETAPBgNVBAsMCE15Um9vdENB
-MREwDwYDVQQDDAhNeVJvb3RDQTAeFw0yMjA2MTMxMjQyMDVaFw00MjA2MDgxMjQy
-MDVaMG8xCzAJBgNVBAYTAlNFMRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAcM
+MREwDwYDVQQDDAhNeVJvb3RDQTAeFw0yMzAxMTIxMzA4MTRaFw00MzAxMDcxMzA4
+MTRaMG8xCzAJBgNVBAYTAlNFMRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAcM
CVN0b2NraG9sbTESMBAGA1UECgwJTXlPcmdOYW1lMREwDwYDVQQLDAhNeVJvb3RD
QTERMA8GA1UEAwwITXlSb290Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
-AoICAQDRKeWdrXluKLuVxTXxpWbCzBm/6x+kg8EjhIKUm9Mq0t+cOLC1sn99s4E0
-/NBA7jc3O+hQ9S2fZuMp9OUXuf8HjjtlKQY2M9T9kCE9Yxc+ygpcPEvDYl0ke/1r
-m6eUOGS2LkIDHebuYbY+KGXjpaF15w49q199wQAk0sbdcCiv+OymBUxi3lrHepo3
-EBIjHtTwNtehgeiJfxCe8TLlLpbPdCsMNwlPvNa0E+1Ol1P9DfHPfK1Dt0ua8X5q
-ZBhnW1cawrwzrnth2ZtrSw7RaWhtNWFt/SdedGPgVUMIgFY2I7f2wT2hoe8R/D+e
-XLDzVMAW+yrlu/LlBaHE2Ffkk2La8mSHwJOvCZ/Q0V1mJnj6F4pfNemY4MnFX6Jm
-7u2TSWooowMppdNPCCRlGk+XS8lfmb9N/0RsOMSz5+1u8wOfFI6Z1GaH6K2Ne2xf
-VIBjhGRAiTCHDIFNYBCeAxR64zYeGFKv8L19oV6cbA6St7GMikfk5U/fyG9SUK88
-Fvjm+MrNDu/EEyjkKhK6I9ao3Pb4LcCofTcu44RBYT0HhkjqGWQgapm0i80NcRlL
-yK7wm5C8Tntmbehg1KE8iqSzAcBZu6L+j4qQ90T+AIHNTmRUa9dH2uhEej4hIhjd
-yJSJcDm4/CYEuK6WgZ6EuJadRy4QgPiH7zWCFXp/OGLvFmUEWQIDAQABo2MwYTAd
-BgNVHQ4EFgQUSsDyxkxfqhuGijde9SlpPLpni6EwHwYDVR0jBBgwFoAUSsDyxkxf
-qhuGijde9SlpPLpni6EwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw
-DQYJKoZIhvcNAQELBQADggIBAJQSy3WpS/j8emep2gJXB7jYxolhhN78DiJaqUZh
-0YXa19YaghAsk5YVqbe2XLAGyFqAmmGQ6ymCbULqkdSNUTLTvwHYGFYH7NizUaCS
-r9XaB9lizr7dwpd/8HwpqMq7rxNXLMNfl3iVywiKkah6r3goNwz9xgclOj1Q2Uly
-s5S3BaNnf8Q9ypygbUMOalYN6KzHloj52inX3fpGfOov0O/1+bkp/3SvATU0aRpB
-4bKLt99b69x1HSIkCNxeJQz2klgEMNQYGsnXOYCvnI0cOpGGDxQuIYiZbYbTJb7X
-FI7FfV0ryn55mMLgZboGezMhWGYeHpWfa7H0La1ZjgedBsu3HH5VaPuHOngFNa+X
-78vbWFcD09biZJwatwZlRjFGItaPSyhqSWJx1IqBZ98ZG9ziOVQ+kq1+uRecI/3S
-jNw8LFDnOH20UxJnhRddA7f7cFWkk3WRIIec+wvE7uOibHDwFmqCo6JeOhkZDF5f
-R1dfN4CZznMzbUb5iqUb4JwGdViijCaDHTEe3C3nKS1mPxt2kn3H1C37y71Fh5yu
-mStVxjZZTdbaP8WPEAEDhK+7eB6pAKa+ERXOlWY1L5nNkh4ahIw5837yIY60oyBh
-goiqX/Vy0wEJMa7HgXT3cDnW4NiXQA8nVKsRUiZco136YAATS89iLk3ibYJxzGP+
-G2LZ
+AoICAQCnBwSOYVJw47IoMHMXTVDtOYvUt3rqsurEhFcB4O8xmf2mmwr6m7s8A5Ft
+AvAehg1GvnXT3t/KiyU7BK+acTwcErGyZwS2wvdB0lpHWSpOn/u5y+4ZETvQefcj
+ZTdDOM9VN5nutpitgNb+1yL8sqSexfVbY7DnYYvFjOVBYoP/SGvM9jVjCad+0WL3
+FhuD+L8QAxzCieX3n9UMymlFwINQuEc+TDjuNcEqt+0J5EgS1fwzxb2RCVL0TNv4
+9a71hFGCNRj20AeZm99hbdufm7+0AFO7ocV5q43rLrWFUoBzqKPYIjga/cv/UdWZ
+c5RLRXw3JDSrCqkf/mOlaEhNPlmWRF9MSus5Da3wuwgGCaVzmrf30rWR5aHHcscG
+e+AOgJ4HayvBUQeb6ZlRXc0YlACiLToMKxuyxDyUcDfVEXpUIsDILF8dkiVQxEU3
+j9g6qjXiqPVdNiwpqXfBKObj8vNCzORnoHYs8cCgib3RgDVWeqkDmlSwlZE7CvQh
+U4Loj4l7813xxzYEKkVaT1JdXPWu42CG/b4Y/+f4V+3rkJkYzUwndX6kZNksIBai
+phmtvKt+CTdP1eAbT+C9AWWF3PT31+BIhuT0u9tR8BVSkXdQB8dG4M/AAJcTo640
+0mdYYOXT153gEKHJuUBm750ZTy+r6NjNvpw8VrMAakJwHqnIdQIDAQABo2MwYTAd
+BgNVHQ4EFgQUP3SR9TmlzmXjxMe7QDKP1I2ke6EwHwYDVR0jBBgwFoAUP3SR9Tml
+zmXjxMe7QDKP1I2ke6EwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw
+DQYJKoZIhvcNAQELBQADggIBAFMFv4C+I0+xOAb9v6G/IOpfPBZ1ez31EXKJJBra
+lulP4nRHQMeb310JS8BIeQ3dl+7+PkSxPABZSwc3jkxdSMvhc+Z4MQtTgos+Qsjs
+gH7sTqwWeeQ0lHYxWmkXijrh5OPRZwTKzYQlkcn85BCUXl2KDuNEdiqPbDTao+lc
+lA0/UAvC6NCyFKq/jqf4CmW5Kx6yG1v1LaE+IXn7cbIXj+DaehocVXi0wsXqj03Q
+DDUHuLHZP+LBsg4e91/0Jy2ekNRTYJifSqr+9ufHl0ZX1pFDZyf396IgZ5CQZ0PJ
+nRxZHlCfsxWxmxxdy3FQSE6YwXhdTjjoAa1ApZcKkkt1beJa6/oRLze/ux5x+5q+
+4QczufHd6rjoKBi6BM3FgFQ8As5iNohHXlMHd/xITo1Go3CWw2j9TGH5vzksOElK
+B0mcwwt2zwNEjvfytc+tI5jcfGN3tiT5fVHS8hw9dWKevypLL+55Ua9G8ZgDHasT
+XFRJHgmnbyFcaAe26D2dSKmhC9u2mHBH+MaI8dj3e7wNBfpxNgp41aFIk+QTmiFW
+VXFED6DHQ/Mxq93ACalHdYg18PlIYClbT6Pf2xXBnn33YPhn5xzoTZ+cDH/RpaQp
+s0UUTSJT1UTXgtXPnZWQfvKlMjJEIiVFiLEC0sgZRlWuZDRAY0CdZJJxvQp59lqu
+cbTm
-----END CERTIFICATE-----
diff --git a/test/emqx_crl_cache_SUITE_data/client-revoked.cert.pem b/test/emqx_crl_cache_SUITE_data/client-revoked.cert.pem
index 53bd2436c..d0a23bf2f 100644
--- a/test/emqx_crl_cache_SUITE_data/client-revoked.cert.pem
+++ b/test/emqx_crl_cache_SUITE_data/client-revoked.cert.pem
@@ -2,31 +2,31 @@
MIIFnDCCA4SgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCU0Ux
EjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UECgwJTXlPcmdOYW1lMRkwFwYDVQQL
DBBNeUludGVybWVkaWF0ZUNBMRkwFwYDVQQDDBBNeUludGVybWVkaWF0ZUNBMB4X
-DTIyMDYxMzEyNDIwNVoXDTIzMDYyMzEyNDIwNVowfTELMAkGA1UEBhMCU0UxEjAQ
+DTIzMDExMjEzMDgxNloXDTMzMDQxOTEzMDgxNlowfTELMAkGA1UEBhMCU0UxEjAQ
BgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMRIwEAYDVQQKDAlN
eU9yZ05hbWUxGTAXBgNVBAsMEE15SW50ZXJtZWRpYXRlQ0ExFzAVBgNVBAMMDmNs
-aWVudC1yZXZva2VkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA584w
-VAczDWrlIJXm6+0oYepacPPrVEMC9WwsQFO5GbBDdxrBvxgQ5u8/DDNEtYk0sJMt
-zgSLxsYK5duhrwVyICXpKgxMI2fKdKP0zxB/eB4V0vrc6FqR4L8D8XoNPKSaTnjv
-NNh3wjLNvmBRfHRSUCe4zEvPZzMLuBIHXRR20prtA90FFV8fliNvMCBIbFkqthjf
-fQ/tSXXxNQNjacuHVfY+LVN3xu9Jjll4AaCKKz19rDexq9HTLLZ8y4jBD1eRobp+
-spKKu4HNpon+YMp3vJuNmxsTU+xBkbESWGJTFot7lZL1PVBvxdgbSd3OrPKI+QbK
-06FN3iBrcW3Yjp04LQIDAQABo4IBNjCCATIwCQYDVR0TBAIwADARBglghkgBhvhC
+aWVudC1yZXZva2VkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs+R6
+PDtIxVlUoLYbDBbaVcxgoLjnWcvqL8wSqyWuqi/Y3cjuNYCziR9nR5dWajtkBjzJ
+HyhgAr6gBVSRt4RRmDXoOcprK3GcpowAr65UAmC4hdH0af6FdKjKCnFw67byUg52
+f7ueXZ6t/XuuKxlU/f2rjXVwmmnlhBi5EHDkXxvfgWXJekDfsPbW9j0kaCUWCpfj
+rzGbfkXqrPkslO41PYlCbPxoiRItJjindFjcQySYvRq7A2uYMGsrxv4n3rzo5NGt
+goBmnGj61ii9WOdopcFxKirhIB9zrxC4x0opRfIaF/n1ZXk6NOnaDxu1LTZ18wfC
+ZB979ge6pleeKoPf7QIDAQABo4IBNjCCATIwCQYDVR0TBAIwADARBglghkgBhvhC
AQEEBAMCBaAwMwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2VuZXJhdGVkIENsaWVu
-dCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUSq+9djRFuryFk0Mdqlsy0chljWswHwYD
-VR0jBBgwFoAUK6/VOTMLV9KBN/MTWbW7mlEImxUwDgYDVR0PAQH/BAQDAgXgMB0G
+dCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUQeItXr3nc6CZ++G9UCoq1YlQ9oowHwYD
+VR0jBBgwFoAUTHCGOxVSibq1D5KqrrExQRO+c/MwDgYDVR0PAQH/BAQDAgXgMB0G
A1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDA7BgNVHR8ENDAyMDCgLqAshipo
dHRwOi8vbG9jYWxob3N0Ojk4NzgvaW50ZXJtZWRpYXRlLmNybC5wZW0wMQYIKwYB
BQUHAQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojk4NzcwDQYJ
-KoZIhvcNAQELBQADggIBAD4XyEjAfU0VE+YRQXUxlqpeJdMij0Io9ZCf1j6JMNFl
-/p8vbOm6orK55bYWXCzRaIEkgOGlpQLDIXpViAjmBbXisA97hS1v6rW10W6LyNkN
-i7LC6kTgBi4yIV3FiQk5CIE3Tj22+0GjaepHc2bPGaLSRBaoe8uBvDlDqRjxW64H
-KYOIyux3WqauEziNEVklXG3VNX+6WfUw0jP9p4cglLaL43htwdavA1g7RP0wE1/6
-hvZ242jK4bvCGn/p7IDa8YtgXTufjQf6hJB9kRAJRqrSJQnihb6P9UZr2saaR7mp
-28w7a6L1RLSkCSpcwRoTHgTMkFwCD/h7NxZmpoOCBk4vrHY7SXG05ptb6o7x8TD7
-lRV/+ay8EIPWCKGpTrGWHGzjxiuXw4TqnfETlvz0rFUG4TapXwmWnaSwTUk5d10v
-olBQJ22CIidkKvoW/6bmD6mtyRX/F3KDTN7vHSsjvaty+TzqjWLLd2rjWpZi5xcc
-h/lOyWHXbFkakRT879USUvqU/Y6+2CpbZ2ssks4+bnD8Dsdq1fFLTXtLhBBFcz11
-amuwx923tJTY9f6e7y3X/TveCKcibo+aluA4ACkYix8mR/oFxmsulW6MTVcqZZ+i
-9+oo9hyOPQsJhWYISAtLBuDCqz9fKM4llmnuQZA55FuZBkSmHBRAXw5xwA+gbZcs
+KoZIhvcNAQELBQADggIBAIFuhokODd54/1B2JiNyG6FMq/2z8B+UquC2iw3p2pyM
+g/Jz4Ouvg6gGwUwmykEua06FRCxx5vJ5ahdhXvKst/zH/0qmYTFNMhNsDy76J/Ot
+Ss+VwQ8ddpEG3EIUI9BQxB3xL7z7kRQzploQjakNcDWtDt1BmN05Iy2vz4lnYJky
+Kss6ya9jEkNibHekhxJuchJ0fVGlVe74MO7RNDFG7+O3tMlxu0zH/LpW093V7BI2
+snXNAwQBizvWTrDKWLDu5JsX8KKkrmDtFTs9gegnxDCOYdtG5GbbMq+H1SjWUJPV
+wiXTF8/eE02s4Jzm7ZAxre4bRt/hAg7xTGmDQ1Hn+LzLn18I9LaW5ZWqSwwpgv+g
+Z/jiLO9DJ/y525Cl7DLCpSFoDTWlQXouKhcgALcVay/cXCsZ3oFZCustburLiJi/
+zgBeEk1gVpwljriJLeZifyfWtJx6yfgB/h6fid8XLsGRD+Yc8Tzs8J1LIgi+j4ZT
+UzKX3B85Kht/dr43UDMtWOF3edkOMaJu7rcg5tTsK+LIyHtXvebKPVvvA9f27Dz/
+4gmhAwwqS87Xv3FMVhZ03DNOJ6XAF+T6OTEqwYs+iK56IMSl1Jy+bCzo0j5jZVbl
+XFwGxUHzM7pfM6PDx657oUxG1QwM/fIWA18F+kY/yigXxq6pYMeAiQsPanOThgHp
-----END CERTIFICATE-----
diff --git a/test/emqx_crl_cache_SUITE_data/client-revoked.key.pem b/test/emqx_crl_cache_SUITE_data/client-revoked.key.pem
index b9865d4d6..0b7698da9 100644
--- a/test/emqx_crl_cache_SUITE_data/client-revoked.key.pem
+++ b/test/emqx_crl_cache_SUITE_data/client-revoked.key.pem
@@ -1,27 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEA584wVAczDWrlIJXm6+0oYepacPPrVEMC9WwsQFO5GbBDdxrB
-vxgQ5u8/DDNEtYk0sJMtzgSLxsYK5duhrwVyICXpKgxMI2fKdKP0zxB/eB4V0vrc
-6FqR4L8D8XoNPKSaTnjvNNh3wjLNvmBRfHRSUCe4zEvPZzMLuBIHXRR20prtA90F
-FV8fliNvMCBIbFkqthjffQ/tSXXxNQNjacuHVfY+LVN3xu9Jjll4AaCKKz19rDex
-q9HTLLZ8y4jBD1eRobp+spKKu4HNpon+YMp3vJuNmxsTU+xBkbESWGJTFot7lZL1
-PVBvxdgbSd3OrPKI+QbK06FN3iBrcW3Yjp04LQIDAQABAoIBAQDN52MaYMLCel9I
-0J6slp62SxtHFgPFdzjbk9jC0xuqa92hoIzVF6V73KxeQ/QWZOf+qN2ZEISwbh4k
-CzHVa7ryP3qbtQy0rm8xqKm+fGMd6WttWxR6+Gh4AHSaPNYhNf0zE0033ciTIdmL
-77ayHAk51e7a2cRDYR5ZxPnxfkoFy5M2y9U7daAZsEjIyoxjGmkO92YU4byPfUxA
-vxC+rcSCUHA1OSoKONuGmwAYrLyHHoIgmVSXe6qSjgSWBPFVLp6OKTiBc7klRnlw
-EAcoop7NSit+eMCqQM85Tp8wMmKd+9jfoek9yc5ahWgLDMsd5Dlc/+CXoChmQ5dO
-w0h7vqbpAoGBAPk5HEuZ752VJQOtcSfJacOsYlAc8tlOBl33negGIplAKYeWKib7
-xtCzdU29oW4tPIJO6v+e7y+GcV7n2+6DpoXTUr6f4fG3vPQ3ZKPctsAHyFpKvzR3
-137YllShpgQKIcnwC7y/KG+wwgiVjZ+cDWCUuGA9/3m249DdO2b8F+jXAoGBAO4b
-1KC32rjzOk3QOZWIvWADbC8MxY0jeM+phtycoeyCreSOKq6dLpX4JD5NZ1XP4uol
-wr0Ta0D8FN7T/JRfT8FnoFXTJxwKTi6oGwXQ3Am/bXsz2A2H8vsXL8tgutYfX4Xi
-YNf57zNiCTHLC4K9aiS8iJ2UtJIwGi558ONVOPKbAoGBAJcjS0WN1QJ7sDbKuBSo
-0LsZj4WGCMA/0RyrTden4NOPVaAkMOvzRF7MdhbvKTbnuApOUbUzbVok7hvgAEBl
-FleSEFwKGbu88Zoo/Z9h+nH6RkZ7jfkDtGv4bTJl1YgdnOAZ8wRD6QHS79jE2V4y
-BOrNRgMXlhb6Eq5Xe+64cseBAoGBANuLB6tEukQr6AdVRbMNyGbd4QMkyIXRPhRj
-IDkLpvVWrJV/S/WCcjDPAkP7xJrHulbgiEUjwZHCnE+0sD/x/ay7KofX0Ei3a8zz
-LS9Ym3nValHdxIj9X9mKUIQ6ZSsG9GGTEG4zQg1jiEzEBZH/qf3DZEe/lBryhUFz
-J9vEeWSfAoGAPV6RXEP4uJstCBUsWnWXGNtQ8TwS/NsH5FyPuWEXWxJwrUHEDyiA
-FhRW2tGH/k5cCZw7lvzmZui+iWBv90l1/N3J2+SKZMVZNGsXCYx9szSd5uAer/Zs
-emH0oOBC6NXXVDTIp+vDzy/lx6Xxcp4n6iiI3I+uCOeI5qRhM0GHcdU=
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCz5Ho8O0jFWVSg
+thsMFtpVzGCguOdZy+ovzBKrJa6qL9jdyO41gLOJH2dHl1ZqO2QGPMkfKGACvqAF
+VJG3hFGYNeg5ymsrcZymjACvrlQCYLiF0fRp/oV0qMoKcXDrtvJSDnZ/u55dnq39
+e64rGVT9/auNdXCaaeWEGLkQcORfG9+BZcl6QN+w9tb2PSRoJRYKl+OvMZt+Reqs
++SyU7jU9iUJs/GiJEi0mOKd0WNxDJJi9GrsDa5gwayvG/ifevOjk0a2CgGacaPrW
+KL1Y52ilwXEqKuEgH3OvELjHSilF8hoX+fVleTo06doPG7UtNnXzB8JkH3v2B7qm
+V54qg9/tAgMBAAECggEAAml+HRgjZ+gEezot3yngSBW7NvR7v6e9DmKDXpGdB7Go
+DANBdGyzG5PU9/AGy9pbgzzl6nnJXcgOD7w8TvRifrK8WCgHa1f05IPMj458GGMR
+HlQ8HX647eFEgkLWo4Z6tdB1VM2geDtkNFmn8nJ+wgAYgIdSWPOyDOUi+B43ZbIN
+eaLWkP2fiX9tcJp41cytW+ng2YIm4s90Nt4FJPNBNzOrhVm35jciId02MmEjCEnr
+0YbK9uoMDC2YLg8vhRcjtsUHV2rREkwEAQj8nCWvWWheIwk943d6OicGAD/yebpV
+PTjtlZlpIbrovfvuMcoTxJg3WS8LTg/+cNWAX5a3eQKBgQDcRY7nVSJusYyN0Bij
+YWc9H47wU+YucaGT25xKe26w1pl6s4fmr1Sc3NcaN2iyUv4BuAvaQzymHe4g9deU
+D9Ws/NCQ9EjHJJsklNyn2KCgkSp7oPKhPwyl64XfPdV2gr5AD6MILf7Rkyib5sSf
+1WK8i25KatT7M4mCtrBVJYHNpQKBgQDREjwPIaQBPXouVpnHhSwRHfKD0B1a2koq
+4VE6Fnf3ogkiGfV9kqXwIfPHL0tfotFraM3FFmld8RcxhKUPr4oj+K9KTxmMD9lm
+9Hal0ANXYmHs5a1iHyoNmTpBGHALWLT9fCoeg+EIYabi2+P1c7cDIdUPkEzo4GmI
+nCIpv7hGqQKBgEFUC+8GK+EinWoN1tDV+ZWCP5V9fJ43q1E7592bQBgIfZqLlnnP
+dEvVn6Ix3sZMoPMHj9Ra7qjh5Zc28ooCLEBS9tSW7uLJM44k7FCHihQ1GaFy+aLj
+HTA0aw7rutycKCq9uH+bjKDBgWDDj3tMAS2kOMCvcJ1UCquO3TtTlWzVAoGBAIDN
+8yJ/X0NEVNnnkKZTbWq+QILk3LD0e20fk6Nt5Es0ENxpkczjZEglIsM8Z/trnAnI
+b71UqWWu+tMPHYIka77tn1DwmpSnzxCW2+Ib3XMgsaP5fHBPMuFd3X3tSFo1NIxW
+yrwyE5nOT7rELhUyTTYoydLk2/09BMedKY7/BtDBAoGAXeX1pX74K1i/uWyYKwYZ
+sskRueSo9whDJuZWgNiUovArr57eA+oA+bKdFpiE419348bkFF8jNoGFQ6MXMedD
+LqHAYIj+ZPIC4+rObHqO5EaIyblgutwx3citkQp7HXDBxojnOKA9mKQXj1vxCaL1
+/1fFNJQCzEqwnKwnhI2MJ28=
+-----END PRIVATE KEY-----
diff --git a/test/emqx_crl_cache_SUITE_data/client.cert.pem b/test/emqx_crl_cache_SUITE_data/client.cert.pem
index e0405e673..b37d1b0ba 100644
--- a/test/emqx_crl_cache_SUITE_data/client.cert.pem
+++ b/test/emqx_crl_cache_SUITE_data/client.cert.pem
@@ -2,31 +2,31 @@
MIIFljCCA36gAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCU0Ux
EjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UECgwJTXlPcmdOYW1lMRkwFwYDVQQL
DBBNeUludGVybWVkaWF0ZUNBMRkwFwYDVQQDDBBNeUludGVybWVkaWF0ZUNBMB4X
-DTIyMDYxMzEyNDIwNVoXDTIzMDYyMzEyNDIwNVowdzELMAkGA1UEBhMCU0UxEjAQ
+DTIzMDExMjEzMDgxNloXDTMzMDQxOTEzMDgxNlowdzELMAkGA1UEBhMCU0UxEjAQ
BgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMRIwEAYDVQQKDAlN
eU9yZ05hbWUxGTAXBgNVBAsMEE15SW50ZXJtZWRpYXRlQ0ExETAPBgNVBAMMCE15
-Q2xpZW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtoHIpsxDnO4y
-TLKghUGkAIg5102fcVj2sQ4kJhybnN7tfbQ0gZo0GE8A7SQAYM/lO0VcDknp/nkz
-A8Lsc5Lc1SJ7z1Iyd+/ZUg3GJE/ijPoPdMlFU4/HndmoMdLhcflCRZiirnLGwdvT
-bBrlGD0alK/kOqbSc9LT3oFVXWo2XvAyNtBxU7dHznxT5JuFnPyCZvoY+FvSpCbP
-5rV0NLzdCpk+6C4KTs3YAaTh6kVvSCch55E7hE0I2KKLjz1Ge563vPEWOnB40p6w
-ZhzcwFIbiXmq8TpA342HInES1tFRwv7ZGSs+B8t/q9nGWTDf1as4+wBrQ/i35Xav
-sMuNp+O+mQIDAQABo4IBNjCCATIwCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMC
+Q2xpZW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvGuAShewEo8V
+/+aWVO/MuUt92m8K0Ut4nC2gOvpjMjf8mhSSf6KfnxPklsFwP4fdyPOjOiXwCsf3
+1QO5fjVr8to3iGTHhEyZpzRcRqmw1eYJC7iDh3BqtYLAT30R+Kq6Mk+f4tXB5Lp/
+2jXgdi0wshWagCPgJO3CtiwGyE8XSa+Q6EBYwzgh3NFbgYdJma4x+S86Y/5WfmXP
+zF//UipsFp4gFUqwGuj6kJrN9NnA1xCiuOxCyN4JuFNMfM/tkeh26jAp0OHhJGsT
+s3YiUm9Dpt7Rs7o0so9ov9K+hgDFuQw9HZW3WIJI99M5a9QZ4ZEQqKpABtYBl/Nb
+VPXcr+T3fQIDAQABo4IBNjCCATIwCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMC
BaAwMwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2VuZXJhdGVkIENsaWVudCBDZXJ0
-aWZpY2F0ZTAdBgNVHQ4EFgQUwRox6T4QUt1kUQDCuZ6NJNKGHIgwHwYDVR0jBBgw
-FoAUK6/VOTMLV9KBN/MTWbW7mlEImxUwDgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQW
+aWZpY2F0ZTAdBgNVHQ4EFgQUOIChBA5aZB0dPWEtALfMIfSopIIwHwYDVR0jBBgw
+FoAUTHCGOxVSibq1D5KqrrExQRO+c/MwDgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQW
MBQGCCsGAQUFBwMCBggrBgEFBQcDBDA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8v
bG9jYWxob3N0Ojk4NzgvaW50ZXJtZWRpYXRlLmNybC5wZW0wMQYIKwYBBQUHAQEE
JTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojk4NzcwDQYJKoZIhvcN
-AQELBQADggIBAEFjWfL32GKfOExZ+4FPUj80V282pJ4iEuRSmbti/EVZse0GsKvZ
-xF1swDdoTrcdNTruHxIKfojwKz28XP6JoM6MUruxQglwdwZGJGlC0KpanR7dvQHa
-XT/ushugHptobRh3+f47Gbyd0A0MKfGFLGLC1XZokdrvLPoKHCJWq/DRUgHMnn53
-FrM7a+JXZUpkSU+uqCPTMpkmuZc0E+SPVtLGiH71q1kbMzJKIKSuzkRCG91PW8fT
-B2PUmy4W6YV6MUSi+jHx5JDLvjwycTsNFBiK0zZtcKsaz9QWi/qnrjkCWR0LXaRZ
-W99ER7hEMe8J5CYt3lrmtaVL8lZ4TnoQE/Rsr1GBr7+WA9WnB/ijSG/3Q02hyqcK
-EaFE+aqOvY03UlIyk/m+PFoRwge9vERf2dGgFN4osbczDMwXc67jx1MKyFQLQvg4
-TcN7fXCbqQeWDH0RCAF4goFGqjq/KZQYHN+BOJ1cubUxbY4+9zuQ7pZ1s1tonchA
-TQFYbZNXKFUYTrgSSZRoJGGkSQkUKvARsraIdFvOt6qzLq4k86efQAgPDwFd1Kni
-+iML7b3fIzHAl00WYH/hvjyjiDbh9YJpGorflgzjyt/dDNcYk5mcMNJJyrY/kPUG
-3/eiMMIfW6UFSJq3ePK0NBFCzmdGWGUb+ZQS+JYP51eN2zsbZRm/Pfel
+AQELBQADggIBAE0qTL5WIWcxRPU9oTrzJ+oxMTp1JZ7oQdS+ZekLkQ8mP7T6C/Ew
+6YftjvkopnHUvn842+PTRXSoEtlFiTccmA60eMAai2tn5asxWBsLIRC9FH3LzOgV
+/jgyY7HXuh8XyDBCDD+Sj9QityO+accTHijYAbHPAVBwmZU8nO5D/HsxLjRrCfQf
+qf4OQpX3l1ryOi19lqoRXRGwcoZ95dqq3YgTMlLiEqmerQZSR6iSPELw3bcwnAV1
+hoYYzeKps3xhwszCTz2+WaSsUO2sQlcFEsZ9oHex/02UiM4a8W6hGFJl5eojErxH
+7MqaSyhwwyX6yt8c75RlNcUThv+4+TLkUTbTnWgC9sFjYfd5KSfAdIMp3jYzw3zw
+XEMTX5FaLaOCAfUDttPzn+oNezWZ2UyFTQXQE2CazpRdJoDd04qVg9WLpQxLYRP7
+xSFEHulOPccdAYF2C45yNtJAZyWKfGaAZIxrgEXbMkcdDMlYphpRwpjS8SIBNZ31
+KFE8BczKrg2qO0ywIjanPaRgrFVmeSvBKeU/YLQVx6fZMgOk6vtidLGZLyDXy0Ff
+yaZSoj+on++RDz1IXb96Y8scuNlfcYI8QeoNjwiLtf80BV8SRJiG4e/jTvMf/z9L
+kWrnDWvx4xkUmxFg4TK42dkNp7sEYBTlVVq9fjKE92ha7FGZRqsxOLNQ
-----END CERTIFICATE-----
diff --git a/test/emqx_crl_cache_SUITE_data/client.key.pem b/test/emqx_crl_cache_SUITE_data/client.key.pem
index 6df146424..2e767d81f 100644
--- a/test/emqx_crl_cache_SUITE_data/client.key.pem
+++ b/test/emqx_crl_cache_SUITE_data/client.key.pem
@@ -1,27 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEAtoHIpsxDnO4yTLKghUGkAIg5102fcVj2sQ4kJhybnN7tfbQ0
-gZo0GE8A7SQAYM/lO0VcDknp/nkzA8Lsc5Lc1SJ7z1Iyd+/ZUg3GJE/ijPoPdMlF
-U4/HndmoMdLhcflCRZiirnLGwdvTbBrlGD0alK/kOqbSc9LT3oFVXWo2XvAyNtBx
-U7dHznxT5JuFnPyCZvoY+FvSpCbP5rV0NLzdCpk+6C4KTs3YAaTh6kVvSCch55E7
-hE0I2KKLjz1Ge563vPEWOnB40p6wZhzcwFIbiXmq8TpA342HInES1tFRwv7ZGSs+
-B8t/q9nGWTDf1as4+wBrQ/i35XavsMuNp+O+mQIDAQABAoIBACZaJ5xFmH/F3nQX
-pXvbS2eBOQZxnWvoUg7q9dW8dUcF4cpksBP8H65sC7nJsvqlNXq7HJk0FyQOvBWy
-RJYU6qsvT+1FTK2/jV+c3WKMFwOhGNZl5VemA0C8mIe/1PhqdO7DIIygOfxLAaba
-EAKD9K4COGfK3rbQOw2rCBFVXI+ed0L2q+IzpyZdvtUFVdDKF9d5i3m2Qr6Ayeuq
-dpf2ig69nC+4I505govODX2O9+q7x+zkddooxL72OXdEQFHn8p1K69Zk9iLz2jPX
-HPVyKXGYzCOyfZZk/jJjBCv+8bkFQg/Ncm/KSBeBjp2Gxo6EjfERUhkShkxtOB5P
-pAETPXECgYEA4SP/hV/MbmXnouKvjoWCZ0dYH92lNVOMMr2Ij/nOpvxTAyc1FXg+
-m5NrvMjRnGu32QfLcJmaXnK9YjqAZD9koQ3DisS0FbwTa7V8NSR5ImJfPWpa2VMP
-SiyWQCh6Iba2852hl8Ryph7wbbSXAcocthx6dIuP/QsX2Q95jrh+g0cCgYEAz4XO
-MSjwsrT/9i3voVKD+7eWBYkFpOJ+piYxrrmIrkMSWrwPIE9KBFfn7TlPvBPCb+W2
-uN/eLtO8HDePKfJQdZxphvlmy8eeIfjzBhod2HELJy3ShHS57uaD7iLLhPXrV9Gm
-As99lS+kKGeH30j9Si53oQU0eIyH8iZX+beR3x8CgYB/DGhqZHghqIIByjhVjgPb
-skgJm3NaV25bR9ejn829L9DMi7iKCBQUiSmYHB8lTSgvYhWs0hFp0QgMQYUojRmF
-RRYe3gfd6AdxlbWk65MsEyU5rCXeU9/h9K1JQU5CbjBp439H/MTR982nquw4R0zS
-e9mioQs9OaBYjkIDhxtliwKBgCRtaHRYq2ezPfsItTesNF7LKxptov/+ghzIN5Bk
-IQn13BLxT/Zr9KIujBeoJ8br8QWTXS+2nFm78RlC526Finoaqqt2vASpVajA+mfn
-zbVgooSOFpYJp1m4PRBgKzl7sYQI2QtFQNYfNsGg6sjXFx8eaQFq2HsQsAxhjq/W
-+VQhAoGBALWrW12fQ0dJffRIXs/PCfwPy24071Q41YEadiZbV2/ZYlpDG6MQIENe
-KaDMpflkuHhR6RQZmfJoImLvpKH0iOoxnTzPJhDQHKvwiqei3v7SuN2vh7VWGCGH
-ikLROTT/oVrq4Z5XrZuAR1wtqRgi/KwvztG+QTzxLhygOmmkbSdt
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC8a4BKF7ASjxX/
+5pZU78y5S33abwrRS3icLaA6+mMyN/yaFJJ/op+fE+SWwXA/h93I86M6JfAKx/fV
+A7l+NWvy2jeIZMeETJmnNFxGqbDV5gkLuIOHcGq1gsBPfRH4qroyT5/i1cHkun/a
+NeB2LTCyFZqAI+Ak7cK2LAbITxdJr5DoQFjDOCHc0VuBh0mZrjH5Lzpj/lZ+Zc/M
+X/9SKmwWniAVSrAa6PqQms302cDXEKK47ELI3gm4U0x8z+2R6HbqMCnQ4eEkaxOz
+diJSb0Om3tGzujSyj2i/0r6GAMW5DD0dlbdYgkj30zlr1BnhkRCoqkAG1gGX81tU
+9dyv5Pd9AgMBAAECggEAAifx6dZKIeNkQ8OaNp5V2IKIPSqBOV4/h/xKMkUZXisV
+eDmTCf8du0PR7hfLqrt9xYsGDv+6FQ1/8K231l8qR0tP/6CTl/0ynM4qqEAGeFXN
+3h2LvM4liFbdjImechrcwcnVaNKg/DogT5zHUYSMtB/rokaG0VBO3IX/+SGz0aXi
+LOLAx6SPaLOVX9GYUCiigTSEDwaQA+F3F6J2fR4u8PrXo+OQUqxjQ/fGXWp+4IfA
+6djlpvzO2849/WPB1tL20iLXJlL2OL0UgQNtbKWTjexMe+wgCR5BzCwTyPsQvMwX
+YOQrTOwgF3b6O+gLks5wSRT0ivq1sKgzA534+X4M+wKBgQDirPTLlrYobOO8KUpV
+LOJU8x9leiRNU9CZWrW/mOw/BXGXikqNWvgL595vvADsjYciuRxSqEE7lClB8Pp9
+20TMlES9orx7gdoQJCodpNV1BuBJhE9YtUiXzWAj+7m3D9LsXM1ewW/2A7Vvopj3
+4zKY7uHAFlo3nXwLOfChG5/i9wKBgQDUy5fPFa58xmn7Elb6x4vmUDHg6P4pf75E
+XHRQvNA8I7DTrpqfcsF1N4WuJ3Lm//RSpw7bnyqP20GoEfGHu/iCUPf29B7CuXhO
+vvD+I8uPdn8EcKUBWV+V0xNQN/gCe0TzrEjAkZcO2Lq0j93R8HVl3BbowxgRvQV9
+GmxQG/boKwKBgFeV8uSzsGEAaiKrZbBxrmaappgEUQCcES8gULfes/JJ/TFL2zCx
+ZMTc7CMKZuUAbqXpFtuNbd9CiYqUPYXh8ryF0eXgeqnSa9ruzmMz7NLSPFnLyQkC
+yzD0x2BABOuKLrrrxOMHJWbO2g1vq2GlJUjYjNw3BtcUf/iqg6MM1IPTAoGAWYWJ
+SSqS7JVAcsrFYt1eIrdsNHVwr565OeM3X9v/Mr3FH1jeXeQWNSz1hU29Ticx7y+u
+1YBBlKGmHoHl/bd7lb9ggjkzU7JZRa+YjSIb+i/cwc5t7IJf7xUMk/vnz4tyd5zs
+Qm89gJZ2/Y1kwXSKvx53WNbyokvGKlpaZN1O418CgYACliGux77pe4bWeXSFFd9N
+50ipxDLVghw1c5AiZn25GR5YHJZaV4R0wmFcHdZvogLKi0jDMPvU69PaiT8eX/A1
+COkxv7jY1vtKlEtb+gugMjMN8wvb2va4kyFamjqnleiZlBSqIF/Y17wBoMvaWgZ0
+bEPCN//ts5hBwgb1TwGrrg==
+-----END PRIVATE KEY-----
diff --git a/test/emqx_crl_cache_SUITE_data/emqx_crl_cache_http_server.erl b/test/emqx_crl_cache_SUITE_data/emqx_crl_cache_http_server.erl
index cceee7333..925ac3742 100644
--- a/test/emqx_crl_cache_SUITE_data/emqx_crl_cache_http_server.erl
+++ b/test/emqx_crl_cache_SUITE_data/emqx_crl_cache_http_server.erl
@@ -3,8 +3,11 @@
-behaviour(gen_server).
-compile([nowarn_export_all, export_all]).
+set_crl(CRLPem) ->
+ ets:insert(?MODULE, {crl, CRLPem}).
+
%%--------------------------------------------------------------------
-%% APIs
+%% `gen_server' APIs
%%--------------------------------------------------------------------
start_link(Parent, BasePort, CRLPem, Opts) ->
@@ -14,9 +17,11 @@ start_link(Parent, BasePort, CRLPem, Opts) ->
gen_server:start_link(?MODULE, {Parent, BasePort, CRLPem, Opts}, []).
init({Parent, BasePort, CRLPem, Opts}) ->
- ok = start_http(Parent, CRLPem, [{port, BasePort} | Opts]),
+ Tab = ets:new(?MODULE, [named_table, ordered_set, public]),
+ ets:insert(Tab, {crl, CRLPem}),
+ ok = start_http(Parent, [{port, BasePort} | Opts]),
Parent ! {self(), ready},
- {ok, #{parent => Parent, crl_pem => CRLPem}}.
+ {ok, #{parent => Parent}}.
handle_call(_Request, _From, State) ->
{reply, ignored, State}.
@@ -40,9 +45,9 @@ stop(Pid) ->
%% Callbacks
%%--------------------------------------------------------------------
-start_http(Parent, CRLPem, Opts) ->
+start_http(Parent, Opts) ->
{ok, _Pid1} = cowboy:start_clear(http, Opts, #{
- env => #{dispatch => compile_router(Parent, CRLPem)}
+ env => #{dispatch => compile_router(Parent)}
}),
ok.
@@ -50,15 +55,16 @@ stop_http() ->
cowboy:stop_listener(http),
ok.
-compile_router(Parent, CRLPem) ->
+compile_router(Parent) ->
{ok, _} = application:ensure_all_started(cowboy),
cowboy_router:compile([
- {'_', [{'_', ?MODULE, #{parent => Parent, crl_pem => CRLPem}}]}
+ {'_', [{'_', ?MODULE, #{parent => Parent}}]}
]).
-init(Req, #{parent := Parent, crl_pem := CRLPem} = State) ->
+init(Req, #{parent := Parent} = State) ->
%% assert
<<"GET">> = cowboy_req:method(Req),
+ [{crl, CRLPem}] = ets:lookup(?MODULE, crl),
Parent ! http_get,
Reply = reply(Req, CRLPem),
{ok, Reply, State}.
diff --git a/test/emqx_crl_cache_SUITE_data/intermediate-not-revoked.crl.pem b/test/emqx_crl_cache_SUITE_data/intermediate-not-revoked.crl.pem
new file mode 100644
index 000000000..e484b44c0
--- /dev/null
+++ b/test/emqx_crl_cache_SUITE_data/intermediate-not-revoked.crl.pem
@@ -0,0 +1,19 @@
+-----BEGIN X509 CRL-----
+MIIDJTCCAQ0CAQEwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCU0UxEjAQBgNV
+BAgMCVN0b2NraG9sbTESMBAGA1UECgwJTXlPcmdOYW1lMRkwFwYDVQQLDBBNeUlu
+dGVybWVkaWF0ZUNBMRkwFwYDVQQDDBBNeUludGVybWVkaWF0ZUNBFw0yMzAxMTIx
+MzA4MTZaFw0zMzAxMDkxMzA4MTZaoG4wbDAfBgNVHSMEGDAWgBRMcIY7FVKJurUP
+kqqusTFBE75z8zA8BgNVHRwENTAzoC6gLIYqaHR0cDovL2xvY2FsaG9zdDo5ODc4
+L2ludGVybWVkaWF0ZS5jcmwucGVthAH/MAsGA1UdFAQEAgIQADANBgkqhkiG9w0B
+AQsFAAOCAgEAJGOZuqZL4m7zUaRyBrxeT6Tqo+XKz7HeD5zvO4BTNX+0E0CRyki4
+HhIGbxjv2NKWoaUv0HYbGAiZdO4TaPu3w3tm4+pGEDBclBj2KTdbB+4Hlzv956gD
+KXZ//ziNwx1SCoxxkxB+TALxReN0shE7Mof9GlB5HPskhLorZgg/pmgJtIykEpsq
+QAjJo4aq+f2/L+9dzRM205fVFegtsHvgEVNKz6iK6skt+kDhj/ks9BKsnfCDIGr+
+XnPYwS9yDnnhFdoJ40AQQDtomxggAjfgcSnqtHCxZwKJohuztbSWUgD/4yxzlrwP
+Dk1cT/Ajjjqb2dXVOfTLK1VB2168uuouArxZ7KYbXwBjHduYWGGkA6FfkNJO/jpF
+SL9qhX3oxcRF3hDhWigN1ZRD7NpDKwVal3Y9tmvO5bWhb5VF+3qv0HGeSGp6V0dp
+sjwhIj+78bkUrcXxrivACLAXgSTGonx1uXD+T4P4NCt148dgRAbgd8sUXK5FcgU2
+cdBl8Kv2ZUjEaod5gUzDtf22VGSoO9lHvfHdpG9o2H3wC7s4tyLTidNrduIguJff
+IIgc44Y252iV0sOmZ5S0jjTRiF1YUUPy9qA/6bOnr2LohbwbNZv9tDlNj8cdhxUz
+cKiS+c7Qsz+YCcrp19QRiJoQae/gUqz7kmUZQgyPmDd+ArE0V+kDZEE=
+-----END X509 CRL-----
diff --git a/test/emqx_crl_cache_SUITE_data/intermediate-revoked.crl.pem b/test/emqx_crl_cache_SUITE_data/intermediate-revoked.crl.pem
new file mode 100644
index 000000000..4c5cdd441
--- /dev/null
+++ b/test/emqx_crl_cache_SUITE_data/intermediate-revoked.crl.pem
@@ -0,0 +1,20 @@
+-----BEGIN X509 CRL-----
+MIIDPDCCASQCAQEwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCU0UxEjAQBgNV
+BAgMCVN0b2NraG9sbTESMBAGA1UECgwJTXlPcmdOYW1lMRkwFwYDVQQLDBBNeUlu
+dGVybWVkaWF0ZUNBMRkwFwYDVQQDDBBNeUludGVybWVkaWF0ZUNBFw0yMzAxMTIx
+MzA4MTZaFw0zMzAxMDkxMzA4MTZaMBUwEwICEAIXDTIzMDExMjEzMDgxNlqgbjBs
+MB8GA1UdIwQYMBaAFExwhjsVUom6tQ+Sqq6xMUETvnPzMDwGA1UdHAQ1MDOgLqAs
+hipodHRwOi8vbG9jYWxob3N0Ojk4NzgvaW50ZXJtZWRpYXRlLmNybC5wZW2EAf8w
+CwYDVR0UBAQCAhABMA0GCSqGSIb3DQEBCwUAA4ICAQCPadbaehEqLv4pwqF8em8T
+CW8TOQ4Vjz02uiVk9Bo0za1dQqQmwCBA6UE1BcOh+aWzQxBRz56NeUcfhgDxTntG
+xLs896N9MHIG6UxpqJH8cH+DXKHsQjvvCjXtiObmBQR1RiG5C1vEMkfzTt/WSrq5
+7blowLDs4NP6YbtqXEyyUkF7DQSUEUuIDWPQdx1f++nSpVaHWW4xpoO4umesaJco
+FuxaXQnZpTHHQfqUJVIL2Mmzvez9thgfKTV3vgkYrGiSLW2m2+Tfga30pUc0qaVI
+RrBVORVbcu9m1sV0aJyk96b2T/+i2FRR/np4TOcLgckBpHKeK2FH69lHFr0W/71w
+CErNTxahoh82Yi8POenu+S1m2sDnrF1FMf+ZG/i2wr0nW6/+zVGQsEOw77Spbmei
+dbEchu3iWF1XEO/n4zVBzl6a1o2RyVg+1pItYd5C5bPwcrfZnBrm4WECPxO+6rbW
+2/wz9Iku4XznTLqLEpXLAtenAdo73mLGC7riviX7mhcxfN2UjNfLuVGHmG8XwIsM
+Lgpr6DKaxHwpHgW3wA3SGJrY5dj0TvGWaoInrNt1cOMnIpoxRNy5+ko71Ubx3yrV
+RhbUMggd1GG1ct9uZn82v74RYF6J8Xcxn9vDFJu5LLT5kvfy414kdJeTXKqfKXA/
+atdUgFa0otoccn5FzyUuzg==
+-----END X509 CRL-----
diff --git a/test/emqx_crl_cache_SUITE_data/intermediate.crl.pem b/test/emqx_crl_cache_SUITE_data/intermediate.crl.pem
deleted file mode 100644
index a119cede2..000000000
--- a/test/emqx_crl_cache_SUITE_data/intermediate.crl.pem
+++ /dev/null
@@ -1,20 +0,0 @@
------BEGIN X509 CRL-----
-MIIDPDCCASQCAQEwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCU0UxEjAQBgNV
-BAgMCVN0b2NraG9sbTESMBAGA1UECgwJTXlPcmdOYW1lMRkwFwYDVQQLDBBNeUlu
-dGVybWVkaWF0ZUNBMRkwFwYDVQQDDBBNeUludGVybWVkaWF0ZUNBFw0yMjA3MjAy
-MDIzNTNaFw0zMjEwMjUyMDIzNTNaMBUwEwICEAIXDTIyMDYxMzEyNDIwNVqgbjBs
-MB8GA1UdIwQYMBaAFCuv1TkzC1fSgTfzE1m1u5pRCJsVMDwGA1UdHAQ1MDOgLqAs
-hipodHRwOi8vbG9jYWxob3N0Ojk4NzgvaW50ZXJtZWRpYXRlLmNybC5wZW2EAf8w
-CwYDVR0UBAQCAhADMA0GCSqGSIb3DQEBCwUAA4ICAQBbWdqRFsIrG6coL6ln1RL+
-uhgW9l3XMmjNlyiYHHNzOgnlBok9xu9UdaVCOKC6GEthWSzSlBY1AZugje57DQQd
-RkIJol9am94lKMTjF/qhzFLiSjho8fwZGDGyES5YeZXkLqNMOf6m/drKaI3iofWf
-l63qU9jY8dnSrVDkwgCguUL2FTx60v5H9NPxSctQ3VDxDvDj0sTAcHFknQcZbfvY
-ZWpOYNS0FAJlQPVK9wUoDxI0LhrWDq5h/T1jcGO34fPT8RUA5HRtFVUevqSuOLWx
-WTfTx5oDeMZPJTvHWUcg4yMElHty4tEvtkFxLSYbZqj7qTU+mi/LAN3UKBH/gBEN
-y2OsJvFhVRgHf+zPYegf3WzBSoeaXNAJZ4UnRo34P9AL3Mrh+4OOUP++oYRKjWno
-pYtAmTrIwEYoLyisEhhZ6aD92f/Op3dIYsxwhHt0n0lKrbTmUfiJUAe7kUZ4PMn4
-Gg/OHlbEDaDxW1dCymjyRGl+3/8kjy7bkYUXCf7w6JBeL2Hw2dFp1Gh13NRjre93
-PYlSOvI6QNisYGscfuYPwefXogVrNjf/ttCksMa51tUk+ylw7ZMZqQjcPPSzmwKc
-5CqpnQHfolvRuN0xIVZiAn5V6/MdHm7ocrXxOkzWQyaoNODTq4js8h8eYXgAkt1w
-p1PTEFBucGud7uBDE6Ub6A==
------END X509 CRL-----
diff --git a/test/emqx_crl_cache_SUITE_data/server.cert.pem b/test/emqx_crl_cache_SUITE_data/server.cert.pem
index 41f04044a..38cc63534 100644
--- a/test/emqx_crl_cache_SUITE_data/server.cert.pem
+++ b/test/emqx_crl_cache_SUITE_data/server.cert.pem
@@ -2,34 +2,34 @@
MIIGCTCCA/GgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCU0Ux
EjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UECgwJTXlPcmdOYW1lMRkwFwYDVQQL
DBBNeUludGVybWVkaWF0ZUNBMRkwFwYDVQQDDBBNeUludGVybWVkaWF0ZUNBMB4X
-DTIyMDYxMzEyNDIwNVoXDTIzMDYyMzEyNDIwNVoweDELMAkGA1UEBhMCU0UxEjAQ
+DTIzMDExMjEzMDgxNloXDTMzMDQxOTEzMDgxNloweDELMAkGA1UEBhMCU0UxEjAQ
BgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMRIwEAYDVQQKDAlN
eU9yZ05hbWUxGTAXBgNVBAsMEE15SW50ZXJtZWRpYXRlQ0ExEjAQBgNVBAMMCWxv
-Y2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOpBaUId5ga7
-NzIXvSvnzqLAsyejjEZYcSVwWQinAH3il/Y/NbUOakPbDCQbb3U7p3oD6H0R0pVx
-x0nQyhh2XlSNRc8ORAcrZlfS6/Su5o07htSKL7FZ0ySYbia2EQ6ZRFpke/+UPwr3
-eXSQUhdOX+iA0Uf5gN3fUtgGorCuT2POGemGjBvYiPoA3aD1MxHyV7PnI7CoTw8Y
-cvFiXIW0Jqp69ZgSuzrmfIiMyum94pfkB1ljxao9TBSFqJTn2A3ysNZAXpGPyfP+
-1zPznxiMSvAFLihUVjKwE+glSNKvdhUgl3yAxaFI9+IeoAytPNmQU+E+o4YCuRHT
-TCM1Tch95/ECAwEAAaOCAagwggGkMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQD
+Y2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKdU9FaA/n0Z
+TXkd10XA9l+UV9xKR65ZTy2ApCFlw2gGWLiUh96a6hX+GQZFUV7ECIDDf+7nC85o
+xo1Xyf0rHGABQ0uHlhqSemc12F9APIzRLlQkhtV4vMBBbGQFekje4F9bhY9JQtGd
+XJGmwsR+XWo6SUY7K5l9FuSSSRXC0kSYYQfSTPR/LrF6efdHf+ZN4huP7lM2qIFd
+afX+qBOI1/Y2LtITo2TaU/hXyKh9wEiuynoq0RZ2KkYQll5cKD9fSD+pW3Xm0XWX
+TQy4RZEe3WoYEQsklNw3NC92ocA/PQB9BGNO1fKhzDn6kW2HxDxruDKOuO/meGek
+ApCayu3e/I0CAwEAAaOCAagwggGkMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQD
AgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2Vy
-dGlmaWNhdGUwHQYDVR0OBBYEFAPF2lui5EhHG8lTbpglZ3BZYj2kMIGaBgNVHSME
-gZIwgY+AFCuv1TkzC1fSgTfzE1m1u5pRCJsVoXOkcTBvMQswCQYDVQQGEwJTRTES
+dGlmaWNhdGUwHQYDVR0OBBYEFGy5LQPzIelruJl7mL0mtUXM57XhMIGaBgNVHSME
+gZIwgY+AFExwhjsVUom6tQ+Sqq6xMUETvnPzoXOkcTBvMQswCQYDVQQGEwJTRTES
MBAGA1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xEjAQBgNVBAoM
CU15T3JnTmFtZTERMA8GA1UECwwITXlSb290Q0ExETAPBgNVBAMMCE15Um9vdENB
ggIQADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwOwYDVR0f
BDQwMjAwoC6gLIYqaHR0cDovL2xvY2FsaG9zdDo5ODc4L2ludGVybWVkaWF0ZS5j
cmwucGVtMDEGCCsGAQUFBwEBBCUwIzAhBggrBgEFBQcwAYYVaHR0cDovL2xvY2Fs
-aG9zdDo5ODc3MA0GCSqGSIb3DQEBCwUAA4ICAQCCTuM+KXLH2EuUn+TB78LgYrzl
-/dlPj5UWPTDgiF+93fQSNvkg2uWVKPkckKNKttg+VyoRnRX87vI/bZp+dzvHfp5v
-hXZuv2TkvA8ZMnJ6QUbAmiQlNTqNh0esftfXbmZAo+VvtwC/NZfevH08SO1+3R4S
-PMC/Bnqmv/G3mR2qWqLu4X1ikpkgNGj4DTEkkqZFerlRyaeZHZLSVRNt6x3u4lXa
-KQKbTPYP+yYpJfi0eBFy6t0hdN63BZDao3z9fulpxfjWfL32gt+TQLMf/6aJugs+
-+2BS0LAWXr9mP89Ljzo4V0G6pMBQ84/oK+mYtkFCNjRaAT+b4xGE1Ttp9H40xRZY
-hm2xzVH05PgXw+IJdfnvH+245vtPUTtrnysy9FEfF7px3tAAZCiT4ogrgr52+VK6
-vGliEIxZq2ICWCK1Wy0i9zZFk3lQCFF3bWjKQCapCAFPE0naZZv7g10HkXl8+5Gc
-1aSyP2LcroUyDfYx8VwKw1sLi1KtO71hs/TOTeoAPzFBmZA8h325mU5krpQtuNPg
-TRxAPLztWltHR3T+WKOUMq+YZx0IiUvS6VZaCeoQeXTSZZTX5j6BXz8ffmyAcXMZ
-tNATxIgDyGUfw0V6fiKQrnZCqP+fF/tdks5LKeU6tYE4JKWDarIzNNnPmhPQnJOI
-YeW1Ts3aExER9EorUw==
+aG9zdDo5ODc3MA0GCSqGSIb3DQEBCwUAA4ICAQCX3EQgiCVqLhnCNd0pmptxXPxo
+l1KyZkpdrFa/NgSqRhkuZSAkszwBDDS/gzkHFKEUhmqs6/UZwN4+Rr3LzrHonBiN
+aQ6GeNNXZ/3xAQfUCwjjGmz9Sgw6kaX19Gnk2CjI6xP7T+O5UmsMI9hHUepC9nWa
+XX2a0hsO/KOVu5ZZckI16Ek/jxs2/HEN0epYdvjKFAaVmzZZ5PATNjrPQXvPmq2r
+x++La+3bXZsrH8P2FhPpM5t/IxKKW/Tlpgz92c2jVSIHF5khSA/MFDC+dk80OFmm
+v4ZTPIMuZ//Q+wo0f9P48rsL9D27qS7CA+8pn9wu+cfnBDSt7JD5Yipa1gHz71fy
+YTa9qRxIAPpzW2v7TFZE8eSKFUY9ipCeM2BbdmCQGmq4+v36b5TZoyjH4k0UVWGo
+Gclos2cic5Vxi8E6hb7b7yZpjEfn/5lbCiGMfAnI6aoOyrWg6keaRA33kaLUEZiK
+OgFNbPkjiTV0ZQyLXf7uK9YFhpVzJ0dv0CFNse8rZb7A7PLn8VrV/ZFnJ9rPoawn
+t7ZGxC0d5BRSEyEeEgsQdxuY4m8OkE18zwhCkt2Qs3uosOWlIrYmqSEa0i/sPSQP
+jiwB4nEdBrf8ZygzuYjT5T9YRSwhVox4spS/Av8Ells5JnkuKAhCVv9gHxYwbj0c
+CzyLJgE1z9Tq63m+gQ==
-----END CERTIFICATE-----
diff --git a/test/emqx_crl_cache_SUITE_data/server.key.pem b/test/emqx_crl_cache_SUITE_data/server.key.pem
index ab62ccffa..d456ece72 100644
--- a/test/emqx_crl_cache_SUITE_data/server.key.pem
+++ b/test/emqx_crl_cache_SUITE_data/server.key.pem
@@ -1,27 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEA6kFpQh3mBrs3Mhe9K+fOosCzJ6OMRlhxJXBZCKcAfeKX9j81
-tQ5qQ9sMJBtvdTunegPofRHSlXHHSdDKGHZeVI1Fzw5EBytmV9Lr9K7mjTuG1Iov
-sVnTJJhuJrYRDplEWmR7/5Q/Cvd5dJBSF05f6IDRR/mA3d9S2AaisK5PY84Z6YaM
-G9iI+gDdoPUzEfJXs+cjsKhPDxhy8WJchbQmqnr1mBK7OuZ8iIzK6b3il+QHWWPF
-qj1MFIWolOfYDfKw1kBekY/J8/7XM/OfGIxK8AUuKFRWMrAT6CVI0q92FSCXfIDF
-oUj34h6gDK082ZBT4T6jhgK5EdNMIzVNyH3n8QIDAQABAoIBABG/NN86bqPR6SOV
-YtKBtEjmOmxlWoo1xxSkB0q9hC8FTKfuL/5wgiJz5N6TaYVDKLP4udNH12FVBlkU
-RUtHJGxZa5F9LjAw3IcIxrF50qOef994PJa+DF34YlfycSZe/Cuw8yfwrjoBd6Ua
-De4QFPoDUFeYkme8tIUDM64Y9pDD9llfS/ZOQiCAgn+8mk99uCnJVIFo19Umof5N
-009Cn6PElDKOw40Pz8s4ZJ9bpXH/YPKLeNRn0wlgFzYGhJ1z74YBmXF3CUHU6WEy
-pVbJkPDAwnFScuAjpwJmzO4TDBfTBd5L/CJy4nsLpY06UOm1PHuUpAhPAgiwuADR
-TM3100ECgYEA/F5Glpb0ROR38UTgCSOT8xvxyzNV84YMaQrWzGMUxqJpWWyVaKEy
-k/jzUxUKbkUrJDz/Y+bcGElVCI+g8x0yekpcLn1mtB8XwltpmCSBhNBTMgUHnI9v
-M+PadQhyZiJFrE/eoXo0V/K30Xv8jokWhWGTIkCdhiVSks/0eWSzPzkCgYEA7aBo
-d/0e0R2Y2wXDsfGqxcKFs4IMHnzNl0isycakLOoZwinKPvb1MSg1zxW0mU+I1c/n
-18rftcS8/siai26iXErDeZnvtlj+OKzQboRQf5JvDHp+rXBjGpZSmI2Nb+kAQ71S
-JeIkglfBHGCKAMJQjE3N3U9YMBqCB1xdJ/TnNnkCgYA4PJnmPMU6BN9leD+kSbVS
-W0vKSCpDFf/1+GBdM0cR7GclcjjpE+K9bqBqRyoH4In4jU8r5+nrz4uPWNI42qzA
-64kXIwKb6MHWoaAqMxhZjEK9xrknfh79pSytH7C+aay09SdbPGwlnQSxPbvN12aZ
-WmD7JQL1PaPk60pDMtluoQKBgDYJLxhyB+r3twW/VtQFJ5dW975tSUI5kSrgzOIJ
-eNX52iesByCwWet2wF26Ctp+Gpi8cXVB3gNgnLW3emVQoD0qhy8E0Vz++bh7m941
-2nRYIUaOKHZaQz8NhfTI46vaKUQ+LgsNVM4LFI/WaCtqBJUTMEguPdiafo0b9Ncc
-OuPJAoGBAPSYfuXinT9IAVwzIjc1TkfdN3G39ckBFQtNSvIoynBro+dlh3us+QJi
-i24MtpUiBbCKmFZrrk5WrddxNLbE/JSa40+O+s1RaP3SfNuDGTWMe3HGMh+PVH8D
-yte7L8pWouXSQPLVXUb3SmPboxBvXwPZMB54gkbKcSB2Gg7CjfCS
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCnVPRWgP59GU15
+HddFwPZflFfcSkeuWU8tgKQhZcNoBli4lIfemuoV/hkGRVFexAiAw3/u5wvOaMaN
+V8n9KxxgAUNLh5YaknpnNdhfQDyM0S5UJIbVeLzAQWxkBXpI3uBfW4WPSULRnVyR
+psLEfl1qOklGOyuZfRbkkkkVwtJEmGEH0kz0fy6xenn3R3/mTeIbj+5TNqiBXWn1
+/qgTiNf2Ni7SE6Nk2lP4V8iofcBIrsp6KtEWdipGEJZeXCg/X0g/qVt15tF1l00M
+uEWRHt1qGBELJJTcNzQvdqHAPz0AfQRjTtXyocw5+pFth8Q8a7gyjrjv5nhnpAKQ
+msrt3vyNAgMBAAECggEABnWvIQ/Fw0qQxRYz00uJt1LguW5cqgxklBsdOvTUwFVO
+Y4HIZP2R/9tZV/ahF4l10pK5g52DxSoiUB6Ne6qIY+RolqfbUZdKBmX7vmGadM02
+fqUSV3dbwghEiO/1Mo74FnZQB6IKZFEw26aWakN+k7VAUufB3SEJGzXSgHaO63ru
+dFGSiYI8U+q+YnhUJjCnmI12fycNfy451TdUQtGZb6pNmm5HRUF6hpAV8Le9LojP
+Ql9eacPpsrzU15X5ElCQZ/f9iNh1bplcISuhrULgKUKOvAVrBlEK67uRVy6g98xA
+c/rgNLkbL/jZEsAc3/vHAyFgd3lABfwpBGLHej3QgQKBgQDFNYmfBNQr89HC5Zc+
+M6jXcAT/R+0GNczBTfC4iyNemwqsumSSRelNZ748UefKuS3F6Mvb2CBqE2LbB61G
+hrnCffG2pARjZ491SefRwghhWWVGLP1p8KliLgOGBehA1REgJb+XULncjuHZuh4O
+LVn3HVnWGxeBGg+yKa6Z4YQi3QKBgQDZN0O8ZcZY74lRJ0UjscD9mJ1yHlsssZag
+njkX/f0GR/iVpfaIxQNC3gvWUy2LsU0He9sidcB0cfej0j/qZObQyFsCB0+utOgy
++hX7gokV2pes27WICbNWE2lJL4QZRJgvf82OaEy57kfDrm+eK1XaSZTZ10P82C9u
+gAmMnontcQKBgGu29lhY9tqa7jOZ26Yp6Uri8JfO3XPK5u+edqEVvlfqL0Zw+IW8
+kdWpmIqx4f0kcA/tO4v03J+TvycLZmVjKQtGZ0PvCkaRRhY2K9yyMomZnmtaH4BB
+5wKtR1do2pauyg/ZDnDDswD5OfsGYWw08TK8YVlEqu3lIjWZ9rguKVIxAoGAZYUk
+zVqr10ks3pcCA2rCjkPT4lA5wKvHgI4ylPoKVfMxRY/pp4acvZXV5ne9o7pcDBFh
+G7v5FPNnEFPlt4EtN4tMragJH9hBZgHoYEJkG6islweg0lHmVWaBIMlqbfzXO+v5
+gINSyNuLAvP2CvCqEXmubhnkFrpbgMOqsuQuBqECgYB3ss2PDhBF+5qoWgqymFof
+1ovRPuQ9sPjWBn5IrCdoYITDnbBzBZERx7GLs6A/PUlWgST7jkb1PY/TxYSUfXzJ
+SNd47q0mCQ+IUdqUbHgpK9b1ncwLMsnexpYZdHJWRLgnUhOx7OMjJc/4iLCAFCoN
+3KJ7/V1keo7GBHOwnsFcCA==
+-----END PRIVATE KEY-----
diff --git a/test/emqx_exclusive_sub_SUITE.erl b/test/emqx_exclusive_sub_SUITE.erl
new file mode 100644
index 000000000..e5eec83e9
--- /dev/null
+++ b/test/emqx_exclusive_sub_SUITE.erl
@@ -0,0 +1,170 @@
+%%--------------------------------------------------------------------
+%% Copyright (c) 2018-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%--------------------------------------------------------------------
+
+-module(emqx_exclusive_sub_SUITE).
+
+-compile(export_all).
+-compile(nowarn_export_all).
+
+-include_lib("emqx/include/emqx.hrl").
+-include_lib("emqx/include/emqx_mqtt.hrl").
+-include_lib("eunit/include/eunit.hrl").
+
+-define(TAB, emqx_exclusive_subscription).
+-define(EXCLUSIVE_TOPIC, <<"$exclusive/t/1">>).
+-define(NORMAL_TOPIC, <<"t/1">>).
+
+-define(CHECK_SUB(Client, Code), ?CHECK_SUB(Client, ?EXCLUSIVE_TOPIC, Code)).
+-define(CHECK_SUB(Client, Topic, Code),
+ {ok, _, [Code]} = emqtt:subscribe(Client, Topic, [])
+).
+
+all() -> emqx_ct:all(?MODULE).
+
+init_per_suite(Config) ->
+ emqx_ct_helpers:start_apps([]),
+ enable_exclusive_sub(true),
+ Config.
+
+end_per_suite(_Config) ->
+ reset_zone_env(),
+ emqx_ct_helpers:stop_apps([]).
+
+end_per_testcase(_TestCase, _Config) ->
+ mnesia:clear_table(?TAB).
+
+%% test that this feature is working during the whole session life cycle
+t_exclusive_sub(_) ->
+ {ok, C1} = emqtt:start_link([
+ {clientid, <<"client1">>},
+ {clean_start, false},
+ {proto_ver, v5},
+ {properties, #{'Session-Expiry-Interval' => 100}}
+ ]),
+ {ok, _} = emqtt:connect(C1),
+ ?CHECK_SUB(C1, 0),
+
+ {ok, C2} = emqtt:start_link([
+ {clientid, <<"client2">>},
+ {clean_start, false},
+ {proto_ver, v5}
+ ]),
+ {ok, _} = emqtt:connect(C2),
+ ?CHECK_SUB(C2, ?RC_QUOTA_EXCEEDED),
+
+ %% keep exclusive even disconnected
+ ok = emqtt:disconnect(C1),
+ timer:sleep(1000),
+
+ ?CHECK_SUB(C2, ?RC_QUOTA_EXCEEDED),
+
+ ok = emqtt:disconnect(C2).
+
+%% test this feature does not interfere with normal subs
+t_allow_normal_sub(_) ->
+ {ok, C1} = emqtt:start_link([
+ {clientid, <<"client1">>},
+ {proto_ver, v5}
+ ]),
+ {ok, _} = emqtt:connect(C1),
+ ?CHECK_SUB(C1, 0),
+
+ {ok, C2} = emqtt:start_link([
+ {clientid, <<"client2">>},
+ {proto_ver, v5}
+ ]),
+ {ok, _} = emqtt:connect(C2),
+ ?CHECK_SUB(C2, ?NORMAL_TOPIC, 0),
+
+ ok = emqtt:disconnect(C1),
+ ok = emqtt:disconnect(C2).
+
+%% test the exclusive topics can be released correctly
+t_unsub(_) ->
+ {ok, C1} = emqtt:start_link([
+ {clientid, <<"client1">>},
+ {proto_ver, v5}
+ ]),
+ {ok, _} = emqtt:connect(C1),
+ ?CHECK_SUB(C1, 0),
+
+ {ok, C2} = emqtt:start_link([
+ {clientid, <<"client2">>},
+ {proto_ver, v5}
+ ]),
+ {ok, _} = emqtt:connect(C2),
+ ?CHECK_SUB(C2, ?RC_QUOTA_EXCEEDED),
+
+ {ok, #{}, [0]} = emqtt:unsubscribe(C1, ?EXCLUSIVE_TOPIC),
+
+ ?CHECK_SUB(C2, 0),
+
+ ok = emqtt:disconnect(C1),
+ ok = emqtt:disconnect(C2).
+
+%% test whether the exclusive topics would auto-clean after the session was cleaned
+t_clean_session(_) ->
+ erlang:process_flag(trap_exit, true),
+ {ok, C1} = emqtt:start_link([
+ {clientid, <<"client1">>},
+ {clean_start, true},
+ {proto_ver, v5},
+ {properties, #{'Session-Expiry-Interval' => 0}}
+ ]),
+ {ok, _} = emqtt:connect(C1),
+ ?CHECK_SUB(C1, 0),
+
+ {ok, C2} = emqtt:start_link([
+ {clientid, <<"client2">>},
+ {proto_ver, v5}
+ ]),
+ {ok, _} = emqtt:connect(C2),
+ ?CHECK_SUB(C2, ?RC_QUOTA_EXCEEDED),
+
+ %% auto clean when session was cleand
+ ok = emqtt:disconnect(C1),
+
+ timer:sleep(1000),
+
+ ?CHECK_SUB(C2, 0),
+
+ ok = emqtt:disconnect(C2).
+
+%% test the feature switch
+t_feat_disabled(_) ->
+ enable_exclusive_sub(false),
+
+ {ok, C1} = emqtt:start_link([
+ {clientid, <<"client1">>},
+ {proto_ver, v5}
+ ]),
+ {ok, _} = emqtt:connect(C1),
+ ?CHECK_SUB(C1, ?RC_TOPIC_FILTER_INVALID),
+ ok = emqtt:disconnect(C1),
+
+ enable_exclusive_sub(true).
+
+enable_exclusive_sub(Enable) ->
+ emqx_zone:set_env(
+ external,
+ '$mqtt_sub_caps',
+ #{exclusive_subscription => Enable}
+ ),
+ timer:sleep(50).
+
+reset_zone_env() ->
+ emqx_zone:unset_env(external, '$mqtt_sub_caps'),
+ timer:sleep(50).
diff --git a/test/emqx_mqtt_caps_SUITE.erl b/test/emqx_mqtt_caps_SUITE.erl
index 58170a181..925e9af44 100644
--- a/test/emqx_mqtt_caps_SUITE.erl
+++ b/test/emqx_mqtt_caps_SUITE.erl
@@ -62,5 +62,5 @@ t_check_sub(_) ->
?assertEqual({error, ?RC_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED},
emqx_mqtt_caps:check_sub(ClientInfo, <<"topic">>, SubOpts#{share => true}))
after
- emqx_zone:unset_env(zone, '$mqtt_pub_caps')
+ emqx_zone:unset_env(zone, '$mqtt_sub_caps')
end.
diff --git a/test/emqx_node_helpers.erl b/test/emqx_node_helpers.erl
index 938318690..0c0250885 100644
--- a/test/emqx_node_helpers.erl
+++ b/test/emqx_node_helpers.erl
@@ -56,6 +56,7 @@ start_slave(Name, Opts) ->
throw(Other)
end,
pong = net_adm:ping(Node),
+ put_slave_mod(Node, SlaveMod),
setup_node(Node, Opts),
Node.
@@ -70,11 +71,14 @@ make_node_name(Name) ->
stop_slave(Node0) ->
Node = make_node_name(Node0),
+ SlaveMod = get_slave_mod(Node),
+ erase_slave_mod(Node),
case rpc:call(Node, ekka, leave, []) of
ok -> ok;
{badrpc, nodedown} -> ok
end,
- case ct_slave:stop(Node) of
+ case SlaveMod:stop(Node) of
+ ok -> ok;
{ok, _} -> ok;
{error, not_started, _} -> ok
end.
@@ -167,3 +171,16 @@ check_consistent_view([{View, Node} | Rest], Acc) ->
add_to_list(Node, Nodes) when is_list(Nodes) -> [Node | Nodes];
add_to_list(Node, Node1) -> [Node, Node1].
+
+put_slave_mod(Node, SlaveMod) ->
+ put({?MODULE, Node}, SlaveMod),
+ ok.
+
+get_slave_mod(Node) ->
+ case get({?MODULE, Node}) of
+ undefined -> ct_slave;
+ SlaveMod -> SlaveMod
+ end.
+
+erase_slave_mod(Node) ->
+ erase({?MODULE, Node}).