diff --git a/lib-ee/emqx_license/etc/emqx_license.conf b/lib-ee/emqx_license/etc/emqx_license.conf index e8a2cc5a9..331d98aa8 100644 --- a/lib-ee/emqx_license/etc/emqx_license.conf +++ b/lib-ee/emqx_license/etc/emqx_license.conf @@ -1,3 +1,3 @@ license { - key = "MjIwMTExCjAKMTAKRm9vCmNvbnRhY3RAZm9vLmNvbQoyMDIyMDExMQoxMDAwMDAKMTAK.Iyle9eMrXSAZwJczR8MEI2dtpxLuL2OKRikTwYvFK/SgxfwZQLR7JJM2rKfkuT5eP4cxh0Y1+84hOoB7fj/MWA==" + key = "MjIwMTExCjAKMTAKRXZhbHVhdGlvbgpjb250YWN0QGVtcXguaW8KMjAyMjAxMDEKMzY1MDAKMTAK.MEUCIFc9EUjqB3SjpRqWjqmAzI4Tg4LwhCRet9scEoxMRt8fAiEAk6vfYUiPOTzBC+3EjNF3WmLTiA3B0TN5ZNwuTKbTXJQ=" } diff --git a/lib-ee/emqx_license/src/emqx_license_parser.erl b/lib-ee/emqx_license/src/emqx_license_parser.erl index 59aa86640..9d634f624 100644 --- a/lib-ee/emqx_license/src/emqx_license_parser.erl +++ b/lib-ee/emqx_license/src/emqx_license_parser.erl @@ -9,8 +9,12 @@ -include_lib("emqx/include/logger.hrl"). -include("emqx_license.hrl"). --define(PUBKEY, <<"MEgCQQChzN6lCUdt4sYPQmWBYA3b8Zk87Jfk+1A1zcTd+lCU0Tf - vXhSHgEWz18No4lL2v1n+70CoYpc2fzfhNJitgnV9AgMBAAE=">>). +-define(PUBKEY, <<""" +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbtkdos3TZmSv+D7+X5pc0yfcjum2 +Q1DK6PCWkiQihjvjJjKFzdYzcWOgC6f4Ou3mgGAUSjdQYYnFKZ/9f5ax4g== +-----END PUBLIC KEY----- +""">>). -define(LICENSE_PARSE_MODULES, [emqx_license_parser_v20220101 ]). @@ -40,11 +44,6 @@ max_connections/1 ]). --ifdef(TEST). --export([public_key/0 - ]). --endif. - %%-------------------------------------------------------------------- %% Behaviour %%-------------------------------------------------------------------- @@ -67,10 +66,11 @@ -spec parse(string() | binary()) -> {ok, license()} | {error, term()}. parse(Content) -> - DecodedKey = base64:decode(public_key()), - parse(Content, DecodedKey). + parse(Content, ?PUBKEY). -parse(Content, Key) -> +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()}). @@ -107,8 +107,6 @@ do_parse(Content, Key, [Module | Modules], Errors) -> {error, Error} -> do_parse(Content, Key, Modules, [{Module, Error} | Errors]) catch - _Class : Error -> - do_parse(Content, Key, Modules, [{Module, Error} | Errors]) + _Class : Error : Stacktrace -> + do_parse(Content, Key, Modules, [{Module, {Error, Stacktrace}} | Errors]) end. - -public_key() -> ?PUBKEY. diff --git a/lib-ee/emqx_license/src/emqx_license_parser_v20220101.erl b/lib-ee/emqx_license/src/emqx_license_parser_v20220101.erl index 6447679e4..959e61ad4 100644 --- a/lib-ee/emqx_license/src/emqx_license_parser_v20220101.erl +++ b/lib-ee/emqx_license/src/emqx_license_parser_v20220101.erl @@ -81,8 +81,7 @@ do_parse(Content) -> end. verify_signature(Payload, Signature, Key) -> - RSAPublicKey = public_key:der_decode('RSAPublicKey', Key), - public_key:verify(Payload, ?DIGEST_TYPE, Signature, RSAPublicKey). + public_key:verify(Payload, ?DIGEST_TYPE, Signature, Key). parse_payload(Payload) -> Lines = lists:map( diff --git a/lib-ee/emqx_license/test/data/pub.pem b/lib-ee/emqx_license/test/data/pub.pem index e283992d1..09fccd092 100644 --- a/lib-ee/emqx_license/test/data/pub.pem +++ b/lib-ee/emqx_license/test/data/pub.pem @@ -1,4 +1,4 @@ -----BEGIN PUBLIC KEY----- -MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKHM3qUJR23ixg9CZYFgDdvxmTzsl+T7 -UDXNxN36UJTRN+9eFIeARbPXw2jiUva/Wf7vQKhilzZ/N+E0mK2CdX0CAwEAAQ== +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGul8oM77eCk9HgOt0mOkBnQHUf0G +M8QyDrnMYLOTpP93XcEQlf70nvodmEmHBbDzKTa7DoZMZRRIW3vGCK6zsw== -----END PUBLIC KEY----- diff --git a/lib-ee/emqx_license/test/data/pvt.key b/lib-ee/emqx_license/test/data/pvt.key index 3d6a00feb..8d7a53502 100644 --- a/lib-ee/emqx_license/test/data/pvt.key +++ b/lib-ee/emqx_license/test/data/pvt.key @@ -1,9 +1,5 @@ ------BEGIN RSA PRIVATE KEY----- -MIIBPAIBAAJBAKHM3qUJR23ixg9CZYFgDdvxmTzsl+T7UDXNxN36UJTRN+9eFIeA -RbPXw2jiUva/Wf7vQKhilzZ/N+E0mK2CdX0CAwEAAQJBAJCy2UKbA8hgEGTBKmoD -byGN9U8o/8aGgns7pJ4oKDyNWwM6Z3/omObDSTDcKn8Mfo26ccHUprIh+eiUW7TX -F4ECIQDMfCREBKniVK1yDZgqKFe1+uZqj7ylT1DQne2S9bn2UQIhAMqP3TIAED3C -MUfF3AN9oVDKJ/SFhQSKqI38XBmw9QVtAiEAqq801lHOPE3SOVF/ojDqhcxYaLpy -DMqX+orYs8LI5wECIQC/5tuf6v94Aum9HW36wKJ7b4m61mPWkaZuHY8Dp+n5YQIg -MrcXYujtNHEMWidC8S3ca1Ytp8kjMNcZVIil5CroP8E= ------END RSA PRIVATE KEY----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIDBWnjhdKzQ5VWsjJouCdl7MmPKFc664K+MMfsekbtBaoAoGCCqGSM49 +AwEHoUQDQgAEGul8oM77eCk9HgOt0mOkBnQHUf0GM8QyDrnMYLOTpP93XcEQlf70 +nvodmEmHBbDzKTa7DoZMZRRIW3vGCK6zsw== +-----END EC PRIVATE KEY----- diff --git a/lib-ee/emqx_license/test/emqx_license_SUITE.erl b/lib-ee/emqx_license/test/emqx_license_SUITE.erl index d75d10c3e..9d7e7fd45 100644 --- a/lib-ee/emqx_license/test/emqx_license_SUITE.erl +++ b/lib-ee/emqx_license/test/emqx_license_SUITE.erl @@ -27,13 +27,10 @@ end_per_suite(_) -> init_per_testcase(Case, Config) -> {ok, _} = emqx_cluster_rpc:start_link(node(), emqx_cluster_rpc, 1000), - meck:new(emqx_license_parser, [passthrough]), - meck:expect(emqx_license_parser, public_key, fun public_key/0), set_invalid_license_file(Case), Config. end_per_testcase(Case, _Config) -> - meck:unload(emqx_license_parser), restore_valid_license_file(Case), ok. @@ -167,8 +164,5 @@ mk_license(Fields) -> EncodedLicense = emqx_license_test_lib:make_license(Fields), {ok, License} = emqx_license_parser:parse( EncodedLicense, - emqx_license_test_lib:public_key_encoded()), + emqx_license_test_lib:public_key_pem()), License. - -public_key() -> <<"MEgCQQChzN6lCUdt4sYPQmWBYA3b8Zk87Jfk+1A1zcTd+lCU0Tf - vXhSHgEWz18No4lL2v1n+70CoYpc2fzfhNJitgnV9AgMBAAE=">>. diff --git a/lib-ee/emqx_license/test/emqx_license_checker_SUITE.erl b/lib-ee/emqx_license/test/emqx_license_checker_SUITE.erl index 0790b8f13..9e2da67d9 100644 --- a/lib-ee/emqx_license/test/emqx_license_checker_SUITE.erl +++ b/lib-ee/emqx_license/test/emqx_license_checker_SUITE.erl @@ -198,7 +198,7 @@ mk_license(Fields) -> EncodedLicense = emqx_license_test_lib:make_license(Fields), {ok, License} = emqx_license_parser:parse( EncodedLicense, - emqx_license_test_lib:public_key_encoded()), + emqx_license_test_lib:public_key_pem()), License. format_date({Year, Month, Day}) -> diff --git a/lib-ee/emqx_license/test/emqx_license_cli_SUITE.erl b/lib-ee/emqx_license/test/emqx_license_cli_SUITE.erl index 25a854024..d8fcf8f98 100644 --- a/lib-ee/emqx_license/test/emqx_license_cli_SUITE.erl +++ b/lib-ee/emqx_license/test/emqx_license_cli_SUITE.erl @@ -25,12 +25,9 @@ end_per_suite(_) -> init_per_testcase(_Case, Config) -> {ok, _} = emqx_cluster_rpc:start_link(node(), emqx_cluster_rpc, 1000), - meck:new(emqx_license_parser, [passthrough]), - meck:expect(emqx_license_parser, public_key, fun public_key/0), Config. end_per_testcase(_Case, _Config) -> - meck:unload(emqx_license_parser), ok. set_special_configs(emqx_license) -> @@ -62,11 +59,3 @@ t_update(_Config) -> _ = emqx_license_cli:license(["reload"]), _ = emqx_license_cli:license(["update", "Invalid License Value"]). -%%------------------------------------------------------------------------------ -%% Helpers -%%------------------------------------------------------------------------------ - -public_key() -> <<"MEgCQQChzN6lCUdt4sYPQmWBYA3b8Zk87Jfk+1A1zcTd+lCU0Tf - vXhSHgEWz18No4lL2v1n+70CoYpc2fzfhNJitgnV9AgMBAAE=">>. - -digest() -> <<"3jHg0zCb4NL5v8eIoKn+CNDMq8A04mXEOefqlUBSSVs=">>. diff --git a/lib-ee/emqx_license/test/emqx_license_parser_SUITE.erl b/lib-ee/emqx_license/test/emqx_license_parser_SUITE.erl index 898f5f95c..0f4a77ded 100644 --- a/lib-ee/emqx_license/test/emqx_license_parser_SUITE.erl +++ b/lib-ee/emqx_license/test/emqx_license_parser_SUITE.erl @@ -40,7 +40,7 @@ set_special_configs(_) -> ok. %%------------------------------------------------------------------------------ t_parse(_Config) -> - ?assertMatch({ok, _}, emqx_license_parser:parse(sample_license(), public_key_encoded())), + ?assertMatch({ok, _}, emqx_license_parser:parse(sample_license(), public_key_pem())), %% invalid version ?assertMatch( @@ -57,7 +57,7 @@ t_parse(_Config) -> "100000", "10" ]), - public_key_encoded())), + public_key_pem())), %% invalid field number ?assertMatch( @@ -74,7 +74,7 @@ t_parse(_Config) -> "100000", "10" ]), - public_key_encoded())), + public_key_pem())), ?assertMatch( {error, @@ -94,7 +94,7 @@ t_parse(_Config) -> "-10", "10" ]), - public_key_encoded())), + public_key_pem())), %% invalid signature [LicensePart, _] = binary:split( @@ -125,23 +125,23 @@ t_parse(_Config) -> [{emqx_license_parser_v20220101,invalid_signature}]}, emqx_license_parser:parse( iolist_to_binary([LicensePart, <<".">>, SignaturePart]), - public_key_encoded())), + public_key_pem())), %% totally invalid strings as license ?assertMatch( {error, [_ | _]}, emqx_license_parser:parse( <<"badlicense">>, - public_key_encoded())), + public_key_pem())), ?assertMatch( {error, [_ | _]}, emqx_license_parser:parse( <<"bad.license">>, - public_key_encoded())). + public_key_pem())). t_dump(_Config) -> - {ok, License} = emqx_license_parser:parse(sample_license(), public_key_encoded()), + {ok, License} = emqx_license_parser:parse(sample_license(), public_key_pem()), ?assertEqual( [{customer,<<"Foo">>}, @@ -155,22 +155,22 @@ t_dump(_Config) -> emqx_license_parser:dump(License)). t_customer_type(_Config) -> - {ok, License} = emqx_license_parser:parse(sample_license(), public_key_encoded()), + {ok, License} = emqx_license_parser:parse(sample_license(), public_key_pem()), ?assertEqual(10, emqx_license_parser:customer_type(License)). t_license_type(_Config) -> - {ok, License} = emqx_license_parser:parse(sample_license(), public_key_encoded()), + {ok, License} = emqx_license_parser:parse(sample_license(), public_key_pem()), ?assertEqual(0, emqx_license_parser:license_type(License)). t_max_connections(_Config) -> - {ok, License} = emqx_license_parser:parse(sample_license(), public_key_encoded()), + {ok, License} = emqx_license_parser:parse(sample_license(), public_key_pem()), ?assertEqual(10, emqx_license_parser:max_connections(License)). t_expiry_date(_Config) -> - {ok, License} = emqx_license_parser:parse(sample_license(), public_key_encoded()), + {ok, License} = emqx_license_parser:parse(sample_license(), public_key_pem()), ?assertEqual({2295,10,27}, emqx_license_parser:expiry_date(License)). @@ -178,8 +178,8 @@ t_expiry_date(_Config) -> %% Helpers %%------------------------------------------------------------------------------ -public_key_encoded() -> - emqx_license_test_lib:public_key_encoded(). +public_key_pem() -> + emqx_license_test_lib:public_key_pem(). sample_license() -> emqx_license_test_lib:make_license( diff --git a/lib-ee/emqx_license/test/emqx_license_test_lib.erl b/lib-ee/emqx_license/test/emqx_license_test_lib.erl index 9a2c05e9d..c78583911 100644 --- a/lib-ee/emqx_license/test/emqx_license_test_lib.erl +++ b/lib-ee/emqx_license/test/emqx_license_test_lib.erl @@ -25,16 +25,22 @@ private_key() -> public_key() -> test_key("pub.pem"). -public_key_encoded() -> - public_key:der_encode('RSAPublicKey', public_key()). +public_key_pem() -> + test_key("pub.pem", pem). test_key(Filename) -> + test_key(Filename, decoded). + +test_key(Filename, Format) -> Dir = code:lib_dir(emqx_license, test), Path = filename:join([Dir, "data", Filename]), {ok, KeyData} = file:read_file(Path), - [PemEntry] = public_key:pem_decode(KeyData), - Key = public_key:pem_entry_decode(PemEntry), - Key. + case Format of + pem -> KeyData; + decoded -> + [PemEntry] = public_key:pem_decode(KeyData), + public_key:pem_entry_decode(PemEntry) + end. make_license(Values) -> Key = private_key(), @@ -45,6 +51,9 @@ make_license(Values) -> iolist_to_binary([EncodedText, ".", EncodedSignature]). default_license() -> - License = make_license(?DEFAULT_LICENSE_VALUES), + %% keep it the same as in etc/emqx_license.conf + License = + "MjIwMTExCjAKMTAKRXZhbHVhdGlvbgpjb250YWN0QGVtcXguaW8KMjAyMjAxMDEKMzY1MDAKMTAK." + "MEUCIFc9EUjqB3SjpRqWjqmAzI4Tg4LwhCRet9scEoxMRt8fAiEAk6vfYUiPOTzBC+3EjNF3WmLTiA3B0TN5ZNwuTKbTXJQ=", ok = file:write_file(?DEFAULT_LICENSE_FILE, License), ?DEFAULT_LICENSE_FILE.