feat(license): check license before node start
This commit is contained in:
parent
50859bbd83
commit
64c59b5469
53
bin/emqx
53
bin/emqx
|
@ -341,19 +341,51 @@ relx_gen_id() {
|
|||
od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
|
||||
}
|
||||
|
||||
call_nodetool() {
|
||||
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$@"
|
||||
}
|
||||
|
||||
# Control a node
|
||||
relx_nodetool() {
|
||||
command="$1"; shift
|
||||
ERL_FLAGS="${ERL_FLAGS:-} $EPMD_ARG" \
|
||||
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
|
||||
call_nodetool "$NAME_TYPE" "$NAME" \
|
||||
-setcookie "$COOKIE" "$command" "$@"
|
||||
}
|
||||
|
||||
call_hocon() {
|
||||
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" hocon "$@" \
|
||||
call_nodetool hocon "$@" \
|
||||
|| die "call_hocon_failed: $*" $?
|
||||
}
|
||||
|
||||
get_config_value() {
|
||||
path_to_value="$1"
|
||||
call_hocon -s "$SCHEMA_MOD" -I "$CONFIGS_DIR/" -c "$RUNNER_ETC_DIR"/emqx.conf get "$path_to_value" | tr -d \"
|
||||
}
|
||||
|
||||
check_license() {
|
||||
if [ "$IS_ENTERPRISE" == "no" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
file_license="${EMQX_LICENSE__FILE:-$(get_config_value license.file)}"
|
||||
|
||||
if [[ -n "$file_license" && ("$file_license" != "undefined") ]]; then
|
||||
call_nodetool check_license_file "$file_license"
|
||||
else
|
||||
key_license="${EMQX_LICENSE__KEY:-$(get_config_value license.key)}"
|
||||
|
||||
if [[ -n "$key_license" && ("$key_license" != "undefined") ]]; then
|
||||
call_nodetool check_license_key "$key_license"
|
||||
else
|
||||
echoerr "License not found."
|
||||
echoerr "Please specify one via EMQX_LICENSE__KEY or EMQX_LICENSE__FILE variables"
|
||||
echoerr "or via license.key|file in emqx_enterprise.conf."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Run an escript in the node's environment
|
||||
relx_escript() {
|
||||
shift; scriptpath="$1"; shift
|
||||
|
@ -374,11 +406,6 @@ generate_config() {
|
|||
## changing the config 'log.rotation.size'
|
||||
rm -rf "${RUNNER_LOG_DIR}"/*.siz
|
||||
|
||||
EMQX_LICENSE_CONF_OPTION=""
|
||||
if [ "${EMQX_LICENSE_CONF:-}" != "" ]; then
|
||||
EMQX_LICENSE_CONF_OPTION="-c ${EMQX_LICENSE_CONF}"
|
||||
fi
|
||||
|
||||
## timestamp for each generation
|
||||
local NOW_TIME
|
||||
NOW_TIME="$(call_hocon now_time)"
|
||||
|
@ -387,9 +414,7 @@ generate_config() {
|
|||
## NOTE: the generate command merges environment variables to the base config (emqx.conf),
|
||||
## but does not include the cluster-override.conf and local-override.conf
|
||||
## meaning, certain overrides will not be mapped to app.<time>.config file
|
||||
## disable SC2086 to allow EMQX_LICENSE_CONF_OPTION to split
|
||||
# shellcheck disable=SC2086
|
||||
call_hocon -v -t "$NOW_TIME" -I "$CONFIGS_DIR/" -s "$SCHEMA_MOD" -c "$RUNNER_ETC_DIR"/emqx.conf $EMQX_LICENSE_CONF_OPTION -d "$RUNNER_DATA_DIR"/configs generate
|
||||
call_hocon -v -t "$NOW_TIME" -I "$CONFIGS_DIR/" -s "$SCHEMA_MOD" -c "$RUNNER_ETC_DIR"/emqx.conf -d "$RUNNER_DATA_DIR"/configs generate
|
||||
|
||||
## filenames are per-hocon convention
|
||||
local CONF_FILE="$CONFIGS_DIR/app.$NOW_TIME.config"
|
||||
|
@ -539,7 +564,7 @@ NAME="${EMQX_NODE__NAME:-}"
|
|||
if [ -z "$NAME" ]; then
|
||||
if [ "$IS_BOOT_COMMAND" = 'yes' ]; then
|
||||
# for boot commands, inspect emqx.conf for node name
|
||||
NAME="$(call_hocon -s "$SCHEMA_MOD" -I "$CONFIGS_DIR/" -c "$RUNNER_ETC_DIR"/emqx.conf get node.name | tr -d \")"
|
||||
NAME="$(get_config_value node.name)"
|
||||
else
|
||||
vm_args_file="$(latest_vm_args 'EMQX_NODE__NAME')"
|
||||
NAME="$(grep -E '^-s?name' "${vm_args_file}" | awk '{print $2}')"
|
||||
|
@ -570,7 +595,7 @@ fi
|
|||
COOKIE="${EMQX_NODE__COOKIE:-}"
|
||||
if [ -z "$COOKIE" ]; then
|
||||
if [ "$IS_BOOT_COMMAND" = 'yes' ]; then
|
||||
COOKIE="$(call_hocon -s "$SCHEMA_MOD" -I "$CONFIGS_DIR/" -c "$RUNNER_ETC_DIR"/emqx.conf get node.cookie | tr -d \")"
|
||||
COOKIE="$(get_config_value node.cookie)"
|
||||
else
|
||||
vm_args_file="$(latest_vm_args 'EMQX_NODE__COOKIE')"
|
||||
COOKIE="$(grep -E '^-setcookie' "${vm_args_file}" | awk '{print $2}')"
|
||||
|
@ -742,6 +767,8 @@ case "${COMMAND}" in
|
|||
#generate app.config and vm.args
|
||||
generate_config "$NAME_TYPE" "$NAME"
|
||||
|
||||
check_license
|
||||
|
||||
# Setup beam-required vars
|
||||
EMU="beam"
|
||||
PROGNAME="${0#*/}"
|
||||
|
@ -790,6 +817,8 @@ case "${COMMAND}" in
|
|||
#generate app.config and vm.args
|
||||
generate_config "$NAME_TYPE" "$NAME"
|
||||
|
||||
check_license
|
||||
|
||||
[ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
|
||||
FOREGROUNDOPTIONS="-noshell -noinput +Bd"
|
||||
|
||||
|
|
19
bin/nodetool
19
bin/nodetool
|
@ -24,6 +24,10 @@ main(Args) ->
|
|||
["hocon" | Rest] ->
|
||||
%% forward the call to hocon_cli
|
||||
hocon_cli:main(Rest);
|
||||
["check_license_key", Key] ->
|
||||
check_license(#{key => list_to_binary(Key)});
|
||||
["check_license_file", File] ->
|
||||
check_license(#{file => list_to_binary(File)});
|
||||
_ ->
|
||||
do(Args)
|
||||
end.
|
||||
|
@ -253,6 +257,21 @@ chkconfig(File) ->
|
|||
halt(1)
|
||||
end.
|
||||
|
||||
check_license(Config) ->
|
||||
ok = application:load(emqx_license),
|
||||
%% This checks formal license validity to ensure
|
||||
%% that the node can successfully start with the given license.
|
||||
|
||||
%% However, a valid license may be expired. In this case, the node will
|
||||
%% start but will not be able to receive connections due to connection limits.
|
||||
%% It may receive license updates from the cluster further.
|
||||
case emqx_license:read_license(Config) of
|
||||
{ok, _} -> ok;
|
||||
{error, Error} ->
|
||||
io:format(standard_error, "Error reading license: ~p~n", [Error]),
|
||||
halt(1)
|
||||
end.
|
||||
|
||||
%%
|
||||
%% Given a string or binary, parse it into a list of terms, ala file:consult/0
|
||||
%%
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
check/2,
|
||||
unload/0,
|
||||
read_license/0,
|
||||
read_license/1,
|
||||
update_file/1,
|
||||
update_key/1]).
|
||||
|
||||
|
|
6
mix.exs
6
mix.exs
|
@ -552,7 +552,8 @@ defmodule EMQXUmbrella.MixProject do
|
|||
emqx_schema_mod: emqx_schema_mod(edition_type),
|
||||
emqx_machine_boot_apps: emqx_machine_boot_app_list(edition_type),
|
||||
built_on_arch: built_on(),
|
||||
is_elixir: "yes"
|
||||
is_elixir: "yes",
|
||||
is_enterprise: (if edition_type == :enterprise, do: "yes", else: "no")
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -579,7 +580,8 @@ defmodule EMQXUmbrella.MixProject do
|
|||
built_on_arch: built_on(),
|
||||
emqx_schema_mod: emqx_schema_mod(edition_type),
|
||||
emqx_machine_boot_apps: emqx_machine_boot_app_list(edition_type),
|
||||
is_elixir: "yes"
|
||||
is_elixir: "yes",
|
||||
is_enterprise: (if edition_type == :enterprise, do: "yes", else: "no")
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -239,10 +239,12 @@ overlay_vars_rel(RelType) ->
|
|||
|
||||
overlay_vars_edition(ce) ->
|
||||
[ {emqx_schema_mod, emqx_conf_schema}
|
||||
, {is_enterprise, "no"}
|
||||
, {emqx_machine_boot_apps, emqx_machine_boot_app_list(ce)}
|
||||
];
|
||||
overlay_vars_edition(ee) ->
|
||||
[ {emqx_schema_mod, emqx_enterprise_conf_schema}
|
||||
, {is_enterprise, "yes"}
|
||||
, {emqx_machine_boot_apps, emqx_machine_boot_app_list(ee)}
|
||||
].
|
||||
|
||||
|
@ -324,7 +326,6 @@ relx_apps(ReleaseType, Edition) ->
|
|||
, emqx_plugins
|
||||
]
|
||||
++ [quicer || is_quicer_supported()]
|
||||
%++ [emqx_license || is_enterprise(Edition)]
|
||||
++ [bcrypt || provide_bcrypt_release(ReleaseType)]
|
||||
++ relx_apps_per_rel(ReleaseType)
|
||||
++ relx_additional_apps(ReleaseType, Edition).
|
||||
|
|
|
@ -15,6 +15,7 @@ RUNNER_DATA_DIR="{{ runner_data_dir }}"
|
|||
RUNNER_USER="{{ runner_user }}"
|
||||
IS_ELIXIR="{{ is_elixir }}"
|
||||
SCHEMA_MOD="{{ emqx_schema_mod }}"
|
||||
IS_ENTERPRISE="{{ is_enterprise }}"
|
||||
|
||||
export EMQX_DESCRIPTION='{{ emqx_description }}'
|
||||
|
||||
|
|
Loading…
Reference in New Issue