Merge branch 'main-v4.4' into kjell/mongodb_upgrade_in_4.4

This commit is contained in:
Xinyu Liu 2023-02-13 11:45:56 +08:00 committed by GitHub
commit 99d46bd1ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
112 changed files with 1786 additions and 627 deletions

22
.github/CODEOWNERS vendored
View File

@ -1,3 +1,6 @@
## Default
* @emqx/emqx-review-board
## MQTT & Core ## MQTT & Core
/src/ @qzhuyan /src/ @qzhuyan
/include/ @qzhuyan /include/ @qzhuyan
@ -5,13 +8,13 @@
/test/ @qzhuyan /test/ @qzhuyan
## CI ## CI
/.github/ @id /.github/ @emqx/emqx-review-board @id
/.ci/ @id /.ci/ @emqx/emqx-review-board @id
/scripts/ @id /scripts/ @emqx/emqx-review-board @id
/build @id /build @emqx/emqx-review-board @id
/deploy/ @id /deploy/ @emqx/emqx-review-board @id
## Authenticatio & ACL ## Authentication & ACL
/apps/emqx_auth_*/ @savonarola /apps/emqx_auth_*/ @savonarola
/apps/emqx_psk_file/ @savonarola /apps/emqx_psk_file/ @savonarola
/apps/emqx_retainer/ @savonarola /apps/emqx_retainer/ @savonarola
@ -31,13 +34,6 @@
/apps/emqx_prometheus/ @zhongwencool /apps/emqx_prometheus/ @zhongwencool
/apps/emqx_recon/ @zhongwencool /apps/emqx_recon/ @zhongwencool
## Data integration ## Data integration
/apps/emqx_rule_engine/ @thalesmg /apps/emqx_rule_engine/ @thalesmg
/apps/emqx_web_hook/ @thalesmg /apps/emqx_web_hook/ @thalesmg
## External Plugins
/lib-extra/ @zmstone
## Default
* @zmstone

View File

@ -13,7 +13,7 @@ jobs:
os: os:
- ubuntu20.04 - 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: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3

View File

@ -157,6 +157,7 @@ jobs:
- amd64 - amd64
- arm64 - arm64
os: os:
- ubuntu22.04
- ubuntu20.04 - ubuntu20.04
- ubuntu18.04 - ubuntu18.04
- ubuntu16.04 - ubuntu16.04
@ -195,7 +196,7 @@ jobs:
--profile "${PROFILE}" \ --profile "${PROFILE}" \
--pkgtype "${PACKAGE}" \ --pkgtype "${PACKAGE}" \
--arch "${ARCH}" \ --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 - uses: actions/upload-artifact@v3
with: with:
name: ${{ matrix.profile }} name: ${{ matrix.profile }}
@ -271,7 +272,7 @@ jobs:
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
build-args: | 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 RUN_FROM=alpine:3.15.1
EMQX_NAME=${{ matrix.profile }} EMQX_NAME=${{ matrix.profile }}
file: source/deploy/docker/Dockerfile file: source/deploy/docker/Dockerfile
@ -287,7 +288,7 @@ jobs:
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
build-args: | 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 RUN_FROM=alpine:3.15.1
EMQX_NAME=${{ matrix.profile }} EMQX_NAME=${{ matrix.profile }}
file: source/deploy/docker/Dockerfile.enterprise file: source/deploy/docker/Dockerfile.enterprise

View File

@ -19,6 +19,7 @@ jobs:
otp: otp:
- 24.3.4.2-1 - 24.3.4.2-1
os: os:
- ubuntu22.04
- ubuntu20.04 - ubuntu20.04
- el7 - el7
runs-on: runs-on:
@ -32,7 +33,7 @@ jobs:
- runs-on: aws-amd64 - runs-on: aws-amd64
use-self-hosted: false 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: steps:
- uses: AutoModality/action-clean@v1 - uses: AutoModality/action-clean@v1

View File

@ -5,7 +5,7 @@ on: [pull_request]
jobs: jobs:
check_deps_integrity: check_deps_integrity:
runs-on: ubuntu-20.04 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: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3

View File

@ -7,7 +7,7 @@ on:
jobs: jobs:
prepare: prepare:
runs-on: ubuntu-20.04 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: outputs:
profiles: ${{ steps.detect-profiles.outputs.profiles}} profiles: ${{ steps.detect-profiles.outputs.profiles}}

View File

@ -5,7 +5,7 @@ on: workflow_dispatch
jobs: jobs:
test: test:
runs-on: ubuntu-20.04 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: strategy:
fail-fast: true fail-fast: true
env: env:

View File

@ -200,7 +200,7 @@ jobs:
relup_test_plan: relup_test_plan:
runs-on: ubuntu-20.04 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: outputs:
profile: ${{ steps.profile-and-versions.outputs.profile }} profile: ${{ steps.profile-and-versions.outputs.profile }}
vsn: ${{ steps.profile-and-versions.outputs.vsn }} vsn: ${{ steps.profile-and-versions.outputs.vsn }}
@ -251,7 +251,7 @@ jobs:
otp: otp:
- 24.3.4.2-1 - 24.3.4.2-1
runs-on: ubuntu-20.04 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: defaults:
run: run:
shell: bash shell: bash
@ -288,7 +288,7 @@ jobs:
- relup_test_plan - relup_test_plan
- relup_test_build - relup_test_build
runs-on: ubuntu-20.04 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: strategy:
fail-fast: false fail-fast: false
matrix: matrix:

View File

@ -12,7 +12,7 @@ on:
jobs: jobs:
prepare: prepare:
runs-on: aws-amd64 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: outputs:
fast_ct_apps: ${{ steps.run_find_apps.outputs.fast_ct_apps }} fast_ct_apps: ${{ steps.run_find_apps.outputs.fast_ct_apps }}
docker_ct_apps: ${{ steps.run_find_apps.outputs.docker_ct_apps }} docker_ct_apps: ${{ steps.run_find_apps.outputs.docker_ct_apps }}
@ -58,7 +58,7 @@ jobs:
eunit_and_proper: eunit_and_proper:
needs: prepare needs: prepare
runs-on: aws-amd64 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: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -86,7 +86,7 @@ jobs:
fast_ct: fast_ct:
needs: prepare needs: prepare
runs-on: ${{ matrix.runs-on }} 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: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -249,7 +249,7 @@ jobs:
- fast_ct - fast_ct
- docker_ct - docker_ct
runs-on: aws-amd64 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: steps:
- uses: AutoModality/action-clean@v1 - uses: AutoModality/action-clean@v1
- uses: actions/download-artifact@v3 - uses: actions/download-artifact@v3

View File

@ -44,7 +44,10 @@ check_acl(ClientInfo, PubSub, Topic, _AclResult, #{acl := ACLParams = #{path :=
Username = maps:get(username, ClientInfo1, undefined), Username = maps:get(username, ClientInfo1, undefined),
case check_acl_request(ACLParams, ClientInfo1) of case check_acl_request(ACLParams, ClientInfo1) of
{ok, 200, <<"ignore">>} -> ok; {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} -> {ok, Code, _Body} ->
?LOG(warning, "Deny ~s to topic ~ts, username: ~ts, http response code: ~p", ?LOG(warning, "Deny ~s to topic ~ts, username: ~ts, http response code: ~p",
[PubSub, Topic, Username, Code]), [PubSub, Topic, Username, Code]),
@ -74,4 +77,3 @@ check_acl_request(ACLParams =
access(subscribe) -> 1; access(subscribe) -> 1;
access(publish) -> 2. access(publish) -> 2.

View File

@ -1,6 +1,6 @@
{application, emqx_auth_http, {application, emqx_auth_http,
[{description, "EMQ X Authentication/ACL with HTTP API"}, [{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, []}, {modules, []},
{registered, [emqx_auth_http_sup]}, {registered, [emqx_auth_http_sup]},
{applications, [kernel,stdlib,ehttpc]}, {applications, [kernel,stdlib,ehttpc]},

View File

@ -1,7 +1,13 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {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", {"4.3.8",
[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http,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,[]}]}, {load_module,emqx_auth_http_cli,brutal_purge,soft_purge,[]}]},
{<<"4.3.[0-1]">>,[{restart_application,emqx_auth_http}]}, {<<"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", {"4.3.8",
[{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_http_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_http,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_http,brutal_purge,soft_purge,[]},

View File

@ -41,19 +41,20 @@ check(ClientInfo, AuthResult, #{auth := AuthParms = #{path := Path},
{ok, 200, <<"ignore">>} -> {ok, 200, <<"ignore">>} ->
ok; ok;
{ok, 200, Body} -> {ok, 200, Body} ->
?LOG(debug, "Auth succeeded from path: ~ts, username: ~ts", [Path, Username]),
IsSuperuser = is_superuser(SuperParams, ClientInfo), IsSuperuser = is_superuser(SuperParams, ClientInfo),
{stop, AuthResult#{is_superuser => IsSuperuser, {stop, AuthResult#{is_superuser => IsSuperuser,
auth_result => success, auth_result => success,
anonymous => false, anonymous => false,
mountpoint => mountpoint(Body, ClientInfo)}}; mountpoint => mountpoint(Body, ClientInfo)}};
{ok, Code, _Body} -> {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", "response code: ~p",
[Path, Username, Code]), [Path, Username, Code]),
{stop, AuthResult#{auth_result => http_to_connack_error(Code), {stop, AuthResult#{auth_result => http_to_connack_error(Code),
anonymous => false}}; anonymous => false}};
{error, Error} -> {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]), "request http-server failed: ~0p", [Path, Username, Error]),
%%FIXME later: server_unavailable is not right. %%FIXME later: server_unavailable is not right.
{stop, AuthResult#{auth_result => server_unavailable, {stop, AuthResult#{auth_result => server_unavailable,

View File

@ -1,6 +1,6 @@
{application, emqx_auth_jwt, {application, emqx_auth_jwt,
[{description, "EMQ X Authentication with JWT"}, [{description, "EMQ X Authentication with JWT"},
{vsn, "4.4.8"}, % strict semver, bump manually! {vsn, "4.4.9"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_auth_jwt_sup]}, {registered, [emqx_auth_jwt_sup]},
{applications, [kernel,stdlib,jose]}, {applications, [kernel,stdlib,jose]},

View File

@ -1,38 +1,18 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.4.7",[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]}, [{"4.4.8",
{"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",
[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
{"4.4.4", {<<"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.3",
[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
{"4.4.2",
[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]},
{<<"4\\.4\\.[0-1]">>,[{restart_application,emqx_auth_jwt}]}, {<<"4\\.4\\.[0-1]">>,[{restart_application,emqx_auth_jwt}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.4.7",[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]}, [{"4.4.8",
{"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",
[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
{"4.4.4", {<<"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.3",
[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
{"4.4.2",
[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}, [{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]},
{<<"4\\.4\\.[0-1]">>,[{restart_application,emqx_auth_jwt}]}, {<<"4\\.4\\.[0-1]">>,[{restart_application,emqx_auth_jwt}]},

View File

@ -51,8 +51,14 @@ check_auth(ClientInfo, AuthResult, #{from := From, checklists := Checklists}) ->
{error, not_token} -> {error, not_token} ->
ok; ok;
{error, Reason} -> {error, Reason} ->
?LOG_SENSITIVE(debug,
"Auth from JWT failed, Client: ~p, Reason: ~p",
[ClientInfo, Reason]),
{stop, AuthResult#{auth_result => Reason, anonymous => false}}; {stop, AuthResult#{auth_result => Reason, anonymous => false}};
{ok, Claims} -> {ok, Claims} ->
?LOG_SENSITIVE(debug,
"Auth from JWT succeeded, Client: ~p",
[ClientInfo]),
{stop, maps:merge(AuthResult, verify_claims(Checklists, Claims, ClientInfo))} {stop, maps:merge(AuthResult, verify_claims(Checklists, Claims, ClientInfo))}
end end
end. end.

View File

@ -99,13 +99,13 @@ handle_cast(_Msg, State) ->
{noreply, State}. {noreply, State}.
handle_info({timeout, _TRef, refresh}, State = #state{addr = Addr}) -> handle_info({timeout, _TRef, refresh}, State = #state{addr = Addr}) ->
NState = try try
true = ets:insert(?TAB, {remote, request_jwks(Addr)}), true = ets:insert(?TAB, {remote, request_jwks(Addr)})
State catch Err:Reason ->
catch _:_ -> ?LOG_SENSITIVE(warning, "Request JWKS failed, jwks_addr: ~p, reason: ~p",
State [Addr, {Err, Reason}])
end, end,
{noreply, reset_timer(NState)}; {noreply, reset_timer(State)};
handle_info({request_jwks, Options}, State) -> handle_info({request_jwks, Options}, State) ->
Remote = key2jwt_value(jwks_addr, fun request_jwks/1, Options), Remote = key2jwt_value(jwks_addr, fun request_jwks/1, Options),

View File

@ -29,8 +29,16 @@
check_acl(ClientInfo, PubSub, Topic, NoMatchAction, State) -> check_acl(ClientInfo, PubSub, Topic, NoMatchAction, State) ->
case do_check_acl(ClientInfo, PubSub, Topic, NoMatchAction, State) of case do_check_acl(ClientInfo, PubSub, Topic, NoMatchAction, State) of
ok -> ok; ok -> ok;
{stop, allow} -> {stop, allow}; {stop, allow} ->
{stop, deny} -> {stop, deny} ?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. end.
do_check_acl(#{username := <<$$, _/binary>>}, _PubSub, _Topic, _NoMatchAction, _State) -> do_check_acl(#{username := <<$$, _/binary>>}, _PubSub, _Topic, _NoMatchAction, _State) ->

View File

@ -1,6 +1,6 @@
{application, emqx_auth_ldap, {application, emqx_auth_ldap,
[{description, "EMQ X Authentication/ACL with 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, []}, {modules, []},
{registered, [emqx_auth_ldap_sup]}, {registered, [emqx_auth_ldap_sup]},
{applications, [kernel,stdlib,eldap2,ecpool]}, {applications, [kernel,stdlib,eldap2,ecpool]},

View File

@ -1,7 +1,10 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {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_acl_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_ldap_cli,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_acl_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_ldap_cli,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_acl_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_ldap,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_ldap_cli,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_ldap_cli,brutal_purge,soft_purge,[]}]},

View File

@ -58,6 +58,9 @@ check(ClientInfo = #{username := Username, password := Password}, AuthResult,
end, end,
case CheckResult of case CheckResult of
ok -> ok ->
?LOG_SENSITIVE(debug,
"[LDAP] Auth from ldap succeeded, Client: ~p",
[ClientInfo]),
{stop, AuthResult#{auth_result => success, anonymous => false}}; {stop, AuthResult#{auth_result => success, anonymous => false}};
{error, not_found} -> {error, not_found} ->
ok; ok;

View File

@ -17,6 +17,7 @@
-module(emqx_acl_mnesia). -module(emqx_acl_mnesia).
-include("emqx_auth_mnesia.hrl"). -include("emqx_auth_mnesia.hrl").
-include_lib("emqx/include/logger.hrl").
%% ACL Callbacks %% ACL Callbacks
-export([ init/0 -export([ init/0
@ -43,8 +44,14 @@ check_acl(ClientInfo = #{ clientid := Clientid }, PubSub, Topic, _NoMatchAction,
case match(ClientInfo, PubSub, Topic, Acls) of case match(ClientInfo, PubSub, Topic, Acls) of
allow -> allow ->
?LOG_SENSITIVE(debug,
"[Mnesia] Allow Topic: ~p, Action: ~p for Client: ~p",
[Topic, PubSub, ClientInfo]),
{stop, allow}; {stop, allow};
deny -> deny ->
?LOG_SENSITIVE(debug,
"[Mnesia] Deny Topic: ~p, Action: ~p for Client: ~p",
[Topic, PubSub, ClientInfo]),
{stop, deny}; {stop, deny};
_ -> _ ->
ok ok

View File

@ -1,6 +1,6 @@
{application, emqx_auth_mnesia, {application, emqx_auth_mnesia,
[{description, "EMQ X Authentication with Mnesia"}, [{description, "EMQ X Authentication with Mnesia"},
{vsn, "4.3.10"}, % strict semver, bump manually {vsn, "4.3.11"}, % strict semver, bump manually
{modules, []}, {modules, []},
{registered, []}, {registered, []},
{applications, [kernel,stdlib,mnesia]}, {applications, [kernel,stdlib,mnesia]},

View File

@ -1,13 +1,25 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.3.9",[{load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]}, [{"4.3.10",
{"4.3.8",[{load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]}, [{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", {"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,[]}]}, {load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[5-6]">>, {<<"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,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mnesia_db,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_acl_mnesia_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia_app,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.10",
{"4.3.8",[{load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]}, [{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", {"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,[]}]}, {load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[5-6]">>, {<<"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,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mnesia_db,brutal_purge,soft_purge,[]}, {load_module,emqx_acl_mnesia_db,brutal_purge,soft_purge,[]},

View File

@ -70,6 +70,9 @@ check(ClientInfo = #{ clientid := Clientid
?LOG(info, "[Mnesia] Auth from mnesia failed: ~p", [Info]), ?LOG(info, "[Mnesia] Auth from mnesia failed: ~p", [Info]),
{stop, AuthResult#{anonymous => false, auth_result => password_error}}; {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}} {stop, AuthResult#{anonymous => false, auth_result => success}}
end end
end. end.

View File

@ -38,8 +38,16 @@ check_acl(ClientInfo, PubSub, Topic, _AclResult, Env = #{aclquery := AclQuery})
[] -> ok; [] -> ok;
Rows -> Rows ->
try match(ClientInfo, Topic, topics(PubSub, Rows)) of try match(ClientInfo, Topic, topics(PubSub, Rows)) of
matched -> {stop, allow}; matched ->
nomatch -> {stop, deny} ?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 catch
_Err:Reason-> _Err:Reason->
?LOG(error, "[MongoDB] Check mongo ~p ACL failed, got ACL config: ~p, error: :~p", ?LOG(error, "[MongoDB] Check mongo ~p ACL failed, got ACL config: ~p, error: :~p",

View File

@ -1,6 +1,6 @@
{application, emqx_auth_mongo, {application, emqx_auth_mongo,
[{description, "EMQ X Authentication/ACL with MongoDB"}, [{description, "EMQ X Authentication/ACL with MongoDB"},
{vsn, "4.4.5"}, % strict semver, bump manually! {vsn, "4.4.6"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_auth_mongo_sup]}, {registered, [emqx_auth_mongo_sup]},
{applications, [kernel,stdlib,mongodb,ecpool]}, {applications, [kernel,stdlib,mongodb,ecpool]},

View File

@ -1,12 +1,19 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {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]">>, {<<"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,[]}]}, {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.4.1", {"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_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.4.0", {"4.4.0",
@ -15,12 +22,19 @@
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_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.5",
{<<"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.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,[]}]}, {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.4.1", {"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_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
{"4.4.0", {"4.4.0",

View File

@ -68,6 +68,9 @@ check(ClientInfo = #{password := Password}, AuthResult,
case Result of case Result of
ok -> ok ->
?tp(emqx_auth_mongo_superuser_check_authn_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), {stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo),
anonymous => false, anonymous => false,
auth_result => success}}; auth_result => success}};

View File

@ -1,7 +1,4 @@
{deps, {deps, []}.
[
{mysql, {git, "https://github.com/emqx/mysql-otp", {tag, "1.7.1"}}}
]}.
{edoc_opts, [{preprocess, true}]}. {edoc_opts, [{preprocess, true}]}.
{erl_opts, [warn_unused_vars, {erl_opts, [warn_unused_vars,

View File

@ -29,8 +29,16 @@
check_acl(ClientInfo, PubSub, Topic, NoMatchAction, #{pool := Pool} = State) -> check_acl(ClientInfo, PubSub, Topic, NoMatchAction, #{pool := Pool} = State) ->
case do_check_acl(Pool, ClientInfo, PubSub, Topic, NoMatchAction, State) of case do_check_acl(Pool, ClientInfo, PubSub, Topic, NoMatchAction, State) of
ok -> ok; ok -> ok;
{stop, allow} -> {stop, allow}; {stop, allow} ->
{stop, deny} -> {stop, deny} ?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. end.
do_check_acl(_Pool, #{username := <<$$, _/binary>>}, _PubSub, _Topic, _NoMatchAction, _State) -> do_check_acl(_Pool, #{username := <<$$, _/binary>>}, _PubSub, _Topic, _NoMatchAction, _State) ->

View File

@ -1,6 +1,6 @@
{application, emqx_auth_mysql, {application, emqx_auth_mysql,
[{description, "EMQ X Authentication/ACL with 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, []}, {modules, []},
{registered, [emqx_auth_mysql_sup]}, {registered, [emqx_auth_mysql_sup]},
{applications, [kernel,stdlib,mysql,ecpool]}, {applications, [kernel,stdlib,mysql,ecpool]},

View File

@ -1,10 +1,17 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.3.3", [{"4.3.4",
[{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]}, [{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,[]}]}, {load_module,emqx_auth_mysql_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[1-2]">>, {<<"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_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]}]},
{"4.3.0", {"4.3.0",
@ -13,11 +20,17 @@
{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_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_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,[]}]}, {load_module,emqx_auth_mysql_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[1-2]">>, {<<"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_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]}]},
{"4.3.0", {"4.3.0",
@ -25,5 +38,4 @@
{load_module,emqx_auth_mysql_app,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_mysql_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_mysql,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]}]}, {load_module,emqx_acl_mysql,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}] {<<".*">>,[]}]}.
}.

View File

@ -46,6 +46,9 @@ check(ClientInfo = #{password := Password}, AuthResult,
end, end,
case CheckPass of case CheckPass of
ok -> ok ->
?LOG_SENSITIVE(debug,
"[MySQL] Auth from mysql succeeded, Client: ~p",
[ClientInfo]),
{stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo), {stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo),
anonymous => false, anonymous => false,
auth_result => success}}; auth_result => success}};

View File

@ -36,9 +36,17 @@ do_check_acl(Pool, ClientInfo, PubSub, Topic, _NoMatchAction, #{acl_query := {Ac
{ok, _, Rows} -> {ok, _, Rows} ->
Rules = filter(PubSub, compile(Rows)), Rules = filter(PubSub, compile(Rows)),
case match(ClientInfo, Topic, Rules) of case match(ClientInfo, Topic, Rules) of
{matched, allow} -> {stop, allow}; {matched, allow} ->
{matched, deny} -> {stop, deny}; ?LOG_SENSITIVE(debug,
nomatch -> ok "[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; end;
{error, Reason} -> {error, Reason} ->
?LOG(error, "[Postgres] do_check_acl error: ~p~n", [Reason]), ?LOG(error, "[Postgres] do_check_acl error: ~p~n", [Reason]),
@ -105,4 +113,3 @@ empty(null) -> true;
empty("") -> true; empty("") -> true;
empty(<<>>) -> true; empty(<<>>) -> true;
empty(_) -> false. empty(_) -> false.

View File

@ -1,6 +1,6 @@
{application, emqx_auth_pgsql, {application, emqx_auth_pgsql,
[{description, "EMQ X Authentication/ACL with PostgreSQL"}, [{description, "EMQ X Authentication/ACL with PostgreSQL"},
{vsn, "4.4.4"}, % strict semver, bump manually! {vsn, "4.4.5"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_auth_pgsql_sup]}, {registered, [emqx_auth_pgsql_sup]},
{applications, [kernel,stdlib,epgsql,ecpool]}, {applications, [kernel,stdlib,epgsql,ecpool]},

View File

@ -1,20 +1,29 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.4.3", [{"4.4.4",
[{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]}, [{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,[]}]}, {load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]}]},
{<<"4\\.4\\.[0-2]">>, {<<"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,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.4.3", [{"4.4.4",
[{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]}, [{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,[]}]}, {load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]}]},
{<<"4\\.4\\.[0-2]">>, {<<"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,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}]}. {<<".*">>,[]}]}.

View File

@ -45,6 +45,9 @@ check(ClientInfo = #{password := Password}, AuthResult,
end, end,
case CheckPass of case CheckPass of
ok -> ok ->
?LOG_SENSITIVE(debug,
"[Postgres] Auth from pgsql succeeded, Client: ~p",
[ClientInfo]),
{stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo), {stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo),
anonymous => false, anonymous => false,
auth_result => success}}; auth_result => success}};

View File

@ -33,8 +33,16 @@ check_acl(ClientInfo, PubSub, Topic, _AclResult,
{ok, []} -> ok; {ok, []} -> ok;
{ok, Rules} -> {ok, Rules} ->
case match(ClientInfo, PubSub, Topic, Rules) of case match(ClientInfo, PubSub, Topic, Rules) of
allow -> {stop, allow}; allow ->
nomatch -> {stop, deny} ?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; end;
{error, Reason} -> {error, Reason} ->
?LOG(error, "[Redis] do_check_acl error: ~p", [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)). b2i(Bin) -> list_to_integer(binary_to_list(Bin)).
description() -> "Redis ACL Module". description() -> "Redis ACL Module".

View File

@ -1,6 +1,6 @@
{application, emqx_auth_redis, {application, emqx_auth_redis,
[{description, "EMQ X Authentication/ACL with 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, []}, {modules, []},
{registered, [emqx_auth_redis_sup]}, {registered, [emqx_auth_redis_sup]},
{applications, [kernel,stdlib,eredis,eredis_cluster,ecpool]}, {applications, [kernel,stdlib,eredis,eredis_cluster,ecpool]},

View File

@ -1,11 +1,15 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.3.3", [{"4.3.4",
[{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]}, [{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,[]}]}, {load_module,emqx_auth_redis_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[1-2]">>, {<<"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_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_redis,brutal_purge,soft_purge,[]}]},
{"4.3.0", {"4.3.0",
@ -14,11 +18,15 @@
{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_redis,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_redis,brutal_purge,soft_purge,[]}]}, {load_module,emqx_acl_redis,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.3.3", [{"4.3.4",
[{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]}, [{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,[]}]}, {load_module,emqx_auth_redis_cli,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[1-2]">>, {<<"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_app,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_redis,brutal_purge,soft_purge,[]}]}, {load_module,emqx_auth_redis,brutal_purge,soft_purge,[]}]},
{"4.3.0", {"4.3.0",

View File

@ -1,6 +1,6 @@
{application, emqx_bridge_mqtt, {application, emqx_bridge_mqtt,
[{description, "EMQ X Bridge to MQTT Broker"}, [{description, "EMQ X Bridge to MQTT Broker"},
{vsn, "4.3.7"}, % strict semver, bump manually! {vsn, "4.3.8"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, []}, {registered, []},
{applications, [kernel,stdlib,replayq,emqtt]}, {applications, [kernel,stdlib,replayq,emqtt]},

View File

@ -1,7 +1,9 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {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_connect,brutal_purge,soft_purge,[]},
{load_module,emqx_bridge_mqtt_actions,brutal_purge,soft_purge,[]}]}, {load_module,emqx_bridge_mqtt_actions,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[4-5]">>, {<<"4\\.3\\.[4-5]">>,
@ -21,7 +23,9 @@
{load_module,emqx_bridge_worker,brutal_purge,soft_purge,[]}, {load_module,emqx_bridge_worker,brutal_purge,soft_purge,[]},
{load_module,emqx_bridge_mqtt_actions,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_connect,brutal_purge,soft_purge,[]},
{load_module,emqx_bridge_mqtt_actions,brutal_purge,soft_purge,[]}]}, {load_module,emqx_bridge_mqtt_actions,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[4-5]">>, {<<"4\\.3\\.[4-5]">>,

View File

@ -111,11 +111,11 @@
zh => <<"桥接挂载点"/utf8>>}, zh => <<"桥接挂载点"/utf8>>},
description => #{ description => #{
en => <<"MountPoint for bridge topic:<br/>" en => <<"MountPoint for bridge topic:<br/>"
"Example: The topic of messages sent to `topic1` on local node " "Example: The topic of messages sent to <code>topic1</code> on local node "
"will be transformed to `bridge/aws/${node}/topic1`">>, "will be transformed to <code>bridge/aws/${node}/topic1</code>">>,
zh => <<"桥接主题的挂载点:<br/>" zh => <<"桥接主题的挂载点:<br/>"
"示例: 本地节点向 `topic1` 发消息,远程桥接节点的主题" "示例: 本地节点向 <code>topic1</code> 发消息,远程桥接节点的主题"
"会变换为 `bridge/aws/${node}/topic1`"/utf8>> "会变换为 <code>bridge/aws/${node}/topic1</code>"/utf8>>
} }
}, },
disk_cache => #{ disk_cache => #{
@ -267,10 +267,10 @@
type => string, type => string,
required => true, required => true,
default => <<"emqx2@127.0.0.1">>, default => <<"emqx2@127.0.0.1">>,
title => #{en => <<"EMQ X Node Name">>, title => #{en => <<"EMQX Node Name">>,
zh => <<"EMQ X 节点名称"/utf8>>}, zh => <<"EMQX 节点名称"/utf8>>},
description => #{en => <<"EMQ X Remote Node Name">>, description => #{en => <<"EMQX Remote Node Name">>,
zh => <<"远程 EMQ X 节点名称 "/utf8>>} zh => <<"远程 EMQX 节点名称 "/utf8>>}
}, },
mountpoint => #{ mountpoint => #{
order => 2, order => 2,
@ -280,11 +280,11 @@
title => #{en => <<"Bridge MountPoint">>, title => #{en => <<"Bridge MountPoint">>,
zh => <<"桥接挂载点"/utf8>>}, zh => <<"桥接挂载点"/utf8>>},
description => #{en => <<"MountPoint for bridge topic<br/>" description => #{en => <<"MountPoint for bridge topic<br/>"
"Example: The topic of messages sent to `topic1` on local node " "Example: The topic of messages sent to <code>topic1</code> on local node "
"will be transformed to `bridge/aws/${node}/topic1`">>, "will be transformed to <code>bridge/emqx/${node}/topic1</code>">>,
zh => <<"桥接主题的挂载点<br/>" zh => <<"桥接主题的挂载点<br/>"
"示例: 本地节点向 `topic1` 发消息,远程桥接节点的主题" "示例: 本地节点向 <code>topic1</code> 发消息,远程桥接节点的主题"
"会变换为 `bridge/aws/${node}/topic1`"/utf8>>} "会变换为 <code>bridge/emqx/${node}/topic1</code>"/utf8>>}
}, },
pool_size => #{ pool_size => #{
order => 3, order => 3,
@ -358,7 +358,7 @@
destroy => on_resource_destroy, destroy => on_resource_destroy,
params => ?RESOURCE_CONFIG_SPEC_RPC, params => ?RESOURCE_CONFIG_SPEC_RPC,
title => #{en => <<"EMQX Bridge">>, zh => <<"EMQX Bridge"/utf8>>}, 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(#{ -rule_action(#{

View File

@ -1,4 +1,4 @@
{deps, {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"}}}
]}. ]}.

View File

@ -90,6 +90,11 @@
{datatype, {enum, [true, false]}} {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", [ {mapping, "management.listener.https", "emqx_management.listeners", [
{datatype, [integer, ip]} {datatype, [integer, ip]}
]}. ]}.
@ -186,6 +191,11 @@
{datatype, {enum, [true, false]}} {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) -> {translation, "emqx_management.application", fun(Conf) ->
Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end, Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
Opts = fun(Prefix) -> Opts = fun(Prefix) ->
@ -202,7 +212,9 @@ end}.
Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end, Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
Opts = fun(Prefix) -> Opts = fun(Prefix) ->
Filter([{num_acceptors, cuttlefish:conf_get(Prefix ++ ".acceptors", Conf)}, 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, end,
TcpOpts = fun(Prefix) -> TcpOpts = fun(Prefix) ->
Filter([{backlog, cuttlefish:conf_get(Prefix ++ ".backlog", Conf, undefined)}, Filter([{backlog, cuttlefish:conf_get(Prefix ++ ".backlog", Conf, undefined)},

View File

@ -1,6 +1,6 @@
{application, emqx_management, {application, emqx_management,
[{description, "EMQ X Management API and CLI"}, [{description, "EMQ X Management API and CLI"},
{vsn, "4.4.12"}, % strict semver, bump manually! {vsn, "4.4.13"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_management_sup]}, {registered, [emqx_management_sup]},
{applications, [kernel,stdlib,emqx_plugin_libs,minirest]}, {applications, [kernel,stdlib,emqx_plugin_libs,minirest]},

View File

@ -167,7 +167,7 @@ cluster_query(Params, {Tab, QsSchema}, QueryFun) ->
Start = if Page > 1 -> (Page-1) * Limit; Start = if Page > 1 -> (Page-1) * Limit;
true -> 0 true -> 0
end, end,
Nodes = ekka_mnesia:running_nodes(), Nodes = lists:sort(ekka_mnesia:running_nodes()),
Rows = do_cluster_query(Nodes, Qs, QueryFun, Start, Limit+1, []), Rows = do_cluster_query(Nodes, Qs, QueryFun, Start, Limit+1, []),
Meta = #{page => Page, limit => Limit}, Meta = #{page => Page, limit => Limit},
NMeta = case CodCnt =:= 0 of NMeta = case CodCnt =:= 0 of

View File

@ -52,12 +52,12 @@ stop_listeners() ->
start_listener({Proto, Port, Options}) when Proto == http -> start_listener({Proto, Port, Options}) when Proto == http ->
Dispatch = [{"/status", emqx_mgmt_http, []}, Dispatch = [{"/status", emqx_mgmt_http, []},
{"/api/v4/[...]", minirest, http_handlers()}], {"/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 -> start_listener({Proto, Port, Options}) when Proto == https ->
Dispatch = [{"/status", emqx_mgmt_http, []}, Dispatch = [{"/status", emqx_mgmt_http, []},
{"/api/v4/[...]", minirest, http_handlers()}], {"/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) -> ranch_opts(Port, Options0) ->
NumAcceptors = proplists:get_value(num_acceptors, Options0, 4), NumAcceptors = proplists:get_value(num_acceptors, Options0, 4),
@ -68,6 +68,7 @@ ranch_opts(Port, Options0) ->
({inet6, false}, Acc) -> Acc; ({inet6, false}, Acc) -> Acc;
({ipv6_v6only, true}, Acc) -> [{ipv6_v6only, true} | Acc]; ({ipv6_v6only, true}, Acc) -> [{ipv6_v6only, true} | Acc];
({ipv6_v6only, false}, Acc) -> Acc; ({ipv6_v6only, false}, Acc) -> Acc;
({proxy_header, _}, Acc) -> Acc;
({K, V}, Acc)-> ({K, V}, Acc)->
[{K, V} | Acc] [{K, V} | Acc]
end, [], Options0), end, [], Options0),
@ -77,6 +78,9 @@ ranch_opts(Port, Options0) ->
socket_opts => [{port, Port} | Options]}, socket_opts => [{port, Port} | Options]},
Res. Res.
proto_opts(Options) ->
maps:with([proxy_header], maps:from_list(Options)).
stop_listener({Proto, Port, _}) -> stop_listener({Proto, Port, _}) ->
io:format("Stop http:management listener on ~s successfully.~n",[format(Port)]), io:format("Stop http:management listener on ~s successfully.~n",[format(Port)]),
minirest:stop_http(listener_name(Proto)). minirest:stop_http(listener_name(Proto)).

View File

@ -794,13 +794,7 @@ t_keepalive(_Config) ->
Path = api_path(["clients", ClientId, "keepalive"]), Path = api_path(["clients", ClientId, "keepalive"]),
{ok, NotFound} = request_api(put, Path, "interval=5", AuthHeader, [#{}]), {ok, NotFound} = request_api(put, Path, "interval=5", AuthHeader, [#{}]),
?assertEqual("{\"message\":\"not_found\",\"code\":112}", NotFound), ?assertEqual("{\"message\":\"not_found\",\"code\":112}", NotFound),
{ok, C1} = emqtt:start_link(#{username => Username, clientid => ClientId}), C1 = keepalive_ok(61, 0, Username, ClientId, Path, AuthHeader),
{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),
{ok, Error1} = request_api(put, Path, "interval=-1", AuthHeader, [#{}]), {ok, Error1} = request_api(put, Path, "interval=-1", AuthHeader, [#{}]),
{ok, Error2} = request_api(put, Path, "interval=65536", AuthHeader, [#{}]), {ok, Error2} = request_api(put, Path, "interval=65536", AuthHeader, [#{}]),
ErrMsg = #{<<"code">> => 102, ErrMsg = #{<<"code">> => 102,
@ -808,9 +802,26 @@ t_keepalive(_Config) ->
?assertEqual(ErrMsg, jiffy:decode(Error1, [return_maps])), ?assertEqual(ErrMsg, jiffy:decode(Error1, [return_maps])),
?assertEqual(Error1, Error2), ?assertEqual(Error1, Error2),
emqtt:disconnect(C1), 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), application:stop(emqx_dashboard),
ok. 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) -> t_status_ok(_Config) ->
{ok, #{ body := Resp {ok, #{ body := Resp
, status_code := StatusCode , status_code := StatusCode

View File

@ -1,6 +1,6 @@
{application, emqx_prometheus, {application, emqx_prometheus,
[{description, "Prometheus for EMQ X"}, [{description, "Prometheus for EMQ X"},
{vsn, "4.3.1"}, % strict semver, bump manually! {vsn, "4.3.2"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_prometheus_sup]}, {registered, [emqx_prometheus_sup]},
{applications, [kernel,stdlib,prometheus]}, {applications, [kernel,stdlib,prometheus]},

View File

@ -1,9 +1,9 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.3.0", [{"4.3.1",[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]}, {"4.3.0",[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.3.0", [{"4.3.1",[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]}, {"4.3.0",[{load_module,emqx_prometheus,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}]}. {<<".*">>,[]}]}.

View File

@ -185,6 +185,10 @@ emqx_collect(emqx_connections_count, Stats) ->
gauge_metric(?C('connections.count', Stats)); gauge_metric(?C('connections.count', Stats));
emqx_collect(emqx_connections_max, Stats) -> emqx_collect(emqx_connections_max, Stats) ->
gauge_metric(?C('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 %% sessions
emqx_collect(emqx_sessions_count, Stats) -> emqx_collect(emqx_sessions_count, Stats) ->
@ -471,6 +475,8 @@ emqx_collect(emqx_cluster_nodes_stopped, ClusterData) ->
emqx_stats() -> emqx_stats() ->
[ emqx_connections_count [ emqx_connections_count
, emqx_connections_max , emqx_connections_max
, emqx_live_connections_count
, emqx_live_connections_max
, emqx_sessions_count , emqx_sessions_count
, emqx_sessions_max , emqx_sessions_max
, emqx_topics_count , emqx_topics_count

View File

@ -1,6 +1,6 @@
{application, emqx_retainer, {application, emqx_retainer,
[{description, "EMQ X Retainer"}, [{description, "EMQ X Retainer"},
{vsn, "4.4.3"}, % strict semver, bump manually! {vsn, "4.4.4"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_retainer_sup]}, {registered, [emqx_retainer_sup]},
{applications, [kernel,stdlib]}, {applications, [kernel,stdlib]},

View File

@ -1,15 +1,27 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.4.2",[{load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}]}, [{"4.4.3",[{load_module,emqx_retainer,brutal_purge,soft_purge,[]}]},
{"4.4.1",[{load_module,emqx_retainer_sup,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", {"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,[]}]}, {load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.4.2",[{load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}]}, [{"4.4.3",[{load_module,emqx_retainer,brutal_purge,soft_purge,[]}]},
{"4.4.1",[{load_module,emqx_retainer_sup,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", {"4.4.0",
[{load_module,emqx_retainer_sup,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_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_retainer_sup,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}]}. {<<".*">>,[]}]}.

View File

@ -22,6 +22,7 @@
-include_lib("emqx/include/emqx.hrl"). -include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/logger.hrl"). -include_lib("emqx/include/logger.hrl").
-include_lib("stdlib/include/ms_transform.hrl"). -include_lib("stdlib/include/ms_transform.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
-logger_header("[Retainer]"). -logger_header("[Retainer]").
@ -74,11 +75,12 @@ on_session_subscribed(_, Topic, #{rh := Rh, is_new := IsNew}) ->
%% @private %% @private
dispatch(Pid, Topic) -> dispatch(Pid, Topic) ->
Msgs = case emqx_topic:wildcard(Topic) of MsgsT = case emqx_topic:wildcard(Topic) of
false -> read_messages(Topic); false -> read_messages(Topic);
true -> match_messages(Topic) true -> match_messages(Topic)
end, end,
Now = erlang:system_time(millisecond), Now = erlang:system_time(millisecond),
Msgs = drop_banned_messages(MsgsT),
[Pid ! {deliver, Topic, refresh_timestamp_expiry(Msg, Now)} || Msg <- sort_retained(Msgs)]. [Pid ! {deliver, Topic, refresh_timestamp_expiry(Msg, Now)} || Msg <- sort_retained(Msgs)].
%% RETAIN flag set to 1 and payload containing zero bytes %% 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) -> refresh_timestamp_expiry(Msg, Now) ->
Msg#message{timestamp = 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).

View File

@ -23,6 +23,7 @@
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
-include_lib("common_test/include/ct.hrl"). -include_lib("common_test/include/ct.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
all() -> emqx_ct:all(?MODULE). all() -> emqx_ct:all(?MODULE).
@ -189,6 +190,53 @@ t_stop_publish_clear_msg(_) ->
ok = emqtt:disconnect(C1). 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 %% Helper functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------

View File

@ -1,22 +1,32 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.4.14",[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]}, [{<<"4\\.4\\.1[3-4]">>,
{"4.4.13",[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]}, [{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", {"4.4.12",
[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, [{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,[]}, {load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]},
{update,emqx_rule_engine_jwt_sup,supervisor}, {update,emqx_rule_engine_jwt_sup,supervisor},
{load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]}]}, {load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]}]},
{"4.4.11", {"4.4.11",
[{load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]}, [{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}, {update,emqx_rule_engine_jwt_sup,supervisor},
{load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_registry,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_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]},
{apply,{emqx_rule_engine_sup,ensure_api_delegator_started,[]}}, {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", {"4.4.10",
[{add_module,emqx_rule_engine_jwt}, [{add_module,emqx_rule_engine_jwt},
{add_module,emqx_rule_engine_jwt_worker}, {add_module,emqx_rule_engine_jwt_worker},
@ -222,15 +232,24 @@
{load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_runtime,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\\.1[3-4]">>,
{"4.4.13",[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]}, [{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", {"4.4.12",
[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, [{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,[]}, {load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]},
{update,emqx_rule_engine_jwt_sup,supervisor}, {update,emqx_rule_engine_jwt_sup,supervisor},
{load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]}]}, {load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]}]},
{"4.4.11", {"4.4.11",
[{load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]}, [{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}, {update,emqx_rule_engine_jwt_sup,supervisor},
{load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_jwt,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},

View File

@ -36,6 +36,7 @@
, create_resource/1 , create_resource/1
, test_resource/1 , test_resource/1
, start_resource/1 , start_resource/1
, start_all_resources_of_type/1
, get_resource_status/1 , get_resource_status/1
, is_resource_alive/1 , is_resource_alive/1
, is_resource_alive/2 , 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()}). -spec(start_resource(resource_id()) -> ok | {error, Reason :: term()}).
start_resource(ResId) -> start_resource(ResId) ->
case emqx_rule_registry:find_resource(ResId) of case emqx_rule_registry:find_resource(ResId) of
{ok, #resource{type = ResType, config = Config}} -> {ok, Res} ->
{ok, #resource_type{on_create = {Mod, Create}}} do_start_resource(Res);
= 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;
not_found -> not_found ->
{error, {resource_not_found, ResId}} {error, {resource_not_found, ResId}}
end. 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()}). -spec(test_resource(#{type := _, config := _, _ => _}) -> ok | {error, Reason :: term()}).
test_resource(#{type := Type} = Params) -> test_resource(#{type := Type} = Params) ->
case emqx_rule_registry:find_resource_type(Type) of 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() -> refresh_rules_when_boot() ->
lists:foreach(fun lists:foreach(fun
(#rule{enabled = true} = Rule) -> (#rule{enabled = true} = Rule) ->
try refresh_rule(Rule) ensure_rule_retrier(Rule);
catch _:_ -> (#rule{enabled = false, state = refresh_failed_at_bootup} = Rule) ->
%% We set the enable = false when rule init failed to avoid bad rules running %% the rule was previously disabled by emqx so we need to retry it
%% without actions created properly. ensure_rule_retrier(Rule);
%% The init failure might be caused by a disconnected resource, in this case the (#rule{enabled = false, id = RuleId}) ->
%% actions can not be created, so the rules won't work. ?LOG(warning, "rule ~s was disabled by the user, won't re-enable it", [RuleId])
%% 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
end, emqx_rule_registry:get_rules()). 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}) -> refresh_rule(#rule{id = RuleId, for = Topics, actions = Actions}) ->
ok = emqx_rule_metrics:create_rule_metrics(RuleId), ok = emqx_rule_metrics:create_rule_metrics(RuleId),
lists:foreach(fun emqx_rule_events:load/1, Topics), lists:foreach(fun emqx_rule_events:load/1, Topics),

View File

@ -853,9 +853,25 @@ printable_maps(Headers) ->
value => Value value => Value
} || {Key, Value} <- V0] } || {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) -> (_K, V, AccIn) when is_tuple(V) ->
%% internal header %% internal header, remove it
AccIn; AccIn;
(K, V, AccIn) -> (K, V, AccIn) ->
AccIn#{K => V} AccIn#{K => V}
end, #{}, Headers). 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}.

View File

@ -33,16 +33,21 @@
, stop/0 , stop/0
, async_refresh_resources_rules/0 , async_refresh_resources_rules/0
, ensure_resource_retrier/1 , ensure_resource_retrier/1
, ensure_rule_retrier/1
, retry_loop/2
, retry_loop/3 , retry_loop/3
]). ]).
%% fot test -export([ put_resource_retry_interval/1
-export([ put_retry_interval/1 , put_rule_retry_interval/1
, get_retry_interval/0 , get_resource_retry_interval/0
, erase_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() -> start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
@ -54,23 +59,33 @@ init([]) ->
_ = erlang:process_flag(trap_exit, true), _ = erlang:process_flag(trap_exit, true),
{ok, #{retryers => #{}}}. {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), _ = persistent_term:put({?MODULE, resource_restart_interval}, I),
ok. ok.
put_rule_retry_interval(I) when is_integer(I) andalso I >= 10 ->
erase_retry_interval() -> _ = persistent_term:put({?MODULE, rule_restart_interval}, I),
_ = persistent_term:erase({?MODULE, resource_restart_interval}),
ok. ok.
get_retry_interval() -> erase_resource_retry_interval() ->
persistent_term:get({?MODULE, resource_restart_interval}, ?T_RETRY). _ = 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() -> async_refresh_resources_rules() ->
gen_server:cast(?MODULE, async_refresh). gen_server:cast(?MODULE, async_refresh).
ensure_resource_retrier(ResId) -> ensure_resource_retrier(ResId) ->
Interval = get_retry_interval(), gen_server:cast(?MODULE, {create_restart_handler, resource, ResId}).
gen_server:cast(?MODULE, {create_restart_handler, resource, ResId, Interval}).
ensure_rule_retrier(RuleId) ->
gen_server:cast(?MODULE, {create_restart_handler, rule, RuleId}).
handle_call(_Msg, _From, State) -> handle_call(_Msg, _From, State) ->
{reply, ok, State}. {reply, ok, State}.
@ -82,12 +97,12 @@ handle_cast(async_refresh, State) ->
Pid = spawn_link(fun do_async_refresh/0), Pid = spawn_link(fun do_async_refresh/0),
{noreply, State#{boot_refresh_pid => Pid}}; {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, #{}), Objects = maps:get(Tag, State, #{}),
NewState = case maps:find(Obj, Objects) of NewState = case maps:find(Obj, Objects) of
error -> error ->
update_object(Tag, Obj, update_object(Tag, Obj,
create_restart_handler(Tag, Obj, Interval), State); create_restart_handler(Tag, Obj), State);
{ok, _Pid} -> {ok, _Pid} ->
State State
end, end,
@ -130,13 +145,17 @@ update_object(Tag, Obj, Retryer, State) ->
retryers => Retryers#{Retryer => {Tag, Obj}} retryers => Retryers#{Retryer => {Tag, Obj}}
}. }.
create_restart_handler(Tag, Obj, Interval) -> create_restart_handler(Tag, Obj) ->
?LOG(info, "starting_a_retry_loop for ~p ~p, with delay interval: ~p", [Tag, Obj, Interval]), ?LOG(warning, "starting_a_retry_loop for ~p ~p", [Tag, Obj]),
%% spawn a dedicated process to handle the restarting asynchronously %% 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) -> %% retry_loop/3 is to avoid crashes during relup
timer:sleep(Interval), 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 case emqx_rule_registry:find_resource(ResId) of
{ok, #resource{type = Type, config = Config}} -> {ok, #resource{type = Type, config = Config}} ->
try try
@ -154,10 +173,30 @@ retry_loop(resource, ResId, Interval) ->
end, end,
?LOG_SENSITIVE(warning, "init_resource_retry_failed ~p, ~0p", [ResId, LogContext]), ?LOG_SENSITIVE(warning, "init_resource_retry_failed ~p, ~0p", [ResId, LogContext]),
%% keep looping %% keep looping
?MODULE:retry_loop(resource, ResId, Interval) ?MODULE:retry_loop(resource, ResId)
end; end;
not_found -> not_found ->
ok 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. end.
do_async_refresh() -> 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) -> fun (#rule{id = Id, enabled = false, state = refresh_failed_at_bootup} = Rule) ->
emqx_rule_engine:refresh_rule(Rule), emqx_rule_engine:refresh_rule(Rule),
emqx_rule_registry:add_rule(Rule#rule{enabled = true, state = normal}), 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 (_) -> ok
end, emqx_rule_registry:find_rules_depends_on_resource(ResId)). end, emqx_rule_registry:find_rules_depends_on_resource(ResId)).

View File

@ -36,18 +36,44 @@ t_mod_hook_fun(_) ->
]]. ]].
t_printable_maps(_) -> t_printable_maps(_) ->
Headers = #{peerhost => {127,0,0,1}, TestMap = #{
peername => {{127,0,0,1}, 9980}, peerhost => {127,0,0,1},
sockname => {{127,0,0,1}, 1883}, peername => {{127,0,0,1}, 9980},
redispatch_to => {<<"group">>, <<"sub/topic/+">>}, sockname => {{127,0,0,1}, 1883},
shared_dispatch_ack => {self(), ref} 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), Converted = emqx_rule_events:printable_maps(Headers),
?assertMatch( Verify = fun(Result) ->
#{peerhost := <<"127.0.0.1">>, ?assertMatch(
peername := <<"127.0.0.1:9980">>, #{peerhost := <<"127.0.0.1">>,
sockname := <<"127.0.0.1:1883">> peername := <<"127.0.0.1:9980">>,
}, Converted), sockname := <<"127.0.0.1:1883">>,
?assertNot(maps:is_key(redispatch_to, Converted)), string := <<"abc">>,
?assertNot(maps:is_key(shared_dispatch_ack, Converted)), 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. ok.

View File

@ -48,7 +48,7 @@ end_per_suite(_Config) ->
ok. ok.
init_per_testcase(t_restart_resource, Config) -> 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}], Opts = [public, named_table, set, {read_concurrency, true}],
_ = ets:new(?RES_PARAMS_TAB, [{keypos, #resource_params.id}|Opts]), _ = ets:new(?RES_PARAMS_TAB, [{keypos, #resource_params.id}|Opts]),
ets:new(t_restart_resource, [named_table, public]), ets:new(t_restart_resource, [named_table, public]),
@ -90,12 +90,13 @@ end_per_testcase(_, Config) ->
common_init_per_testcase() -> common_init_per_testcase() ->
AlarmOpts = [{actions, [log, publish]}, {size_limit, 1000}, {validity_period, 86400}], AlarmOpts = [{actions, [log, publish]}, {size_limit, 1000}, {validity_period, 86400}],
_ = emqx_alarm:mnesia(boot),
{ok, _} = emqx_alarm:start_link(AlarmOpts), {ok, _} = emqx_alarm:start_link(AlarmOpts),
{ok, _} = emqx_rule_monitor:start_link(). {ok, _} = emqx_rule_monitor:start_link().
common_end_per_testcases() -> common_end_per_testcases() ->
ok = emqx_alarm:stop(), ok = emqx_alarm:stop(),
emqx_rule_monitor:erase_retry_interval(), emqx_rule_monitor:erase_resource_retry_interval(),
emqx_rule_monitor:stop(). emqx_rule_monitor:stop().
t_restart_resource(_) -> t_restart_resource(_) ->

View File

@ -2,8 +2,7 @@
{plugins, [rebar3_proper]}. {plugins, [rebar3_proper]}.
{deps, {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}]}. {edoc_opts, [{preprocess, true}]}.

8
build
View File

@ -205,6 +205,14 @@ make_zip() {
;; ;;
esac esac
;; ;;
ubuntu22)
case "$PKG_VSN" in
4.4.15*)
# this is the first version for amzn2, no relup
has_relup='no'
;;
esac
;;
macos*) macos*)
case "$PKG_VSN" in case "$PKG_VSN" in
4.4.12*) 4.4.12*)

View File

@ -1,7 +1,53 @@
# v4.4.15 # v4.4.15
## Enhancements ## Enhancements
- The MongoDB library has been upgraded to support MongoDB version 5.1 and greater. - 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 ## 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).

View File

@ -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)。

View File

@ -40,6 +40,9 @@ Parameter | Description | Default Value
`image.pullPolicy` | The image pull policy | `IfNotPresent` `image.pullPolicy` | The image pull policy | `IfNotPresent`
`image.pullSecrets ` | The image pull secrets (does not add image pull secrets to deployed pods) |``[]`` `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` `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 | `{}` `podAnnotations ` | Annotations for pod | `{}`
`podManagementPolicy`| To redeploy a chart with existing PVC(s), the value must be set to Parallel to avoid deadlock | `Parallel` `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` `persistence.enabled` | Enable EMQX persistence using PVC | `false`

View File

@ -64,6 +64,7 @@ spec:
checksum/config: {{ $configData | sha256sum | quote }} checksum/config: {{ $configData | sha256sum | quote }}
{{- end }} {{- end }}
spec: spec:
serviceAccountName: {{ include "emqx.serviceAccountName" . }}
volumes: volumes:
{{- if .Values.emqxLoadedPlugins }} {{- if .Values.emqxLoadedPlugins }}
- name: emqx-loaded-plugins - name: emqx-loaded-plugins
@ -107,9 +108,6 @@ spec:
secret: secret:
secretName: {{ $licenseSecretName }} secretName: {{ $licenseSecretName }}
{{- end }} {{- end }}
{{- if eq (.Values.emqxConfig.EMQX_CLUSTER__DISCOVERY | default "k8s") "k8s" }}
serviceAccountName: {{ include "emqx.fullname" . }}
{{- end }}
{{- if .Values.podSecurityContext.enabled }} {{- if .Values.podSecurityContext.enabled }}
securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }}
{{- end }} {{- end }}

View File

@ -30,3 +30,14 @@ Create chart name and version as used by the chart label.
{{- define "emqx.chart" -}} {{- define "emqx.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}} {{- 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 }}

View File

@ -1,10 +1,23 @@
{{- if eq (.Values.emqxConfig.EMQX_CLUSTER__DISCOVERY | default "k8s") "k8s" }} {{- if .Values.serviceAccount.create }}
apiVersion: v1 apiVersion: v1
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
namespace: {{ .Release.Namespace }} 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 kind: Role
{{- if semverCompare ">=1.17-0" .Capabilities.KubeVersion.GitVersion }} {{- if semverCompare ">=1.17-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
@ -23,7 +36,12 @@ rules:
- get - get
- watch - watch
- list - list
{{- end }}
{{- end }}
--- ---
{{- if .Values.serviceAccount.create }}
{{- if eq (.Values.emqxConfig.EMQX_CLUSTER__DISCOVERY | default "k8s") "k8s" }}
kind: RoleBinding kind: RoleBinding
{{- if semverCompare ">=1.17-0" .Capabilities.KubeVersion.GitVersion }} {{- if semverCompare ">=1.17-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
@ -35,10 +53,11 @@ metadata:
name: {{ include "emqx.fullname" . }} name: {{ include "emqx.fullname" . }}
subjects: subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: {{ include "emqx.fullname" . }} name: {{ include "emqx.serviceAccountName" . }}
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
roleRef: roleRef:
kind: Role kind: Role
name: {{ include "emqx.fullname" . }} name: {{ include "emqx.fullname" . }}
apiGroup: rbac.authorization.k8s.io apiGroup: rbac.authorization.k8s.io
{{- end }} {{- end }}
{{- end }}

View File

@ -14,6 +14,16 @@ image:
# pullSecrets: # pullSecrets:
# - myRegistryKeySecretName # - 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. ## 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 recreatePods: false

View File

@ -57,7 +57,7 @@ reload(Env) ->
unload(Env), load(Env). unload(Env), load(Env).
description() -> description() ->
"EMQ X Internal ACL Module". "EMQX Internal ACL Module".
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% ACL callbacks %% ACL callbacks
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------

View File

@ -21,6 +21,7 @@
-include_lib("emqx/include/emqx.hrl"). -include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/logger.hrl"). -include_lib("emqx/include/logger.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
-logger_header("[Delayed]"). -logger_header("[Delayed]").
@ -94,7 +95,7 @@ unload(_Env) ->
emqx_mod_sup:stop_child(?MODULE). emqx_mod_sup:stop_child(?MODULE).
description() -> description() ->
"EMQ X Delayed Publish Module". "EMQX Delayed Publish Module".
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Hooks %% Hooks
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -228,7 +229,20 @@ do_publish(Key = {Ts, _Id}, Now, Acc) when Ts =< Now ->
case mnesia:dirty_read(?TAB, Key) of case mnesia:dirty_read(?TAB, Key) of
[] -> ok; [] -> ok;
[#delayed_message{msg = Msg}] -> [#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, end,
do_publish(mnesia:dirty_next(?TAB, Key), Now, [Key|Acc]). do_publish(mnesia:dirty_next(?TAB, Key), Now, [Key|Acc]).

View File

@ -46,7 +46,7 @@ unload(_Env) ->
emqx_hooks:del('client.disconnected', {?MODULE, on_client_disconnected}). emqx_hooks:del('client.disconnected', {?MODULE, on_client_disconnected}).
description() -> description() ->
"EMQ X Presence Module". "EMQX Presence Module".
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Callbacks %% Callbacks
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------

View File

@ -71,7 +71,7 @@ unload(_) ->
emqx_hooks:del('message.publish', {?MODULE, rewrite_publish}). emqx_hooks:del('message.publish', {?MODULE, rewrite_publish}).
description() -> description() ->
"EMQ X Topic Rewrite Module". "EMQX Topic Rewrite Module".
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------

View File

@ -46,4 +46,4 @@ unload(_Env) ->
ok. ok.
description() -> description() ->
"EMQ X Slow Subscribers Statistics Module". "EMQX Slow Subscribers Statistics Module".

View File

@ -71,7 +71,7 @@ unload(_) ->
emqx_hooks:del('client.connected', {?MODULE, on_client_connected}). emqx_hooks:del('client.connected', {?MODULE, on_client_connected}).
description() -> description() ->
"EMQ X Subscription Module". "EMQX Subscription Module".
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------

View File

@ -113,7 +113,7 @@ unload(_Env) ->
emqx_mod_sup:stop_child(?MODULE). emqx_mod_sup:stop_child(?MODULE).
description() -> description() ->
"EMQ X Topic Metrics Module". "EMQX Topic Metrics Module".
on_message_publish(#message{topic = Topic, qos = QoS}) -> on_message_publish(#message{topic = Topic, qos = QoS}) ->
case is_registered(Topic) of case is_registered(Topic) of

View File

@ -28,7 +28,7 @@
-spec description() -> string(). -spec description() -> string().
description() -> description() ->
"EMQ X Trace Module". "EMQX Trace Module".
-spec load(any()) -> ok. -spec load(any()) -> ok.
load(_Env) -> load(_Env) ->

View File

@ -1,6 +1,6 @@
{application, emqx_modules, {application, emqx_modules,
[{description, "EMQ X Module Management"}, [{description, "EMQ X Module Management"},
{vsn, "4.4.8"}, {vsn, "4.4.9"},
{modules, []}, {modules, []},
{applications, [kernel,stdlib]}, {applications, [kernel,stdlib]},
{mod, {emqx_modules_app, []}}, {mod, {emqx_modules_app, []}},

View File

@ -1,81 +1,75 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.4.7",[{load_module,emqx_mod_rewrite,brutal_purge,soft_purge,[]}]}, [{<<"4\\.4\\.[6-8]">>,
{"4.4.6", [{load_module,emqx_mod_acl_internal,brutal_purge,soft_purge,[]},
[{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,[]},
{load_module,emqx_mod_delayed,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_presence,brutal_purge,soft_purge,[]},
{load_module,emqx_mod_sup,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_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-8]">>,
{"4.4.6", [{load_module,emqx_mod_acl_internal,brutal_purge,soft_purge,[]},
[{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,[]},
{load_module,emqx_mod_delayed,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_presence,brutal_purge,soft_purge,[]},
{load_module,emqx_mod_sup,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_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,[]}
]},
{<<".*">>,[]}]}. {<<".*">>,[]}]}.

View File

@ -26,6 +26,7 @@
-include_lib("common_test/include/ct.hrl"). -include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
-include_lib("emqx/include/emqx.hrl"). -include_lib("emqx/include/emqx.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Setups %% Setups
@ -78,3 +79,46 @@ t_delayed_message(_) ->
EmptyKey = mnesia:dirty_all_keys(emqx_mod_delayed), EmptyKey = mnesia:dirty_all_keys(emqx_mod_delayed),
?assertEqual([], EmptyKey), ?assertEqual([], EmptyKey),
ok = emqx_mod_delayed:unload([]). 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([]).

View File

@ -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 [ {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"} , {redbug, "2.0.7"}
, {covertool, {git, "https://github.com/zmstone/covertool", {tag, "2.0.4.1"}}} , {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"}}} , {gun, {git, "https://github.com/emqx/gun", {tag, "1.3.8"}}}
, {eredis_cluster, {git, "https://github.com/emqx/eredis_cluster", {tag, "0.7.4"}}} , {eredis_cluster, {git, "https://github.com/emqx/eredis_cluster", {tag, "0.7.4"}}}
, {gproc, {git, "https://github.com/uwiger/gproc", {tag, "0.9.0"}}} , {gproc, {git, "https://github.com/uwiger/gproc", {tag, "0.9.0"}}}
, {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.5"}}} , {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.5"}}}
, {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.9.0"}}} , {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.9.1"}}}
, {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.8.7"}}} , {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.8.8"}}}
, {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.8.1.11"}}} , {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"}}} , {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "3.0.1"}}}
, {cuttlefish, {git, "https://github.com/emqx/cuttlefish", {tag, "v3.3.6"}}} , {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"}}} , {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"}}} , {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"}}} , {emqtt, {git, "https://github.com/emqx/emqtt", {tag, "1.2.3.1"}}}
, {rulesql, {git, "https://github.com/emqx/rulesql", {tag, "0.1.5"}}} , {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"}}} , {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "1.0.3"}}}
, {lc, {git, "https://github.com/emqx/lc.git", {tag, "0.3.2"}}} , {lc, {git, "https://github.com/emqx/lc.git", {tag, "0.3.2"}}}
, {mongodb, {git,"https://github.com/emqx/mongodb-erlang", {tag, "v3.0.19"}}} , {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"}}} , {epgsql, {git, "https://github.com/emqx/epgsql.git", {tag, "4.6.0"}}}
, {grpc, {git, "https://github.com/emqx/grpc-erl", {tag, "0.6.7"}}} , {grpc, {git, "https://github.com/emqx/grpc-erl", {tag, "0.6.7"}}}
]}. ]}.

View File

@ -176,6 +176,11 @@ filter_froms(Froms0, AvailableVersionsIndex) ->
{"amzn2", _} -> {"amzn2", _} ->
Excluded = [list_to_binary(["4.4.", integer_to_list(X)]) || X <- lists:seq(0,11)], 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); 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 %% macos arm64 (M1/M2) packages are introduced since v4.4.12 and e4.4.12
%% exclude tags before them %% exclude tags before them
{"macos" ++ _, "aarch64" ++ _} -> {"macos" ++ _, "aarch64" ++ _} ->

View File

@ -2,23 +2,57 @@
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.4.14", [{"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,[]}]}, {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]}]},
{"4.4.13", {"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_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_cm,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_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}]}, {load_module,emqx_app,brutal_purge,soft_purge,[]}]},
{"4.4.12", {"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_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_cm,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_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}]}, {load_module,emqx_app,brutal_purge,soft_purge,[]}]},
{"4.4.11", {"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}, {add_module,emqx_cover},
{load_module,emqx,brutal_purge,soft_purge,[]},
{load_module,emqx_relup,brutal_purge,soft_purge,[]}, {load_module,emqx_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_misc,brutal_purge,soft_purge,[]}, {load_module,emqx_misc,brutal_purge,soft_purge,[]},
{load_module,emqx_app,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_session,brutal_purge,soft_purge,[]},
{load_module,emqx_channel,brutal_purge,soft_purge,[]}]}, {load_module,emqx_channel,brutal_purge,soft_purge,[]}]},
{"4.4.10", {"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_cover},
{add_module,emqx_ocsp_cache}, {add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache}, {add_module,emqx_crl_cache},
@ -47,7 +86,12 @@
{apply,{application,set_env, {apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]}, [gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.9", {"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_cover},
{add_module,emqx_ocsp_cache}, {add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache}, {add_module,emqx_crl_cache},
@ -74,7 +118,12 @@
{apply,{application,set_env, {apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]}, [gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.8", {"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_cover},
{add_module,emqx_ocsp_cache}, {add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache}, {add_module,emqx_crl_cache},
@ -102,7 +151,12 @@
{apply,{application,set_env, {apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]}, [gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.7", {"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_cover},
{add_module,emqx_ocsp_cache}, {add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache}, {add_module,emqx_crl_cache},
@ -130,7 +184,12 @@
{apply,{application,set_env, {apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]}, [gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.6", {"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_cover},
{add_module,emqx_ocsp_cache}, {add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache}, {add_module,emqx_crl_cache},
@ -158,7 +217,12 @@
{apply,{application,set_env, {apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]}, [gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.5", {"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_cover},
{add_module,emqx_ocsp_cache}, {add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache}, {add_module,emqx_crl_cache},
@ -188,7 +252,11 @@
{apply,{application,set_env, {apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]}, [gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.4", {"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_cover},
{add_module,emqx_ocsp_cache}, {add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache}, {add_module,emqx_crl_cache},
@ -225,7 +293,10 @@
{apply,{application,set_env, {apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]}, [gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.3", {"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_cover},
{add_module,emqx_ocsp_cache}, {add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache}, {add_module,emqx_crl_cache},
@ -269,7 +340,10 @@
{apply,{application,set_env, {apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]}, [gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.2", {"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_cover},
{add_module,emqx_ocsp_cache}, {add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache}, {add_module,emqx_crl_cache},
@ -314,7 +388,9 @@
{apply,{application,set_env, {apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]}, [gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.1", {"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_cover},
{add_module,emqx_ocsp_cache}, {add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache}, {add_module,emqx_crl_cache},
@ -364,7 +440,9 @@
{apply,{application,set_env, {apply,{application,set_env,
[gen_rpc,insecure_auth_fallback_allowed,true]}}]}, [gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{"4.4.0", {"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_cover},
{add_module,emqx_ocsp_cache}, {add_module,emqx_ocsp_cache},
{add_module,emqx_crl_cache}, {add_module,emqx_crl_cache},
@ -417,22 +495,56 @@
[gen_rpc,insecure_auth_fallback_allowed,true]}}]}, [gen_rpc,insecure_auth_fallback_allowed,true]}}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.4.14", [{"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,[]}]}, {load_module,emqx_rule_actions_trans,brutal_purge,soft_purge,[]}]},
{"4.4.13", {"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_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_cm,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_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}]}, {load_module,emqx_app,brutal_purge,soft_purge,[]}]},
{"4.4.12", {"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_rule_actions_trans,brutal_purge,soft_purge,[]},
{load_module,emqx_cm,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_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}]}, {load_module,emqx_app,brutal_purge,soft_purge,[]}]},
{"4.4.11", {"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_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}, {load_module,emqx_app,brutal_purge,soft_purge,[]},
{load_module,emqx_misc,brutal_purge,soft_purge,[]}, {load_module,emqx_misc,brutal_purge,soft_purge,[]},
@ -441,7 +553,12 @@
{load_module,emqx_session,brutal_purge,soft_purge,[]}, {load_module,emqx_session,brutal_purge,soft_purge,[]},
{delete_module,emqx_cover}]}, {delete_module,emqx_cover}]},
{"4.4.10", {"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_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]}, {load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,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_crl_cache},
{delete_module,emqx_ocsp_cache}]}, {delete_module,emqx_ocsp_cache}]},
{"4.4.9", {"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_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]}, {load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,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_crl_cache},
{delete_module,emqx_ocsp_cache}]}, {delete_module,emqx_ocsp_cache}]},
{"4.4.8", {"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_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]}, {load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,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_crl_cache},
{delete_module,emqx_ocsp_cache}]}, {delete_module,emqx_ocsp_cache}]},
{"4.4.7", {"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_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]}, {load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,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_crl_cache},
{delete_module,emqx_ocsp_cache}]}, {delete_module,emqx_ocsp_cache}]},
{"4.4.6", {"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_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]}, {load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,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_crl_cache},
{delete_module,emqx_ocsp_cache}]}, {delete_module,emqx_ocsp_cache}]},
{"4.4.5", {"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_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]}, {load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_access_rule,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_crl_cache},
{delete_module,emqx_ocsp_cache}]}, {delete_module,emqx_ocsp_cache}]},
{"4.4.4", {"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_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]}, {load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]},
@ -613,7 +759,10 @@
{delete_module,emqx_crl_cache}, {delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]}, {delete_module,emqx_ocsp_cache}]},
{"4.4.3", {"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_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]}, {load_module,emqx_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]},
@ -652,7 +801,10 @@
{delete_module,emqx_crl_cache}, {delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]}, {delete_module,emqx_ocsp_cache}]},
{"4.4.2", {"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_listeners,brutal_purge,soft_purge,[]},
{load_module,emqx_kernel_sup,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_helper,brutal_purge,soft_purge,[]},
@ -692,7 +844,9 @@
{delete_module,emqx_crl_cache}, {delete_module,emqx_crl_cache},
{delete_module,emqx_ocsp_cache}]}, {delete_module,emqx_ocsp_cache}]},
{"4.4.1", {"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_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_router_helper,brutal_purge,soft_purge,[]}, {load_module,emqx_router_helper,brutal_purge,soft_purge,[]},
{load_module,emqx_ws_connection,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_crl_cache},
{delete_module,emqx_ocsp_cache}]}, {delete_module,emqx_ocsp_cache}]},
{"4.4.0", {"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_kernel_sup,brutal_purge,soft_purge,[]},
{load_module,emqx_router_helper,brutal_purge,soft_purge,[]}, {load_module,emqx_router_helper,brutal_purge,soft_purge,[]},
{load_module,emqx_router,brutal_purge,soft_purge,[]}, {load_module,emqx_router,brutal_purge,soft_purge,[]},

View File

@ -65,6 +65,8 @@
%% Troubleshooting %% Troubleshooting
-export([ set_debug_secret/1 -export([ set_debug_secret/1
, default_started_applications/0
, expand_apps/1
]). ]).
-define(APP, ?MODULE). -define(APP, ?MODULE).
@ -252,14 +254,6 @@ is_application_running(App) ->
StartedApps = proplists:get_value(started, application:info()), StartedApps = proplists:get_value(started, application:info()),
proplists:is_defined(App, StartedApps). 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). -ifdef(EMQX_ENTERPRISE).
on_reboot() -> on_reboot() ->
try try
@ -290,6 +284,54 @@ on_shutdown(_) ->
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% 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) -> reload_config(ConfFile) ->
{ok, [Conf]} = file:consult(ConfFile), {ok, [Conf]} = file:consult(ConfFile),

View File

@ -21,6 +21,7 @@
-include("emqx.hrl"). -include("emqx.hrl").
-include("logger.hrl"). -include("logger.hrl").
-include("types.hrl"). -include("types.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
-logger_header("[Banned]"). -logger_header("[Banned]").
@ -36,6 +37,7 @@
, create/1 , create/1
, delete/1 , delete/1
, info/1 , info/1
, look_up/1
]). ]).
%% gen_server callbacks %% gen_server callbacks
@ -94,13 +96,15 @@ create(#{who := Who,
reason := Reason, reason := Reason,
at := At, at := At,
until := Until}) -> until := Until}) ->
mnesia:dirty_write(?BANNED_TAB, #banned{who = Who, insert_banned(#banned{
by = By, who = Who,
reason = Reason, by = By,
at = At, reason = Reason,
until = Until}); at = At,
until = Until
});
create(Banned) when is_record(Banned, banned) -> create(Banned) when is_record(Banned, banned) ->
mnesia:dirty_write(?BANNED_TAB, Banned). insert_banned(Banned).
-spec(delete({clientid, emqx_types:clientid()} -spec(delete({clientid, emqx_types:clientid()}
| {username, emqx_types:username()} | {username, emqx_types:username()}
@ -111,6 +115,9 @@ delete(Who) ->
info(InfoKey) -> info(InfoKey) ->
mnesia:table_info(?BANNED_TAB, InfoKey). mnesia:table_info(?BANNED_TAB, InfoKey).
look_up(Who) ->
mnesia:dirty_read(?BANNED_TAB, Who).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% gen_server callbacks %% gen_server callbacks
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -159,3 +166,20 @@ expire_banned_items(Now) ->
(_, _Acc) -> ok (_, _Acc) -> ok
end, ok, ?BANNED_TAB). 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.

View File

@ -183,8 +183,7 @@ do_unsubscribe(Topic, SubPid, SubOpts) ->
true = ets:delete(?SUBOPTION, {SubPid, Topic}), true = ets:delete(?SUBOPTION, {SubPid, Topic}),
true = ets:delete_object(?SUBSCRIPTION, {SubPid, Topic}), true = ets:delete_object(?SUBSCRIPTION, {SubPid, Topic}),
Group = maps:get(share, SubOpts, undefined), Group = maps:get(share, SubOpts, undefined),
do_unsubscribe(Group, Topic, SubPid, SubOpts), do_unsubscribe(Group, Topic, SubPid, SubOpts).
emqx_exclusive_subscription:unsubscribe(Topic, SubOpts).
do_unsubscribe(undefined, Topic, SubPid, SubOpts) -> do_unsubscribe(undefined, Topic, SubPid, SubOpts) ->
clean_subscribe(SubOpts, Topic, SubPid); clean_subscribe(SubOpts, Topic, SubPid);
@ -344,9 +343,12 @@ subscriber_down(SubPid) ->
clean_subscribe(SubOpts, Topic, SubPid) -> clean_subscribe(SubOpts, Topic, SubPid) ->
case maps:get(shard, SubOpts, 0) of 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}); 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}) ok = cast(pick({Topic, I}), {unsubscribed, Topic, I})
end. end.

View File

@ -434,7 +434,7 @@ handle_msg({'$gen_cast', Req}, State) ->
{ok, NewState}; {ok, NewState};
handle_msg({Inet, _Sock, Data}, State) when Inet == tcp; Inet == ssl -> 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), Oct = iolist_size(Data),
inc_counter(incoming_bytes, Oct), inc_counter(incoming_bytes, Oct),
ok = emqx_metrics:inc('bytes.received', Oct), ok = emqx_metrics:inc('bytes.received', Oct),

View File

@ -147,6 +147,7 @@ handle_info({timeout, TRef, {refresh, URL}},
{noreply, ensure_timer(URL, State, ?RETRY_TIMEOUT)}; {noreply, ensure_timer(URL, State, ?RETRY_TIMEOUT)};
{ok, _CRLs} -> {ok, _CRLs} ->
?LOG(debug, "fetched crl response for ~p", [URL]), ?LOG(debug, "fetched crl response for ~p", [URL]),
?tp(crl_refresh_timer_done, #{url => URL}),
{noreply, ensure_timer(URL, State)} {noreply, ensure_timer(URL, State)}
end; end;
_ -> _ ->

View File

@ -73,6 +73,7 @@ check(NewVal, KeepAlive = #keepalive{statval = OldVal,
true -> {error, timeout} true -> {error, timeout}
end. end.
-define(IS_KEEPALIVE(Interval), Interval >= 0 andalso Interval =< 65535000).
%% from mqtt-v3.1.1 specific %% from mqtt-v3.1.1 specific
%% A Keep Alive value of zero (0) has the effect of turning off the keep alive mechanism. %% 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 %% 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. %% typically this is a few minutes.
%% The maximum value is (65535s) 18 hours 12 minutes and 15 seconds. %% The maximum value is (65535s) 18 hours 12 minutes and 15 seconds.
%% @doc Update keepalive's interval %% @doc Update keepalive interval
-spec(set(interval, non_neg_integer(), keepalive()) -> keepalive()). %% The keepalive() is undefined when connecting via keepalive=0.
set(interval, Interval, KeepAlive) when Interval >= 0 andalso Interval =< 65535000 -> -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}. KeepAlive#keepalive{interval = Interval}.

View File

@ -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)]), Header = io_lib:format("~s(Q~p, R~p, D~p", [type_name(Type), QoS, i(Retain), i(Dup)]),
case S == undefined of case S == undefined of
true -> [Header, ")"]; true -> [Header, ")"];
false -> [Header, S, ")"] false -> [Header, ", ", S, ")"]
end. end.
format_variable(undefined, _) -> format_variable(undefined, _) ->

View File

@ -32,6 +32,7 @@ post_release_upgrade(FromRelVsn, _) ->
{_, CurrRelVsn} = ?EMQX_RELEASE, {_, CurrRelVsn} = ?EMQX_RELEASE,
?INFO("emqx has been upgraded from ~s to ~s!", [FromRelVsn, CurrRelVsn]), ?INFO("emqx has been upgraded from ~s to ~s!", [FromRelVsn, CurrRelVsn]),
maybe_refresh_jwt_module(FromRelVsn), maybe_refresh_jwt_module(FromRelVsn),
_ = maybe_restart_oracle_resources(FromRelVsn),
reload_components(). reload_components().
%% What to do after downgraded to an old release vsn. %% What to do after downgraded to an old release vsn.
@ -93,3 +94,27 @@ maybe_refresh_jwt_module(_) ->
ok. ok.
-endif. -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.

View File

@ -380,14 +380,19 @@ read_otp_version() ->
Filename = filename:join([ReleasesDir, emqx_app:get_release(), "BUILT_ON"]), Filename = filename:join([ReleasesDir, emqx_app:get_release(), "BUILT_ON"]),
case file:read_file(Filename) of case file:read_file(Filename) of
{ok, BuiltOn} -> {ok, BuiltOn} ->
%% running on EQM X release %% running on EQMX release
BuiltOn; BuiltOn;
{error, enoent} -> {error, enoent} ->
%% running tests etc.
OtpMajor = erlang:system_info(otp_release), OtpMajor = erlang:system_info(otp_release),
OtpVsnFile = filename:join([ReleasesDir, OtpMajor, "OTP_VERSION"]), OtpVsnFile = filename:join([ReleasesDir, OtpMajor, "OTP_VERSION"]),
{ok, Vsn} = file:read_file(OtpVsnFile), case file:read_file(OtpVsnFile) of
Vsn {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. end.
parse_built_on(BuiltOn) -> parse_built_on(BuiltOn) ->

View File

@ -336,7 +336,7 @@ websocket_handle({binary, Data}, State) when is_list(Data) ->
websocket_handle({binary, iolist_to_binary(Data)}, State); websocket_handle({binary, iolist_to_binary(Data)}, State);
websocket_handle({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)), ok = inc_recv_stats(1, iolist_size(Data)),
NState = ensure_stats_timer(State), NState = ensure_stats_timer(State),
return(parse_incoming(Data, NState)); return(parse_incoming(Data, NState));

View File

@ -21,11 +21,12 @@
-include_lib("emqx/include/emqx.hrl"). -include_lib("emqx/include/emqx.hrl").
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
all() -> emqx_ct:all(?MODULE). all() -> emqx_ct:all(?MODULE).
init_per_suite(Config) -> init_per_suite(Config) ->
application:load(emqx), emqx_ct_helpers:start_apps([]),
ok = ekka:start(), ok = ekka:start(),
%% for coverage %% for coverage
ok = emqx_banned:mnesia(copy), ok = emqx_banned:mnesia(copy),
@ -34,7 +35,8 @@ init_per_suite(Config) ->
end_per_suite(_Config) -> end_per_suite(_Config) ->
ekka:stop(), ekka:stop(),
ekka_mnesia:ensure_stopped(), ekka_mnesia:ensure_stopped(),
ekka_mnesia:delete_schema(). ekka_mnesia:delete_schema(),
emqx_ct_helpers:stop_apps([]).
t_add_delete(_) -> t_add_delete(_) ->
Banned = #banned{who = {clientid, <<"TestClient">>}, Banned = #banned{who = {clientid, <<"TestClient">>},
@ -84,7 +86,10 @@ t_check(_) ->
?assertEqual(0, emqx_banned:info(size)). ?assertEqual(0, emqx_banned:info(size)).
t_unused(_) -> 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">>}, ok = emqx_banned:create(#banned{who = {clientid, <<"BannedClient">>},
until = erlang:system_time(second)}), until = erlang:system_time(second)}),
?assertEqual(ignored, gen_server:call(Banned, unexpected_req)), ?assertEqual(ignored, gen_server:call(Banned, unexpected_req)),
@ -93,3 +98,22 @@ t_unused(_) ->
timer:sleep(500), %% expiry timer timer:sleep(500), %% expiry timer
ok = emqx_banned:stop(). 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))).

View File

@ -43,7 +43,7 @@ init_per_testcase(TestCase, Config)
TestCase =:= t_filled_cache; TestCase =:= t_filled_cache;
TestCase =:= t_revoked -> TestCase =:= t_revoked ->
DataDir = ?config(data_dir, 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), {ok, CRLPem} = file:read_file(CRLFile),
[{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem), [{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem),
ServerPid = start_crl_server(CRLPem), ServerPid = start_crl_server(CRLPem),
@ -53,9 +53,44 @@ init_per_testcase(TestCase, Config)
, {crl_der, CRLDer} , {crl_der, CRLDer}
, {http_server, ServerPid} , {http_server, ServerPid}
| Config]; | 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) -> init_per_testcase(t_not_cached_and_unreachable, Config) ->
DataDir = ?config(data_dir, 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), {ok, CRLPem} = file:read_file(CRLFile),
[{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem), [{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem),
application:stop(cowboy), application:stop(cowboy),
@ -65,7 +100,7 @@ init_per_testcase(t_not_cached_and_unreachable, Config) ->
| Config]; | Config];
init_per_testcase(t_refresh_config, Config) -> init_per_testcase(t_refresh_config, Config) ->
DataDir = ?config(data_dir, 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), {ok, CRLPem} = file:read_file(CRLFile),
[{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem), [{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem),
TestPid = self(), TestPid = self(),
@ -88,7 +123,7 @@ init_per_testcase(t_refresh_config, Config) ->
| Config]; | Config];
init_per_testcase(_TestCase, Config) -> init_per_testcase(_TestCase, Config) ->
DataDir = ?config(data_dir, 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), {ok, CRLPem} = file:read_file(CRLFile),
[{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem), [{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem),
TestPid = self(), TestPid = self(),
@ -118,6 +153,30 @@ end_per_testcase(TestCase, Config)
clear_crl_cache(), clear_crl_cache(),
ok = snabbkaffe:stop(), ok = snabbkaffe:stop(),
ok; 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) -> end_per_testcase(t_not_cached_and_unreachable, _Config) ->
emqx_ct_helpers:stop_apps([]), emqx_ct_helpers:stop_apps([]),
emqx_ct_helpers:change_emqx_opts( emqx_ct_helpers:change_emqx_opts(
@ -229,7 +288,7 @@ force_cacertfile(Cacertfile) ->
application:set_env(emqx, listeners, SSLListeners ++ OtherListeners), application:set_env(emqx, listeners, SSLListeners ++ OtherListeners),
ok. ok.
setup_crl_options(Config, #{is_cached := IsCached}) -> setup_crl_options(Config, Opts = #{is_cached := IsCached}) ->
DataDir = ?config(data_dir, Config), DataDir = ?config(data_dir, Config),
Cacertfile = filename:join(DataDir, "ca-chain.cert.pem"), Cacertfile = filename:join(DataDir, "ca-chain.cert.pem"),
Certfile = filename:join(DataDir, "server.cert.pem"), Certfile = filename:join(DataDir, "server.cert.pem"),
@ -238,6 +297,7 @@ setup_crl_options(Config, #{is_cached := IsCached}) ->
false -> []; false -> [];
true -> ["http://localhost:9878/intermediate.crl.pem"] true -> ["http://localhost:9878/intermediate.crl.pem"]
end, end,
ExtraHandler = maps:get(extra_handler, Opts, fun(_) -> ok end),
Handler = Handler =
fun(emqx) -> fun(emqx) ->
emqx_ct_helpers:change_emqx_opts( 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.... %% emqx_ct_helpers:change_emqx_opts has cacertfile hardcoded....
ok = force_cacertfile(Cacertfile), ok = force_cacertfile(Cacertfile),
ExtraHandler(emqx),
ok; ok;
(_) -> (App) ->
ExtraHandler(App),
ok ok
end, end,
emqx_ct_helpers:start_apps([], Handler), emqx_ct_helpers:start_apps([], Handler),
@ -546,3 +608,39 @@ t_revoked(Config) ->
process_flag(trap_exit, true), process_flag(trap_exit, true),
?assertMatch({error, {{shutdown, {tls_alert, {certificate_revoked, _}}}, _}}, emqtt:connect(C)), ?assertMatch({error, {{shutdown, {tls_alert, {certificate_revoked, _}}}, _}}, emqtt:connect(C)),
ok. 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.

View File

@ -2,67 +2,67 @@
MIIF+zCCA+OgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwbzELMAkGA1UEBhMCU0Ux MIIF+zCCA+OgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwbzELMAkGA1UEBhMCU0Ux
EjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMRIwEAYDVQQK EjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMRIwEAYDVQQK
DAlNeU9yZ05hbWUxETAPBgNVBAsMCE15Um9vdENBMREwDwYDVQQDDAhNeVJvb3RD DAlNeU9yZ05hbWUxETAPBgNVBAsMCE15Um9vdENBMREwDwYDVQQDDAhNeVJvb3RD
QTAeFw0yMjA2MTMxMjQyMDVaFw0zMjA2MTAxMjQyMDVaMGsxCzAJBgNVBAYTAlNF QTAeFw0yMzAxMTIxMzA4MTZaFw0zMzAxMDkxMzA4MTZaMGsxCzAJBgNVBAYTAlNF
MRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAoMCU15T3JnTmFtZTEZMBcGA1UE MRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAoMCU15T3JnTmFtZTEZMBcGA1UE
CwwQTXlJbnRlcm1lZGlhdGVDQTEZMBcGA1UEAwwQTXlJbnRlcm1lZGlhdGVDQTCC CwwQTXlJbnRlcm1lZGlhdGVDQTEZMBcGA1UEAwwQTXlJbnRlcm1lZGlhdGVDQTCC
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAN32wUPOGrLjVHY37ICI4sWH AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALQG7dMeU/y9HDNHzhydR0bm
2GBEYgGtoKyZTfLKqK8W965uxHxMKKeKC7Ro93ScT4giR2GdsCvMyLP4Dlv7FxL7 wN9UGplqJOJPwqJRaZZcrn9umgJ9SU2il2ceEVxMDwzBWCRKJO5/H9A9k13SqsXM
rWEHc7vbP22uT4NQQ0hgfl4ch8rTiSl/5FfynOuvMHnKh58z+lGyQ/uqKqAzc6OD 2c2c9xXfIF1kb820lCm1Uow5hZ/auDjxliNk9kNJDigCRi3QoIs/dVeWzFsgEC2l
6FypzSQO2R6JpA+kxKlbTYmOcsLiLFKjCjxyA1ibeozUaRHjPRM7VLHVxYfmpGm/ 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
-----END CERTIFICATE----- -----END CERTIFICATE-----
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIFzzCCA7egAwIBAgIUVYtdlrTMH1BoMy9JpiiL/FXv5NMwDQYJKoZIhvcNAQEL MIIFzzCCA7egAwIBAgIUYjc7hD7/UJ0/VPADfNfp/WpOwRowDQYJKoZIhvcNAQEL
BQAwbzELMAkGA1UEBhMCU0UxEjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJ BQAwbzELMAkGA1UEBhMCU0UxEjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJ
U3RvY2tob2xtMRIwEAYDVQQKDAlNeU9yZ05hbWUxETAPBgNVBAsMCE15Um9vdENB U3RvY2tob2xtMRIwEAYDVQQKDAlNeU9yZ05hbWUxETAPBgNVBAsMCE15Um9vdENB
MREwDwYDVQQDDAhNeVJvb3RDQTAeFw0yMjA2MTMxMjQyMDVaFw00MjA2MDgxMjQy MREwDwYDVQQDDAhNeVJvb3RDQTAeFw0yMzAxMTIxMzA4MTRaFw00MzAxMDcxMzA4
MDVaMG8xCzAJBgNVBAYTAlNFMRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAcM MTRaMG8xCzAJBgNVBAYTAlNFMRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAcM
CVN0b2NraG9sbTESMBAGA1UECgwJTXlPcmdOYW1lMREwDwYDVQQLDAhNeVJvb3RD CVN0b2NraG9sbTESMBAGA1UECgwJTXlPcmdOYW1lMREwDwYDVQQLDAhNeVJvb3RD
QTERMA8GA1UEAwwITXlSb290Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK QTERMA8GA1UEAwwITXlSb290Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
AoICAQDRKeWdrXluKLuVxTXxpWbCzBm/6x+kg8EjhIKUm9Mq0t+cOLC1sn99s4E0 AoICAQCnBwSOYVJw47IoMHMXTVDtOYvUt3rqsurEhFcB4O8xmf2mmwr6m7s8A5Ft
/NBA7jc3O+hQ9S2fZuMp9OUXuf8HjjtlKQY2M9T9kCE9Yxc+ygpcPEvDYl0ke/1r AvAehg1GvnXT3t/KiyU7BK+acTwcErGyZwS2wvdB0lpHWSpOn/u5y+4ZETvQefcj
m6eUOGS2LkIDHebuYbY+KGXjpaF15w49q199wQAk0sbdcCiv+OymBUxi3lrHepo3 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
G2LZ cbTm
-----END CERTIFICATE----- -----END CERTIFICATE-----

View File

@ -2,31 +2,31 @@
MIIFnDCCA4SgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCU0Ux MIIFnDCCA4SgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCU0Ux
EjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UECgwJTXlPcmdOYW1lMRkwFwYDVQQL EjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UECgwJTXlPcmdOYW1lMRkwFwYDVQQL
DBBNeUludGVybWVkaWF0ZUNBMRkwFwYDVQQDDBBNeUludGVybWVkaWF0ZUNBMB4X DBBNeUludGVybWVkaWF0ZUNBMRkwFwYDVQQDDBBNeUludGVybWVkaWF0ZUNBMB4X
DTIyMDYxMzEyNDIwNVoXDTIzMDYyMzEyNDIwNVowfTELMAkGA1UEBhMCU0UxEjAQ DTIzMDExMjEzMDgxNloXDTMzMDQxOTEzMDgxNlowfTELMAkGA1UEBhMCU0UxEjAQ
BgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMRIwEAYDVQQKDAlN BgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMRIwEAYDVQQKDAlN
eU9yZ05hbWUxGTAXBgNVBAsMEE15SW50ZXJtZWRpYXRlQ0ExFzAVBgNVBAMMDmNs eU9yZ05hbWUxGTAXBgNVBAsMEE15SW50ZXJtZWRpYXRlQ0ExFzAVBgNVBAMMDmNs
aWVudC1yZXZva2VkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA584w aWVudC1yZXZva2VkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs+R6
VAczDWrlIJXm6+0oYepacPPrVEMC9WwsQFO5GbBDdxrBvxgQ5u8/DDNEtYk0sJMt PDtIxVlUoLYbDBbaVcxgoLjnWcvqL8wSqyWuqi/Y3cjuNYCziR9nR5dWajtkBjzJ
zgSLxsYK5duhrwVyICXpKgxMI2fKdKP0zxB/eB4V0vrc6FqR4L8D8XoNPKSaTnjv HyhgAr6gBVSRt4RRmDXoOcprK3GcpowAr65UAmC4hdH0af6FdKjKCnFw67byUg52
NNh3wjLNvmBRfHRSUCe4zEvPZzMLuBIHXRR20prtA90FFV8fliNvMCBIbFkqthjf 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
-----END CERTIFICATE----- -----END CERTIFICATE-----

Some files were not shown because too many files have changed in this diff Show More