From c09ae9bd1624224e269ea68fe9b19900232b9df8 Mon Sep 17 00:00:00 2001 From: Antonio Murdaca Date: Fri, 7 Oct 2022 16:07:51 +0200 Subject: [PATCH] distro/rhel: make edge images properly sysroot.readonly=true Make edge raw images (both the raw image type and the same in the edge simplified installer) mount the /sysroot as read-only. This was already done in Fedora 37+ (547f7a66b3bcbb9cc498ed1b4db23a081883bc49). Copied commit message from 6f89e9d49956102fdeddd441fbc6e9f50f27ae92 to a comment in all places where the accompanying "rw" kernel option is set explaining the requirement, since the option is counter-intuitive. Signed-off-by: Antonio Murdaca Signed-off-by: Antonio Murdaca Co-Authored-By: Achilleas Koutsou --- internal/distro/fedora/images.go | 2 ++ internal/distro/rhel8/pipelines.go | 5 ++- internal/distro/rhel9/images.go | 8 +++-- test/cases/ostree-raw-image.sh | 6 ++-- test/cases/ostree-simplified-installer.sh | 10 +++--- test/data/ansible/check_ostree.yaml | 37 ++++++++++++++++++----- 6 files changed, 49 insertions(+), 19 deletions(-) diff --git a/internal/distro/fedora/images.go b/internal/distro/fedora/images.go index b1c95c4c913..23e70e92c60 100644 --- a/internal/distro/fedora/images.go +++ b/internal/distro/fedora/images.go @@ -365,6 +365,8 @@ func iotRawImage(workload workload.Workload, img.Users = users.UsersFromBP(customizations.GetUsers()) img.Groups = users.GroupsFromBP(customizations.GetGroups()) + // "rw" kernel option is required when /sysroot is mounted read-only to + // keep stateful parts of the filesystem writeable (/var/ and /etc) img.KernelOptionsAppend = []string{"modprobe.blacklist=vc4", "rw"} img.Keyboard = "us" img.Locale = "C.UTF-8" diff --git a/internal/distro/rhel8/pipelines.go b/internal/distro/rhel8/pipelines.go index a125bcbe1df..7293c2b9ac2 100644 --- a/internal/distro/rhel8/pipelines.go +++ b/internal/distro/rhel8/pipelines.go @@ -953,9 +953,12 @@ func ostreeDeployPipeline( OSName: osname, }, )) - p.AddStage(osbuild.NewOSTreeConfigStage(ostreeConfigStageOptions(repoPath, false))) + p.AddStage(osbuild.NewOSTreeConfigStage(ostreeConfigStageOptions(repoPath, true))) p.AddStage(osbuild.NewMkdirStage(efiMkdirStageOptions())) kernelOpts := osbuild.GenImageKernelOptions(pt) + // "rw" kernel option is required when /sysroot is mounted read-only to + // keep stateful parts of the filesystem writeable (/var/ and /etc) + kernelOpts = append(kernelOpts, "rw") p.AddStage(osbuild.NewOSTreeDeployStage( &osbuild.OSTreeDeployStageOptions{ OsName: osname, diff --git a/internal/distro/rhel9/images.go b/internal/distro/rhel9/images.go index f5e87c1490a..05f010a5fb8 100644 --- a/internal/distro/rhel9/images.go +++ b/internal/distro/rhel9/images.go @@ -317,9 +317,10 @@ func edgeRawImage(workload workload.Workload, img.Users = users.UsersFromBP(customizations.GetUsers()) img.Groups = users.GroupsFromBP(customizations.GetGroups()) - img.KernelOptionsAppend = []string{"modprobe.blacklist=vc4"} + img.KernelOptionsAppend = []string{"modprobe.blacklist=vc4", "rw"} img.Keyboard = "us" img.Locale = "C.UTF-8" + img.SysrootReadOnly = true img.Platform = t.platform img.Workload = workload @@ -361,9 +362,12 @@ func edgeSimplifiedInstallerImage(workload workload.Workload, rawImg.Users = users.UsersFromBP(customizations.GetUsers()) rawImg.Groups = users.GroupsFromBP(customizations.GetGroups()) - rawImg.KernelOptionsAppend = []string{"modprobe.blacklist=vc4"} + // "rw" kernel option is required when /sysroot is mounted read-only to + // keep stateful parts of the filesystem writeable (/var/ and /etc) + rawImg.KernelOptionsAppend = []string{"modprobe.blacklist=vc4", "rw"} rawImg.Keyboard = "us" rawImg.Locale = "C.UTF-8" + rawImg.SysrootReadOnly = true rawImg.Platform = t.platform rawImg.Workload = workload diff --git a/test/cases/ostree-raw-image.sh b/test/cases/ostree-raw-image.sh index 57171511589..243307ed611 100755 --- a/test/cases/ostree-raw-image.sh +++ b/test/cases/ostree-raw-image.sh @@ -491,7 +491,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD} EOF # Test IoT/Edge OS - sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type="${OSTREE_OSNAME}" -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 + sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type="${OSTREE_OSNAME}" -e edge_type=edge-raw-image -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 check_result # Clean up BIOS VM @@ -567,7 +567,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD} EOF # Test IoT/Edge OS -sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type="${OSTREE_OSNAME}" -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 +sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type="${OSTREE_OSNAME}" -e edge_type=edge-raw-image -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 check_result ################################################################## @@ -721,7 +721,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD} EOF # Test IoT/Edge OS -sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type="${OSTREE_OSNAME}" -e ostree_commit="${UPGRADE_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 +sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type="${OSTREE_OSNAME}" -e edge_type=edge-raw-image -e ostree_commit="${UPGRADE_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 check_result # Final success clean up diff --git a/test/cases/ostree-simplified-installer.sh b/test/cases/ostree-simplified-installer.sh index ed840960810..f4d21b19fcd 100755 --- a/test/cases/ostree-simplified-installer.sh +++ b/test/cases/ostree-simplified-installer.sh @@ -519,7 +519,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD} EOF # Test IoT/Edge OS -sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" -e fdo_credential="true" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 +sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" -e edge_type=edge-simplified-installer -e fdo_credential="true" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 check_result # Clean up BIOS VM @@ -643,7 +643,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD} EOF # Test IoT/Edge OS -sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" -e fdo_credential="true" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 +sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" -e edge_type=edge-simplified-installer -e fdo_credential="true" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 check_result # Clean up BIOS VM @@ -765,7 +765,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD} EOF # Test IoT/Edge OS -sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" -e fdo_credential="true" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 +sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" -e edge_type=edge-simplified-installer -e fdo_credential="true" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 check_result greenprint "🧹 Clean up VM" @@ -882,7 +882,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD} EOF # Test IoT/Edge OS -sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" -e fdo_credential="false" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 +sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" -e edge_type=edge-simplified-installer -e fdo_credential="false" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 check_result ######################## @@ -1016,7 +1016,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD} EOF # Test IoT/Edge OS -sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${UPGRADE_HASH}" -e fdo_credential="false" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 +sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${UPGRADE_HASH}" -e edge_type=edge-simplified-installer -e fdo_credential="false" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0 check_result # Final success clean up diff --git a/test/data/ansible/check_ostree.yaml b/test/data/ansible/check_ostree.yaml index 96919b737e4..c8313c4d16b 100644 --- a/test/data/ansible/check_ostree.yaml +++ b/test/data/ansible/check_ostree.yaml @@ -5,6 +5,7 @@ workspace: "{{ lookup('env', 'WORKSPACE') }}" skip_rollback_test: "false" fdo_credential: "false" + edge_type: "none" embeded_container: "false" total_counter: "0" failed_counter: "0" @@ -232,7 +233,28 @@ shell: findmnt -r -o OPTIONS -n /sysroot | awk -F "," '{print $1}' register: result_sysroot_mount_status - - name: /sysroot should be mount with rw permission + # https://fedoraproject.org/wiki/Changes/Silverblue_Kinoite_readonly_sysroot + # There are three checks here for /sysroot permission based on pr https://github.com/osbuild/osbuild-composer/pull/3053 + # 1. for edge-commit and edge-installer, check ro when fedora >= 37 + # 2. for edge-commit and edge-installer, check rw for other os. + # 3. for edge-simplified-installer and edge-raw-image, check ro for all os. + - name: /sysroot should be mount with ro permission for edge-commit and edge-installer on Fedora >= 37 + block: + - assert: + that: + - result_sysroot_mount_status.stdout == "ro" + fail_msg: "/sysroot is not mounted with ro permission" + success_msg: "/sysroot is mounted with ro permission" + always: + - set_fact: + total_counter: "{{ total_counter | int + 1 }}" + rescue: + - name: failed count + 1 + set_fact: + failed_counter: "{{ failed_counter | int + 1 }}" + when: (edge_type == "none") and (ansible_facts['distribution'] == 'Fedora' and ansible_facts['distribution_version'] is version('37', '>=')) + + - name: /sysroot should be mount with rw permission for edge-commit and edge-installer on all OS except Fedora >= 37 block: - assert: that: @@ -246,11 +268,10 @@ - name: failed count + 1 set_fact: failed_counter: "{{ failed_counter | int + 1 }}" - when: (ansible_facts['distribution'] == 'Fedora' and ansible_facts['distribution_version'] is version('37', '<')) or - (ansible_facts['distribution'] == 'CentOS') or (ansible_facts['distribution'] == 'RedHat') + when: (edge_type == "none") and ((ansible_facts['distribution'] == 'Fedora' and ansible_facts['distribution_version'] is version('37', '<')) or + (ansible_facts['distribution'] == 'CentOS') or (ansible_facts['distribution'] == 'RedHat')) - # https://fedoraproject.org/wiki/Changes/Silverblue_Kinoite_readonly_sysroot - - name: /sysroot should be mount with ro permission since Fedora 37 + - name: /sysroot should be mount with ro permission for edge-simplified-installer and edge-raw-image block: - assert: that: @@ -264,7 +285,7 @@ - name: failed count + 1 set_fact: failed_counter: "{{ failed_counter | int + 1 }}" - when: ansible_facts['distribution'] == 'Fedora' and ansible_facts['distribution_version'] is version('37', '>=') + when: edge_type == "edge-simplified-installer" or edge_type == "edge-raw-image" # case: check /var mount point - name: check /var mount point @@ -397,8 +418,8 @@ - name: failed count + 1 set_fact: failed_counter: "{{ failed_counter | int + 1 }}" - when: (ansible_facts['distribution'] == 'Fedora' and ansible_facts['distribution_version'] is version('37', '<')) or - (ansible_facts['distribution'] == 'CentOS') or (ansible_facts['distribution'] == 'RedHat') + when: (edge_type == "none") and ((ansible_facts['distribution'] == 'Fedora' and ansible_facts['distribution_version'] is version('37', '<')) or + (ansible_facts['distribution'] == 'CentOS') or (ansible_facts['distribution'] == 'RedHat')) # case: check dmesg error and failed log - name: check dmesg output