From 01ce01b1c77a81d3acc32fe7186eb3212d50c089 Mon Sep 17 00:00:00 2001 From: Christian Kellner Date: Sat, 25 Apr 2020 14:17:57 +0200 Subject: [PATCH] stages & assemblers: don't allow additional props Change all the schemata to not allow additional properties. This should help with misspelled properties as well as missing schema information in the stage itself. Done via a small python3 script: --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- import os import sys def list_stages(base): return [(base, f) for f in os.listdir(base) if f.startswith("org.osbuild")] stages = list_stages("stages") stages += list_stages("assemblers") def find_line(lines, start): for i, l in enumerate(lines): if l.startswith(start): return i return None NOADD = '"additionalProperties": false' for stage in stages: with open(f"{stage[0]}/{stage[1]}", "r") as f: print(f"{stage[0]}/{stage[1]}", file=sys.stderr) data = f.readlines() i = find_line(data, 'STAGE_OPTS = """') if i: data.insert(i+1, NOADD + ",\n") else: i = find_line(data, 'STAGE_OPTS = ""') if i: data[i] = f'STAGE_OPTS = """\n' data.insert(i+1, NOADD + "\n") data.insert(i+2, '"""\n') with open(f"{stage[0]}/{stage[1]}", "w") as f: f.writelines(data) --- assemblers/org.osbuild.noop | 4 +++- assemblers/org.osbuild.ostree.commit | 1 + assemblers/org.osbuild.qemu | 1 + assemblers/org.osbuild.rawfs | 1 + assemblers/org.osbuild.tar | 1 + stages/org.osbuild.chrony | 1 + stages/org.osbuild.debug-shell | 1 + stages/org.osbuild.error | 1 + stages/org.osbuild.firewall | 1 + stages/org.osbuild.first-boot | 1 + stages/org.osbuild.fix-bls | 1 + stages/org.osbuild.fstab | 1 + stages/org.osbuild.groups | 1 + stages/org.osbuild.grub2 | 1 + stages/org.osbuild.hostname | 1 + stages/org.osbuild.kernel-cmdline | 1 + stages/org.osbuild.keymap | 1 + stages/org.osbuild.locale | 1 + stages/org.osbuild.noop | 4 +++- stages/org.osbuild.rpm | 1 + stages/org.osbuild.rpm-ostree | 1 + stages/org.osbuild.script | 1 + stages/org.osbuild.selinux | 1 + stages/org.osbuild.systemd | 1 + stages/org.osbuild.test | 1 + stages/org.osbuild.timezone | 1 + stages/org.osbuild.users | 1 + stages/org.osbuild.zipl | 1 + 28 files changed, 32 insertions(+), 2 deletions(-) diff --git a/assemblers/org.osbuild.noop b/assemblers/org.osbuild.noop index 09061305..615ee5f7 100755 --- a/assemblers/org.osbuild.noop +++ b/assemblers/org.osbuild.noop @@ -8,7 +8,9 @@ STAGE_INFO = """ No-op assembler. Produces no output, just prints a JSON dump of its options and then exits. """ -STAGE_OPTS = "" +STAGE_OPTS = """ +"additionalProperties": false +""" def main(_tree, _output_dir, options): print("Not doing anything with these options:", json.dumps(options)) diff --git a/assemblers/org.osbuild.ostree.commit b/assemblers/org.osbuild.ostree.commit index 48b0dcb7..1c640d6b 100755 --- a/assemblers/org.osbuild.ostree.commit +++ b/assemblers/org.osbuild.ostree.commit @@ -22,6 +22,7 @@ the commit id and the compose information respectively. [1] https://ostree.readthedocs.io/en/stable/manual/adapting-existing/ """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["ref"], "properties": { "ref": { diff --git a/assemblers/org.osbuild.qemu b/assemblers/org.osbuild.qemu index c3e29d54..41e94dfb 100755 --- a/assemblers/org.osbuild.qemu +++ b/assemblers/org.osbuild.qemu @@ -30,6 +30,7 @@ Buildhost commands used: `truncate`, `mount`, `umount`, `sfdisk`, `grub2-mkimage`, `mkfs.ext4` or `mkfs.xfs`, `qemu-img`. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["format", "filename", "ptuuid", "size"], "oneOf": [{ "required": ["root_fs_uuid"] diff --git a/assemblers/org.osbuild.rawfs b/assemblers/org.osbuild.rawfs index ae07a059..b8dc5b75 100755 --- a/assemblers/org.osbuild.rawfs +++ b/assemblers/org.osbuild.rawfs @@ -26,6 +26,7 @@ generate with uuid.uuid4() in Python, `uuidgen(1)` in a shell script, or read from `/proc/sys/kernel/random/uuid` if your kernel provides it. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["filename", "root_fs_uuid", "size"], "properties": { "filename": { diff --git a/assemblers/org.osbuild.tar b/assemblers/org.osbuild.tar index 860e7256..17088510 100755 --- a/assemblers/org.osbuild.tar +++ b/assemblers/org.osbuild.tar @@ -22,6 +22,7 @@ caller is responsible for making sure that `compression` and `filename` match. Buildhost commands used: `tar` and any named `compression` program. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["filename"], "properties": { "filename": { diff --git a/stages/org.osbuild.chrony b/stages/org.osbuild.chrony index c5da8ba0..d159966a 100755 --- a/stages/org.osbuild.chrony +++ b/stages/org.osbuild.chrony @@ -11,6 +11,7 @@ Modifies /etc/chrony.conf, removing all "server" or "pool" lines and adding a "server" line for each server listed in `timeservers`. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["timeservers"], "properties": { "timeservers": { diff --git a/stages/org.osbuild.debug-shell b/stages/org.osbuild.debug-shell index f8047fea..56241c0d 100755 --- a/stages/org.osbuild.debug-shell +++ b/stages/org.osbuild.debug-shell @@ -12,6 +12,7 @@ which starts an early-boot root shell on the given `tty`. Also symlinks the service file into /etc/systemd/system/sysinit.target.wants/. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["tty"], "properties": { "tty": { diff --git a/stages/org.osbuild.error b/stages/org.osbuild.error index a615063c..88041dbb 100755 --- a/stages/org.osbuild.error +++ b/stages/org.osbuild.error @@ -9,6 +9,7 @@ Error stage. Return the given error. Useful for testing, debugging, and wasting time. """ STAGE_OPTS = """ +"additionalProperties": false, "properties": { "returncode": { "description": "What to return code to use", diff --git a/stages/org.osbuild.firewall b/stages/org.osbuild.firewall index 225f2516..d5d156cf 100755 --- a/stages/org.osbuild.firewall +++ b/stages/org.osbuild.firewall @@ -29,6 +29,7 @@ target tree, which means it may fail unexpectedly when the buildhost and target are different arches or OSes. """ STAGE_OPTS = """ +"additionalProperties": false, "properties": { "ports": { "description": "Ports (or port ranges) to open", diff --git a/stages/org.osbuild.first-boot b/stages/org.osbuild.first-boot index 1995b50c..c071eb23 100755 --- a/stages/org.osbuild.first-boot +++ b/stages/org.osbuild.first-boot @@ -19,6 +19,7 @@ If the flag-file cannot be removed, the service fails without executing any further first-boot commands. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["commands"], "properties": { "commands": { diff --git a/stages/org.osbuild.fix-bls b/stages/org.osbuild.fix-bls index b7a1780d..2233248b 100755 --- a/stages/org.osbuild.fix-bls +++ b/stages/org.osbuild.fix-bls @@ -22,6 +22,7 @@ By default it is `/boot`, i.e. assumes `/boot` is on the root file-system. This stage reads and (re)writes all .conf files in /boot/loader/entries. """ STAGE_OPTS = """ +"additionalProperties": false, "properties": { "prefix": { "description": "Prefix to use, normally `/boot`", diff --git a/stages/org.osbuild.fstab b/stages/org.osbuild.fstab index 4f69574f..2df985d7 100755 --- a/stages/org.osbuild.fstab +++ b/stages/org.osbuild.fstab @@ -13,6 +13,7 @@ a `path` (mount point). This stage replaces /etc/fstab, removing any existing entries. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["filesystems"], "properties": { "filesystems": { diff --git a/stages/org.osbuild.groups b/stages/org.osbuild.groups index 9be1afd3..dd17170e 100755 --- a/stages/org.osbuild.groups +++ b/stages/org.osbuild.groups @@ -13,6 +13,7 @@ If no `gid` is given, `groupadd` will choose one. If the specified group name or GID is already in use, this stage will fail. """ STAGE_OPTS = """ +"additionalProperties": false, "properties": { "groups": { "type": "object", diff --git a/stages/org.osbuild.grub2 b/stages/org.osbuild.grub2 index 6af2c0a9..60594312 100755 --- a/stages/org.osbuild.grub2 +++ b/stages/org.osbuild.grub2 @@ -42,6 +42,7 @@ and accompanying data can be installed from the built root via `uefi.install`. Both UEFI and Legacy can be specified at the same time. """ STAGE_OPTS = """ +"additionalProperties": false, "oneOf": [{ "required": ["root_fs_uuid"] }, { diff --git a/stages/org.osbuild.hostname b/stages/org.osbuild.hostname index d6c9914b..2e169aa4 100755 --- a/stages/org.osbuild.hostname +++ b/stages/org.osbuild.hostname @@ -14,6 +14,7 @@ buildhost with `--hostname={hostname}`, which checks the validity of the hostname and writes it to /etc/hostname. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["hostname"], "properties": { "hostname": { diff --git a/stages/org.osbuild.kernel-cmdline b/stages/org.osbuild.kernel-cmdline index 5573974d..f1ba73db 100755 --- a/stages/org.osbuild.kernel-cmdline +++ b/stages/org.osbuild.kernel-cmdline @@ -11,6 +11,7 @@ command line. https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html """ STAGE_OPTS = """ +"additionalProperties": false, "properties": { "root_fs_uuid": { "description": "UUID of the root filesystem image", diff --git a/stages/org.osbuild.keymap b/stages/org.osbuild.keymap index 2e31c22c..89f8c1e0 100755 --- a/stages/org.osbuild.keymap +++ b/stages/org.osbuild.keymap @@ -15,6 +15,7 @@ Removes any existing /etc/vconsole.conf, then runs `systemd-firstboot` with the Valid keymaps are generally found in /lib/kbd/keymaps. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["keymap"], "properties": { "keymap": { diff --git a/stages/org.osbuild.locale b/stages/org.osbuild.locale index 41745c15..d65a2dd8 100755 --- a/stages/org.osbuild.locale +++ b/stages/org.osbuild.locale @@ -15,6 +15,7 @@ with the `--locale` flag, which will write a new `/etc/locale.conf` in the target system with `LANG={language}`. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["language"], "properties": { "language": { diff --git a/stages/org.osbuild.noop b/stages/org.osbuild.noop index 69c13065..e77c3439 100755 --- a/stages/org.osbuild.noop +++ b/stages/org.osbuild.noop @@ -8,7 +8,9 @@ STAGE_INFO = """ No-op stage. Prints a JSON dump of the options passed into this stage and leaves the tree untouched. Useful for testing, debugging, and wasting time. """ -STAGE_OPTS = "" +STAGE_OPTS = """ +"additionalProperties": false +""" def main(_tree, options): print("Not doing anything with these options:", json.dumps(options)) diff --git a/stages/org.osbuild.rpm b/stages/org.osbuild.rpm index f9d27ceb..af6caf6e 100755 --- a/stages/org.osbuild.rpm +++ b/stages/org.osbuild.rpm @@ -34,6 +34,7 @@ Uses the following binaries from the host: * `rpm` to install packages into the target tree """ STAGE_OPTS = """ +"additionalProperties": false, "properties": { "gpgkeys": { "description": "Array of GPG key contents to import", diff --git a/stages/org.osbuild.rpm-ostree b/stages/org.osbuild.rpm-ostree index 1047911c..d2e99429 100755 --- a/stages/org.osbuild.rpm-ostree +++ b/stages/org.osbuild.rpm-ostree @@ -38,6 +38,7 @@ human users need to be part of. [2] https://rpm-ostree.readthedocs.io/en/latest/manual/treefile/ """ STAGE_OPTS = """ +"additionalProperties": false, "properties": { "etc_group_members": { "description": "Array of group names to still keep in /etc/group", diff --git a/stages/org.osbuild.script b/stages/org.osbuild.script index 062fad03..bbd9f733 100755 --- a/stages/org.osbuild.script +++ b/stages/org.osbuild.script @@ -25,6 +25,7 @@ through `/bin/sh` in that case, so it might still work, but that behavior is not guaranteed. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["script"], "properties": { "script": { diff --git a/stages/org.osbuild.selinux b/stages/org.osbuild.selinux index ea675409..4cb5c569 100755 --- a/stages/org.osbuild.selinux +++ b/stages/org.osbuild.selinux @@ -24,6 +24,7 @@ labels for newly-created files are determined by the host's SELinux policy and may not match the tree's policy. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["file_contexts"], "properties": { "file_contexts": { diff --git a/stages/org.osbuild.systemd b/stages/org.osbuild.systemd index 8bdbe6ee..0ddf79c5 100755 --- a/stages/org.osbuild.systemd +++ b/stages/org.osbuild.systemd @@ -16,6 +16,7 @@ items, which will delete _all_ symlinks to the named services. Uses `systemctl` from the buildhost. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["enabled_services"], "properties": { "enabled_services": { diff --git a/stages/org.osbuild.test b/stages/org.osbuild.test index 81fce175..7a4a9f88 100755 --- a/stages/org.osbuild.test +++ b/stages/org.osbuild.test @@ -13,6 +13,7 @@ Creates `/etc/systemd/system/osbuild-test.service`, and a symlink to it in `/etc/systemd/system/multi-user.target.wants/`. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["script"], "properties": { "script": { diff --git a/stages/org.osbuild.timezone b/stages/org.osbuild.timezone index c1b92486..4ac01e2c 100755 --- a/stages/org.osbuild.timezone +++ b/stages/org.osbuild.timezone @@ -14,6 +14,7 @@ Removes `/etc/localtime`, then runs the host's `systemd-firstboot` binary with the `--timezone` option, which will re-create `/etc/localtime`. """ STAGE_OPTS = """ +"additionalProperties": false, "required": ["zone"], "properties": { "zone": { diff --git a/stages/org.osbuild.users b/stages/org.osbuild.users index 4c652c72..4c30af4f 100755 --- a/stages/org.osbuild.users +++ b/stages/org.osbuild.users @@ -15,6 +15,7 @@ misbehave if the `usermod`/`useradd` binary inside the tree makes incorrect assumptions about its host system. """ STAGE_OPTS = """ +"additionalProperties": false, "properties": { "users": { "type": "object", diff --git a/stages/org.osbuild.zipl b/stages/org.osbuild.zipl index 9967eba4..efed206c 100755 --- a/stages/org.osbuild.zipl +++ b/stages/org.osbuild.zipl @@ -10,6 +10,7 @@ Configures `zipl` with a minimal config so it can be used in the assembler to write the bootmap and bootloader code. """ STAGE_OPTS = """ +"additionalProperties": false, "properties": { "timeout": { "description": "Boot loader timeout value",