Ниже показан английский оригинал.
Security
The login in the URL or credentials sends a user name and a password; tls_ca trusts a certificate authority and selects TLS, and tls_client_auth adds a client certificate.
The user name and the password travel in the CONNECT packet.
A server that refuses them fails startup at once, naming the refusal.
A URL such as mqtt://user:password@host:1884 logs in with the user name and the password it carries.
They are percent-decoded, as a URL writes them, so p%40ss is the password p@ss.
The URL logs in only when it carries both a non-empty user name and a password.
credentials is the explicit choice and wins over a login in the URL.
TLS takes PEM bytes, so the service reads its files itself and hands their contents over.
tls_ca is the certificate authority that signed the server's certificate.
The client verifies the server against it and against no other store.
So a TLS connection needs it: an mqtts:// URL without tls_ca fails startup, naming the missing setting.
tls_ca also selects TLS on an mqtt:// URL.
tls_client_auth takes the service's own certificate and key, for a server that verifies each client by its certificate, as managed MQTT services commonly do.
A server may ask for both: a client certificate on a TLS listener, and a user name and a password inside the session.
The login and the handshake happen on the server, so a TestApp test runs the same app in process without them.
The settings are still checked as at the connect: an mqtts:// URL without tls_ca fails TestApp::start too.
The generated AsyncAPI document reports the host and the port, never the credentials.
Example
The service logs in with its user name and the password the environment gives it.
- Macros
- Manual
/// A server that asks every client for a user name and a password.
fn password_broker(url: &str, client_id: &str, username: &str, password: &str) -> MqttBroker {
MqttBroker::new(url, client_id).credentials(username, password)
}
#[ruststream::app]
fn app() -> impl App<State = ()> {
let password = env::var("MQTT_PASSWORD").unwrap_or_default();
service(password_broker(
"mqtt://localhost:1884",
"telemetry-svc",
"telemetry-svc",
&password,
))
}
/// A server that asks every client for a user name and a password.
fn password_broker(url: &str, client_id: &str, username: &str, password: &str) -> MqttBroker {
MqttBroker::new(url, client_id).credentials(username, password)
}
fn app() -> impl App<State = ()> {
let password = env::var("MQTT_PASSWORD").unwrap_or_default();
service(password_broker(
"mqtt://localhost:1884",
"telemetry-svc",
"telemetry-svc",
&password,
))
}
A deployment that hands over one connection string passes it as it is.
- Macros
- Manual
/// The deployment hands over one connection string with the login in it, such as
/// `mqtt://telemetry-svc:p%40ss@broker.internal:1884` for the password `p@ss`.
fn url_broker(url: &str, client_id: &str) -> MqttBroker {
MqttBroker::new(url, client_id)
}
/// The deployment hands over one connection string with the login in it, such as
/// `mqtt://telemetry-svc:p%40ss@broker.internal:1884` for the password `p@ss`.
fn url_broker(url: &str, client_id: &str) -> MqttBroker {
MqttBroker::new(url, client_id)
}
On a TLS listener that verifies clients by their certificates, the service hands over the three PEM files of its deployment.
- Macros
- Manual
/// A TLS listener that verifies the service by its certificate. `dir` holds the PEM files the
/// deployment mounts: the authority that signed the server's certificate, and the service's own
/// certificate and key.
fn tls_broker(url: &str, client_id: &str, dir: &Path) -> io::Result<MqttBroker> {
Ok(MqttBroker::new(url, client_id)
.tls_ca(fs::read(dir.join("ca.crt"))?)
.tls_client_auth(
fs::read(dir.join("client.crt"))?,
fs::read(dir.join("client.key"))?,
))
}
/// A TLS listener that verifies the service by its certificate. `dir` holds the PEM files the
/// deployment mounts: the authority that signed the server's certificate, and the service's own
/// certificate and key.
fn tls_broker(url: &str, client_id: &str, dir: &Path) -> io::Result<MqttBroker> {
Ok(MqttBroker::new(url, client_id)
.tls_ca(fs::read(dir.join("ca.crt"))?)
.tls_client_auth(
fs::read(dir.join("client.crt"))?,
fs::read(dir.join("client.key"))?,
))
}