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,
|
||||
non_empty_string/1,
|
||||
validations/0,
|
||||
naive_env_interpolation/1
|
||||
naive_env_interpolation/1,
|
||||
validate_server_ssl_opts/1
|
||||
]).
|
||||
|
||||
-export([qos/0]).
|
||||
|
@ -958,7 +959,7 @@ fields("mqtt_wss_listener") ->
|
|||
{"ssl_options",
|
||||
sc(
|
||||
ref("listener_wss_opts"),
|
||||
#{}
|
||||
#{validator => fun validate_server_ssl_opts/1}
|
||||
)},
|
||||
{"websocket",
|
||||
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) ->
|
||||
Checks = [
|
||||
fun validate_server_ssl_opts/1,
|
||||
fun ocsp_outer_validator/1,
|
||||
fun crl_outer_validator/1
|
||||
],
|
||||
|
|
|
@ -106,6 +106,67 @@ bad_cipher_test() ->
|
|||
),
|
||||
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) ->
|
||||
Sc = #{
|
||||
roots => [ssl_opts],
|
||||
|
|
|
@ -120,7 +120,10 @@ fields(ssl_listener) ->
|
|||
{ssl_options,
|
||||
sc(
|
||||
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) ->
|
||||
|
@ -132,7 +135,13 @@ fields(udp_listener) ->
|
|||
fields(dtls_listener) ->
|
||||
[{acceptors, sc(integer(), #{default => 16, desc => ?DESC(dtls_listener_acceptors)})}] ++
|
||||
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) ->
|
||||
[
|
||||
{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