diff --git a/live-build/config/hooks/vm-artifacts/90-raw-disk-image.binary b/live-build/config/hooks/vm-artifacts/90-raw-disk-image.binary index 96236f3a..165fb22f 100755 --- a/live-build/config/hooks/vm-artifacts/90-raw-disk-image.binary +++ b/live-build/config/hooks/vm-artifacts/90-raw-disk-image.binary @@ -1,6 +1,6 @@ #!/bin/bash -ex # -# Copyright 2018 Delphix +# Copyright 2018, 2026 Delphix # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -274,8 +274,8 @@ zfs create \ # contents. During normal boot up, we'll rely on "/etc/fstab" to handle # these mounts. # -mkdir -p "$DIRECTORY/export/home" -mount -t zfs "$FSNAME/ROOT/$FSNAME/home" "$DIRECTORY/export/home" +mkdir -p "$DIRECTORY/home" +mount -t zfs "$FSNAME/ROOT/$FSNAME/home" "$DIRECTORY/home" mkdir -p "$DIRECTORY/var/delphix" mount -t zfs "$FSNAME/ROOT/$FSNAME/data" "$DIRECTORY/var/delphix" @@ -314,7 +314,7 @@ rsync --info=stats3 -WaAX binary/* "$DIRECTORY/" # automatically whenever we boot into the crash kernel. # cat <<-EOF >"$DIRECTORY/etc/fstab" - rpool/ROOT/$FSNAME/home /export/home zfs defaults,x-systemd.before=zfs-import-cache.service 0 0 + rpool/ROOT/$FSNAME/home /home zfs defaults,nodev,nosuid,x-systemd.before=zfs-import-cache.service 0 0 rpool/ROOT/$FSNAME/data /var/delphix zfs defaults,x-systemd.before=zfs-import-cache.service 0 0 rpool/ROOT/$FSNAME/log /var/log zfs defaults,x-systemd.before=zfs-import-cache.service 0 0 rpool/ROOT/$FSNAME/tmp /tmp zfs defaults,nosuid,nodev,exec,x-systemd.before=zfs-import-cache.service 0 0 @@ -440,7 +440,7 @@ done umount "$DIRECTORY/var/log" umount "$DIRECTORY/var/delphix" -umount "$DIRECTORY/export/home" +umount "$DIRECTORY/home" umount "$DIRECTORY/tmp" umount "$DIRECTORY/var/tmp" umount "/var/crash" diff --git a/live-build/misc/ansible-roles/appliance-build.delphix-ldap/tasks/main.yml b/live-build/misc/ansible-roles/appliance-build.delphix-ldap/tasks/main.yml index 0a2bd8d1..037bdcf9 100644 --- a/live-build/misc/ansible-roles/appliance-build.delphix-ldap/tasks/main.yml +++ b/live-build/misc/ansible-roles/appliance-build.delphix-ldap/tasks/main.yml @@ -63,10 +63,6 @@ group: root mode: 0755 -- lineinfile: - dest: etc/auto.master - line: "/home auto_home -nobrowse" - - copy: src: 80-internal-ldap dest: /etc/sudoers.d/ diff --git a/live-build/misc/ansible-roles/appliance-build.masking-development/tasks/main.yml b/live-build/misc/ansible-roles/appliance-build.masking-development/tasks/main.yml index 9fde6f6d..657229ba 100644 --- a/live-build/misc/ansible-roles/appliance-build.masking-development/tasks/main.yml +++ b/live-build/misc/ansible-roles/appliance-build.masking-development/tasks/main.yml @@ -1,5 +1,5 @@ # -# Copyright 2018 Delphix +# Copyright 2018, 2026 Delphix # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -26,14 +26,14 @@ - git: repo: "https://{{ lookup('env', 'GITHUB_TOKEN') }}@github.com/delphix/dms-core-gate.git" dest: - "/export/home/delphix/dms-core-gate" + "/home/delphix/dms-core-gate" version: "develop" accept_hostkey: yes update: no when: lookup('env', 'GITHUB_TOKEN') != '' - file: - path: "/export/home/delphix/{{ item }}" + path: "/home/delphix/{{ item }}" owner: delphix group: staff mode: "g+w" diff --git a/live-build/misc/ansible-roles/appliance-build.minimal-common/tasks/main.yml b/live-build/misc/ansible-roles/appliance-build.minimal-common/tasks/main.yml index d95545e6..67902dea 100644 --- a/live-build/misc/ansible-roles/appliance-build.minimal-common/tasks/main.yml +++ b/live-build/misc/ansible-roles/appliance-build.minimal-common/tasks/main.yml @@ -1,5 +1,5 @@ # -# Copyright 2018 Delphix +# Copyright 2018, 2026 Delphix # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ no_log: true - file: - path: /export/home + path: /home state: directory mode: 0755 @@ -39,7 +39,7 @@ shell: /bin/bash create_home: yes comment: Delphix User - home: /export/home/delphix + home: /home/delphix password: "{{ lookup('env', 'APPLIANCE_PASSWORD') | password_hash('sha512') }}" diff --git a/live-build/misc/ansible-roles/appliance-build.minimal-internal/tasks/main.yml b/live-build/misc/ansible-roles/appliance-build.minimal-internal/tasks/main.yml index 7025c0eb..4bd24ef9 100644 --- a/live-build/misc/ansible-roles/appliance-build.minimal-internal/tasks/main.yml +++ b/live-build/misc/ansible-roles/appliance-build.minimal-internal/tasks/main.yml @@ -34,6 +34,7 @@ ansible.builtin.pip: name: awscli break_system_packages: true + extra_args: --no-cache-dir become: true # Add /usr/local/bin to the PATH (awscli needs it) diff --git a/live-build/misc/ansible-roles/appliance-build.unittest-internal/tasks/main.yml b/live-build/misc/ansible-roles/appliance-build.unittest-internal/tasks/main.yml index 00f7606c..e8b7e78f 100644 --- a/live-build/misc/ansible-roles/appliance-build.unittest-internal/tasks/main.yml +++ b/live-build/misc/ansible-roles/appliance-build.unittest-internal/tasks/main.yml @@ -94,7 +94,7 @@ - user: name: testrunner comment: "Delphix" - home: /export/home/testrunner + home: /home/testrunner groups: docker password: "$6$pWQE0MPZWgue7fNC$8RvR0u04Mt67792b.x4ao0G2Z/H/hrYPWezOqCkz59MIA\ diff --git a/live-build/misc/ansible-roles/appliance-build.virtualization-development/tasks/main.yml b/live-build/misc/ansible-roles/appliance-build.virtualization-development/tasks/main.yml index 862376f6..4d08b0cf 100644 --- a/live-build/misc/ansible-roles/appliance-build.virtualization-development/tasks/main.yml +++ b/live-build/misc/ansible-roles/appliance-build.virtualization-development/tasks/main.yml @@ -1,5 +1,5 @@ # -# Copyright 2018 Delphix +# Copyright 2018, 2026 Delphix # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -73,14 +73,14 @@ - git: repo: "https://{{ lookup('env', 'GITHUB_TOKEN') }}@github.com/delphix/dlpx-app-gate.git" - dest: "/export/home/delphix/dlpx-app-gate" + dest: "/home/delphix/dlpx-app-gate" version: "develop" accept_hostkey: yes update: no when: lookup('env', 'GITHUB_TOKEN') != '' - file: - path: "/export/home/delphix/{{ item }}" + path: "/home/delphix/{{ item }}" owner: delphix group: staff mode: "g+w" diff --git a/live-build/misc/ansible-roles/appliance-build.zfsonlinux-development/tasks/main.yml b/live-build/misc/ansible-roles/appliance-build.zfsonlinux-development/tasks/main.yml index 7df32cf3..8d9052b7 100644 --- a/live-build/misc/ansible-roles/appliance-build.zfsonlinux-development/tasks/main.yml +++ b/live-build/misc/ansible-roles/appliance-build.zfsonlinux-development/tasks/main.yml @@ -1,5 +1,5 @@ # -# Copyright 2018 Delphix +# Copyright 2018, 2026 Delphix # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -67,26 +67,26 @@ - git: repo: "https://{{ lookup('env', 'GITHUB_TOKEN') }}@github.com/delphix/zfs.git" dest: - "/export/home/delphix/zfs" + "/home/delphix/zfs" version: develop accept_hostkey: yes update: no when: lookup('env', 'GITHUB_TOKEN') != '' - file: - path: "/export/home/delphix/zfs" + path: "/home/delphix/zfs" owner: delphix group: staff state: directory recurse: yes - file: - path: "/export/home/delphix/.cargo/" + path: "/home/delphix/.cargo/" state: directory owner: delphix group: staff - copy: - dest: "/export/home/delphix/.cargo/config.toml" + dest: "/home/delphix/.cargo/config.toml" content: | [target.x86_64-unknown-linux-gnu] rustflags = ["-C", "link-arg=-B/usr/libexec/mold"] diff --git a/upgrade/FAQ.md b/upgrade/FAQ.md index 4b4ff44e..08f7e442 100644 --- a/upgrade/FAQ.md +++ b/upgrade/FAQ.md @@ -89,7 +89,7 @@ resemble the following: A "rootfs container" is a collection of ZFS datasets that can be used as the "root filesytsem" of the appliance. This includes a dataset for "/" -of the appliance, but also seperate datasets for "/export/home" and +of the appliance, but also seperate datasets for "/home" and "/var/delphix". Here's an example of the datasets for a rootfs container: diff --git a/upgrade/upgrade-scripts/common.sh b/upgrade/upgrade-scripts/common.sh index a45f233d..f0fe2a6d 100644 --- a/upgrade/upgrade-scripts/common.sh +++ b/upgrade/upgrade-scripts/common.sh @@ -529,3 +529,99 @@ function fix_and_migrate_services() { telegraf.service EOF } + +# +# Home directories were historically mounted at /export/home. For CIS +# compliance, the home dataset is now mounted at /home instead. This +# function migrates an engine that is being upgraded in place from the +# old layout to the new one. +# +# The home dataset uses a legacy ZFS mountpoint, so /etc/fstab controls +# where it is mounted. We repoint the home dataset's fstab entry and any +# affected /etc/passwd home directory from /export/home to /home, then +# mount the dataset at /home. +# +# The pre-existing /export/home mount is intentionally left in place: the +# dataset stays mounted at both /export/home and /home until the next +# reboot. This avoids disrupting processes that hold /export/home open and +# prevents a busy unmount from failing the upgrade. After a reboot only +# /home is mounted, since /export/home is no longer present in fstab. +# +# The function is idempotent. If /etc/fstab no longer maps the home +# dataset to /export/home -- because the engine was already migrated, or +# the image was built to use /home -- it returns without making changes. +# This also makes it a harmless no-op inside an upgrade container, whose +# fstab is generated with the /home mountpoint already. +# +function migrate_export_home_to_home() { + # + # Identify the home dataset's fstab entry: a "/.../home" + # source mounted at /export/home. If it is absent, there is + # nothing to migrate. + # + if ! grep -qE '^[^#]*/home[[:space:]]+/export/home[[:space:]]' /etc/fstab; then + return + fi + + # + # Repoint only the home dataset's mountpoint field, leaving every + # other fstab entry (and any comments) untouched. + # + sed -i -E \ + '/^[^#]*\/home[[:space:]]+\/export\/home[[:space:]]/ s|/export/home|/home|' \ + /etc/fstab || + die "failed to update home mountpoint in /etc/fstab" + + # + # Repoint the home-directory field (field 6) of any user whose home + # lived under /export/home, so logins resolve to the new location. + # + sed -i -E \ + 's|^([^:]*:[^:]*:[^:]*:[^:]*:[^:]*:)/export/home(/[^:]*)?:|\1/home\2:|' \ + /etc/passwd || + die "failed to update home directories in /etc/passwd" + + # + # Mount the home dataset at its new /home location. The existing + # /export/home mount is deliberately left mounted until reboot. + # + mkdir -p /home || die "failed to create /home mountpoint" + mount /home || die "failed to mount /home" +} + +# +# Ensure the /home entry in /etc/fstab carries the nodev and nosuid mount +# options, required for CIS compliance on systems being upgraded that +# predate this hardening. This is idempotent and a no-op where the options +# are already present (fresh installs and upgrade containers set them via +# their fstab templates), so it is safe to call regardless of context. +# +function harden_home_mount_options() { + # + # Nothing to do if there is no /home entry in /etc/fstab. + # + grep -qE '^[^#].*[[:space:]]/home[[:space:]]' /etc/fstab || return + + # + # Nothing to do if both options are already present. + # + if grep -qE '^[^#].*[[:space:]]/home[[:space:]].*nodev' /etc/fstab && + grep -qE '^[^#].*[[:space:]]/home[[:space:]].*nosuid' /etc/fstab; then + return + fi + + sed -i '/^[^#].*[[:space:]]\/home[[:space:]]/ s/defaults/defaults,nodev,nosuid/' \ + /etc/fstab || + die "failed to add nodev,nosuid to /home entry in /etc/fstab" + + # + # Verify the options were actually applied. The substitution above + # relies on the /home entry carrying the "defaults" token; if a + # hand-edited fstab lacks it, the sed would be a no-op and silently + # leave this CIS control unsatisfied. Fail loudly instead. + # + if ! { grep -qE '^[^#].*[[:space:]]/home[[:space:]].*nodev' /etc/fstab && + grep -qE '^[^#].*[[:space:]]/home[[:space:]].*nosuid' /etc/fstab; }; then + die "failed to add nodev,nosuid to /home entry in /etc/fstab" + fi +} diff --git a/upgrade/upgrade-scripts/execute b/upgrade/upgrade-scripts/execute index 9d9f55c8..9b1011fe 100755 --- a/upgrade/upgrade-scripts/execute +++ b/upgrade/upgrade-scripts/execute @@ -264,6 +264,25 @@ if compare_versions "$CURRENT_VERSION" lt "2025.6.0.0-0"; then systemctl mask docker.service fi +# +# Migrate the home dataset's mountpoint from /export/home to /home, and +# harden it with nodev,nosuid, for engines upgrading from a release that +# predates this change. +# +# This must run *before* the package phase below. Package maintainer +# scripts (e.g. the delphix-platform postinst) now operate in terms of +# /home, so the home dataset must already be mounted there by the time they +# run; otherwise they would create/modify content under a /home directory on +# the root filesystem that the dataset mount later shadows. +# +# Both functions (in common.sh) self-guard and are no-ops once the engine +# already uses /home -- i.e. on fresh installs and inside upgrade +# containers, whose fstab maps the dataset to /home. migrate must run before +# harden, which hardens the /home fstab entry the migration creates. +# +migrate_export_home_to_home +harden_home_mount_options + # # When an upgrade gets interrupted while it’s in the middle of upgrading # packages, the package manager can get into a state where “dpkg --configure -a” diff --git a/upgrade/upgrade-scripts/upgrade-container b/upgrade/upgrade-scripts/upgrade-container index 6a436a5c..a59bcbb8 100755 --- a/upgrade/upgrade-scripts/upgrade-container +++ b/upgrade/upgrade-scripts/upgrade-container @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright 2018, 2025 Delphix +# Copyright 2018, 2026 Delphix # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -177,7 +177,7 @@ function create_upgrade_container() { -o mountpoint=legacy \ "$ROOTFS_DATASET/home@$SNAPSHOT_NAME" \ "rpool/ROOT/$CONTAINER/home" || - die "failed to create upgrade /export/home clone" + die "failed to create upgrade /home clone" zfs clone \ -o mountpoint=legacy \ @@ -213,7 +213,7 @@ function create_upgrade_container() { # before the zfs-import service is run. # cat <<-EOF >"$DIRECTORY/etc/fstab" - rpool/ROOT/$CONTAINER/home /export/home zfs defaults,x-systemd.before=zfs-import-cache.service 0 0 + rpool/ROOT/$CONTAINER/home /home zfs defaults,nodev,nosuid,x-systemd.before=zfs-import-cache.service 0 0 rpool/ROOT/$CONTAINER/data /var/delphix zfs defaults,x-systemd.before=zfs-import-cache.service 0 0 rpool/ROOT/$CONTAINER/log /var/log zfs defaults,x-systemd.before=zfs-import-cache.service 0 0 rpool/crashdump /var/crash zfs defaults,x-systemd.before=zfs-import-cache.service,x-systemd.before=kdump-tools.service 0 0