Merge pull request #10952 from SergeTupchiy/EMQX-9586-validate-fail_if_no_peer_cert
fix(emqx_schema): don't allow enabling `fail_if_no_peer_cert` if `verify_none` is set
This commit is contained in:
commit
e749ae6863
|
@ -94,7 +94,8 @@
|
||||||
validate_keepalive_multiplier/1,
|
validate_keepalive_multiplier/1,
|
||||||
non_empty_string/1,
|
non_empty_string/1,
|
||||||
validations/0,
|
validations/0,
|
||||||
naive_env_interpolation/1
|
naive_env_interpolation/1,
|
||||||
|
validate_server_ssl_opts/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export([qos/0]).
|
-export([qos/0]).
|
||||||
|
@ -958,7 +959,7 @@ fields("mqtt_wss_listener") ->
|
||||||
{"ssl_options",
|
{"ssl_options",
|
||||||
sc(
|
sc(
|
||||||
ref("listener_wss_opts"),
|
ref("listener_wss_opts"),
|
||||||
#{}
|
#{validator => fun validate_server_ssl_opts/1}
|
||||||
)},
|
)},
|
||||||
{"websocket",
|
{"websocket",
|
||||||
sc(
|
sc(
|
||||||
|
@ -2426,8 +2427,21 @@ server_ssl_opts_schema(Defaults, IsRanchListener) ->
|
||||||
]
|
]
|
||||||
].
|
].
|
||||||
|
|
||||||
|
validate_server_ssl_opts(#{<<"fail_if_no_peer_cert">> := true, <<"verify">> := Verify}) ->
|
||||||
|
validate_verify(Verify);
|
||||||
|
validate_server_ssl_opts(#{fail_if_no_peer_cert := true, verify := Verify}) ->
|
||||||
|
validate_verify(Verify);
|
||||||
|
validate_server_ssl_opts(_SSLOpts) ->
|
||||||
|
ok.
|
||||||
|
|
||||||
|
validate_verify(verify_peer) ->
|
||||||
|
ok;
|
||||||
|
validate_verify(_) ->
|
||||||
|
{error, "verify must be verify_peer when fail_if_no_peer_cert is true"}.
|
||||||
|
|
||||||
mqtt_ssl_listener_ssl_options_validator(Conf) ->
|
mqtt_ssl_listener_ssl_options_validator(Conf) ->
|
||||||
Checks = [
|
Checks = [
|
||||||
|
fun validate_server_ssl_opts/1,
|
||||||
fun ocsp_outer_validator/1,
|
fun ocsp_outer_validator/1,
|
||||||
fun crl_outer_validator/1
|
fun crl_outer_validator/1
|
||||||
],
|
],
|
||||||
|
|
|
@ -106,6 +106,67 @@ bad_cipher_test() ->
|
||||||
),
|
),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
fail_if_no_peer_cert_test_() ->
|
||||||
|
Sc = #{
|
||||||
|
roots => [mqtt_ssl_listener],
|
||||||
|
fields => #{mqtt_ssl_listener => emqx_schema:fields("mqtt_ssl_listener")}
|
||||||
|
},
|
||||||
|
Opts = #{atom_key => false, required => false},
|
||||||
|
OptsAtomKey = #{atom_key => true, required => false},
|
||||||
|
InvalidConf = #{
|
||||||
|
<<"bind">> => <<"0.0.0.0:9883">>,
|
||||||
|
<<"ssl_options">> => #{
|
||||||
|
<<"fail_if_no_peer_cert">> => true,
|
||||||
|
<<"verify">> => <<"verify_none">>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
InvalidListener = #{<<"mqtt_ssl_listener">> => InvalidConf},
|
||||||
|
ValidListener = #{
|
||||||
|
<<"mqtt_ssl_listener">> => InvalidConf#{
|
||||||
|
<<"ssl_options">> =>
|
||||||
|
#{
|
||||||
|
<<"fail_if_no_peer_cert">> => true,
|
||||||
|
<<"verify">> => <<"verify_peer">>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ValidListener1 = #{
|
||||||
|
<<"mqtt_ssl_listener">> => InvalidConf#{
|
||||||
|
<<"ssl_options">> =>
|
||||||
|
#{
|
||||||
|
<<"fail_if_no_peer_cert">> => false,
|
||||||
|
<<"verify">> => <<"verify_none">>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Reason = "verify must be verify_peer when fail_if_no_peer_cert is true",
|
||||||
|
[
|
||||||
|
?_assertThrow(
|
||||||
|
{_Sc, [#{kind := validation_error, reason := Reason}]},
|
||||||
|
hocon_tconf:check_plain(Sc, InvalidListener, Opts)
|
||||||
|
),
|
||||||
|
?_assertThrow(
|
||||||
|
{_Sc, [#{kind := validation_error, reason := Reason}]},
|
||||||
|
hocon_tconf:check_plain(Sc, InvalidListener, OptsAtomKey)
|
||||||
|
),
|
||||||
|
?_assertMatch(
|
||||||
|
#{mqtt_ssl_listener := #{}},
|
||||||
|
hocon_tconf:check_plain(Sc, ValidListener, OptsAtomKey)
|
||||||
|
),
|
||||||
|
?_assertMatch(
|
||||||
|
#{mqtt_ssl_listener := #{}},
|
||||||
|
hocon_tconf:check_plain(Sc, ValidListener1, OptsAtomKey)
|
||||||
|
),
|
||||||
|
?_assertMatch(
|
||||||
|
#{<<"mqtt_ssl_listener">> := #{}},
|
||||||
|
hocon_tconf:check_plain(Sc, ValidListener, Opts)
|
||||||
|
),
|
||||||
|
?_assertMatch(
|
||||||
|
#{<<"mqtt_ssl_listener">> := #{}},
|
||||||
|
hocon_tconf:check_plain(Sc, ValidListener1, Opts)
|
||||||
|
)
|
||||||
|
].
|
||||||
|
|
||||||
validate(Schema, Data0) ->
|
validate(Schema, Data0) ->
|
||||||
Sc = #{
|
Sc = #{
|
||||||
roots => [ssl_opts],
|
roots => [ssl_opts],
|
||||||
|
|
|
@ -120,7 +120,10 @@ fields(ssl_listener) ->
|
||||||
{ssl_options,
|
{ssl_options,
|
||||||
sc(
|
sc(
|
||||||
hoconsc:ref(emqx_schema, "listener_ssl_opts"),
|
hoconsc:ref(emqx_schema, "listener_ssl_opts"),
|
||||||
#{desc => ?DESC(ssl_listener_options)}
|
#{
|
||||||
|
desc => ?DESC(ssl_listener_options),
|
||||||
|
validator => fun emqx_schema:validate_server_ssl_opts/1
|
||||||
|
}
|
||||||
)}
|
)}
|
||||||
];
|
];
|
||||||
fields(udp_listener) ->
|
fields(udp_listener) ->
|
||||||
|
@ -132,7 +135,13 @@ fields(udp_listener) ->
|
||||||
fields(dtls_listener) ->
|
fields(dtls_listener) ->
|
||||||
[{acceptors, sc(integer(), #{default => 16, desc => ?DESC(dtls_listener_acceptors)})}] ++
|
[{acceptors, sc(integer(), #{default => 16, desc => ?DESC(dtls_listener_acceptors)})}] ++
|
||||||
fields(udp_listener) ++
|
fields(udp_listener) ++
|
||||||
[{dtls_options, sc(ref(dtls_opts), #{desc => ?DESC(dtls_listener_dtls_opts)})}];
|
[
|
||||||
|
{dtls_options,
|
||||||
|
sc(ref(dtls_opts), #{
|
||||||
|
desc => ?DESC(dtls_listener_dtls_opts),
|
||||||
|
validator => fun emqx_schema:validate_server_ssl_opts/1
|
||||||
|
})}
|
||||||
|
];
|
||||||
fields(udp_opts) ->
|
fields(udp_opts) ->
|
||||||
[
|
[
|
||||||
{active_n,
|
{active_n,
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
Disallow enabling `fail_if_no_peer_cert` in listener SSL options if `verify_none` is set.
|
||||||
|
|
||||||
|
Setting `fail_if_no_peer_cert = true` and `verify = verify_none` caused connection errors
|
||||||
|
due to incompatible options.
|
||||||
|
This fix validates the options when creating or updating a listener to avoid these errors.
|
||||||
|
|
||||||
|
Note: any old listener configuration with `fail_if_no_peer_cert = true` and `verify = verify_none`
|
||||||
|
that was previously allowed will fail to load after applying this fix and must be manually fixed.
|
Loading…
Reference in New Issue