126 lines
3.7 KiB
Erlang
126 lines
3.7 KiB
Erlang
%%--------------------------------------------------------------------
|
|
%% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
%%
|
|
%% @doc EMQX License Management.
|
|
%%--------------------------------------------------------------------
|
|
|
|
-module(emqx_license_parser).
|
|
|
|
-include_lib("emqx/include/logger.hrl").
|
|
-include("emqx_license.hrl").
|
|
|
|
-define(PUBKEY, <<
|
|
""
|
|
"\n"
|
|
"-----BEGIN PUBLIC KEY-----\n"
|
|
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbtkdos3TZmSv+D7+X5pc0yfcjum2\n"
|
|
"Q1DK6PCWkiQihjvjJjKFzdYzcWOgC6f4Ou3mgGAUSjdQYYnFKZ/9f5ax4g==\n"
|
|
"-----END PUBLIC KEY-----\n"
|
|
""
|
|
>>).
|
|
|
|
-define(LICENSE_PARSE_MODULES, [
|
|
emqx_license_parser_v20220101
|
|
]).
|
|
|
|
-type license_data() :: term().
|
|
-type customer_type() ::
|
|
?SMALL_CUSTOMER
|
|
| ?MEDIUM_CUSTOMER
|
|
| ?LARGE_CUSTOMER
|
|
| ?EVALUATION_CUSTOMER.
|
|
|
|
-type license_type() :: ?OFFICIAL | ?TRIAL.
|
|
|
|
-type license() :: #{module := module(), data := license_data()}.
|
|
|
|
-export_type([
|
|
license_data/0,
|
|
customer_type/0,
|
|
license_type/0,
|
|
license/0
|
|
]).
|
|
|
|
-export([
|
|
parse/1,
|
|
parse/2,
|
|
dump/1,
|
|
customer_type/1,
|
|
license_type/1,
|
|
expiry_date/1,
|
|
max_connections/1
|
|
]).
|
|
|
|
%%--------------------------------------------------------------------
|
|
%% Behaviour
|
|
%%--------------------------------------------------------------------
|
|
|
|
-callback parse(string() | binary(), binary()) -> {ok, license_data()} | {error, term()}.
|
|
|
|
-callback dump(license_data()) -> list({atom(), term()}).
|
|
|
|
-callback customer_type(license_data()) -> customer_type().
|
|
|
|
-callback license_type(license_data()) -> license_type().
|
|
|
|
-callback expiry_date(license_data()) -> calendar:date().
|
|
|
|
-callback max_connections(license_data()) -> non_neg_integer().
|
|
|
|
%%--------------------------------------------------------------------
|
|
%% API
|
|
%%--------------------------------------------------------------------
|
|
|
|
-ifdef(TEST).
|
|
-spec parse(string() | binary()) -> {ok, license()} | {error, term()}.
|
|
parse(Content) ->
|
|
PubKey = persistent_term:get(emqx_license_test_pubkey, ?PUBKEY),
|
|
parse(Content, PubKey).
|
|
-else.
|
|
-spec parse(string() | binary()) -> {ok, license()} | {error, term()}.
|
|
parse(Content) ->
|
|
parse(Content, ?PUBKEY).
|
|
-endif.
|
|
|
|
parse(Content, Pem) ->
|
|
[PemEntry] = public_key:pem_decode(Pem),
|
|
Key = public_key:pem_entry_decode(PemEntry),
|
|
do_parse(iolist_to_binary(Content), Key, ?LICENSE_PARSE_MODULES, []).
|
|
|
|
-spec dump(license()) -> list({atom(), term()}).
|
|
dump(#{module := Module, data := LicenseData}) ->
|
|
Module:dump(LicenseData).
|
|
|
|
-spec customer_type(license()) -> customer_type().
|
|
customer_type(#{module := Module, data := LicenseData}) ->
|
|
Module:customer_type(LicenseData).
|
|
|
|
-spec license_type(license()) -> license_type().
|
|
license_type(#{module := Module, data := LicenseData}) ->
|
|
Module:license_type(LicenseData).
|
|
|
|
-spec expiry_date(license()) -> calendar:date().
|
|
expiry_date(#{module := Module, data := LicenseData}) ->
|
|
Module:expiry_date(LicenseData).
|
|
|
|
-spec max_connections(license()) -> non_neg_integer().
|
|
max_connections(#{module := Module, data := LicenseData}) ->
|
|
Module:max_connections(LicenseData).
|
|
|
|
%%--------------------------------------------------------------------
|
|
%% Private functions
|
|
%%--------------------------------------------------------------------
|
|
|
|
do_parse(_Content, _Key, [], Errors) ->
|
|
{error, lists:reverse(Errors)};
|
|
do_parse(Content, Key, [Module | Modules], Errors) ->
|
|
try Module:parse(Content, Key) of
|
|
{ok, LicenseData} ->
|
|
{ok, #{module => Module, data => LicenseData}};
|
|
{error, Error} ->
|
|
do_parse(Content, Key, Modules, [{Module, Error} | Errors])
|
|
catch
|
|
_Class:Error:Stacktrace ->
|
|
do_parse(Content, Key, Modules, [{Module, {Error, Stacktrace}} | Errors])
|
|
end.
|