From ca6bcd6548ba67679147adf62e98bf5b40b2b478 Mon Sep 17 00:00:00 2001 From: Francois Dupoux <2386566-fdupoux@users.noreply.gitlab.com> Date: Wed, 26 Jan 2022 20:07:53 +0000 Subject: [PATCH] Implement the primary configuration processing script in lua (#251) --- ChangeLog | 1 + airootfs/etc/initcpio/install/sysrescuecfg | 14 ++ .../etc/systemd/scripts/sysrescue-autorun | 66 ++----- .../systemd/scripts/sysrescue-initialize.py | 172 ++++-------------- .../system/sysrescue-configuration.service | 11 ++ airootfs/root/customize_airootfs.sh | 1 + airootfs/usr/bin/sysrescue-configuration.lua | 171 +++++++++++++++++ mkinitcpio.conf | 4 +- packages | 4 +- patches/archiso-v43-07-yaml-config.patch | 58 +++--- sysrescue.d/100-defaults.yaml | 2 +- 11 files changed, 281 insertions(+), 223 deletions(-) create mode 100644 airootfs/etc/initcpio/install/sysrescuecfg create mode 100644 airootfs/etc/systemd/system/sysrescue-configuration.service create mode 100755 airootfs/usr/bin/sysrescue-configuration.lua diff --git a/ChangeLog b/ChangeLog index 1e3cd8f..0be28ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,7 @@ SystemRescue ChangeLog * Optimized the initramfs compression to reduce the size of the ISO (Gerd v. Egidy) * Added development build option: faster build times but lower compression (Gerd v. Egidy) * Remove Q-Logic Fibrechannel/Infiniband HBA firmware to save space (#256) +* Implemented a script to determine the effective configuration from yaml files (#251) ------------------------------------------------------------------------------- 9.00 (2022-01-16): diff --git a/airootfs/etc/initcpio/install/sysrescuecfg b/airootfs/etc/initcpio/install/sysrescuecfg new file mode 100644 index 0000000..7494bb2 --- /dev/null +++ b/airootfs/etc/initcpio/install/sysrescuecfg @@ -0,0 +1,14 @@ +#!/bin/bash + +build() { + add_file "/usr/bin/sysrescue-configuration.lua" + add_binary "/usr/bin/lua" + add_full_dir "/usr/lib/lua" + add_full_dir "/usr/share/lua" +} + +help() { + cat < added 'ar_attempts' # 2022-01-09: Francois Dupoux --> added support for yaml configuration # 2022-01-09: Francois Dupoux --> option 'autoruns=' renamed 'ar_suffixes=' +# 2022-01-23: Francois Dupoux --> use the generated effective configuration file # # ----------------------- autorun exec rules: --------------------------------- # - pass 'ar_source=/dev/fd#' to request floppy device test @@ -29,7 +30,7 @@ # - if option 'ar_ignorefail' is used, do not stop autorun if a script failed # - if option 'ar_disable' is used, absolutely no autorun script will be run -import sys, os, re, subprocess, logging, time, glob, yaml +import sys, os, re, subprocess, logging, time, glob, json # ------------------------ initialize internal variables ----------------------- pidfile='/run/autorun.pid' @@ -38,18 +39,9 @@ autorunlog=basedir+'/log' autorunmnt=basedir+'/mnt' autoruntmp=basedir+'/tmp' defaultsrc=['/run/archiso/bootmnt/autorun','/run/archiso/bootmnt','/run/archiso/copytoram/autorun','/run/archiso/copytoram','/var/autorun/cdrom','/root','/usr/share/sys.autorun'] +effectivecfg="/etc/sysrescue/sysrescue-effective-config.json" autorunfiles=[] - -# ------------------------ default autorun parameters -------------------------- -config = { - 'ar_disable': False, - 'ar_nowait': False, - 'ar_nodel': False, - 'ar_ignorefail': False, - 'ar_attempts': 1, - 'ar_source': '', - 'ar_suffixes': ','.join(list('0123456789ABCDEF')), -} +config = {} # ----------------------- functions definitions -------------------------------- def writemsg(message): @@ -103,54 +95,24 @@ def search_autoruns(dirname, suffixes, copyfilefct): found+=1 return found -def parse_config_file(yamlfile): - logging.info(f"Parsing yaml file: {yamlfile} ...") - with open(yamlfile) as myfile: - try: - curconfig = yaml.safe_load(myfile) - if 'autorun' in curconfig: - curautorun = curconfig['autorun'] - for entry in config: - if entry in curautorun: - config[entry] = curautorun[entry] - return True - except yaml.YAMLError as err: - writemsg(err) - return False - def main(): errcnt=0 # in case no autorun executed logging.basicConfig(filename='/var/log/sysrescue-autorun.log', format='%(asctime)s %(message)s', level=logging.DEBUG) writemsg('Initializing autorun ...') - # ---- parse options passed in the configuration file - writemsg(f"Loading configuration from yaml files located on the boot device ...") - yamlconfdirs = ["/run/archiso/bootmnt/sysrescue.d", "/run/archiso/copytoram/sysrescue.d"] - for yamlconfdir in yamlconfdirs: - if os.path.isdir(yamlconfdir): - conffiles = glob.glob(os.path.join(yamlconfdir, '*.[Yy][Aa][Mm][Ll]'), recursive=True) - conffiles.sort() # Load yaml files in the alphabetical order - for curfile in conffiles: - parse_config_file(curfile) + # ---- read the effective configuration file + if os.path.exists(effectivecfg) == False: + print (f"Failed to find effective configuration file in {effectivecfg}") + sys.exit(1) + with open(effectivecfg) as file: + fullcfg = json.load(file) + config = fullcfg['autorun'] + #print(json.dumps(config, indent=4)) - # ---- parse options passed on the boot command line + # ---- parse legacy options passed on the boot command line for curopt in open("/proc/cmdline","r").read().split(): - if re.match('^ar_nowait$', curopt): - config['ar_nowait'] = True - if re.match('^ar_nodel$', curopt): - config['ar_nodel'] = True - if re.match('^ar_ignorefail$', curopt): - config['ar_ignorefail'] = True - if re.match('^ar_disable$', curopt): - config['ar_disable'] = True - if re.match('^ar_source=', curopt): - config['ar_source'] = curopt.replace('ar_source=','') - if re.match(r'^ar_attempts=\d+$', curopt): - config['ar_attempts'] = int(curopt.replace('ar_attempts=','')) - if re.match('^autoruns=', curopt): # Legacy name for 'ar_suffixes' + if re.match('^autoruns=', curopt): # "autoruns" is the legacy name for 'ar_suffixes' config['ar_suffixes'] = curopt.replace('autoruns=','') - if re.match('^ar_suffixes=', curopt): # New name for 'autoruns' - config['ar_suffixes'] = curopt.replace('ar_suffixes=','') # ---- show the effective configuration logging.info(f"Showing the effective autorun configuration ...") diff --git a/airootfs/etc/systemd/scripts/sysrescue-initialize.py b/airootfs/etc/systemd/scripts/sysrescue-initialize.py index 0ebb3f4..078cdb2 100755 --- a/airootfs/etc/systemd/scripts/sysrescue-initialize.py +++ b/airootfs/etc/systemd/scripts/sysrescue-initialize.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later import subprocess -import yaml +import json import glob import os import sys @@ -16,131 +16,28 @@ print(f"====> Script {sys.argv[0]} starting ...") errcnt = 0 # ============================================================================== -# Define the default configuration +# Read the effective configuration file # ============================================================================== -config_global = { - 'dostartx': False, - 'dovnc': False, - 'noautologin': False, - 'nofirewall': False, - 'rootshell': None, - 'rootpass': None, - 'rootcryptpass': None, - 'setkmap': None, - 'vncpass': None, -} +print(f"====> Read the effective configuration file ...") +effectivecfg = "/etc/sysrescue/sysrescue-effective-config.json" +if os.path.exists(effectivecfg) == False: + print (f"Failed to find effective configuration file in {effectivecfg}") + sys.exit(1) -config_ca_trust = { } - -# ============================================================================== -# Load configuration from the yaml files -# ============================================================================== -print(f"====> Loading configuration from yaml files located on the boot device ...") -yamlconfdirs = ["/run/archiso/bootmnt/sysrescue.d", "/run/archiso/copytoram/sysrescue.d"] - -def parse_config_file(yamlfile): - print(f"Parsing yaml file: {yamlfile} ...") - with open(yamlfile) as myfile: - try: - curconfig = yaml.safe_load(myfile) - if 'global' in curconfig: - curglobal = curconfig['global'] - for entry in config_global: - if entry in curglobal: - config_global[entry] = curglobal[entry] - if 'ca-trust' in curconfig: - # later yaml files take precedence, overwrite if existing - for key, value in curconfig['ca-trust'].items(): - config_ca_trust[key] = value - return True - except yaml.YAMLError as err: - print(err) - errcnt+=1 - return False - -for yamlconfdir in yamlconfdirs: - if os.path.isdir(yamlconfdir): - conffiles = glob.glob(os.path.join(yamlconfdir, '*.[Yy][Aa][Mm][Ll]'), recursive=True) - conffiles.sort() # Load yaml files in the alphabetical order - for curfile in conffiles: - parse_config_file(curfile) - -# ============================================================================== -# Load configuration from the boot command line -# ============================================================================== -print(f"====> Parsing configuration from the boot command line ...") - -bootcmdline = open("/proc/cmdline","r").readline() -bootopts = bootcmdline.split() - -for curopt in bootopts: - - # Configure keyboard layout - match = re.search(r"^setkmap=(\S+)$", curopt) - if match != None: - print(f"Found option '{curopt}' on the boot command line") - config_global['setkmap'] = match.group(1) - - # Configure root login shell - match = re.search(r"^rootshell=(\S+)$", curopt) - if match != None: - print(f"Found option '{curopt}' on the boot command line") - config_global['rootshell'] = match.group(1) - - # Set the system root password from a clear password - match = re.search(r"^rootpass=(\S+)$", curopt) - if match != None: - print(f"Found option 'rootpass=******' on the boot command line") - config_global['rootpass'] = match.group(1) - - # Set the system root password from an encrypted password - match = re.search(r"^rootcryptpass=(\S+)$", curopt) - if match != None: - print(f"Found option 'rootcryptpass=******' on the boot command line") - config_global['rootcryptpass'] = match.group(1) - - # Disable the firewall - match = re.search(r"^nofirewall$", curopt) - if match != None: - print(f"Found option '{curopt}' on the boot command line") - config_global['nofirewall'] = True - - # Auto-start the graphical environment (tty1 only), dovnc implies dostartx - match = re.search(r"^dostartx$", curopt) - if match != None: - print(f"Found option '{curopt}' on the boot command line") - config_global['dostartx'] = True - - # Require authenticated console access - match = re.search(r"^noautologin$", curopt) - if match != None: - print(f"Found option '{curopt}' on the boot command line") - config_global['noautologin'] = True - - # Set the VNC password from a clear password - match = re.search(r"^vncpass=(\S+)$", curopt) - if match != None: - print(f"Found option 'vncpass=******' on the boot command line") - config_global['vncpass'] = match.group(1) - - # Auto-start x11vnc with the graphical environment, "dovnc" implies "dostartx" - match = re.search(r"^dovnc$", curopt) - if match != None: - print(f"Found option '{curopt}' on the boot command line") - config_global['dovnc'] = True - config_global['dostartx'] = True +with open(effectivecfg) as file: + config = json.load(file) # ============================================================================== # Show the effective configuration # ============================================================================== print(f"====> Showing the effective global configuration (except clear passwords) ...") -print(f"config['setkmap']={config_global['setkmap']}") -print(f"config['rootshell']={config_global['rootshell']}") -print(f"config['rootcryptpass']={config_global['rootcryptpass']}") -print(f"config['nofirewall']={config_global['nofirewall']}") -print(f"config['dostartx']={config_global['dostartx']}") -print(f"config['noautologin']={config_global['noautologin']}") -print(f"config['dovnc']={config_global['dovnc']}") +print(f"config['global']['setkmap']='{config['global']['setkmap']}'") +print(f"config['global']['rootshell']='{config['global']['rootshell']}'") +print(f"config['global']['rootcryptpass']='{config['global']['rootcryptpass']}'") +print(f"config['global']['nofirewall']={config['global']['nofirewall']}") +print(f"config['global']['dostartx']={config['global']['dostartx']}") +print(f"config['global']['noautologin']={config['global']['noautologin']}") +print(f"config['global']['dovnc']={config['global']['dovnc']}") # ============================================================================== # Apply the effective configuration @@ -148,8 +45,9 @@ print(f"config['dovnc']={config_global['dovnc']}") print(f"====> Applying configuration ...") # Configure keyboard layout if requested in the configuration -if config_global['setkmap'] != None: - p = subprocess.run(["localectl", "set-keymap", config_global['setkmap']], text=True) +setkmap = config['global']['setkmap'] +if (setkmap != None) and (setkmap != ""): + p = subprocess.run(["localectl", "set-keymap", setkmap], text=True) if p.returncode == 0: print (f"Have changed the keymap successfully") else: @@ -157,8 +55,9 @@ if config_global['setkmap'] != None: errcnt+=1 # Configure root login shell if requested in the configuration -if config_global['rootshell'] != None: - p = subprocess.run(["chsh", "--shell", config_global['rootshell'], "root"], text=True) +rootshell = config['global']['rootshell'] +if (rootshell != None) and (rootshell != ""): + p = subprocess.run(["chsh", "--shell", rootshell, "root"], text=True) if p.returncode == 0: print (f"Have changed the root shell successfully") else: @@ -166,8 +65,9 @@ if config_global['rootshell'] != None: errcnt+=1 # Set the system root password from a clear password -if config_global['rootpass'] != None: - p = subprocess.run(["chpasswd", "--crypt-method", "SHA512"], text=True, input=f"root:{config_global['rootpass']}") +rootpass = config['global']['rootpass'] +if (rootpass != None) and (rootpass != ""): + p = subprocess.run(["chpasswd", "--crypt-method", "SHA512"], text=True, input=f"root:{rootpass}") if p.returncode == 0: print (f"Have changed the root password successfully") else: @@ -177,8 +77,9 @@ if config_global['rootpass'] != None: # Set the system root password from an encrypted password # A password can be encrypted using a one-line python3 command such as: # python3 -c 'import crypt; print(crypt.crypt("MyPassWord123", crypt.mksalt(crypt.METHOD_SHA512)))' -if config_global['rootcryptpass'] != None: - p = subprocess.run(["chpasswd", "--encrypted"], text=True, input=f"root:{config_global['rootcryptpass']}") +rootcryptpass = config['global']['rootcryptpass'] +if (rootcryptpass != None) and (rootcryptpass != ""): + p = subprocess.run(["chpasswd", "--encrypted"], text=True, input=f"root:{rootcryptpass}") if p.returncode == 0: print (f"Have changed the root password successfully") else: @@ -186,7 +87,7 @@ if config_global['rootcryptpass'] != None: errcnt+=1 # Disable the firewall -if config_global['nofirewall'] == True: +if config['global']['nofirewall'] == True: # The firewall service(s) must be in the Before-section of sysrescue-initialize.service p = subprocess.run(["systemctl", "disable", "--now", "iptables.service", "ip6tables.service"], text=True) if p.returncode == 0: @@ -196,7 +97,7 @@ if config_global['nofirewall'] == True: errcnt+=1 # Auto-start the graphical environment (tty1 only) -if config_global['dostartx'] == True: +if config['global']['dostartx'] == True: str = '[[ ! $DISPLAY ]] && [[ ! $SSH_TTY ]] && [[ $XDG_VTNR == 1 ]] && startx' if (os.path.exists("/root/.bash_profile") == False) or (open("/root/.bash_profile", 'r').read().find(str) == -1): file1 = open("/root/.bash_profile", "a") @@ -207,7 +108,7 @@ if config_global['dostartx'] == True: file2.close() # Require authenticated console access -if config_global['noautologin'] == True: +if config['global']['noautologin'] == True: p = subprocess.run(["systemctl", "revert", "getty@.service", "serial-getty@.service"], text=True) if p.returncode == 0: print (f"Have enabled authenticated console access successfully") @@ -216,9 +117,10 @@ if config_global['noautologin'] == True: errcnt+=1 # Set the VNC password from a clear password -if config_global['vncpass'] != None: +vncpass = config['global']['vncpass'] +if (vncpass != None) and (vncpass != ""): os.makedirs("/root/.vnc", exist_ok = True) - p = subprocess.run(["x11vnc", "-storepasswd", config_global['vncpass'], "/root/.vnc/passwd"], text=True) + p = subprocess.run(["x11vnc", "-storepasswd", vncpass, "/root/.vnc/passwd"], text=True) if p.returncode == 0: print (f"Have changed the vnc password successfully") else: @@ -226,7 +128,7 @@ if config_global['vncpass'] != None: errcnt+=1 # Auto-start x11vnc with the graphical environment -if config_global['dovnc'] == True: +if config['global']['dovnc'] == True: print (f"Enabling VNC Server in /root/.xprofile ...") file = open("/root/.xprofile", "w") file.write("""[ -f ~/.vnc/passwd ] && pwopt="-usepw" || pwopt="-nopw"\n""") @@ -238,10 +140,10 @@ if config_global['dovnc'] == True: # ============================================================================== ca_anchor_path = "/etc/ca-certificates/trust-source/anchors/" -if config_ca_trust: +if config['ca-trust']: print(f"====> Adding trusted CA certificates ...") - for name, cert in sorted(config_ca_trust.items()): + for name, cert in sorted(config['ca-trust'].items()): print (f"Adding certificate '{name}' ...") with open(os.path.join(ca_anchor_path, name + ".pem"), "w") as certfile: certfile.write(cert) diff --git a/airootfs/etc/systemd/system/sysrescue-configuration.service b/airootfs/etc/systemd/system/sysrescue-configuration.service new file mode 100644 index 0000000..57641b9 --- /dev/null +++ b/airootfs/etc/systemd/system/sysrescue-configuration.service @@ -0,0 +1,11 @@ +[Unit] +Description=Determine SystemRescue effective configuration +Before=sysrescue-initialize + +[Service] +Type=oneshot +ExecStart=/usr/bin/sysrescue-configuration.lua +RemainAfterExit=true + +[Install] +WantedBy=multi-user.target diff --git a/airootfs/root/customize_airootfs.sh b/airootfs/root/customize_airootfs.sh index 2e6dd9a..c32ec1e 100755 --- a/airootfs/root/customize_airootfs.sh +++ b/airootfs/root/customize_airootfs.sh @@ -34,6 +34,7 @@ systemctl enable ip6tables.service systemctl enable pacman-init.service systemctl enable choose-mirror.service systemctl enable sshd.service +systemctl enable sysrescue-configuration.service systemctl enable sysrescue-initialize.service systemctl enable sysrescue-autorun.service systemctl enable qemu-guest-agent.service diff --git a/airootfs/usr/bin/sysrescue-configuration.lua b/airootfs/usr/bin/sysrescue-configuration.lua new file mode 100755 index 0000000..defd476 --- /dev/null +++ b/airootfs/usr/bin/sysrescue-configuration.lua @@ -0,0 +1,171 @@ +#!/usr/bin/env lua +-- +-- Author: Francois Dupoux +-- SPDX-License-Identifier: GPL-3.0-or-later +-- +-- SystemRescue configuration processing script +-- +-- This script uses the SystemRescue yaml configuration files and the options +-- passed on the boot command line to override the default configuration. +-- It processes yaml configuration files in the alphabetical order, and each option +-- found in a file override the options defined earlier. Options passed on the +-- boot command like take precedence over configuration options defined in files. +-- At the end it writes the effective configuration to a JSON file which is meant +-- to be ready by any initialisation script which needs to know the configuration. +-- Shell scripts can read values from the JSON file using a command such as: +-- jq --raw-output '.global.copytoram' /etc/sysrescue/sysrescue-effective-config.json +-- This script requires the following lua packages to run on Arch Linux: +-- sudo pacman -Sy lua lua-yaml lua-dkjson + +-- ============================================================================== +-- Import modules +-- ============================================================================== +local lfs = require('lfs') +local yaml = require('yaml') +local json = require("dkjson") + +-- ============================================================================== +-- Utility functions +-- ============================================================================== +function read_file_contents(path) + local file = io.open(path, "rb") + if not file then + return nil + end + local content = file:read("*a") + file:close() + return content +end + +function list_config_files(path) + local results = {} + for curfile in lfs.dir(path) do + fullpath = path.."/"..curfile + filetype = lfs.attributes(fullpath, "mode") + if filetype == "file" and curfile:match(".[Yy][Aa][Mm][Ll]$") then + table.insert(results, fullpath) + end + end + table.sort(results) + return results +end + +-- ============================================================================== +-- Define the default configuration +-- ============================================================================== +print ("====> Define the default configuration ...") +config = { + ["global"] = { + ['copytoram'] = false, + ['checksum'] = false, + ['loadsrm'] = false, + ['dostartx'] = false, + ['dovnc'] = false, + ['noautologin'] = false, + ['nofirewall'] = false, + ['rootshell'] = "", + ['rootpass'] = "", + ['rootcryptpass'] = "", + ['setkmap'] = "", + ['vncpass'] = "", + }, + ["autorun"] = { + ['ar_disable'] = false, + ['ar_nowait'] = false, + ['ar_nodel'] = false, + ['ar_ignorefail'] = false, + ['ar_attempts'] = false, + ['ar_source'] = "", + ['ar_suffixes'] = "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F", + }, + ["ca-trust"] = {}, +} + +-- ============================================================================== +-- Override the configuration with values from yaml files +-- ============================================================================== +print ("====> Overriding the default configuration with values from yaml files ...") +yamlconfdirs = {"/run/archiso/bootmnt/sysrescue.d", "/run/archiso/copytoram/sysrescue.d"} +for _, confdir in ipairs(yamlconfdirs) do + if lfs.attributes(confdir, "mode") == "directory" then + print("Searching for yaml configuration files in "..confdir.." ...") + for _, curfile in ipairs(list_config_files(confdir)) do + print("Processing yaml configuration file: "..curfile.." ...") + local curconfig = yaml.loadpath(curfile) + --print("++++++++++++++\n"..yaml.dump(curconfig).."++++++++++++++\n") + if curconfig ~= nil then + -- Override specific pre-defined options + for _, scope in ipairs({"global", "autorun"}) do + for key, val in pairs(config[scope]) do + if (curconfig[scope] ~= nil) and (curconfig[scope][key] ~= nil) then + print("- Overriding config['"..scope.."']['"..key.."'] with the value from the yaml file") + config[scope][key] = curconfig[scope][key] + end + end + end + -- Populate additional items + for _, scope in ipairs({"ca-trust"}) do + if curconfig[scope] ~= nil then + for key, val in pairs(curconfig[scope]) do + print("- Setting config['"..scope.."']['"..key.."'] with the value from the yaml file") + config[scope][key] = val + end + end + end + end + end + else + print("Directory "..confdir.." was not found so it has been ignored") + end +end + +-- ============================================================================== +-- Override the configuration with values passed on the boot command line +-- ============================================================================== +print ("====> Overriding the configuration with options passed on the boot command line ...") +local cmdline = read_file_contents("/proc/cmdline"); +for curopt in cmdline:gmatch("%S+") do + --print ("Found option on the boot command line: "..curopt) + for _, scope in ipairs({"global", "autorun"}) do + for key,val in pairs(config[scope]) do + optmatch1 = string.match(curopt, "^"..key.."$") + _, _, optmatch2 = string.find(curopt, "^"..key.."=([^%s]+)$") + if type(val) == "boolean" then + if (optmatch1 ~= nil) or (optmatch2 == 'y') or (optmatch2 == 'yes') or (optmatch2 == 'true') then + print("- Option '"..key.."' has been enabled on the boot command line") + config[scope][key] = true + elseif (optmatch2 == 'n') or (optmatch2 == 'no') or (optmatch2 == 'false') then + print("- Option '"..key.."' has been disabled on the boot command line") + config[scope][key] = false + end + else + if optmatch2 ~= nil then + print("- Option '"..key.."' has been defined on the boot command line") + config[scope][key] = optmatch2 + end + end + end + end +end + +-- ============================================================================== +-- Print the effective configuration +-- ============================================================================== +print ("====> Printing the effective configuration") +local jsoncfgtxt = json.encode (config, { indent = true }) +print (jsoncfgtxt) + +-- ============================================================================== +-- Write the effective configuration to a JSON file +-- ============================================================================== +print ("====> Writing the effective configuration to a JSON file ...") +output_location = "/etc/sysrescue" +output_filename = "sysrescue-effective-config.json" +output_fullpath = output_location.."/"..output_filename +lfs.mkdir(output_location) +jsoncfgfile = io.open(output_fullpath, "w") +jsoncfgfile:write(jsoncfgtxt) +jsoncfgfile:close() +os.execute("chmod 700 "..output_location) +os.execute("chmod 600 "..output_fullpath) +print ("Effective configuration has been written to "..output_fullpath) diff --git a/mkinitcpio.conf b/mkinitcpio.conf index dd2ad5d..fdac3e4 100644 --- a/mkinitcpio.conf +++ b/mkinitcpio.conf @@ -1,6 +1,6 @@ MODULES=(fuse) -BINARIES=(aq jq mount.ntfs) -HOOKS=(base udev memdisk findroot archiso archiso_loop_mnt archiso_pxe_common archiso_pxe_nbd archiso_pxe_http archiso_pxe_nfs archiso_kms block mdadm_udev modconf encrypt lvm2 filesystems keyboard) +BINARIES=(jq mount.ntfs) +HOOKS=(base udev memdisk sysrescuecfg findroot archiso archiso_loop_mnt archiso_pxe_common archiso_pxe_nbd archiso_pxe_http archiso_pxe_nfs archiso_kms block mdadm_udev modconf encrypt lvm2 filesystems keyboard) COMPRESSION_RELEASE="xz" COMPRESSION_OPTIONS_RELEASE="--threads=0 --lzma2=preset=9e,dict=128MiB --verbose" COMPRESSION_DEVEL="zstd" diff --git a/packages b/packages index e351c07..72d7a48 100644 --- a/packages +++ b/packages @@ -1,4 +1,3 @@ -aq alsa-utils amd-ucode archinstall @@ -97,6 +96,7 @@ ipw2100-fw ipw2200-fw irssi jfsutils +jq keepassxc less lftp @@ -113,6 +113,8 @@ lshw lsof lsscsi lua +lua-dkjson +lua-yaml lvm2 lz4 lzip diff --git a/patches/archiso-v43-07-yaml-config.patch b/patches/archiso-v43-07-yaml-config.patch index 1c07053..5cc953b 100644 --- a/patches/archiso-v43-07-yaml-config.patch +++ b/patches/archiso-v43-07-yaml-config.patch @@ -1,42 +1,36 @@ diff --git a/archiso/initcpio/hooks/archiso b/archiso/initcpio/hooks/archiso -index 51dfcc1..fe709cf 100644 +index 853652e..53215eb 100644 --- a/archiso/initcpio/hooks/archiso +++ b/archiso/initcpio/hooks/archiso -@@ -197,6 +197,38 @@ archiso_mount_handler() { +@@ -197,6 +197,32 @@ archiso_mount_handler() { fi fi - -+ msg ":: Attempt to read configuration from yaml files ..." -+ -+ if ls -l /run/archiso/bootmnt/sysrescue.d/*.[Yy][Aa][Mm][Ll] >/dev/null 2>/dev/null + ++ msg ":: Execute the configuration processing script ..." ++ jsonconfig="/etc/sysrescue/sysrescue-effective-config.json" ++ if ! /usr/bin/sysrescue-configuration.lua > /tmp/sysrescue-configuration.log 2>&1 + then -+ echo "Found yaml files in /run/archiso/bootmnt/sysrescue.d" -+ for curfile in /run/archiso/bootmnt/sysrescue.d/*.[Yy][Aa][Mm][Ll] -+ do -+ echo "Parsing ${curfile} ..." -+ shortname=$(basename ${curfile}) -+ -+ # Attempt to find boolean entries in the yaml configuration file -+ for curentry in "copytoram" "checksum" "loadsrm" -+ do -+ if value=$(cat ${curfile} | aq -i yaml -o toml ".global.${curentry}" 2>/dev/null) -+ then -+ if [[ "${value}" == 'true' ]] || [[ "${value}" == 'y' ]] || [[ "${value}" == 'yes' ]] -+ then -+ echo "Entry '.global.${curentry}' enabled in config: value='${value}'" -+ eval "${curentry}='y'" -+ elif [[ "${value}" == 'false' ]] || [[ "${value}" == 'n' ]] || [[ "${value}" == 'no' ]] -+ then -+ echo "Entry '.global.${curentry}' disabled in config: value='${value}'" -+ # Do not change curentry as this would override values passed using the boot command line -+ else -+ echo "ERROR: Found invalid value for '.global.${curentry}': value='${value}'" -+ sleep 8 -+ fi -+ fi -+ done -+ done ++ echo "ERROR: The configuration processing script has failed" ++ cat /tmp/sysrescue-configuration.log ++ sleep 20 + fi ++ ++ msg ":: Define early boot options based on the configuration ..." ++ for curentry in "copytoram" "checksum" "loadsrm" ++ do ++ if value=$(jq --raw-output ".global.${curentry}" ${jsonconfig} 2>/dev/null) ++ then ++ if [[ "${value}" == 'true' ]]; then ++ echo "Entry '.global.${curentry}' enabled in config: value='${value}'" ++ eval "${curentry}='y'" ++ elif [[ "${value}" == 'false' ]]; then ++ echo "Entry '.global.${curentry}' disabled in config: value='${value}'" ++ else ++ echo "ERROR: Found invalid value for '.global.${curentry}': value='${value}'" ++ sleep 8 ++ fi ++ fi ++ done + if [[ "${checksum}" == "y" ]]; then if [[ -f "/run/archiso/bootmnt/${archisobasedir}/${arch}/airootfs.sha512" ]]; then diff --git a/sysrescue.d/100-defaults.yaml b/sysrescue.d/100-defaults.yaml index 01fc7cf..05e4ef2 100644 --- a/sysrescue.d/100-defaults.yaml +++ b/sysrescue.d/100-defaults.yaml @@ -12,4 +12,4 @@ autorun: ar_nodel: false ar_attempts: 1 ar_ignorefail: false - ar_suffixes: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F + ar_suffixes: "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F"