summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorentin LABBE <clabbe@baylibre.com>2018-07-04 14:45:58 +0200
committerCorentin LABBE <clabbe@baylibre.com>2018-07-23 16:20:48 +0200
commitd42030d39800b930634dba1efafcf43959c40205 (patch)
treedd9bc68db2a8e763fc1032503a85ec9342568185
parent0f09e5c9b89cee21a6ee39db9daf8e17525dd493 (diff)
Handle ZMQ auth
This patch add support for using ZMQ auth. Basicly adding "zmq_auth: True" to a master is sufficient to enable it. Since "ZMQ certificates" are using a custom format (vs X509 classic), we need to use the custom generator. For helping with that a temporary docker is generated which handle generating thoses files.
-rw-r--r--README.md5
-rw-r--r--lava-master/Dockerfile2
-rwxr-xr-xlava-master/scripts/setup.sh9
-rw-r--r--lava-master/zmq_auth/.empty0
-rw-r--r--lava-slave/Dockerfile2
-rwxr-xr-xlava-slave/scripts/setup.sh8
-rw-r--r--lava-slave/zmq_auth/.empty0
-rwxr-xr-xlavalab-gen.py33
-rw-r--r--zmqauth/docker-compose.yml6
-rwxr-xr-xzmqauth/zmq_auth_fill.sh7
-rw-r--r--zmqauth/zmq_auth_gen/Dockerfile17
-rwxr-xr-xzmqauth/zmq_auth_gen/create_certificate.py46
-rw-r--r--zmqauth/zmq_auth_gen/zmq_gen.sh23
13 files changed, 155 insertions, 3 deletions
diff --git a/README.md b/README.md
index 4dd43d9..66bec8f 100644
--- a/README.md
+++ b/README.md
@@ -215,6 +215,9 @@ masters:
- name: lava-master name of the master
host: name name of the host running lava-master (default to "local")
webadmin_https: Does the LAVA webadmin is accessed via https
+ zmq_auth: True/False Does the master requires ZMQ authentication.
+ zmq_auth_key: optional path to a public ZMQ key
+ zmq_auth_key_secret: optional path to a private ZMQ key
persistent_db: True/False (default False) Is the postgres DB is persistent over reboot
users:
- name: LAVA username
@@ -229,6 +232,8 @@ masters:
slaves:
- name: lab-slave-XX The name of the slave (where XX is a number)
host: name name of the host running lava-slave-XX (default to "local")
+ zmq_auth_key: optional path to a public ZMQ key
+ zmq_auth_key_secret: optional path to a private ZMQ key
dispatcher_ip: the IP where the slave could be contacted. In lava-docker it is the host IP since docker proxify TFTP from host to the slave.
remote_master: the name of the master to connect to
remote_address: the FQDN or IP address of the master (if different from remote_master)
diff --git a/lava-master/Dockerfile b/lava-master/Dockerfile
index a074570..3299922 100644
--- a/lava-master/Dockerfile
+++ b/lava-master/Dockerfile
@@ -93,6 +93,8 @@ RUN cd /etc/lava-server/dispatcher-config/device-types/ && for patch in $(ls /ro
COPY lava-patch/ /root/lava-patch
RUN cd /usr/lib/python3/dist-packages && for patch in $(ls /root/lava-patch/*patch) ; do patch -p1 < $patch || exit $?;done
+COPY zmq_auth/ /etc/lava-dispatcher/certificates.d/
+
EXPOSE 69/udp 80 3079 5555 5556
CMD /start.sh && while [ true ];do sleep 365d; done
diff --git a/lava-master/scripts/setup.sh b/lava-master/scripts/setup.sh
index 6ab0663..c7807dc 100755
--- a/lava-master/scripts/setup.sh
+++ b/lava-master/scripts/setup.sh
@@ -118,3 +118,12 @@ do
lava-server manage devices add --device-type $devicetype --worker $worker $devicename || exit $?
done
done
+
+if [ -e /etc/lava-dispatcher/certificates.d/$(hostname).key ];then
+ echo "INFO: Enabling encryption"
+ sed -i 's,.*ENCRYPT=.*,ENCRYPT="--encrypt",' /etc/lava-server/lava-master || exit $?
+ sed -i 's,.*MASTER_CERT=.*,MASTER_CERT="--master-cert /etc/lava-dispatcher/certificates.d/$(hostname).key_secret",' /etc/lava-server/lava-master || exit $?
+ sed -i 's,.*ENCRYPT=.*,ENCRYPT="--encrypt",' /etc/lava-server/lava-logs || exit $?
+ sed -i 's,.*MASTER_CERT=.*,MASTER_CERT="--master-cert /etc/lava-dispatcher/certificates.d/$(hostname).key_secret",' /etc/lava-server/lava-logs || exit $?
+fi
+exit 0
diff --git a/lava-master/zmq_auth/.empty b/lava-master/zmq_auth/.empty
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lava-master/zmq_auth/.empty
diff --git a/lava-slave/Dockerfile b/lava-slave/Dockerfile
index a5b0148..4bd14b4 100644
--- a/lava-slave/Dockerfile
+++ b/lava-slave/Dockerfile
@@ -86,6 +86,8 @@ RUN ssh-keygen -q -f /root/.ssh/id_rsa
RUN cat /root/.ssh/id_rsa.pub > /root/.ssh/authorized_keys
COPY lava-screen.conf /root/
+COPY zmq_auth/ /etc/lava-dispatcher/certificates.d/
+
EXPOSE 69/udp 80
CMD /start.sh
diff --git a/lava-slave/scripts/setup.sh b/lava-slave/scripts/setup.sh
index bf91c7a..e696e57 100755
--- a/lava-slave/scripts/setup.sh
+++ b/lava-slave/scripts/setup.sh
@@ -91,3 +91,11 @@ do
fi
done
done
+
+if [ -e /etc/lava-dispatcher/certificates.d/$(hostname).key ];then
+ echo "INFO: Enabling encryption"
+ sed -i 's,.*ENCRYPT=.*,ENCRYPT="--encrypt",' /etc/lava-dispatcher/lava-slave
+ sed -i "s,.*SLAVE_CERT=.*,SLAVE_CERT=\"--slave-cert /etc/lava-dispatcher/certificates.d/$(hostname).key_secret\"," /etc/lava-dispatcher/lava-slave
+ sed -i "s,.*MASTER_CERT=.*,MASTER_CERT=\"--master-cert /etc/lava-dispatcher/certificates.d/$LAVA_MASTER.key\"," /etc/lava-dispatcher/lava-slave
+fi
+exit 0
diff --git a/lava-slave/zmq_auth/.empty b/lava-slave/zmq_auth/.empty
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lava-slave/zmq_auth/.empty
diff --git a/lavalab-gen.py b/lavalab-gen.py
index e0c1c16..a642400 100755
--- a/lavalab-gen.py
+++ b/lavalab-gen.py
@@ -12,7 +12,7 @@ import shutil
boards_yaml = "boards.yaml"
tokens_yaml = "tokens.yaml"
baud_default = 115200
-
+
template_conmux = string.Template("""#
# auto-generated by lavalab-gen.py for ${board}
#
@@ -74,18 +74,20 @@ template_settings_conf = string.Template("""
""")
def main():
+ need_zmq_auth_gen = False
fp = open(boards_yaml, "r")
workers = yaml.load(fp)
fp.close()
os.mkdir("output")
+ zmq_auth_genlist = open("zmqauth/zmq_auth_gen/zmq_genlist", 'w')
if "masters" not in workers:
print("Missing masters entry in boards.yaml")
sys.exit(1)
masters = workers["masters"]
for master in masters:
- keywords_master = [ "name", "type", "host", "users", "tokens", "webadmin_https", "persistent_db" ]
+ keywords_master = [ "name", "type", "host", "users", "tokens", "webadmin_https", "persistent_db", "zmq_auth", "zmq_auth_key", "zmq_auth_key_secret" ]
for keyword in master:
if not keyword in keywords_master:
print("WARNING: unknown keyword %s" % keyword)
@@ -139,6 +141,16 @@ def main():
fsettings = open("%s/settings.conf" % workerdir, 'w')
fsettings.write(template_settings_conf.substitute(cookie_secure=cookie_secure, session_cookie_secure=session_cookie_secure))
fsettings.close()
+ master_use_zmq_auth = False
+ if "zmq_auth" in worker:
+ master_use_zmq_auth = True
+ if master_use_zmq_auth:
+ if "zmq_auth_key" in worker:
+ shutil.copy(worker["zmq_auth_key"], "%s/zmq_auth/" % workerdir)
+ shutil.copy(worker["zmq_auth_key_secret"], "%s/zmq_auth/" % workerdir)
+ else:
+ zmq_auth_genlist.write("%s/%s\n" % (host, name))
+ need_zmq_auth_gen = True
if "users" in worker:
for user in worker["users"]:
keywords_users = [ "name", "staff", "superuser", "password", "token" ]
@@ -195,7 +207,7 @@ def main():
sys.exit(1)
slaves = workers["slaves"]
for slave in slaves:
- keywords_slaves = [ "name", "host", "dispatcher_ip", "remote_user", "remote_master", "remote_address", "remote_rpc_port", "remote_proto", "extra_actions" ]
+ keywords_slaves = [ "name", "host", "dispatcher_ip", "remote_user", "remote_master", "remote_address", "remote_rpc_port", "remote_proto", "extra_actions", "zmq_auth_key", "zmq_auth_key_secret" ]
for keyword in slave:
if not keyword in keywords_slaves:
print("WARNING: unknown keyword %s" % keyword)
@@ -264,6 +276,17 @@ def main():
for fuser in fm["users"]:
if fuser["name"] == remote_user:
remote_token = fuser["token"]
+ if "zmq_auth" in fm:
+ if "zmq_auth_key" in fm:
+ shutil.copy(fm["zmq_auth_key"], "%s/zmq_auth/" % workerdir)
+ if "zmq_auth_key" in worker:
+ shutil.copy(worker["zmq_auth_key"], "%s/zmq_auth/" % workerdir)
+ shutil.copy(worker["zmq_auth_key_secret"], "%s/zmq_auth/" % workerdir)
+ if "zmq_auth_key" in fm:
+ shutil.copy(worker["zmq_auth_key"], "output/%s/%s/zmq_auth/" % (fm["host"], fm["name"]))
+ else:
+ zmq_auth_genlist.write("%s/%s %s/%s\n" % (host, name, fm["host"], fm["name"]))
+ need_zmq_auth_gen = True
if remote_token is "BAD":
print("Cannot find %s on %s" % (remote_user, remote_master))
sys.exit(1)
@@ -416,6 +439,10 @@ def main():
fp.close()
with open(dockcomposeymlpath, 'w') as f:
yaml.dump(dockcomp, f)
+ zmq_auth_genlist.close()
+ if need_zmq_auth_gen:
+ print("Gen ZMQ auth files")
+ subprocess.check_call(["./zmqauth/zmq_auth_fill.sh"], stdin=None)
if __name__ == "__main__":
diff --git a/zmqauth/docker-compose.yml b/zmqauth/docker-compose.yml
new file mode 100644
index 0000000..a7147e1
--- /dev/null
+++ b/zmqauth/docker-compose.yml
@@ -0,0 +1,6 @@
+services:
+ master1:
+ build: {context: zmq_auth_gen }
+ hostname: zmqauth_builder
+ volumes: ['../output:/root/output']
+version: '2.0'
diff --git a/zmqauth/zmq_auth_fill.sh b/zmqauth/zmq_auth_fill.sh
new file mode 100755
index 0000000..31d406f
--- /dev/null
+++ b/zmqauth/zmq_auth_fill.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+cd $(dirname $0)
+id -u > zmq_auth_gen/id
+docker-compose build || exit $?
+docker-compose up || exit $?
+docker-compose down --rmi all
diff --git a/zmqauth/zmq_auth_gen/Dockerfile b/zmqauth/zmq_auth_gen/Dockerfile
new file mode 100644
index 0000000..46ae47a
--- /dev/null
+++ b/zmqauth/zmq_auth_gen/Dockerfile
@@ -0,0 +1,17 @@
+FROM bitnami/minideb:stretch
+
+RUN apt-get update
+
+RUN DEBIAN_FRONTEND=noninteractive apt-get -y install python3-zmq
+
+COPY create_certificate.py /root/
+RUN chmod 750 /root/create_certificate.py
+RUN mkdir /root/output
+
+COPY id /root/
+
+COPY zmq_gen.sh /root/
+RUN chmod 755 /root/zmq_gen.sh
+COPY zmq_genlist /root/
+
+CMD /root/zmq_gen.sh
diff --git a/zmqauth/zmq_auth_gen/create_certificate.py b/zmqauth/zmq_auth_gen/create_certificate.py
new file mode 100755
index 0000000..2c4445d
--- /dev/null
+++ b/zmqauth/zmq_auth_gen/create_certificate.py
@@ -0,0 +1,46 @@
+#! /usr/bin/python3
+# -*- coding: utf-8 -*-
+#
+# Copyright 2016 RĂ©mi Duraffort <remi.duraffort@linaro.org>
+#
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+import argparse
+import zmq.auth
+
+
+def main():
+ """
+ Parse options and create the certificate
+ """
+ parser = argparse.ArgumentParser(description="")
+ parser.add_argument("--directory", type=str,
+ default="/etc/lava-dispatcher/certificates.d",
+ help="Directory where to store the certificates")
+ parser.add_argument(type=str, dest="name",
+ help="Name of the certificate")
+ args = parser.parse_args()
+
+ # Create the certificate
+ print("Creating the certificate in %s" % args.directory)
+ zmq.auth.create_certificates(args.directory, args.name)
+ print(" - %s.key" % args.name)
+ print(" - %s.key_secret" % args.name)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/zmqauth/zmq_auth_gen/zmq_gen.sh b/zmqauth/zmq_auth_gen/zmq_gen.sh
new file mode 100644
index 0000000..8b67280
--- /dev/null
+++ b/zmqauth/zmq_auth_gen/zmq_gen.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+#rm /root/output/*
+while read line
+do
+ NAME=$(echo $line | cut -d' ' -f1 | sed 's,.*/,,')
+ DIR=$(echo $line | cut -d' ' -f1)
+ MASTERDIR=$(echo $line | cut -d' ' -f2)
+ echo "DEBUG: $LINE NAME=$NAME DIR=$DIR"
+ if [ ! -e /root/output/$DIR/zmq_auth/${NAME}.key ];then
+ /root/create_certificate.py $NAME --directory /root/output/$DIR/zmq_auth/ || exit $?
+ else
+ echo "DEBUG: ZMQ files for $NAME already exists"
+ fi
+ if [ ! -z "$MASTERDIR" -a "$MASTERDIR" != "$DIR" ];then
+ MASTERNAME=$(echo $MASTERDIR | sed 's,.*/,,')
+ cp /root/output/$MASTERDIR/zmq_auth/$MASTERNAME.key /root/output/$DIR/zmq_auth/master.key || exit $?
+ cp /root/output/$DIR/zmq_auth/$NAME.key /root/output/$MASTERDIR/zmq_auth/ || exit $?
+ chown $(cat /root/id) /root/output/$MASTERDIR/zmq_auth/* || exit $?
+ fi
+ # All files are generated by root, chown them to the user using the docker
+ chown $(cat /root/id) /root/output/$DIR/zmq_auth/* || exit $?
+done < /root/zmq_genlist