mirror of
https://github.com/ilyakooo0/nixpkgs.git
synced 2024-11-13 09:17:07 +03:00
Merge pull request #142765 from pennae/mosquitto-fixes
nixos/mosquitto: restore checkPasswords=false from old module, add module doc chapter
This commit is contained in:
commit
185aeb4ab8
102
nixos/modules/services/networking/mosquitto.md
Normal file
102
nixos/modules/services/networking/mosquitto.md
Normal file
@ -0,0 +1,102 @@
|
||||
# Mosquitto {#module-services-mosquitto}
|
||||
|
||||
Mosquitto is a MQTT broker often used for IoT or home automation data transport.
|
||||
|
||||
## Quickstart {#module-services-mosquitto-quickstart}
|
||||
|
||||
A minimal configuration for Mosquitto is
|
||||
|
||||
```nix
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
acl = [ "pattern readwrite #" ];
|
||||
omitPasswordAuth = true;
|
||||
settings.allow_anonymous = true;
|
||||
} ];
|
||||
};
|
||||
```
|
||||
|
||||
This will start a broker on port 1883, listening on all interfaces of the machine, allowing
|
||||
read/write access to all topics to any user without password requirements.
|
||||
|
||||
User authentication can be configured with the `users` key of listeners. A config that gives
|
||||
full read access to a user `monitor` and restricted write access to a user `service` could look
|
||||
like
|
||||
|
||||
```nix
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
users = {
|
||||
monitor = {
|
||||
acl = [ "read #" ];
|
||||
password = "monitor";
|
||||
};
|
||||
service = {
|
||||
acl = [ "write service/#" ];
|
||||
password = "service";
|
||||
};
|
||||
};
|
||||
} ];
|
||||
};
|
||||
```
|
||||
|
||||
TLS authentication is configured by setting TLS-related options of the listener:
|
||||
|
||||
```nix
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
port = 8883; # port change is not required, but helpful to avoid mistakes
|
||||
# ...
|
||||
settings = {
|
||||
cafile = "/path/to/mqtt.ca.pem";
|
||||
certfile = "/path/to/mqtt.pem";
|
||||
keyfile = "/path/to/mqtt.key";
|
||||
};
|
||||
} ];
|
||||
```
|
||||
|
||||
## Configuration {#module-services-mosquitto-config}
|
||||
|
||||
The Mosquitto configuration has four distinct types of settings:
|
||||
the global settings of the daemon, listeners, plugins, and bridges.
|
||||
Bridges and listeners are part of the global configuration, plugins are part of listeners.
|
||||
Users of the broker are configured as parts of listeners rather than globally, allowing
|
||||
configurations in which a given user is only allowed to log in to the broker using specific
|
||||
listeners (eg to configure an admin user with full access to all topics, but restricted to
|
||||
localhost).
|
||||
|
||||
Almost all options of Mosquitto are available for configuration at their appropriate levels, some
|
||||
as NixOS options written in camel case, the remainders under `settings` with their exact names in
|
||||
the Mosquitto config file. The exceptions are `acl_file` (which is always set according to the
|
||||
`acl` attributes of a listener and its users) and `per_listener_settings` (which is always set to
|
||||
`true`).
|
||||
|
||||
### Password authentication {#module-services-mosquitto-config-passwords}
|
||||
|
||||
Mosquitto can be run in two modes, with a password file or without. Each listener has its own
|
||||
password file, and different listeners may use different password files. Password file generation
|
||||
can be disabled by setting `omitPasswordAuth = true` for a listener; in this case it is necessary
|
||||
to either set `settings.allow_anonymous = true` to allow all logins, or to configure other
|
||||
authentication methods like TLS client certificates with `settings.use_identity_as_username = true`.
|
||||
|
||||
The default is to generate a password file for each listener from the users configured to that
|
||||
listener. Users with no configured password will not be added to the password file and thus
|
||||
will not be able to use the broker.
|
||||
|
||||
### ACL format {#module-services-mosquitto-config-acl}
|
||||
|
||||
Every listener has a Mosquitto `acl_file` attached to it. This ACL is configured via two
|
||||
attributes of the config:
|
||||
|
||||
* the `acl` attribute of the listener configures pattern ACL entries and topic ACL entries
|
||||
for anonymous users. Each entry must be prefixed with `pattern` or `topic` to distinguish
|
||||
between these two cases.
|
||||
* the `acl` attribute of every user configures in the listener configured the ACL for that
|
||||
given user. Only topic ACLs are supported by Mosquitto in this setting, so no prefix is
|
||||
required or allowed.
|
||||
|
||||
The default ACL for a listener is empty, disallowing all accesses from all clients. To configure
|
||||
a completely open ACL, set `acl = [ "pattern readwrite #" ]` in the listener.
|
@ -257,18 +257,28 @@ let
|
||||
|
||||
users = mkOption {
|
||||
type = attrsOf userOptions;
|
||||
example = { john = { password = "123456"; acl = [ "topic readwrite john/#" ]; }; };
|
||||
example = { john = { password = "123456"; acl = [ "readwrite john/#" ]; }; };
|
||||
description = ''
|
||||
A set of users and their passwords and ACLs.
|
||||
'';
|
||||
default = {};
|
||||
};
|
||||
|
||||
omitPasswordAuth = mkOption {
|
||||
type = bool;
|
||||
description = ''
|
||||
Omits password checking, allowing anyone to log in with any user name unless
|
||||
other mandatory authentication methods (eg TLS client certificates) are configured.
|
||||
'';
|
||||
default = false;
|
||||
};
|
||||
|
||||
acl = mkOption {
|
||||
type = listOf str;
|
||||
description = ''
|
||||
Additional ACL items to prepend to the generated ACL file.
|
||||
'';
|
||||
example = [ "pattern read #" "topic readwrite anon/report/#" ];
|
||||
default = [];
|
||||
};
|
||||
|
||||
@ -294,9 +304,9 @@ let
|
||||
formatListener = idx: listener:
|
||||
[
|
||||
"listener ${toString listener.port} ${toString listener.address}"
|
||||
"password_file ${cfg.dataDir}/passwd-${toString idx}"
|
||||
"acl_file ${makeACLFile idx listener.users listener.acl}"
|
||||
]
|
||||
++ optional (! listener.omitPasswordAuth) "password_file ${cfg.dataDir}/passwd-${toString idx}"
|
||||
++ formatFreeform {} listener.settings
|
||||
++ concatMap formatAuthPlugin listener.authPlugins;
|
||||
|
||||
@ -645,5 +655,10 @@ in
|
||||
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ pennae ];
|
||||
meta = {
|
||||
maintainers = with lib.maintainers; [ pennae ];
|
||||
# Don't edit the docbook xml directly, edit the md and generate it:
|
||||
# `pandoc mosquitto.md -t docbook --top-level-division=chapter --extract-media=media -f markdown+smart > mosquitto.xml`
|
||||
doc = ./mosquitto.xml;
|
||||
};
|
||||
}
|
||||
|
147
nixos/modules/services/networking/mosquitto.xml
Normal file
147
nixos/modules/services/networking/mosquitto.xml
Normal file
@ -0,0 +1,147 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="module-services-mosquitto">
|
||||
<title>Mosquitto</title>
|
||||
<para>
|
||||
Mosquitto is a MQTT broker often used for IoT or home automation
|
||||
data transport.
|
||||
</para>
|
||||
<section xml:id="module-services-mosquitto-quickstart">
|
||||
<title>Quickstart</title>
|
||||
<para>
|
||||
A minimal configuration for Mosquitto is
|
||||
</para>
|
||||
<programlisting language="bash">
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
acl = [ "pattern readwrite #" ];
|
||||
omitPasswordAuth = true;
|
||||
settings.allow_anonymous = true;
|
||||
} ];
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
This will start a broker on port 1883, listening on all interfaces
|
||||
of the machine, allowing read/write access to all topics to any
|
||||
user without password requirements.
|
||||
</para>
|
||||
<para>
|
||||
User authentication can be configured with the
|
||||
<literal>users</literal> key of listeners. A config that gives
|
||||
full read access to a user <literal>monitor</literal> and
|
||||
restricted write access to a user <literal>service</literal> could
|
||||
look like
|
||||
</para>
|
||||
<programlisting language="bash">
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
users = {
|
||||
monitor = {
|
||||
acl = [ "read #" ];
|
||||
password = "monitor";
|
||||
};
|
||||
service = {
|
||||
acl = [ "write service/#" ];
|
||||
password = "service";
|
||||
};
|
||||
};
|
||||
} ];
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
TLS authentication is configured by setting TLS-related options of
|
||||
the listener:
|
||||
</para>
|
||||
<programlisting language="bash">
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [ {
|
||||
port = 8883; # port change is not required, but helpful to avoid mistakes
|
||||
# ...
|
||||
settings = {
|
||||
cafile = "/path/to/mqtt.ca.pem";
|
||||
certfile = "/path/to/mqtt.pem";
|
||||
keyfile = "/path/to/mqtt.key";
|
||||
};
|
||||
} ];
|
||||
</programlisting>
|
||||
</section>
|
||||
<section xml:id="module-services-mosquitto-config">
|
||||
<title>Configuration</title>
|
||||
<para>
|
||||
The Mosquitto configuration has four distinct types of settings:
|
||||
the global settings of the daemon, listeners, plugins, and
|
||||
bridges. Bridges and listeners are part of the global
|
||||
configuration, plugins are part of listeners. Users of the broker
|
||||
are configured as parts of listeners rather than globally,
|
||||
allowing configurations in which a given user is only allowed to
|
||||
log in to the broker using specific listeners (eg to configure an
|
||||
admin user with full access to all topics, but restricted to
|
||||
localhost).
|
||||
</para>
|
||||
<para>
|
||||
Almost all options of Mosquitto are available for configuration at
|
||||
their appropriate levels, some as NixOS options written in camel
|
||||
case, the remainders under <literal>settings</literal> with their
|
||||
exact names in the Mosquitto config file. The exceptions are
|
||||
<literal>acl_file</literal> (which is always set according to the
|
||||
<literal>acl</literal> attributes of a listener and its users) and
|
||||
<literal>per_listener_settings</literal> (which is always set to
|
||||
<literal>true</literal>).
|
||||
</para>
|
||||
<section xml:id="module-services-mosquitto-config-passwords">
|
||||
<title>Password authentication</title>
|
||||
<para>
|
||||
Mosquitto can be run in two modes, with a password file or
|
||||
without. Each listener has its own password file, and different
|
||||
listeners may use different password files. Password file
|
||||
generation can be disabled by setting
|
||||
<literal>omitPasswordAuth = true</literal> for a listener; in
|
||||
this case it is necessary to either set
|
||||
<literal>settings.allow_anonymous = true</literal> to allow all
|
||||
logins, or to configure other authentication methods like TLS
|
||||
client certificates with
|
||||
<literal>settings.use_identity_as_username = true</literal>.
|
||||
</para>
|
||||
<para>
|
||||
The default is to generate a password file for each listener
|
||||
from the users configured to that listener. Users with no
|
||||
configured password will not be added to the password file and
|
||||
thus will not be able to use the broker.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="module-services-mosquitto-config-acl">
|
||||
<title>ACL format</title>
|
||||
<para>
|
||||
Every listener has a Mosquitto <literal>acl_file</literal>
|
||||
attached to it. This ACL is configured via two attributes of the
|
||||
config:
|
||||
</para>
|
||||
<itemizedlist spacing="compact">
|
||||
<listitem>
|
||||
<para>
|
||||
the <literal>acl</literal> attribute of the listener
|
||||
configures pattern ACL entries and topic ACL entries for
|
||||
anonymous users. Each entry must be prefixed with
|
||||
<literal>pattern</literal> or <literal>topic</literal> to
|
||||
distinguish between these two cases.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
the <literal>acl</literal> attribute of every user
|
||||
configures in the listener configured the ACL for that given
|
||||
user. Only topic ACLs are supported by Mosquitto in this
|
||||
setting, so no prefix is required or allowed.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
The default ACL for a listener is empty, disallowing all
|
||||
accesses from all clients. To configure a completely open ACL,
|
||||
set <literal>acl = [ "pattern readwrite #" ]</literal>
|
||||
in the listener.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
@ -3,6 +3,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||
let
|
||||
port = 1888;
|
||||
tlsPort = 1889;
|
||||
anonPort = 1890;
|
||||
password = "VERY_secret";
|
||||
hashedPassword = "$7$101$/WJc4Mp+I+uYE9sR$o7z9rD1EYXHPwEP5GqQj6A7k4W1yVbePlb8TqNcuOLV9WNCiDgwHOB0JHC1WCtdkssqTBduBNUnUGd6kmZvDSw==";
|
||||
topic = "test/foo";
|
||||
@ -63,7 +64,7 @@ in {
|
||||
};
|
||||
in {
|
||||
server = { pkgs, ... }: {
|
||||
networking.firewall.allowedTCPPorts = [ port tlsPort ];
|
||||
networking.firewall.allowedTCPPorts = [ port tlsPort anonPort ];
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
settings = {
|
||||
@ -112,6 +113,18 @@ in {
|
||||
use_identity_as_username = true;
|
||||
};
|
||||
}
|
||||
{
|
||||
port = anonPort;
|
||||
omitPasswordAuth = true;
|
||||
settings.allow_anonymous = true;
|
||||
acl = [ "pattern read #" ];
|
||||
users = {
|
||||
anonWriter = {
|
||||
password = "<ignored>" + password;
|
||||
acl = [ "write ${topic}" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
@ -136,9 +149,8 @@ in {
|
||||
def publish(args, user, topic="${topic}", port=${toString port}):
|
||||
return "{} {}".format(mosquitto_cmd("pub", user, topic, port), args)
|
||||
|
||||
|
||||
def subscribe(args, user, topic="${topic}", port=${toString port}):
|
||||
return "{} -C 1 {}".format(mosquitto_cmd("sub", user, topic, port), args)
|
||||
return "{} -W 5 -C 1 {}".format(mosquitto_cmd("sub", user, topic, port), args)
|
||||
|
||||
def parallel(*fns):
|
||||
from threading import Thread
|
||||
@ -150,17 +162,15 @@ in {
|
||||
start_all()
|
||||
server.wait_for_unit("mosquitto.service")
|
||||
|
||||
def check_passwords():
|
||||
with subtest("check passwords"):
|
||||
client1.succeed(publish("-m test", "password_store"))
|
||||
client1.succeed(publish("-m test", "password_file"))
|
||||
client1.succeed(publish("-m test", "hashed_store"))
|
||||
client1.succeed(publish("-m test", "hashed_file"))
|
||||
|
||||
check_passwords()
|
||||
|
||||
def check_acl():
|
||||
with subtest("check acl"):
|
||||
client1.succeed(subscribe("", "reader", topic="$SYS/#"))
|
||||
client1.fail(subscribe("-W 5", "writer", topic="$SYS/#"))
|
||||
client1.fail(subscribe("", "writer", topic="$SYS/#"))
|
||||
|
||||
parallel(
|
||||
lambda: client1.succeed(subscribe("-i 3688cdd7-aa07-42a4-be22-cb9352917e40", "reader")),
|
||||
@ -170,15 +180,13 @@ in {
|
||||
])
|
||||
|
||||
parallel(
|
||||
lambda: client1.fail(subscribe("-W 5 -i 24ff16a2-ae33-4a51-9098-1b417153c712", "reader")),
|
||||
lambda: client1.fail(subscribe("-i 24ff16a2-ae33-4a51-9098-1b417153c712", "reader")),
|
||||
lambda: [
|
||||
server.wait_for_console_text("24ff16a2-ae33-4a51-9098-1b417153c712"),
|
||||
client2.succeed(publish("-m test", "reader"))
|
||||
])
|
||||
|
||||
check_acl()
|
||||
|
||||
def check_tls():
|
||||
with subtest("check tls"):
|
||||
client1.succeed(
|
||||
subscribe(
|
||||
"--cafile ${snakeOil}/ca.crt "
|
||||
@ -188,6 +196,13 @@ in {
|
||||
port=${toString tlsPort},
|
||||
user="no_such_user"))
|
||||
|
||||
check_tls()
|
||||
with subtest("check omitPasswordAuth"):
|
||||
parallel(
|
||||
lambda: client1.succeed(subscribe("-i fd56032c-d9cb-4813-a3b4-6be0e04c8fc3",
|
||||
"anonReader", port=${toString anonPort})),
|
||||
lambda: [
|
||||
server.wait_for_console_text("fd56032c-d9cb-4813-a3b4-6be0e04c8fc3"),
|
||||
client2.succeed(publish("-m test", "anonWriter", port=${toString anonPort}))
|
||||
])
|
||||
'';
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user