Verified Commit 92999a62 authored by Štěpán Henek's avatar Štěpán Henek 🌩

foris+friends: use passwords when connecting to local mqtt

parent 0df04656
......@@ -8,8 +8,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=foris-client
PKG_VERSION:=0.9.6
PKG_RELEASE:=2
PKG_VERSION:=0.9.7
PKG_RELEASE:=1
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://gitlab.labs.nic.cz/turris/foris-client
......
#!/bin/sh
#
# foris-controller-wrapper - wrapper around foris-client command
# Copyright (C) 2018 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
# foris-client-wrapper - wrapper around foris-client command
# Copyright (C) 2019 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -38,5 +38,7 @@ elif [ "$bus" = "unix-socket" ]; then
elif [ "$bus" = "mqtt" ]; then
config_get host mqtt host localhost
config_get port mqtt port 11883
/usr/bin/foris-client $@ mqtt --host "$host" --port "$port"
config_get credentials_file mqtt credentials_file /etc/fosquitto/credentials.plain
/usr/bin/foris-client $@ mqtt --host "$host" --port "$port" --passwd-file "$credentials_file"
fi
#!/bin/sh
#
# foris-controller-wrapper - wrapper around foris-client command
# Copyright (C) 2018 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
# foris-notify-wrapper - wrapper around foris-notify command
# Copyright (C) 2019 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -65,5 +65,7 @@ elif [ "$bus" = "unix-socket" ]; then
elif [ "$bus" = "mqtt" ]; then
config_get host mqtt host localhost
config_get port mqtt port 11883
/usr/bin/foris-notify $args mqtt --host "$host" --port "$port" "$1" # only first notification
config_get credentials_file mqtt credentials_file /etc/fosquitto/credentials.plain
/usr/bin/foris-notify $args mqtt --host "$host" --port "$port" --passwd-file "$credentials_file" "$1" # only first notification
fi
......@@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=foris-controller
PKG_VERSION:=0.11.4.1
PKG_VERSION:=0.11.5
PKG_RELEASE:=1
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
PKG_SOURCE_PROTO:=git
......
......@@ -18,3 +18,4 @@ config unix 'unix'
config mqtt 'mqtt'
option host localhost
option port 11883
option credentials_file /etc/fosquitto/credentials.plain
......@@ -51,7 +51,8 @@ start_service() {
elif [ "$bus" == "mqtt" ]; then
config_get host mqtt host "localhost"
config_get port mqtt port "11883"
procd_set_param command "$PROG" ${debug_arg:-} -b "$backend" -C "$client_socket" mqtt --host "${host}" --port "${port}"
config_get credentials_file mqtt credentials_file "/etc/fosquitto/credentials.plain"
procd_set_param command "$PROG" ${debug_arg:-} -b "$backend" -C "$client_socket" mqtt --host "${host}" --port "${port}" --passwd-file "${credentials_file}"
fi
procd_set_param stdout 1 # forward stdout of the command to logd
......
......@@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=foris-ws
PKG_VERSION:=1.2
PKG_VERSION:=1.3
PKG_RELEASE:=1
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
PKG_SOURCE_PROTO:=git
......
......@@ -45,7 +45,8 @@ start_service() {
elif [ "$bus" == "mqtt" ]; then
config_get mqtt_host mqtt host "localhost"
config_get mqtt_port mqtt port "11883"
procd_set_param command "$PROG" ${debug_arg:-} -a ubus --host "127.0.0.1" --port "$port" mqtt --mqtt-host "${mqtt_host}" --mqtt-port "${mqtt_port}"
config_get credentials_file mqtt credentials_file "/etc/fosquitto/credentials.plain"
procd_set_param command "$PROG" ${debug_arg:-} -a ubus --host "127.0.0.1" --port "$port" mqtt --mqtt-host "${mqtt_host}" --mqtt-port "${mqtt_port}" --mqtt-passwd-file "${credentials_file}"
fi
procd_set_param respawn
procd_close_instance
......
......@@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=foris
PKG_VERSION:=99.3.2
PKG_VERSION:=99.4
PKG_RELEASE:=1
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
PKG_SOURCE_PROTO:=git
......
......@@ -32,7 +32,8 @@ case "$BUS" in
mqtt)
config_get HOST mqtt host "localhost"
config_get PORT mqtt port "11883"
exec /usr/bin/foris -s cgi $EXTRA_FLAGS -b "$BUS" --mqtt-host "$HOST" --mqtt-port "$PORT" -a config
config_get credentials_file mqtt credentials_file "/etc/fosquitto/credentials.plain"
exec /usr/bin/foris -s cgi $EXTRA_FLAGS -b "$BUS" --mqtt-host "$HOST" --mqtt-port "$PORT" --mqtt-passwd-file "$credentials_file" -a config
;;
esac
......@@ -42,6 +42,7 @@ case "$BUS" in
mqtt)
config_get BUS_HOST mqtt host "localhost"
config_get BUS_PORT mqtt port "11883"
config_get CREDENTIALS_FILE mqtt credentials_file "/etc/fosquitto/credentials.plain"
BUS="mqtt"
;;
esac
......@@ -54,7 +55,7 @@ case "$BUS" in
echo "var.foris-$APP.flags = \"$EXTRA_FLAGS -a $APP -b $BUS --bus-socket $BUS_PATH\""
;;
mqtt)
echo "var.foris-$APP.flags = \"$EXTRA_FLAGS -a $APP -b $BUS --mqtt-host $BUS_HOST --mqtt-port $BUS_PORT\""
echo "var.foris-$APP.flags = \"$EXTRA_FLAGS -a $APP -b $BUS --mqtt-host $BUS_HOST --mqtt-port $BUS_PORT --mqtt-passwd-file $CREDENTIALS_FILE\""
;;
esac
echo "var.foris-$APP.paths = \"$FORIS_PATHS\""
......
......@@ -22,10 +22,22 @@ def uci_get(config: str, section: str, option: str, default):
return val
def read_passwd_file(path: str) -> typing.Tuple[str]:
""" Returns username and password from passwd file
"""
with open(path, "r") as f:
return re.match(r"^([^:]+):(.*)$", f.readlines()[0][:-1]).groups()
def parse_cmdline():
parser = argparse.ArgumentParser(prog="fosquitto-monitor")
parser.add_argument("-H", "--host", default=None, required=False)
parser.add_argument("-P", "--port", type=int, default=0, required=False)
parser.add_argument(
"-F", "--passwd-file", type=lambda x: read_passwd_file(x),
help="path to passwd file (first record will be used to authenticate)",
default="/etc/fosquitto/credentials.plain",
)
commands = parser.add_subparsers(help="command which will be performend", dest="command")
commands.required = True
......@@ -59,7 +71,10 @@ def parse_cmdline():
return parser.parse_args()
def listener(host: str, port: int, show_advertize: bool, filter_ids: typing.Set[str]):
def listener(
host: str, port: int, show_advertize: bool, filter_ids: typing.Set[str],
credentials: typing.Tuple[str],
):
def on_connect(client, userdata, flags, rc):
print(f"Connected.")
client.subscribe("foris-controller/#")
......@@ -95,12 +110,13 @@ def listener(host: str, port: int, show_advertize: bool, filter_ids: typing.Set[
client.on_message = on_message
client.on_subscribe = on_subscribe
client.username_pw_set(*credentials)
client.connect(host, port, 30)
print(f"Connecting to host {host}:{port}.")
client.loop_forever()
def detect_ids(host: str, port: int, timeout: int):
def detect_ids(host: str, port: int, timeout: int, credentials: typing.Tuple[str]):
ids: typing.Set[str] = set()
def on_message(client, userdata, msg):
......@@ -116,6 +132,7 @@ def detect_ids(host: str, port: int, timeout: int):
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(*credentials)
client.connect(host, port, 30)
if timeout:
start = time.time()
......@@ -125,7 +142,7 @@ def detect_ids(host: str, port: int, timeout: int):
client.loop_forever()
def query_bus(host: str, port: int, topic: str, device_id: str):
def query_bus(host: str, port: int, topic: str, device_id: str, credentials: typing.Tuple[str]):
result = {"data": None}
msg_id = uuid.uuid1()
......@@ -150,6 +167,7 @@ def query_bus(host: str, port: int, topic: str, device_id: str):
client.on_subscribe = on_subscribe
client.on_message = on_message
client.on_connect = on_connect
client.username_pw_set(*credentials)
client.connect(host, port, 30)
client.loop_start()
client._thread.join(5)
......@@ -160,24 +178,26 @@ def query_bus(host: str, port: int, topic: str, device_id: str):
return result["data"]
def list_objects(host: str, port: int, device_id: str, modules: typing.List[str]):
def list_objects(
host: str, port: int, device_id: str, modules: typing.List[str], credentials: typing.Tuple[str]
):
if not modules:
topic = f"foris-controller/{device_id}/list"
for module in query_bus(host, port, topic, device_id):
for module in query_bus(host, port, topic, device_id, credentials):
for action in module["actions"]:
print(f"{module['name']}.{action}")
print()
else:
for module in modules:
topic = f"foris-controller/{device_id}/request/{module}/list"
for action in query_bus(host, port, topic, device_id):
for action in query_bus(host, port, topic, device_id, credentials):
print(f"{module}.{action}")
print()
def display_schemas(host: str, port: int, device_id: str):
def display_schemas(host: str, port: int, device_id: str, credentials: typing.Tuple[str]):
topic = f"foris-controller/{device_id}/jsonschemas"
print(json.dumps(query_bus(host, port, topic, device_id), indent=2))
print(json.dumps(query_bus(host, port, topic, device_id, credentials), indent=2))
def main():
......@@ -186,13 +206,13 @@ def main():
port = options.port or int(uci_get("foris-controller", "mqtt", "port", 11883))
if options.command == "listen":
listener(host, port, options.show_advertize, options.filter_ids)
listener(host, port, options.show_advertize, options.filter_ids, options.passwd_file)
elif options.command == "detect":
detect_ids(host, port, options.timeout)
detect_ids(host, port, options.timeout, options.passwd_file)
elif options.command == "list":
list_objects(host, port, options.device_id, options.filter_modules)
list_objects(host, port, options.device_id, options.filter_modules, options.passwd_file)
elif options.command == "schemas":
display_schemas(host, port, options.device_id)
display_schemas(host, port, options.device_id, options.passwd_file)
if __name__ == "__main__":
......
......@@ -6,6 +6,19 @@ STOP=50
USE_PROCD=1
GENERATED_CONF=/tmp/fosquitto.generated.conf
PLAIN_PASSWORD=/etc/fosquitto/credentials.plain # local:<random_password>
HASHED_PASSWORD=/etc/fosquitto/credentials.hashed # local:<hashed_random_password>
generate_password() {
local new_password=$(hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/urandom)
local stored_umask=$(umask)
umask 0077
mkdir -p /etc/fosquitto
echo "local:${new_password}" > "${PLAIN_PASSWORD}"
cp "${PLAIN_PASSWORD}" "${HASHED_PASSWORD}"
mosquitto_passwd -U "${HASHED_PASSWORD}"
umask ${stored_umask}
}
generate_global() {
config_get_bool debug global debug "0"
......@@ -20,6 +33,8 @@ generate_global() {
echo "autosave_interval 0" >> "$GENERATED_CONF"
echo "persistence true" >> "$GENERATED_CONF"
echo "persistence_file /tmp/fosquitto.db" >> "$GENERATED_CONF"
echo "password_file ${HASHED_PASSWORD}" >> "$GENERATED_CONF"
echo "allow_anonymous false" >> "$GENERATED_CONF"
echo >> "$GENERATED_CONF"
}
......@@ -101,6 +116,10 @@ generate_config() {
start_service() {
generate_config
if [ ! \( -e "$PLAIN_PASSWORD" \) -o ! \( -e "$HASHED_PASSWORD" \) ]; then
generate_password
fi
procd_open_instance
procd_set_param command mosquitto
procd_append_param command -c $GENERATED_CONF
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment