diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl
index 78d6d6eb9..ff95414f8 100644
--- a/apps/emqx/src/emqx_schema.erl
+++ b/apps/emqx/src/emqx_schema.erl
@@ -102,11 +102,6 @@
-elvis([{elvis_style, god_modules, disable}]).
--define(IDLE_TIMOUT_DESC,
- "Close transport-layer connections from the clients that have not sent MQTT CONNECT\n"
- "message within this interval."
-).
-
namespace() -> undefined.
roots() ->
@@ -295,12 +290,7 @@ fields("authorization") ->
default => allow,
required => true,
%% TODO: make sources a reference link
- desc_id => fields_authorization_no_match,
- desc =>
- "Default access control action if the user or client matches no ACL rules,\n"
- "or if no such user or client is found by the configurable authorization\n"
- "sources such as built_in_database, an HTTP API, or a query against PostgreSQL.\n"
- "Find more details in 'authorization.sources' config."
+ desc => ?DESC(fields_authorization_no_match)
}
)},
{"deny_action",
@@ -309,8 +299,7 @@ fields("authorization") ->
#{
default => ignore,
required => true,
- desc_id => fields_authorization_deny_action,
- desc => "The action when the authorization check rejects an operation."
+ desc => ?DESC(fields_authorization_deny_action)
}
)},
{"cache",
@@ -326,8 +315,7 @@ fields("cache") ->
boolean(),
#{
default => true,
- desc_id => fields_cache_enable,
- desc => "Enable or disable the authorization cache."
+ desc => ?DESC(fields_cache_enable)
}
)},
{"max_size",
@@ -335,8 +323,7 @@ fields("cache") ->
range(1, 1048576),
#{
default => 32,
- desc_id => fields_cache_max_size,
- desc => "Maximum number of cached items."
+ desc => ?DESC(fields_cache_max_size)
}
)},
{"ttl",
@@ -344,8 +331,7 @@ fields("cache") ->
duration(),
#{
default => "1m",
- desc_id => fields_cache_ttl,
- desc => "Time to live for the cached data."
+ desc => ?DESC(fields_cache_ttl)
}
)}
];
@@ -586,8 +572,7 @@ fields("rate_limit") ->
hoconsc:union([infinity, integer()]),
#{
default => 1000,
- desc_id => fields_rate_limit_max_conn_rate,
- desc => "Maximum connections per second."
+ desc => ?DESC(fields_rate_limit_max_conn_rate)
}
)},
{"conn_messages_in",
@@ -595,8 +580,7 @@ fields("rate_limit") ->
hoconsc:union([infinity, comma_separated_list()]),
#{
default => infinity,
- desc_id => fields_rate_limit_conn_messages_in,
- desc => "Message limit for the external MQTT connections."
+ desc => ?DESC(fields_rate_limit_conn_messages_in)
}
)},
{"conn_bytes_in",
@@ -604,10 +588,7 @@ fields("rate_limit") ->
hoconsc:union([infinity, comma_separated_list()]),
#{
default => infinity,
- desc_id => fields_rate_limit_conn_bytes_in,
- desc =>
- "Limit the rate of receiving packets for a MQTT connection.\n"
- "The rate is counted by bytes of packets per second."
+ desc => ?DESC(fields_rate_limit_conn_bytes_in)
}
)}
];
@@ -766,8 +747,7 @@ fields("listeners") ->
sc(
map(name, ref("mqtt_tcp_listener")),
#{
- desc_id => fields_listeners_tcp,
- desc => "TCP listeners",
+ desc => ?DESC(fields_listeners_tcp),
required => {false, recursively}
}
)},
@@ -775,8 +755,7 @@ fields("listeners") ->
sc(
map(name, ref("mqtt_ssl_listener")),
#{
- desc_id => fields_listeners_ssl,
- desc => "SSL listeners",
+ desc => ?DESC(fields_listeners_ssl),
required => {false, recursively}
}
)},
@@ -784,8 +763,7 @@ fields("listeners") ->
sc(
map(name, ref("mqtt_ws_listener")),
#{
- desc_id => fields_listeners_ws,
- desc => "HTTP websocket listeners",
+ desc => ?DESC(fields_listeners_ws),
required => {false, recursively}
}
)},
@@ -793,8 +771,7 @@ fields("listeners") ->
sc(
map(name, ref("mqtt_wss_listener")),
#{
- desc_id => fields_listeners_wss,
- desc => "HTTPS websocket listeners",
+ desc => ?DESC(fields_listeners_wss),
required => {false, recursively}
}
)},
@@ -802,8 +779,7 @@ fields("listeners") ->
sc(
map(name, ref("mqtt_quic_listener")),
#{
- desc_id => fields_listeners_quic,
- desc => "QUIC listeners",
+ desc => ?DESC(fields_listeners_quic),
required => {false, recursively}
}
)}
@@ -866,23 +842,20 @@ fields("mqtt_quic_listener") ->
sc(
boolean(),
#{ default => true
- , desc_id => fields_mqtt_quic_listener_enabled
- , desc => "Enable QUIC listener."
+ , desc => ?DESC(fields_mqtt_quic_listener_enabled)
}
)},
%% TODO: ensure cacertfile is configurable
{"certfile",
sc(
string(),
- #{ desc => "Path to the certificate file."
- , desc_id => fields_mqtt_quic_listener_certfile
+ #{ desc => ?DESC(fields_mqtt_quic_listener_certfile)
}
)},
{"keyfile",
sc(
string(),
- #{ desc => "Path to the secret key file."
- , desc_id => fields_mqtt_quic_listener_keyfile
+ #{ desc => ?DESC(fields_mqtt_quic_listener_keyfile)
}
)},
{"ciphers", ciphers_schema(quic)},
@@ -890,8 +863,7 @@ fields("mqtt_quic_listener") ->
sc(
duration(),
#{ default => "15s"
- , desc_id => fields_mqtt_quic_listener_idle_timeout
- , desc => ?IDLE_TIMOUT_DESC
+ , desc => ?DESC(fields_mqtt_quic_listener_idle_timeout)
}
)}
] ++ base_listener();
@@ -902,10 +874,7 @@ fields("ws_opts") ->
string(),
#{
default => "/mqtt",
- desc_id => fields_ws_opts_mqtt_path,
- desc =>
- "WebSocket's MQTT protocol path. So the address of\n"
- " EMQX Broker's WebSocket is: ws://{ip}:{port}/mqtt
"
+ desc => ?DESC(fields_ws_opts_mqtt_path)
}
)},
{"mqtt_piggyback",
@@ -913,9 +882,7 @@ fields("ws_opts") ->
hoconsc:enum([single, multiple]),
#{
default => multiple,
- desc_id => fields_ws_opts_mqtt_piggyback,
- desc =>
- "Whether a WebSocket message is allowed to contain multiple MQTT packets."
+ desc => ?DESC(fields_ws_opts_mqtt_piggyback)
}
)},
{"compress",
@@ -923,11 +890,7 @@ fields("ws_opts") ->
boolean(),
#{
default => false,
- desc_id => fields_ws_opts_compress,
- desc =>
- "If true
, compress WebSocket messages using zlib
.
\n"
- "The configuration items under deflate_opts
"
- "belong to the compression-related parameter configuration."
+ desc => ?DESC(fields_ws_opts_compress)
}
)},
{"idle_timeout",
@@ -935,8 +898,7 @@ fields("ws_opts") ->
duration(),
#{
default => "15s",
- desc_id => fields_ws_opts_idle_timeout,
- desc => ?IDLE_TIMOUT_DESC
+ desc => ?DESC(fields_mqtt_quic_listener_idle_timeout)
}
)},
{"max_frame_size",
@@ -944,8 +906,7 @@ fields("ws_opts") ->
hoconsc:union([infinity, integer()]),
#{
default => infinity,
- desc_id => fields_ws_opts_max_frame_size,
- desc => "The maximum length of a single MQTT packet."
+ desc => ?DESC(fields_ws_opts_max_frame_size)
}
)},
{"fail_if_no_subprotocol",
@@ -953,11 +914,7 @@ fields("ws_opts") ->
boolean(),
#{
default => true,
- desc_id => fields_ws_opts_fail_if_no_subprotocol,
- desc =>
- "If true
, the server will return an error when\n"
- " the client does not carry the Sec-WebSocket-Protocol
field.\n"
- "
Note: WeChat applet needs to disable this verification."
+ desc => ?DESC(fields_ws_opts_fail_if_no_subprotocol)
}
)},
{"supported_subprotocols",
@@ -965,8 +922,7 @@ fields("ws_opts") ->
comma_separated_list(),
#{
default => "mqtt, mqtt-v3, mqtt-v3.1.1, mqtt-v5",
- desc_id => fields_ws_opts_supported_subprotocols,
- desc => "Comma-separated list of supported subprotocols."
+ desc => ?DESC(fields_ws_opts_supported_subprotocols)
}
)},
{"check_origin_enable",
@@ -974,11 +930,7 @@ fields("ws_opts") ->
boolean(),
#{
default => false,
- desc_id => fields_ws_opts_check_origin_enable,
- desc =>
- "If true
, origin
HTTP header will be\n"
- " validated against the list of allowed origins configured in check_origins
\n"
- " parameter."
+ desc => ?DESC(fields_ws_opts_check_origin_enable)
}
)},
{"allow_origin_absence",
@@ -986,11 +938,7 @@ fields("ws_opts") ->
boolean(),
#{
default => true,
- desc_id => fields_ws_opts_allow_origin_absence,
- desc =>
- "If false
and check_origin_enable
is\n"
- " true
, the server will reject requests that don't have origin
\n"
- " HTTP header."
+ desc => ?DESC(fields_ws_opts_allow_origin_absence)
}
)},
{"check_origins",
@@ -998,8 +946,7 @@ fields("ws_opts") ->
hoconsc:array(binary()),
#{
default => [],
- desc_id => fields_ws_opts_check_origins,
- desc => "List of allowed origins.
See check_origin_enable
."
+ desc => ?DESC(fields_ws_opts_check_origins)
}
)},
{"proxy_address_header",
@@ -1007,10 +954,7 @@ fields("ws_opts") ->
string(),
#{
default => "x-forwarded-for",
- desc_id => fields_ws_opts_proxy_address_header,
- desc =>
- "HTTP header used to pass information about the client IP address.\n"
- " Relevant when the EMQX cluster is deployed behind a load-balancer."
+ desc => ?DESC(fields_ws_opts_proxy_address_header)
}
)},
{"proxy_port_header",
@@ -1018,10 +962,7 @@ fields("ws_opts") ->
string(),
#{
default => "x-forwarded-port",
- desc_id => fields_ws_opts_proxy_port_header,
- desc =>
- "HTTP header used to pass information about the client port.\n"
- " Relevant when the EMQX cluster is deployed behind a load-balancer."
+ desc => ?DESC(fields_ws_opts_proxy_port_header)
}
)},
{"deflate_opts",
@@ -1037,10 +978,7 @@ fields("tcp_opts") ->
integer(),
#{
default => 100,
- desc_id => fields_tcp_opts_active_n,
- desc =>
- "Specify the {active, N} option for this Socket.
\n"
- " See: https://erlang.org/doc/man/inet.html#setopts-2"
+ desc => ?DESC(fields_tcp_opts_active_n)
}
)},
{"backlog",
@@ -1048,10 +986,7 @@ fields("tcp_opts") ->
integer(),
#{
default => 1024,
- desc_id => fields_tcp_opts_backlog,
- desc =>
- "TCP backlog defines the maximum length that the queue of\n"
- " pending connections can grow to."
+ desc => ?DESC(fields_tcp_opts_backlog)
}
)},
{"send_timeout",
@@ -1059,8 +994,7 @@ fields("tcp_opts") ->
duration(),
#{
default => "15s",
- desc_id => fields_tcp_opts_send_timeout,
- desc => "The TCP send timeout for the connections."
+ desc => ?DESC(fields_tcp_opts_send_timeout)
}
)},
{"send_timeout_close",
@@ -1068,29 +1002,25 @@ fields("tcp_opts") ->
boolean(),
#{
default => true,
- desc_id => fields_tcp_opts_send_timeout_close,
- desc => "Close the connection if send timeout."
+ desc => ?DESC(fields_tcp_opts_send_timeout_close)
}
)},
{"recbuf",
sc(
bytesize(),
- #{ desc => "The TCP receive buffer (OS kernel) for the connections."
- , desc_id => fields_tcp_opts_recbuf
+ #{ desc => ?DESC(fields_tcp_opts_recbuf)
}
)},
{"sndbuf",
sc(
bytesize(),
- #{ desc => "The TCP send buffer (OS kernel) for the connections."
- , desc_id => fields_tcp_opts_sndbuf
+ #{ desc => ?DESC(fields_tcp_opts_sndbuf)
}
)},
{"buffer",
sc(
bytesize(),
- #{ desc => "The size of the user-space buffer used by the driver."
- , desc_id => fields_tcp_opts_buffer
+ #{ desc => ?DESC(fields_tcp_opts_buffer)
}
)},
{"high_watermark",
@@ -1098,10 +1028,7 @@ fields("tcp_opts") ->
bytesize(),
#{
default => "1MB",
- desc_id => fields_tcp_opts_high_watermark,
- desc =>
- "The socket is set to a busy state when the amount of data queued internally\n"
- " by the VM socket implementation reaches this limit."
+ desc => ?DESC(fields_tcp_opts_high_watermark)
}
)},
{"nodelay",
@@ -1109,8 +1036,7 @@ fields("tcp_opts") ->
boolean(),
#{
default => false,
- desc_id => fields_tcp_opts_nodelay,
- desc => "The TCP_NODELAY flag for the connections."
+ desc => ?DESC(fields_tcp_opts_nodelay)
}
)},
{"reuseaddr",
@@ -1118,8 +1044,7 @@ fields("tcp_opts") ->
boolean(),
#{
default => true,
- desc_id => fields_tcp_opts_reuseaddr,
- desc => "The SO_REUSEADDR flag for the connections."
+ desc => ?DESC(fields_tcp_opts_reuseaddr)
}
)}
];
@@ -1150,8 +1075,7 @@ fields("deflate_opts") ->
{"level",
sc(
hoconsc:enum([none, default, best_compression, best_speed]),
- #{ desc => "Compression level."
- , desc_id => fields_deflate_opts_level
+ #{ desc => ?DESC(fields_deflate_opts_level)
}
)},
{"mem_level",
@@ -1159,55 +1083,43 @@ fields("deflate_opts") ->
range(1, 9),
#{
default => 8,
- desc_id => fields_deflate_opts_mem_level,
- desc =>
- "Specifies the size of the compression state.
\n"
- " Lower values decrease memory usage per connection."
+ desc => ?DESC(fields_deflate_opts_mem_level)
}
)},
{"strategy",
sc(
hoconsc:enum([default, filtered, huffman_only, rle]),
- #{ desc => "Specifies the compression strategy."
- , desc_id => fields_deflate_opts_strategy
+ #{ desc => ?DESC(fields_deflate_opts_strategy)
}
)},
{"server_context_takeover",
sc(
hoconsc:enum([takeover, no_takeover]),
#{
- desc_id => fields_deflate_opts_server_context_takeover,
- desc =>
- "Takeover means the compression state is retained\n"
- " between server messages."
+ desc => ?DESC(fields_deflate_opts_server_context_takeover)
}
)},
{"client_context_takeover",
sc(
hoconsc:enum([takeover, no_takeover]),
#{
- desc_id => fields_deflate_opts_client_context_takeover,
- desc =>
- "Takeover means the compression state is retained\n"
- " between client messages."
+ desc => ?DESC(fields_deflate_opts_client_context_takeover)
}
)},
{"server_max_window_bits",
sc(
range(8, 15),
#{
- desc_id => fields_deflate_opts_server_max_window_bits,
- default => 15,
- desc => "Specifies the size of the compression context for the server."
+ desc => ?DESC(fields_deflate_opts_server_max_window_bits),
+ default => 15
}
)},
{"client_max_window_bits",
sc(
range(8, 15),
#{
- desc_id => fields_deflate_opts_client_max_window_bits,
- default => 15,
- desc => "Specifies the size of the compression context for the client."
+ desc => ?DESC(fields_deflate_opts_client_max_window_bits),
+ default => 15
}
)}
];
@@ -1583,14 +1495,7 @@ fields("trace") ->
{"payload_encode",
sc(hoconsc:enum([hex, text, hidden]), #{
default => text,
- desc_id => fields_trace_payload_encode,
- desc =>
- "Determine the format of the payload format in the trace file.
\n"
- "`text`: Text-based protocol or plain text protocol.\n"
- " It is recommended when payload is JSON encoded.
\n"
- "`hex`: Binary hexadecimal encode. It is recommended when payload is "
- "a custom binary protocol.
\n"
- "`hidden`: payload is obfuscated as `******`\n"
+ desc => ?DESC(fields_trace_payload_encode)
})}
].
@@ -1601,10 +1506,7 @@ mqtt_listener() ->
sc(
hoconsc:array(string()),
#{
- desc_id => mqtt_listener_access_rules,
- desc =>
- "The access control rules for this listener.
"
- "See: https://github.com/emqtt/esockd#allowdeny",
+ desc => ?DESC(mqtt_listener_access_rules),
default => [<<"allow all">>]
}
)},
@@ -1612,22 +1514,15 @@ mqtt_listener() ->
sc(
boolean(),
#{
- desc_id => mqtt_listener_proxy_protocol,
- default => false,
- desc =>
- "Enable the Proxy Protocol V1/2 if the EMQX cluster is deployed\n"
- " behind HAProxy or Nginx.
"
- "See: https://www.haproxy.com/blog/haproxy/proxy-protocol/"
+ desc => ?DESC(mqtt_listener_proxy_protocol),
+ default => false
}
)},
{"proxy_protocol_timeout",
sc(
duration(),
#{
- desc_id => mqtt_listener_proxy_protocol_timeout,
- desc =>
- "Timeout for proxy protocol. EMQX will close the TCP connection "
- "if proxy protocol packet is not received within the timeout.",
+ desc => ?DESC(mqtt_listener_proxy_protocol_timeout),
default => "3s"
}
)},
@@ -1641,9 +1536,8 @@ base_listener() ->
sc(
hoconsc:union([ip_port(), integer()]),
#{
- desc_id => base_listener_bind,
- required => true,
- desc => "IP address and port for the listening socket."
+ desc => ?DESC(base_listener_bind),
+ required => true
}
)},
{"acceptors",
@@ -1651,8 +1545,7 @@ base_listener() ->
integer(),
#{
default => 16,
- desc_id => base_listener_acceptors,
- desc => "The size of the listener's receiving pool."
+ desc => ?DESC(base_listener_acceptors)
}
)},
{"max_connections",
@@ -1660,8 +1553,7 @@ base_listener() ->
hoconsc:union([infinity, integer()]),
#{
default => infinity,
- desc_id => base_listener_max_connections,
- desc => "The maximum number of concurrent connections allowed by the listener."
+ desc => ?DESC(base_listener_max_connections)
}
)},
{"mountpoint",
@@ -1669,41 +1561,23 @@ base_listener() ->
binary(),
#{
default => <<>>,
- desc_id => base_listener_mountpoint,
- desc =>
- "When publishing or subscribing, prefix all topics with a mountpoint string.\n"
- " The prefixed string will be removed from the topic name when the message\n"
- " is delivered to the subscriber. The mountpoint is a way that users can use\n"
- " to implement isolation of message routing between different listeners.\n"
- " For example if a client A subscribes to `t` with `listeners.tcp..mountpoint`\n"
- " set to `some_tenant`, then the client actually subscribes to the topic\n"
- " `some_tenant/t`. Similarly, if another client B (connected to the same listener\n"
- " as the client A) sends a message to topic `t`, the message is routed\n"
- " to all the clients subscribed `some_tenant/t`, so client A will receive the\n"
- " message, with topic name `t`.
\n"
- " Set to `\"\"` to disable the feature.
\n"
- "\n"
- " Variables in mountpoint string:\n"
- " - ${clientid}
: clientid\n"
- " - ${username}
: username"
+ desc => ?DESC(base_listener_mountpoint)
}
)},
{"zone",
sc(
atom(),
#{
- desc_id => base_listener_zone,
- default => 'default',
- desc => "The configuration zone to which the listener belongs."
+ desc => ?DESC(base_listener_zone),
+ default => 'default'
}
)},
{"limiter",
sc(
map("ratelimit's type", emqx_limiter_schema:bucket_name()),
#{
- desc_id => base_listener_limiter,
- default => #{},
- desc => "Type of the rate limit."
+ desc => ?DESC(base_listener_limiter),
+ default => #{}
}
)}
].
@@ -1881,8 +1755,7 @@ common_ssl_opts_schema(Defaults) ->
boolean(),
#{
default => Df("enable", false),
- desc_id => common_ssl_opts_schema_enable,
- desc => "Enable TLS."
+ desc => ?DESC(common_ssl_opts_schema_enable)
}
)},
{"cacertfile",
@@ -1891,15 +1764,7 @@ common_ssl_opts_schema(Defaults) ->
#{
default => D("cacertfile"),
required => false,
- desc_id => common_ssl_opts_schema_cacertfile,
- desc =>
- "Trusted PEM format CA certificates bundle file.
\n"
- "The certificates in this file are used to verify the TLS peer's certificates.\n"
- "Append new certificates to the file if new CAs are to be trusted.\n"
- "There is no need to restart EMQX to have the updated file loaded, because\n"
- "the system regularly checks if file has been updated (and reload).
\n"
- "NOTE: invalidating (deleting) a certificate from the file will not affect\n"
- "already established connections.\n"
+ desc => ?DESC(common_ssl_opts_schema_cacertfile)
}
)},
{"certfile",
@@ -1908,14 +1773,7 @@ common_ssl_opts_schema(Defaults) ->
#{
default => D("certfile"),
required => false,
- desc_id => common_ssl_opts_schema_certfile,
- desc =>
- "PEM format certificates chain file.
\n"
- "The certificates in this file should be in reversed order of the certificate\n"
- "issue chain. That is, the host's certificate should be placed in the beginning\n"
- "of the file, followed by the immediate issuer certificate and so on.\n"
- "Although the root CA certificate is optional, it should be placed at the end of\n"
- "the file if it is to be added."
+ desc => ?DESC(common_ssl_opts_schema_certfile)
}
)},
{"keyfile",
@@ -1924,9 +1782,7 @@ common_ssl_opts_schema(Defaults) ->
#{
default => D("keyfile"),
required => false,
- desc_id => common_ssl_opts_schema_keyfile,
- desc =>
- "PEM format private key file."
+ desc => ?DESC(common_ssl_opts_schema_keyfile)
}
)},
{"verify",
@@ -1934,9 +1790,7 @@ common_ssl_opts_schema(Defaults) ->
hoconsc:enum([verify_peer, verify_none]),
#{
default => Df("verify", verify_none),
- desc_id => common_ssl_opts_schema_verify,
- desc =>
- "Enable or disable peer verification."
+ desc => ?DESC(common_ssl_opts_schema_verify)
}
)},
{"reuse_sessions",
@@ -1944,9 +1798,7 @@ common_ssl_opts_schema(Defaults) ->
boolean(),
#{
default => Df("reuse_sessions", true),
- desc_id => common_ssl_opts_schema_reuse_sessions,
- desc =>
- "Enable TLS session reuse."
+ desc => ?DESC(common_ssl_opts_schema_reuse_sessions)
}
)},
{"depth",
@@ -1954,13 +1806,7 @@ common_ssl_opts_schema(Defaults) ->
integer(),
#{
default => Df("depth", 10),
- desc_id => common_ssl_opts_schema_depth,
- desc =>
- "Maximum number of non-self-issued intermediate certificates that can follow "
- "the peer certificate in a valid certification path. "
- "So, if depth is 0 the PEER must be signed by the trusted ROOT-CA directly; "
- "if 1 the path can be PEER, CA, ROOT-CA; if 2 the path can be PEER, CA, CA, ROOT-CA, "
- "and so on. The default value is 10."
+ desc => ?DESC(common_ssl_opts_schema_depth)
}
)},
{"password",
@@ -1969,10 +1815,7 @@ common_ssl_opts_schema(Defaults) ->
#{
sensitive => true,
required => false,
- desc_id => common_ssl_opts_schema_password,
- desc =>
- "String containing the user's password. Only used if the private\n"
- "key file is password-protected."
+ desc => ?DESC(common_ssl_opts_schema_password)
}
)},
{"versions",
@@ -1980,12 +1823,7 @@ common_ssl_opts_schema(Defaults) ->
hoconsc:array(typerefl:atom()),
#{
default => default_tls_vsns(maps:get(versions, Defaults, tls_all_available)),
- desc_id => common_ssl_opts_schema_versions,
- desc =>
- "All TLS/DTLS versions to be supported.
\n"
- "NOTE: PSK ciphers are suppressed by 'tlsv1.3' version config
\n"
- "In case PSK cipher suites are intended, make sure to configured\n"
- "['tlsv1.2', 'tlsv1.1']
here.",
+ desc => ?DESC(common_ssl_opts_schema_versions),
validator => fun validate_tls_versions/1
}
)},
@@ -1996,9 +1834,7 @@ common_ssl_opts_schema(Defaults) ->
#{
default => <<"emqx_tls_psk:lookup">>,
converter => fun ?MODULE:parse_user_lookup_fun/1,
- desc_id => common_ssl_opts_schema_user_lookup_fun,
- desc =>
- "EMQX-internal callback that is used to lookup pre-shared key (PSK) identity."
+ desc => ?DESC(common_ssl_opts_schema_user_lookup_fun)
}
)},
{"secure_renegotiate",
@@ -2006,12 +1842,7 @@ common_ssl_opts_schema(Defaults) ->
boolean(),
#{
default => Df("secure_renegotiate", true),
- desc_id => common_ssl_opts_schema_secure_renegotiate,
- desc =>
- "SSL parameter renegotiation is a feature that allows a client and a server\n"
- "to renegotiate the parameters of the SSL connection on the fly.\n"
- "RFC 5746 defines a more secure way of doing this. By enabling secure renegotiation,\n"
- "you drop support for the insecure renegotiation, prone to MitM attacks."
+ desc => ?DESC(common_ssl_opts_schema_secure_renegotiate)
}
)}
].
@@ -2036,13 +1867,7 @@ server_ssl_opts_schema(Defaults1, IsRanchListener) ->
#{
default => D("dhfile"),
required => false,
- desc_id => server_ssl_opts_schema_dhfile,
- desc =>
- "Path to a file containing PEM-encoded Diffie-Hellman parameters\n"
- "to be used by the server if a cipher suite using Diffie-Hellman\n"
- "key exchange is negotiated. If not specified, default parameters\n"
- "are used.
\n"
- "NOTE: The dhfile
option is not supported by TLS 1.3."
+ desc => ?DESC(server_ssl_opts_schema_dhfile)
}
)},
{"fail_if_no_peer_cert",
@@ -2050,13 +1875,7 @@ server_ssl_opts_schema(Defaults1, IsRanchListener) ->
boolean(),
#{
default => Df("fail_if_no_peer_cert", false),
- desc_id => server_ssl_opts_schema_fail_if_no_peer_cert,
- desc =>
- "Used together with {verify, verify_peer} by an TLS/DTLS server.\n"
- "If set to true, the server fails if the client does not have a\n"
- "certificate to send, that is, sends an empty certificate.\n"
- "If set to false, it fails only if the client sends an invalid\n"
- "certificate (an empty certificate is considered valid)."
+ desc => ?DESC(server_ssl_opts_schema_fail_if_no_peer_cert)
}
)},
{"honor_cipher_order",
@@ -2064,12 +1883,7 @@ server_ssl_opts_schema(Defaults1, IsRanchListener) ->
boolean(),
#{
default => Df("honor_cipher_order", true),
- desc_id => server_ssl_opts_schema_honor_cipher_order,
- desc =>
- "An important security setting, it forces the cipher to be set based\n"
- " on the server-specified order instead of the client-specified order,\n"
- " hence enforcing the (usually more properly configured) security\n"
- " ordering of the server administrator."
+ desc => ?DESC(server_ssl_opts_schema_honor_cipher_order)
}
)},
{"client_renegotiation",
@@ -2077,18 +1891,7 @@ server_ssl_opts_schema(Defaults1, IsRanchListener) ->
boolean(),
#{
default => Df("client_renegotiation", true),
- desc_id => server_ssl_opts_schema_client_renegotiation,
- desc =>
- "In protocols that support client-initiated renegotiation,\n"
- "the cost of resources of such an operation is higher for the "
- "server than the client.\n"
- "This can act as a vector for denial of service attacks.\n"
- "The SSL application already takes measures to counter-act such attempts,\n"
- "but client-initiated renegotiation can be strictly disabled by setting "
- "this option to false.\n"
- "The default value is true. Note that disabling renegotiation can result in\n"
- "long-lived connections becoming unusable due to limits on\n"
- "the number of messages the underlying cipher suite can encipher."
+ desc => ?DESC(server_ssl_opts_schema_client_renegotiation)
}
)}
| [
@@ -2097,8 +1900,7 @@ server_ssl_opts_schema(Defaults1, IsRanchListener) ->
duration(),
#{
default => Df("handshake_timeout", "15s"),
- desc_id => server_ssl_opts_schema_handshake_timeout,
- desc => "Maximum time duration allowed for the handshake to complete"
+ desc => ?DESC(server_ssl_opts_schema_handshake_timeout)
}
)}
|| IsRanchListener
@@ -2123,19 +1925,7 @@ client_ssl_opts_schema(Defaults1) ->
hoconsc:union([disable, string()]),
#{
required => false,
- desc_id => client_ssl_opts_schema_server_name_indication,
- desc =>
- "Specify the host name to be used in TLS Server Name Indication extension.
\n"
- "For instance, when connecting to \"server.example.net\", the genuine server\n"
- "which accepts the connection and performs TLS handshake may differ from the\n"
- "host the TLS client initially connects to, e.g. when connecting to an IP address\n"
- "or when the host has multiple resolvable DNS records
\n"
- "If not specified, it will default to the host name string which is used\n"
- "to establish the connection, unless it is IP addressed used.
\n"
- "The host name is then also used in the host name verification of the peer\n"
- "certificate.
The special value 'disable' prevents the Server Name\n"
- "Indication extension from being sent and disables the hostname\n"
- "verification check."
+ desc => ?DESC(client_ssl_opts_schema_server_name_indication)
}
)}
].
@@ -2164,8 +1954,11 @@ ciphers_schema(Default) ->
true -> undefined;
false -> fun validate_ciphers/1
end,
- desc_id => ciphers_schema_0,
- desc =>
+ desc_id => "ciphers_schema_" ++ case Default of
+ quic -> "quic";
+ _ -> "0"
+ end,
+ desc_en =>
"This config holds TLS cipher suite names separated by comma,\n"
"or as an array of strings. e.g.\n"
"\"TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256\"
or\n"
@@ -2246,7 +2039,6 @@ ref(Module, Field) -> hoconsc:ref(Module, Field).
mk_duration(Desc, OverrideMeta) ->
DefaultMeta = #{
- desc_id => mk_duration_0,
desc => Desc ++
" Time interval is a string that contains a number followed by time unit:
\n"
"- `ms` for milliseconds,\n"