From 3e5e151beffa996ae86e244907f8cd75eb52dac4 Mon Sep 17 00:00:00 2001 From: pedro Date: Tue, 5 Nov 2024 04:49:09 +0100 Subject: [PATCH 01/20] make nfs mount verbose related to #4 --- deploy-workbench.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy-workbench.sh b/deploy-workbench.sh index c0c124f..42b3002 100755 --- a/deploy-workbench.sh +++ b/deploy-workbench.sh @@ -280,7 +280,7 @@ if [ "\${nfs_host}" ]; then mount --bind /run/live/medium /mnt # debian live nfs path is readonly, do a trick # to make snapshots subdir readwrite - mount \${nfs_host}:/snapshots /run/live/medium/snapshots + mount -v \${nfs_host}:/snapshots /run/live/medium/snapshots # reload mounts on systemd systemctl daemon-reload fi From e8b1d62290291e20e15dbe5d282cac917778e249 Mon Sep 17 00:00:00 2001 From: pedro Date: Wed, 6 Nov 2024 19:31:44 +0100 Subject: [PATCH 02/20] change strategy on example files (added -v to cps) - if it does not exist, copy once from example - added -v flag to cps that did not have it --- deploy-workbench.sh | 10 +++++----- pxe/install-pxe.sh | 12 ++++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/deploy-workbench.sh b/deploy-workbench.sh index 42b3002..d96afa3 100755 --- a/deploy-workbench.sh +++ b/deploy-workbench.sh @@ -199,12 +199,12 @@ create_persistence_partition() { mkdir -p "${tmp_rw_mount}" ${SUDO} mount "$(pwd)/${rw_img_path}" "${tmp_rw_mount}" ${SUDO} mkdir -p "${tmp_rw_mount}" - if [ -f "settings.ini" ]; then - ${SUDO} cp -v settings.ini "${tmp_rw_mount}/settings.ini" - else - echo "ERROR: settings.ini does not exist yet, cannot read config from there. You can take inspiration with file settings.ini.example" - exit 1 + if [ ! -f "settings.ini" ]; then + ${SUDO} cp -v settings.ini.example settings.ini + echo "WARNING: settings.ini was not there, settings.ini.example was copied, this only happens once" fi + ${SUDO} cp -v settings.ini "${tmp_rw_mount}/settings.ini" + ${SUDO} umount "${tmp_rw_mount}" uuid="$(blkid "${rw_img_path}" | awk '{ print $3; }')" diff --git a/pxe/install-pxe.sh b/pxe/install-pxe.sh index 934fb11..bf85630 100755 --- a/pxe/install-pxe.sh +++ b/pxe/install-pxe.sh @@ -37,7 +37,7 @@ backup_file() { if [ -f "${target}" ]; then if ! grep -q 'we should do a backup' "${target}"; then - ${SUDO} cp -a "${target}" "${target}-bak_${ts}" + ${SUDO} cp -v -a "${target}" "${target}-bak_${ts}" fi fi } @@ -72,7 +72,7 @@ END if [ ! -f "${nfs_path}/settings.ini" ]; then if [ -f "settings.ini" ]; then - ${SUDO} cp settings.ini "${nfs_path}/settings.ini" + ${SUDO} cp -v settings.ini "${nfs_path}/settings.ini" else echo "ERROR: $(pwd)/settings.ini does not exist yet, cannot read config from there. You can take inspiration with file $(pwd)/settings.ini.example" exit 1 @@ -110,8 +110,12 @@ install_netboot() { ${SUDO} cp -fv "${PXE_DIR}/../iso/staging/live/vmlinuz" "${tftp_path}/" ${SUDO} cp -fv "${PXE_DIR}/../iso/staging/live/initrd" "${tftp_path}/" - ${SUDO} cp /usr/lib/syslinux/memdisk "${tftp_path}/" - ${SUDO} cp /usr/lib/syslinux/modules/bios/* "${tftp_path}/" + ${SUDO} cp -v /usr/lib/syslinux/memdisk "${tftp_path}/" + ${SUDO} cp -v /usr/lib/syslinux/modules/bios/* "${tftp_path}/" + if [ ! -f ./pxe-menu.cfg ]; then + ${SUDO} cp -v ./pxe-menu.cfg.example pxe-menu.cfg + echo "WARNING: pxe-menu.cfg was not there, pxe-menu.cfg.example was copied, this only happens once" + fi envsubst < ./pxe-menu.cfg | ${SUDO} tee "${tftp_path}/pxelinux.cfg/default" fi From da7b78eae3a2b3d860e13a280826144f9b702ef5 Mon Sep 17 00:00:00 2001 From: pedro Date: Fri, 8 Nov 2024 18:20:47 +0100 Subject: [PATCH 03/20] pxe: .env generated once from example file --- pxe/install-pxe.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pxe/install-pxe.sh b/pxe/install-pxe.sh index bf85630..1d71e52 100755 --- a/pxe/install-pxe.sh +++ b/pxe/install-pxe.sh @@ -132,11 +132,10 @@ init_config() { PXE_DIR="$(pwd)" - if [ -f ./.env ]; then - . ./.env - else - echo "PXE: WARNING: $(pwd)/.env does not exist yet, cannot read config from there. You can take inspiration with file $(pwd)/.env.example" + if [ ! -f ./.env ]; then + echo "WARNING: .env was not there, .env.example was copied, this only happens once" fi + . ./.env VERSION_CODENAME="${VERSION_CODENAME:-bookworm}" tftp_path="${tftp_path:-/srv/pxe-tftp}" # vars used in envsubst require to be exported: From af780b1247077d5bfc06b83eb71934c5760ac577 Mon Sep 17 00:00:00 2001 From: pedro Date: Fri, 8 Nov 2024 18:27:24 +0100 Subject: [PATCH 04/20] Makefile: even easier generate translations --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index fdc7099..03aa432 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,10 @@ boot_iso_uefi_secureboot: -drive file=deploy/iso/workbench_debug.iso,cache=none,if=virtio,format=raw,index=0,media=disk \ -boot menu=on +es_gen: + $(MAKE) es_gen_po + $(MAKE) es_gen_mo + es_gen_po: cp locale/es/LC_MESSAGES/messages.po locale/es/LC_MESSAGES/messages.pot.bak pygettext3 -p locale/es/LC_MESSAGES/ workbench-script.py From b1136e3dd89c1bd2f8966f8d34dd82777cb844c1 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 31 Oct 2024 16:30:45 +0100 Subject: [PATCH 05/20] issue 100 new url in qr for evidence instead of device --- workbench-script.py | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/workbench-script.py b/workbench-script.py index 380dbab..04667ec 100644 --- a/workbench-script.py +++ b/workbench-script.py @@ -6,6 +6,7 @@ import uuid import hashlib import argparse import configparser +import urllib.parse import urllib.request import gettext @@ -16,6 +17,7 @@ from datetime import datetime ## Legacy Functions ## + def convert_to_legacy_snapshot(snapshot): snapshot["sid"] = str(uuid.uuid4()).split("-")[0] snapshot["software"] = "workbench-script" @@ -25,9 +27,8 @@ def convert_to_legacy_snapshot(snapshot): snapshot["timestamp"] = snapshot["timestamp"].replace(" ", "T") snapshot["data"]["smart"] = snapshot["data"]["disks"] snapshot["data"].pop("disks") - snapshot.pop("code") snapshot.pop("erase") - + ## End Legacy Functions ## @@ -54,11 +55,6 @@ def exec_cmd_erase(cmd): return '' # return os.popen(cmd).read() - -def gen_code(): - uid = str(uuid.uuid4()).encode('utf-8') - return hashlib.shake_256(uid).hexdigest(3) - ## End Utility functions ## @@ -66,7 +62,6 @@ SNAPSHOT_BASE = { 'timestamp': str(datetime.now()), 'type': 'Snapshot', 'uuid': str(uuid.uuid4()), - 'code': gen_code(), 'software': "workbench-script", 'version': "0.0.1", 'data': {}, @@ -301,6 +296,15 @@ def save_snapshot_in_disk(snapshot, path): # TODO sanitize url, if url is like this, it fails # url = 'http://127.0.0.1:8000/api/snapshot/' def send_snapshot_to_devicehub(snapshot, token, url): + url_components = urllib.parse.urlparse(url) + ev_path = "evidence/{}".format(snapshot["uuid"]) + components = (url_components.schema, url_components.netloc, ev_path, '', '', '') + ev_url = urllib.parse.urlunparse(components) + # apt install qrencode + qr = "echo {} | qrencode -t ANSI".format(ev_url) + print(exec_cmd(qr)) + print(ev_url) + headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json" @@ -310,26 +314,17 @@ def send_snapshot_to_devicehub(snapshot, token, url): request = urllib.request.Request(url, data=data, headers=headers) with urllib.request.urlopen(request) as response: status_code = response.getcode() - response_text = response.read().decode('utf-8') + #response_text = response.read().decode('utf-8') if 200 <= status_code < 300: logger.info(_("Snapshot successfully sent to '%s'"), url) - - try: - response = json.loads(response_text) - if response.get('url'): - # apt install qrencode - qr = "echo {} | qrencode -t ANSI".format(response['url']) - print(exec_cmd(qr)) - print("url: {}".format(response['url'])) - if response.get("dhid"): - print("dhid: {}".format(response['dhid'])) - except Exception: - logger.error(response_text) + else: + logger.error(_("Snapshot cannot sent to '%s'"), url) except Exception as e: logger.error(_("Snapshot not remotely sent to URL '%s'. Do you have internet? Is your server up & running? Is the url token authorized?\n %s"), url, e) + def load_config(config_file="settings.ini"): """ Tries to load configuration from a config file. From 82f93a9446e5013902b39d4a19eb6d65b8f28f1e Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 7 Nov 2024 10:04:34 +0100 Subject: [PATCH 06/20] fix legacy case --- workbench-script.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/workbench-script.py b/workbench-script.py index 04667ec..623edf5 100644 --- a/workbench-script.py +++ b/workbench-script.py @@ -295,15 +295,16 @@ def save_snapshot_in_disk(snapshot, path): # TODO sanitize url, if url is like this, it fails # url = 'http://127.0.0.1:8000/api/snapshot/' -def send_snapshot_to_devicehub(snapshot, token, url): +def send_snapshot_to_devicehub(snapshot, token, url, legacy): url_components = urllib.parse.urlparse(url) ev_path = "evidence/{}".format(snapshot["uuid"]) components = (url_components.schema, url_components.netloc, ev_path, '', '', '') ev_url = urllib.parse.urlunparse(components) # apt install qrencode qr = "echo {} | qrencode -t ANSI".format(ev_url) - print(exec_cmd(qr)) - print(ev_url) + if not legacy: + print(exec_cmd(qr)) + print(f"url: {ev_url}") headers = { "Authorization": f"Bearer {token}", @@ -314,10 +315,22 @@ def send_snapshot_to_devicehub(snapshot, token, url): request = urllib.request.Request(url, data=data, headers=headers) with urllib.request.urlopen(request) as response: status_code = response.getcode() - #response_text = response.read().decode('utf-8') + response_text = response.read().decode('utf-8') if 200 <= status_code < 300: logger.info(_("Snapshot successfully sent to '%s'"), url) + if legacy: + try: + response = json.loads(response_text) + if response.get('url'): + # apt install qrencode + qr = "echo {} | qrencode -t ANSI".format(response['url']) + print(exec_cmd(qr)) + print("url: {}".format(response['url'])) + if response.get("dhid"): + print("dhid: {}".format(response['dhid'])) + except Exception: + logger.error(response_text) else: logger.error(_("Snapshot cannot sent to '%s'"), url) @@ -409,6 +422,7 @@ def main(): config_file = args.config config = load_config(config_file) + legacy = config.get("legacy") # TODO show warning if non root, means data is not complete # if annotate as potentially invalid snapshot (pending the new API to be done) @@ -423,13 +437,13 @@ def main(): elif config['erase'] and not config.get("legacy"): snapshot['erase'] = gen_erase(all_disks, config['erase']) - if config.get("legacy"): + if legacy: convert_to_legacy_snapshot(snapshot) save_snapshot_in_disk(snapshot, config['path']) if config['url']: - send_snapshot_to_devicehub(snapshot, config['token'], config['url']) + send_snapshot_to_devicehub(snapshot, config['token'], config['url'], legacy) logger.info(_("END")) From 71e06b13a41243e62dcb9dafea1e02e9ae5c7b2c Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 7 Nov 2024 17:42:03 +0100 Subject: [PATCH 07/20] fix process for show qr --- workbench-script.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/workbench-script.py b/workbench-script.py index 623edf5..41bf2ed 100644 --- a/workbench-script.py +++ b/workbench-script.py @@ -301,10 +301,6 @@ def send_snapshot_to_devicehub(snapshot, token, url, legacy): components = (url_components.schema, url_components.netloc, ev_path, '', '', '') ev_url = urllib.parse.urlunparse(components) # apt install qrencode - qr = "echo {} | qrencode -t ANSI".format(ev_url) - if not legacy: - print(exec_cmd(qr)) - print(f"url: {ev_url}") headers = { "Authorization": f"Bearer {token}", @@ -331,8 +327,12 @@ def send_snapshot_to_devicehub(snapshot, token, url, legacy): print("dhid: {}".format(response['dhid'])) except Exception: logger.error(response_text) + else: + qr = "echo {} | qrencode -t ANSI".format(ev_url) + print(exec_cmd(qr)) + print(f"url: {ev_url}") else: - logger.error(_("Snapshot cannot sent to '%s'"), url) + logger.error(_("Snapshot %s, cannot sent to '%s'"), snapshot["uuid"], url) except Exception as e: logger.error(_("Snapshot not remotely sent to URL '%s'. Do you have internet? Is your server up & running? Is the url token authorized?\n %s"), url, e) From 8ac0da99fee8f3b4adbd73d14ce1f4eafe8193a5 Mon Sep 17 00:00:00 2001 From: pedro Date: Fri, 8 Nov 2024 11:27:31 +0100 Subject: [PATCH 08/20] wb.py: improved error msgs when sending to URL --- workbench-script.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/workbench-script.py b/workbench-script.py index 41bf2ed..2129f42 100644 --- a/workbench-script.py +++ b/workbench-script.py @@ -332,10 +332,10 @@ def send_snapshot_to_devicehub(snapshot, token, url, legacy): print(exec_cmd(qr)) print(f"url: {ev_url}") else: - logger.error(_("Snapshot %s, cannot sent to '%s'"), snapshot["uuid"], url) + logger.error(_("Snapshot %s could not be sent to URL '%s'"), snapshot["uuid"], url) except Exception as e: - logger.error(_("Snapshot not remotely sent to URL '%s'. Do you have internet? Is your server up & running? Is the url token authorized?\n %s"), url, e) + logger.error(_("Snapshot %s not remotely sent to URL '%s'. Do you have internet? Is your server up & running? Is the url token authorized?\n %s"), snapshot["uuid"], url, e) def load_config(config_file="settings.ini"): From c1867d1ce397d9249b09da63133f62d3c06b2da7 Mon Sep 17 00:00:00 2001 From: pedro Date: Fri, 8 Nov 2024 18:26:25 +0100 Subject: [PATCH 09/20] add es translations to new logs --- locale/es/LC_MESSAGES/messages.mo | Bin 2335 -> 2443 bytes locale/es/LC_MESSAGES/messages.po | 44 ++++++++++++++++-------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/locale/es/LC_MESSAGES/messages.mo b/locale/es/LC_MESSAGES/messages.mo index 4ca804c76a942dfcfa18f9f6dc006e31698c281c..3d34e18482d995400f3da9e9f2196d8777939ac3 100644 GIT binary patch delta 500 zcmZwD&o2W(6u|MfwN!(mBt7^wA*&IMM32r64oDD5Ph{yPMD4bAmxItaNGcBEu&yEz z|3IC45PyY(tB8n`yYFndndI$fW_I4po4L(g4%A*VW+b$JVwkumvP9nCL#yK^Uf?Xg z;|dNXL?&<_+wdAkF+vL;aS&gy9lvl2zwr#mNE#QZ$sL_ZCZ2HwKX4gSrpOW&G0UM3 zc+9xTZhC&MLu3Q%sPo^DR7odWg=Vn8cpmkIj*umCh0}P0=bSH3bf`oYI$IU)p)MrC zQ*2-n3n>xmh+m2+=^{vtH>Eb|BXsL-5f{T{rHAMx^egr^EydCGAQckKgZtFrxn Ij-6~8KV^+V5&!@I delta 403 zcmXxgJ!=9%5P;#iczVWfG>{@{p(u!zmUdPtLWHDB3X{eZmckW^pcoJfv9t@MNoA4d zYFmpSLJA8(wDM<&d3VnY%s#Wr?e6T26QA+^E^bbRh>=P1gS=L?!9cX}6+2kM4L)G- zLL`fI^xy!~IK&)&;T8U%7x&o117@(nro2dBMieO)zOjZ&yvG}pM!2krUFHK$QR_#1 z!8@NmKxW7m`9;;>8p~)|?n5fbl04!&KBH=2iv{kN6NPG^;CDN`#V6(qMlv>tZIVC=?F5aSN})&TwG#=45)e4w%?qI(K4K($2OgnH8=hM%PJ){ diff --git a/locale/es/LC_MESSAGES/messages.po b/locale/es/LC_MESSAGES/messages.po index c19de48..fccf648 100644 --- a/locale/es/LC_MESSAGES/messages.po +++ b/locale/es/LC_MESSAGES/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-15 21:15+0200\n" +"POT-Creation-Date: 2024-11-08 18:25+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,19 +17,19 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: workbench-script.py:48 workbench-script.py:53 +#: workbench-script.py:49 workbench-script.py:54 msgid "Running command `%s`" msgstr "Ejecutando comando `%s`" -#: workbench-script.py:284 +#: workbench-script.py:279 msgid "Created snapshots directory at '%s'" msgstr "Creado directorio de snapshots en '%s'" -#: workbench-script.py:287 +#: workbench-script.py:282 msgid "Snapshot written in path '%s'" msgstr "Snapshot escrito en ruta '%s'" -#: workbench-script.py:290 +#: workbench-script.py:285 msgid "" "Attempting to save file in actual path. Reason: Failed to write in snapshots " "directory:\n" @@ -39,11 +39,11 @@ msgstr "" "escribir en el directorio de snapshots:\n" " %s." -#: workbench-script.py:297 +#: workbench-script.py:292 msgid "Snapshot written in fallback path '%s'" msgstr "Snapshot escrito en ruta alternativa '%s'" -#: workbench-script.py:299 +#: workbench-script.py:294 msgid "" "Could not save snapshot locally. Reason: Failed to write in fallback path:\n" " %s" @@ -52,49 +52,53 @@ msgstr "" "alternativa:\n" " %s" -#: workbench-script.py:316 +#: workbench-script.py:317 msgid "Snapshot successfully sent to '%s'" msgstr "Snapshot enviado con éxito a '%s'" -#: workbench-script.py:331 +#: workbench-script.py:335 +msgid "Snapshot %s could not be sent to URL '%s'" +msgstr "Snapshot %s no se pudo enviar a la URL '%s'" + +#: workbench-script.py:338 msgid "" -"Snapshot not remotely sent to URL '%s'. Do you have internet? Is your server " -"up & running? Is the url token authorized?\n" +"Snapshot %s not remotely sent to URL '%s'. Do you have internet? Is your " +"server up & running? Is the url token authorized?\n" " %s" msgstr "" -"Snapshot no enviado remotamente a la URL '%s'. Tienes internet? Está el " +"Snapshot %s no enviado remotamente a la URL '%s'. Tienes internet? Está el " "servidor en marcha? Está autorizado el url token?\n" " %s" -#: workbench-script.py:342 +#: workbench-script.py:350 msgid "Found config file in path: %s." msgstr "Encontrado fichero de configuración en ruta: %s." -#: workbench-script.py:353 +#: workbench-script.py:361 msgid "Config file '%s' not found. Using default values." msgstr "" "Fichero de configuración '%s' no encontrado. Utilizando valores por defecto." -#: workbench-script.py:373 +#: workbench-script.py:379 msgid "workbench-script.py [-h] [--config CONFIG]" msgstr "" -#: workbench-script.py:374 +#: workbench-script.py:380 msgid "Optional config loader for workbench." msgstr "Cargador opcional de configuración para workbench" -#: workbench-script.py:377 +#: workbench-script.py:383 msgid "" "path to the config file. Defaults to 'settings.ini' in the current directory." msgstr "" "ruta al fichero de configuración. Por defecto es 'settings.ini' en el " "directorio actual" -#: workbench-script.py:410 +#: workbench-script.py:416 msgid "START" msgstr "INICIO" -#: workbench-script.py:423 +#: workbench-script.py:430 msgid "" "This script must be run as root. Collected data will be incomplete or " "unusable" @@ -102,6 +106,6 @@ msgstr "" "Es conveniente que este script sea ejecutado como administrador (root). Los " "datos recopilados serán incompletos o no usables." -#: workbench-script.py:441 +#: workbench-script.py:448 msgid "END" msgstr "FIN" From 55eec35d585179071f53846e06ede177c94504d8 Mon Sep 17 00:00:00 2001 From: pedro Date: Fri, 8 Nov 2024 20:13:37 +0100 Subject: [PATCH 10/20] relevant improvement in locales - locales fixed - keyboard works - better prepared for other LANGs --- deploy-workbench.sh | 53 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/deploy-workbench.sh b/deploy-workbench.sh index d96afa3..6995ec4 100755 --- a/deploy-workbench.sh +++ b/deploy-workbench.sh @@ -253,6 +253,27 @@ END2 END )" + +# thanks https://wiki.debian.org/Keyboard +chroot_kbd_conf_str="$(cat< /etc/default/keyboard < /etc/locale.gen +# Generate the locale +locale-gen +# feeds /etc/default/locale for the shell env var +update-locale LANG=${LANG} LC_ALL=${LANG} # this is a high level command that does locale-gen and update-locale altogether -dpkg-reconfigure --frontend=noninteractive locales +# but it is too interactive +#dpkg-reconfigure --frontend=noninteractive locales # DEBUG locale -a @@ -387,6 +416,9 @@ apt-get install -y --no-install-recommends \ < /dev/null ${chroot_netdns_conf_str} +CUSTOM_LANG=${CUSTOM_LANG} +${chroot_kbd_conf_str} +chroot_kbd_conf # Set up root user # this is the root password @@ -406,7 +438,19 @@ CHROOT } prepare_chroot_env() { - LANG="${CUSTOM_LANG:-es_ES.UTF-8}" + CUSTOM_LANG="${CUSTOM_LANG:-es}" + case "${CUSTOM_LANG}" in + es) + export LANG="es_ES.UTF-8" + export MYLOCALE="${LANG} UTF-8" + ;; + en) + export LANG="en_US.UTF-8" + ;; + *) + echo "ERROR: CUSTOM_LANG not supported. Available: es" + exit 1 + esac # version of debian the bootstrap is going to build # if no VERSION_CODENAME is specified we assume that the bootstrap is going to # be build with the same version of debian being executed because some files @@ -430,6 +474,7 @@ prepare_chroot_env() { prepare_app } + # thanks https://willhaley.com/blog/custom-debian-live-environment/ install_requirements() { # Install requirements From 12209c84fa810d927dc696b3ad47a7c1386e85f0 Mon Sep 17 00:00:00 2001 From: pedro Date: Fri, 8 Nov 2024 20:14:08 +0100 Subject: [PATCH 11/20] workbench-script: bugfix when url is used --- workbench-script.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workbench-script.py b/workbench-script.py index 2129f42..4188818 100644 --- a/workbench-script.py +++ b/workbench-script.py @@ -298,7 +298,7 @@ def save_snapshot_in_disk(snapshot, path): def send_snapshot_to_devicehub(snapshot, token, url, legacy): url_components = urllib.parse.urlparse(url) ev_path = "evidence/{}".format(snapshot["uuid"]) - components = (url_components.schema, url_components.netloc, ev_path, '', '', '') + components = (url_components.scheme, url_components.netloc, ev_path, '', '', '') ev_url = urllib.parse.urlunparse(components) # apt install qrencode From d9e85dca36f156755bd0657c16cde2e88577dbaa Mon Sep 17 00:00:00 2001 From: pedro Date: Sat, 9 Nov 2024 19:41:26 +0100 Subject: [PATCH 12/20] settings.ini.example: better example/ref --- settings.ini.example | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/settings.ini.example b/settings.ini.example index a51397b..014ada2 100644 --- a/settings.ini.example +++ b/settings.ini.example @@ -1,6 +1,9 @@ [settings] -url = http://localhost:8000/api/snapshot/ -token = '1234' +#url = http://localhost:8000/api/v1/snapshot/ +url = https://demo.ereuse.org/api/v1/snapshot/ +# sample token that works with default deployment such as the previous two urls +token = 5018dd65-9abd-4a62-8896-80f34ac66150 + # path = /path/to/save # device = your_device_name # # erase = basic From 3fb1cd19dcdf607ecaf7fd4342bfc1bc3e98dc05 Mon Sep 17 00:00:00 2001 From: pedro Date: Sat, 9 Nov 2024 19:42:44 +0100 Subject: [PATCH 13/20] settings.ini.example: better localhost by default then avoid sending data by default to the internet, that's weird --- settings.ini.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.ini.example b/settings.ini.example index 014ada2..e37b41e 100644 --- a/settings.ini.example +++ b/settings.ini.example @@ -1,6 +1,6 @@ [settings] -#url = http://localhost:8000/api/v1/snapshot/ -url = https://demo.ereuse.org/api/v1/snapshot/ +url = http://localhost:8000/api/v1/snapshot/ +#url = https://demo.ereuse.org/api/v1/snapshot/ # sample token that works with default deployment such as the previous two urls token = 5018dd65-9abd-4a62-8896-80f34ac66150 From 2d0048433b8f226ccd4ef98647f1e41a744ca9b6 Mon Sep 17 00:00:00 2001 From: pedro Date: Mon, 11 Nov 2024 02:24:06 +0100 Subject: [PATCH 14/20] workbench-script.py: server error is provided --- workbench-script.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/workbench-script.py b/workbench-script.py index 4188818..37058e0 100644 --- a/workbench-script.py +++ b/workbench-script.py @@ -333,6 +333,11 @@ def send_snapshot_to_devicehub(snapshot, token, url, legacy): print(f"url: {ev_url}") else: logger.error(_("Snapshot %s could not be sent to URL '%s'"), snapshot["uuid"], url) + # TODO review all the try-except thing here; maybe the try inside legacy does not make sense anymore + except urllib.error.HTTPError as e: + error_details = e.read().decode('utf-8') # Get the error response body + logger.error(_("Snapshot %s not remotely sent to URL '%s'. Server responded with error:\n %s"), + snapshot["uuid"], url, error_details) except Exception as e: logger.error(_("Snapshot %s not remotely sent to URL '%s'. Do you have internet? Is your server up & running? Is the url token authorized?\n %s"), snapshot["uuid"], url, e) From cf81579819b6943280fefed907f0fd398856eb8c Mon Sep 17 00:00:00 2001 From: pedro Date: Mon, 11 Nov 2024 02:30:30 +0100 Subject: [PATCH 15/20] workbench-script: in legacy, lshw is a json object --- workbench-script.py | 1 + 1 file changed, 1 insertion(+) diff --git a/workbench-script.py b/workbench-script.py index 37058e0..010d593 100644 --- a/workbench-script.py +++ b/workbench-script.py @@ -26,6 +26,7 @@ def convert_to_legacy_snapshot(snapshot): snapshot["settings_version"] = "No Settings Version (NaN)" snapshot["timestamp"] = snapshot["timestamp"].replace(" ", "T") snapshot["data"]["smart"] = snapshot["data"]["disks"] + snapshot["data"]["lshw"] = json.loads(snapshot["data"]["lshw"]) snapshot["data"].pop("disks") snapshot.pop("erase") From 13f38dacb8703baa62c2ca2c99b811c2e8cccc34 Mon Sep 17 00:00:00 2001 From: pedro Date: Mon, 11 Nov 2024 13:17:37 +0100 Subject: [PATCH 16/20] deploy-workbench: add qrencode deb dependency --- deploy-workbench.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy-workbench.sh b/deploy-workbench.sh index 6995ec4..d0884bc 100755 --- a/deploy-workbench.sh +++ b/deploy-workbench.sh @@ -325,7 +325,7 @@ echo 'Install requirements' # Install debian requirements apt-get install -y --no-install-recommends \ - sudo locales keyboard-configuration console-setup \ + sudo locales keyboard-configuration console-setup qrencode \ python-is-python3 python3 python3-dev python3-pip pipenv \ dmidecode smartmontools hwinfo pciutils lshw nfs-common < /dev/null From f7c3e138f18779252ba54bef504974d69a1986ca Mon Sep 17 00:00:00 2001 From: pedro Date: Mon, 11 Nov 2024 13:58:37 +0100 Subject: [PATCH 17/20] pxe: add the missing env --- pxe/install-pxe.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/pxe/install-pxe.sh b/pxe/install-pxe.sh index 1d71e52..70a1a69 100755 --- a/pxe/install-pxe.sh +++ b/pxe/install-pxe.sh @@ -133,6 +133,7 @@ init_config() { PXE_DIR="$(pwd)" if [ ! -f ./.env ]; then + cp -v ./.env.example ./.env echo "WARNING: .env was not there, .env.example was copied, this only happens once" fi . ./.env From 192861b47e9c3654398c31665c14847d4d861630 Mon Sep 17 00:00:00 2001 From: pedro Date: Mon, 11 Nov 2024 14:04:17 +0100 Subject: [PATCH 18/20] pxe: improve first init --- pxe/install-pxe.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pxe/install-pxe.sh b/pxe/install-pxe.sh index 70a1a69..b536a2b 100755 --- a/pxe/install-pxe.sh +++ b/pxe/install-pxe.sh @@ -69,14 +69,14 @@ END # reload nfs exports ${SUDO} exportfs -vra + if [ ! -f ./.settings.ini ]; then + cp -v ./.settings.ini.example ./.settings.ini + echo "WARNING: settings.ini was not there, settings.ini.example was copied, this only happens once" + fi if [ ! -f "${nfs_path}/settings.ini" ]; then - if [ -f "settings.ini" ]; then - ${SUDO} cp -v settings.ini "${nfs_path}/settings.ini" - else - echo "ERROR: $(pwd)/settings.ini does not exist yet, cannot read config from there. You can take inspiration with file $(pwd)/settings.ini.example" - exit 1 - fi + ${SUDO} cp -v settings.ini "${nfs_path}/settings.ini" + echo "WARNING: ${nfs_path}/settings.ini was not there, ./settings.ini was copied, this only happens once" fi } From a857db5de1de2148c6dc4aa29c26a1aca591ded7 Mon Sep 17 00:00:00 2001 From: pedro Date: Mon, 11 Nov 2024 14:05:22 +0100 Subject: [PATCH 19/20] pxe: improve init bugfix --- pxe/install-pxe.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pxe/install-pxe.sh b/pxe/install-pxe.sh index b536a2b..ce721f3 100755 --- a/pxe/install-pxe.sh +++ b/pxe/install-pxe.sh @@ -69,8 +69,8 @@ END # reload nfs exports ${SUDO} exportfs -vra - if [ ! -f ./.settings.ini ]; then - cp -v ./.settings.ini.example ./.settings.ini + if [ ! -f ./settings.ini ]; then + cp -v ./settings.ini.example ./settings.ini echo "WARNING: settings.ini was not there, settings.ini.example was copied, this only happens once" fi From ae5f9c341aaf5d97630a4697dd73ede3dec97a5b Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 15 Nov 2024 11:05:24 +0100 Subject: [PATCH 20/20] add inxi in main --- workbench-script.py | 129 ++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 66 deletions(-) diff --git a/workbench-script.py b/workbench-script.py index 010d593..99dbc4a 100644 --- a/workbench-script.py +++ b/workbench-script.py @@ -3,7 +3,6 @@ import os import json import uuid -import hashlib import argparse import configparser import urllib.parse @@ -16,21 +15,17 @@ import logging from datetime import datetime -## Legacy Functions ## +SNAPSHOT_BASE = { + 'timestamp': str(datetime.now()), + 'type': 'Snapshot', + 'uuid': str(uuid.uuid4()), + 'software': "workbench-script", + 'version': "0.0.1", + 'token_hash': "", + 'data': {}, + 'erase': [] +} -def convert_to_legacy_snapshot(snapshot): - snapshot["sid"] = str(uuid.uuid4()).split("-")[0] - snapshot["software"] = "workbench-script" - snapshot["version"] = "dev" - snapshot["schema_api"] = "1.0.0" - snapshot["settings_version"] = "No Settings Version (NaN)" - snapshot["timestamp"] = snapshot["timestamp"].replace(" ", "T") - snapshot["data"]["smart"] = snapshot["data"]["disks"] - snapshot["data"]["lshw"] = json.loads(snapshot["data"]["lshw"]) - snapshot["data"].pop("disks") - snapshot.pop("erase") - -## End Legacy Functions ## ## Utility Functions ## @@ -59,17 +54,35 @@ def exec_cmd_erase(cmd): ## End Utility functions ## -SNAPSHOT_BASE = { - 'timestamp': str(datetime.now()), - 'type': 'Snapshot', - 'uuid': str(uuid.uuid4()), - 'software': "workbench-script", - 'version': "0.0.1", - 'data': {}, - 'erase': [] -} +## Legacy Functions ## +def convert_to_legacy_snapshot(snapshot): + snapshot["sid"] = str(uuid.uuid4()).split("-")[1] + snapshot["software"] = "workbench-script" + snapshot["version"] = "dev" + snapshot["schema_api"] = "1.0.0" + snapshot["settings_version"] = "No Settings Version (NaN)" + snapshot["timestamp"] = snapshot["timestamp"].replace(" ", "T") + snapshot["data"]["smart"] = snapshot["data"]["disks"] + snapshot["data"].pop("disks") + snapshot["data"].pop("inxi") + snapshot.pop("erase") + snapshot.pop("token_hash") + lshw = 'sudo lshw -xml' + hwinfo = 'sudo hwinfo --reallyall' + lspci = 'sudo lspci -vv' + + data = { + 'lshw': exec_cmd(lshw) or "{}", + 'hwinfo': exec_cmd(hwinfo), + 'lspci': exec_cmd(lspci) + } + snapshot['data'].update(data) + +## End Legacy Functions ## + + ## Command Functions ## ## Erase Functions ## ## Xavier Functions ## @@ -245,16 +258,13 @@ def smartctl(all_disks, disk=None): # TODO permitir selección # TODO permitir que vaya más rápido def get_data(all_disks): - lshw = 'sudo lshw -json' - hwinfo = 'sudo hwinfo --reallyall' dmidecode = 'sudo dmidecode' - lspci = 'sudo lspci -vv' + inxi = "sudo inxi -afmnGEMABD -x 3 --edid --output json --output-file print" + data = { - 'lshw': exec_cmd(lshw) or "{}", 'disks': smartctl(all_disks), - 'hwinfo': exec_cmd(hwinfo), 'dmidecode': exec_cmd(dmidecode), - 'lspci': exec_cmd(lspci) + 'inxi': exec_cmd(inxi) } return data @@ -266,20 +276,20 @@ def gen_snapshot(all_disks): return snapshot -def save_snapshot_in_disk(snapshot, path): +def save_snapshot_in_disk(snapshot, path, snap_uuid): snapshot_path = os.path.join(path, 'snapshots') filename = "{}/{}_{}.json".format( snapshot_path, datetime.now().strftime("%Y%m%d-%H_%M_%S"), - snapshot['uuid']) + snap_uuid) try: if not os.path.exists(snapshot_path): os.makedirs(snapshot_path) logger.info(_("Created snapshots directory at '%s'"), snapshot_path) with open(filename, "w") as f: - f.write(json.dumps(snapshot)) + f.write(snapshot) logger.info(_("Snapshot written in path '%s'"), filename) except Exception as e: try: @@ -287,21 +297,25 @@ def save_snapshot_in_disk(snapshot, path): fallback_filename = "{}/{}_{}.json".format( path, datetime.now().strftime("%Y%m%d-%H_%M_%S"), - snapshot['uuid']) + snap_uuid) with open(fallback_filename, "w") as f: - f.write(json.dumps(snapshot)) + f.write(snapshot) logger.warning(_("Snapshot written in fallback path '%s'"), fallback_filename) except Exception as e: logger.error(_("Could not save snapshot locally. Reason: Failed to write in fallback path:\n %s"), e) + # TODO sanitize url, if url is like this, it fails # url = 'http://127.0.0.1:8000/api/snapshot/' -def send_snapshot_to_devicehub(snapshot, token, url, legacy): +def send_snapshot_to_devicehub(snapshot, token, url): url_components = urllib.parse.urlparse(url) ev_path = "evidence/{}".format(snapshot["uuid"]) - components = (url_components.scheme, url_components.netloc, ev_path, '', '', '') + components = (url_components.schema, url_components.netloc, ev_path, '', '', '') ev_url = urllib.parse.urlunparse(components) # apt install qrencode + qr = "echo {} | qrencode -t ANSI".format(ev_url) + print(exec_cmd(qr)) + print(ev_url) headers = { "Authorization": f"Bearer {token}", @@ -312,36 +326,15 @@ def send_snapshot_to_devicehub(snapshot, token, url, legacy): request = urllib.request.Request(url, data=data, headers=headers) with urllib.request.urlopen(request) as response: status_code = response.getcode() - response_text = response.read().decode('utf-8') + #response_text = response.read().decode('utf-8') if 200 <= status_code < 300: logger.info(_("Snapshot successfully sent to '%s'"), url) - if legacy: - try: - response = json.loads(response_text) - if response.get('url'): - # apt install qrencode - qr = "echo {} | qrencode -t ANSI".format(response['url']) - print(exec_cmd(qr)) - print("url: {}".format(response['url'])) - if response.get("dhid"): - print("dhid: {}".format(response['dhid'])) - except Exception: - logger.error(response_text) - else: - qr = "echo {} | qrencode -t ANSI".format(ev_url) - print(exec_cmd(qr)) - print(f"url: {ev_url}") else: - logger.error(_("Snapshot %s could not be sent to URL '%s'"), snapshot["uuid"], url) - # TODO review all the try-except thing here; maybe the try inside legacy does not make sense anymore - except urllib.error.HTTPError as e: - error_details = e.read().decode('utf-8') # Get the error response body - logger.error(_("Snapshot %s not remotely sent to URL '%s'. Server responded with error:\n %s"), - snapshot["uuid"], url, error_details) + logger.error(_("Snapshot cannot sent to '%s'"), url) except Exception as e: - logger.error(_("Snapshot %s not remotely sent to URL '%s'. Do you have internet? Is your server up & running? Is the url token authorized?\n %s"), snapshot["uuid"], url, e) + logger.error(_("Snapshot not remotely sent to URL '%s'. Do you have internet? Is your server up & running? Is the url token authorized?\n %s"), url, e) def load_config(config_file="settings.ini"): @@ -428,7 +421,6 @@ def main(): config_file = args.config config = load_config(config_file) - legacy = config.get("legacy") # TODO show warning if non root, means data is not complete # if annotate as potentially invalid snapshot (pending the new API to be done) @@ -437,19 +429,24 @@ def main(): all_disks = get_disks() snapshot = gen_snapshot(all_disks) + snap_uuid = snapshot["uuid"] if config['erase'] and config['device'] and not config.get("legacy"): snapshot['erase'] = gen_erase(all_disks, config['erase'], user_disk=config['device']) elif config['erase'] and not config.get("legacy"): snapshot['erase'] = gen_erase(all_disks, config['erase']) - if legacy: - convert_to_legacy_snapshot(snapshot) - save_snapshot_in_disk(snapshot, config['path']) + if config.get("legacy"): + convert_to_legacy_snapshot(snapshot) + snapshot = json.dumps(snapshot) + else: + snapshot = json.dumps(snapshot) + + save_snapshot_in_disk(snapshot, config['path'], snap_uuid) if config['url']: - send_snapshot_to_devicehub(snapshot, config['token'], config['url'], legacy) + send_snapshot_to_devicehub(snapshot, config['token'], config['url']) logger.info(_("END"))