From ce86fb989e43712836c27813d6bad8a49cda44db Mon Sep 17 00:00:00 2001 From: Luke Bakken Date: Tue, 30 Sep 2025 16:40:30 -0700 Subject: [PATCH] Remove all usage of `cacerts` from configuration schemas As mentioned in discussion #14426, the way that `cacerts` is handled by cuttlefish schemas simply will not work if set. If `cacerts` were set to a string value containing one X509 certificate, it would eventually result in a crash because the `cacerts` ssl option must be of [this type](https://www.erlang.org/doc/apps/ssl/ssl.html#t:client_option_cert/0): ``` {cacerts, CACerts :: [public_key:der_encoded()] | [public_key:combined_cert()]} ``` Neither of those are strings, of course. This PR removes all use of `cacerts` in cuttlefish schemas. In addition, it filters out `cacerts` and `certs_keys` from being JSON-encoded by an HTTP API call to `/api/overview`. It _is_ technically possible to set `cacerts` via `advanced.config`, so, if set, it would crash this API call, as would `certs_keys`. --- deps/rabbit/priv/schema/rabbit.schema | 24 +------------------ .../schema/rabbitmq_auth_backend_http.schema | 9 ------- .../schema/rabbitmq_auth_backend_ldap.schema | 9 ------- .../priv/schema/rabbitmq_management.schema | 11 +-------- .../src/rabbit_mgmt_format.erl | 11 +++++++++ .../rabbitmq_peer_discovery_consul.schema | 9 ------- .../rabbitmq_peer_discovery_etcd.schema | 9 ------- .../schema/rabbitmq_management.schema | 9 ------- .../priv/schema/rabbitmq_trust_store.schema | 9 ------- 9 files changed, 13 insertions(+), 87 deletions(-) diff --git a/deps/rabbit/priv/schema/rabbit.schema b/deps/rabbit/priv/schema/rabbit.schema index 8e5e7c41b31e..a62e2fc852ca 100644 --- a/deps/rabbit/priv/schema/rabbit.schema +++ b/deps/rabbit/priv/schema/rabbit.schema @@ -180,15 +180,6 @@ end}. {mapping, "definitions.tls.certfile", "rabbit.definitions.ssl_options.certfile", [{datatype, string}, {validators, ["file_accessible"]}]}. -{mapping, "definitions.tls.cacerts.$name", "rabbit.definitions.ssl_options.cacerts", - [{datatype, string}]}. - -{translation, "rabbit.definitions.ssl_options.cacerts", -fun(Conf) -> - Settings = cuttlefish_variable:filter_by_prefix("definitions.tls.cacerts", Conf), - [ list_to_binary(V) || {_, V} <- Settings ] -end}. - {mapping, "definitions.tls.cert", "rabbit.definitions.ssl_options.cert", [{datatype, string}]}. @@ -330,15 +321,6 @@ end}. {mapping, "ssl_options.certfile", "rabbit.ssl_options.certfile", [{datatype, string}, {validators, ["file_accessible"]}]}. -{mapping, "ssl_options.cacerts.$name", "rabbit.ssl_options.cacerts", - [{datatype, string}]}. - -{translation, "rabbit.ssl_options.cacerts", -fun(Conf) -> - Settings = cuttlefish_variable:filter_by_prefix("ssl_options.cacerts", Conf), - [ list_to_binary(V) || {_, V} <- Settings ] -end}. - {mapping, "ssl_options.cert", "rabbit.ssl_options.cert", [{datatype, string}]}. @@ -1931,9 +1913,6 @@ end}. {mapping, "log.syslog.ssl_options.certfile", "syslog.protocol", [{datatype, string}, {validators, ["file_accessible"]}]}. -{mapping, "log.syslog.ssl_options.cacerts.$name", "syslog.protocol", - [{datatype, string}]}. - {mapping, "log.syslog.ssl_options.cert", "syslog.protocol", [{datatype, string}]}. @@ -2021,8 +2000,7 @@ fun(Conf) -> DefinedSettings) ++ [ {K, V} || {K, V} <- - [{cacerts, [ list_to_binary(V) || {_, V} <- cuttlefish_variable:filter_by_prefix("log.syslog.ssl_options.cacerts", Conf)]}, - {versions, [ V || {_, V} <- cuttlefish_variable:filter_by_prefix("log.syslog.ssl_options.versions", Conf) ]}, + [{versions, [ V || {_, V} <- cuttlefish_variable:filter_by_prefix("log.syslog.ssl_options.versions", Conf)]}, {key, case cuttlefish_variable:filter_by_prefix("log.syslog.ssl_options.key", Conf) of [{[_,_,Key], Val}|_] -> {list_to_atom(Key), list_to_binary(Val)}; _ -> undefined diff --git a/deps/rabbitmq_auth_backend_http/priv/schema/rabbitmq_auth_backend_http.schema b/deps/rabbitmq_auth_backend_http/priv/schema/rabbitmq_auth_backend_http.schema index b50013fb1651..fccf97383ce8 100644 --- a/deps/rabbitmq_auth_backend_http/priv/schema/rabbitmq_auth_backend_http.schema +++ b/deps/rabbitmq_auth_backend_http/priv/schema/rabbitmq_auth_backend_http.schema @@ -49,15 +49,6 @@ end}. {mapping, "auth_http.ssl_options.certfile", "rabbitmq_auth_backend_http.ssl_options.certfile", [{datatype, string}, {validators, ["file_accessible"]}]}. -{mapping, "auth_http.ssl_options.cacerts.$name", "rabbitmq_auth_backend_http.ssl_options.cacerts", - [{datatype, string}]}. - -{translation, "rabbitmq_auth_backend_http.ssl_options.cacerts", -fun(Conf) -> - Settings = cuttlefish_variable:filter_by_prefix("auth_http.ssl_options.cacerts", Conf), - [ list_to_binary(V) || {_, V} <- Settings ] -end}. - {mapping, "auth_http.ssl_options.cert", "rabbitmq_auth_backend_http.ssl_options.cert", [{datatype, string}]}. diff --git a/deps/rabbitmq_auth_backend_ldap/priv/schema/rabbitmq_auth_backend_ldap.schema b/deps/rabbitmq_auth_backend_ldap/priv/schema/rabbitmq_auth_backend_ldap.schema index daf58bb49440..507659b81c4c 100644 --- a/deps/rabbitmq_auth_backend_ldap/priv/schema/rabbitmq_auth_backend_ldap.schema +++ b/deps/rabbitmq_auth_backend_ldap/priv/schema/rabbitmq_auth_backend_ldap.schema @@ -251,15 +251,6 @@ end}. {mapping, "auth_ldap.ssl_options.certfile", "rabbitmq_auth_backend_ldap.ssl_options.certfile", [{datatype, string}, {validators, ["file_accessible"]}]}. -{mapping, "auth_ldap.ssl_options.cacerts.$name", "rabbitmq_auth_backend_ldap.ssl_options.cacerts", - [{datatype, string}]}. - -{translation, "rabbitmq_auth_backend_ldap.ssl_options.cacerts", -fun(Conf) -> - Settings = cuttlefish_variable:filter_by_prefix("auth_ldap.ssl_options.cacerts", Conf), - [ list_to_binary(V) || {_, V} <- Settings ] -end}. - {mapping, "auth_ldap.ssl_options.cert", "rabbitmq_auth_backend_ldap.ssl_options.cert", [{datatype, string}]}. diff --git a/deps/rabbitmq_management/priv/schema/rabbitmq_management.schema b/deps/rabbitmq_management/priv/schema/rabbitmq_management.schema index 1a1b837b0486..0b9589d4b347 100644 --- a/deps/rabbitmq_management/priv/schema/rabbitmq_management.schema +++ b/deps/rabbitmq_management/priv/schema/rabbitmq_management.schema @@ -220,15 +220,6 @@ end}. {mapping, "management.listener.ssl_opts.certfile", "rabbitmq_management.listener.ssl_opts.certfile", [{datatype, string}, {validators, ["file_accessible"]}]}. -{mapping, "management.listener.ssl_opts.cacerts.$name", "rabbitmq_management.listener.ssl_opts.cacerts", - [{datatype, string}]}. - -{translation, "rabbitmq_management.listener.ssl_opts.cacerts", -fun(Conf) -> - Settings = cuttlefish_variable:filter_by_prefix("management.listener.ssl_opts.cacerts", Conf), - [ list_to_binary(V) || {_, V} <- Settings ] -end}. - {mapping, "management.listener.ssl_opts.honor_cipher_order", "rabbitmq_management.listener.ssl_opts.honor_cipher_order", [{datatype, {enum, [true, false]}}]}. @@ -660,4 +651,4 @@ end}. {mapping, "management.require_auth_for_api_reference", "rabbitmq_management.require_auth_for_api_reference", [ {datatype, {enum, [true, false]}}, {include_default, false} -]}. \ No newline at end of file +]}. diff --git a/deps/rabbitmq_management_agent/src/rabbit_mgmt_format.erl b/deps/rabbitmq_management_agent/src/rabbit_mgmt_format.erl index 111e9e9b200e..42b980ad5ea0 100644 --- a/deps/rabbitmq_management_agent/src/rabbit_mgmt_format.erl +++ b/deps/rabbitmq_management_agent/src/rabbit_mgmt_format.erl @@ -317,6 +317,17 @@ format_socket_opts([{user_lookup_fun, _Value} | Tail], Acc) -> format_socket_opts(Tail, Acc); format_socket_opts([{sni_fun, _Value} | Tail], Acc) -> format_socket_opts(Tail, Acc); +%% https://www.erlang.org/doc/apps/ssl/ssl.html#t:server_option_cert/0 +format_socket_opts([{cacerts, Cacerts} | Tail], Acc) -> + CacertsMsg = rabbit_data_coercion:to_utf8_binary( + io_lib:format("(~b cacerts entries)", [length(Cacerts)])), + format_socket_opts(Tail, [{cacerts, CacertsMsg} | Acc]); +%% https://www.erlang.org/doc/apps/ssl/ssl.html#t:common_option_cert/0 +%% https://www.erlang.org/doc/apps/ssl/ssl.html#t:cert_key_conf/0 +format_socket_opts([{certs_keys, CertsKeys} | Tail], Acc) -> + CertsKeysMsg = rabbit_data_coercion:to_utf8_binary( + io_lib:format("(~b certs_keys entries)", [length(CertsKeys)])), + format_socket_opts(Tail, [{cacerts, CertsKeysMsg} | Acc]); %% we do not report SNI host details in the UI, %% so skip this option and avoid some recursive formatting %% complexity diff --git a/deps/rabbitmq_peer_discovery_consul/priv/schema/rabbitmq_peer_discovery_consul.schema b/deps/rabbitmq_peer_discovery_consul/priv/schema/rabbitmq_peer_discovery_consul.schema index 42f9ec286270..2398ae4233d3 100644 --- a/deps/rabbitmq_peer_discovery_consul/priv/schema/rabbitmq_peer_discovery_consul.schema +++ b/deps/rabbitmq_peer_discovery_consul/priv/schema/rabbitmq_peer_discovery_consul.schema @@ -367,15 +367,6 @@ end}. {mapping, "cluster_formation.consul.ssl_options.certfile", "rabbit.cluster_formation.peer_discovery_consul.ssl_options.certfile", [{datatype, string}, {validators, ["file_accessible"]}]}. -{mapping, "cluster_formation.consul.ssl_options.cacerts.$name", "rabbit.cluster_formation.peer_discovery_consul.ssl_options.cacerts", -[{datatype, string}]}. - -{translation, "rabbit.cluster_formation.peer_discovery_consul.ssl_options.cacerts", -fun(Conf) -> -Settings = cuttlefish_variable:filter_by_prefix("cluster_formation.consul.ssl_options.cacerts", Conf), -[ list_to_binary(V) || {_, V} <- Settings ] -end}. - {mapping, "cluster_formation.consul.ssl_options.cert", "rabbit.cluster_formation.peer_discovery_consul.ssl_options.cert", [{datatype, string}]}. diff --git a/deps/rabbitmq_peer_discovery_etcd/priv/schema/rabbitmq_peer_discovery_etcd.schema b/deps/rabbitmq_peer_discovery_etcd/priv/schema/rabbitmq_peer_discovery_etcd.schema index e2e0861f6deb..3553d638e4eb 100644 --- a/deps/rabbitmq_peer_discovery_etcd/priv/schema/rabbitmq_peer_discovery_etcd.schema +++ b/deps/rabbitmq_peer_discovery_etcd/priv/schema/rabbitmq_peer_discovery_etcd.schema @@ -188,15 +188,6 @@ end}. {mapping, "cluster_formation.etcd.ssl_options.certfile", "rabbit.cluster_formation.peer_discovery_etcd.ssl_options.certfile", [{datatype, string}, {validators, ["file_accessible"]}]}. -{mapping, "cluster_formation.etcd.ssl_options.cacerts.$name", "rabbit.cluster_formation.peer_discovery_etcd.ssl_options.cacerts", - [{datatype, string}]}. - -{translation, "rabbit.cluster_formation.peer_discovery_etcd.ssl_options.cacerts", -fun(Conf) -> - Settings = cuttlefish_variable:filter_by_prefix("cluster_formation.etcd.ssl_options.cacerts", Conf), - [ list_to_binary(V) || {_, V} <- Settings ] -end}. - {mapping, "cluster_formation.etcd.ssl_options.cert", "rabbit.cluster_formation.peer_discovery_etcd.ssl_options.cert", [{datatype, string}]}. diff --git a/deps/rabbitmq_prometheus/test/config_schema_SUITE_data/schema/rabbitmq_management.schema b/deps/rabbitmq_prometheus/test/config_schema_SUITE_data/schema/rabbitmq_management.schema index e05da0a00106..b8fa2fcf8c6f 100644 --- a/deps/rabbitmq_prometheus/test/config_schema_SUITE_data/schema/rabbitmq_management.schema +++ b/deps/rabbitmq_prometheus/test/config_schema_SUITE_data/schema/rabbitmq_management.schema @@ -194,15 +194,6 @@ end}. {mapping, "management.listener.ssl_opts.certfile", "rabbitmq_management.listener.ssl_opts.certfile", [{datatype, string}, {validators, ["file_accessible"]}]}. -{mapping, "management.listener.ssl_opts.cacerts.$name", "rabbitmq_management.listener.ssl_opts.cacerts", - [{datatype, string}]}. - -{translation, "rabbitmq_management.listener.ssl_opts.cacerts", -fun(Conf) -> - Settings = cuttlefish_variable:filter_by_prefix("management.listener.ssl_opts.cacerts", Conf), - [ list_to_binary(V) || {_, V} <- Settings ] -end}. - {mapping, "management.listener.ssl_opts.honor_cipher_order", "rabbitmq_management.listener.ssl_opts.honor_cipher_order", [{datatype, {enum, [true, false]}}]}. diff --git a/deps/rabbitmq_trust_store/priv/schema/rabbitmq_trust_store.schema b/deps/rabbitmq_trust_store/priv/schema/rabbitmq_trust_store.schema index 2f7b7e564351..03a41dfd5e0c 100644 --- a/deps/rabbitmq_trust_store/priv/schema/rabbitmq_trust_store.schema +++ b/deps/rabbitmq_trust_store/priv/schema/rabbitmq_trust_store.schema @@ -60,15 +60,6 @@ end}. {mapping, "trust_store.ssl_options.certfile", "rabbitmq_trust_store.ssl_options.certfile", [{datatype, string}, {validators, ["file_accessible"]}]}. -{mapping, "trust_store.ssl_options.cacerts.$name", "rabbitmq_trust_store.ssl_options.cacerts", - [{datatype, string}]}. - -{translation, "rabbitmq_trust_store.ssl_options.cacerts", -fun(Conf) -> - Settings = cuttlefish_variable:filter_by_prefix("trust_store.ssl_options.cacerts", Conf), - [ list_to_binary(V) || {_, V} <- Settings ] -end}. - {mapping, "trust_store.ssl_options.cert", "rabbitmq_trust_store.ssl_options.cert", [{datatype, string}]}.