From 746e8aac3e74c2e40af05728f3c330f0c9e4f3d7 Mon Sep 17 00:00:00 2001 From: Matthew Kocher Date: Wed, 25 Mar 2026 23:02:19 -0700 Subject: [PATCH] Inital Resolute Raccoon stemcell changes --- .gitignore | 2 + CONTRIBUTING.md | 3 +- README.md | 92 +++++----- Rakefile | 8 +- .../image-metalinks/ubuntu-resolute.meta4 | 19 +++ .../lib/bosh/stemcell/build_environment.rb | 2 +- .../spec/assets/dpkg-list-ubuntu-kernel.txt | 10 +- .../spec/assets/dpkg-list-ubuntu.txt | 160 +++++++++++++----- .../spec/bosh/stemcell/helpers_sh_spec.rb | 42 ++--- .../bosh/stemcell/stemcell_packager_spec.rb | 13 ++ bosh-stemcell/spec/os_image/ubuntu_spec.rb | 123 +++++++------- bosh-stemcell/spec/stemcells/ubuntu_spec.rb | 44 ++++- .../os-image-stemcell-builder/.gitignore | 1 + .../os-image-stemcell-builder/Dockerfile | 30 +--- ci/docker/os-image-stemcell-builder/README.md | 37 ++++ .../os-image-stemcell-builder/Vagrantfile | 54 ------ docs/resolute-dev.md | 148 ++++++++++++++++ stemcell_builder/lib/prelude_bosh.bash | 5 +- .../stages/base_ubuntu_packages/apply.sh | 8 +- stemcell_builder/stages/base_warden/apply.sh | 13 ++ .../stages/bosh_audit_ubuntu/apply.sh | 3 +- stemcell_builder/stages/bosh_monit/apply.sh | 4 +- stemcell_builder/stages/bosh_users/apply.sh | 4 + .../stages/bosh_users/assets/sudoers | 2 +- .../stages/password_policies/apply.sh | 2 + .../assets/ubuntu/common-auth.patch | 2 +- .../assets/ubuntu/common-password.patch | 2 +- .../stages/restrict_su_command/apply.sh | 11 +- .../stages/static_libraries_config/apply.sh | 2 +- .../assets/static_libraries_list.txt | 42 +++++ 30 files changed, 602 insertions(+), 286 deletions(-) create mode 100644 bosh-stemcell/image-metalinks/ubuntu-resolute.meta4 create mode 100644 ci/docker/os-image-stemcell-builder/README.md delete mode 100644 ci/docker/os-image-stemcell-builder/Vagrantfile create mode 100644 docs/resolute-dev.md diff --git a/.gitignore b/.gitignore index 98e888ffb2..a9b07cc433 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ acceptance-tests/os-conf-release ci/docker/VMware-ovftool-*.bundle ci/docker/*/VMware-ovftool-*.bundle + +tmp/* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c2392d50b0..0bd548fac6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,8 @@ Please ensure that changes are made to any current branches. These are named after the Ubuntu release they are based on, ex: `ubuntu-` -At the time of writing (2025-05-29) there are two "stemcell lines": +At the time of writing (2025-05-29) there are three "stemcell lines": - `ubuntu-jammy` - `ubuntu-noble` +- `ubuntu-resolute` diff --git a/README.md b/README.md index 6c0251f745..1a49ae228c 100644 --- a/README.md +++ b/README.md @@ -3,34 +3,38 @@ This repo contains tools for creating BOSH stemcells. A stemcell is a bootable disk image that is used as a template by a BOSH Director to create VMs. +This branch (`ubuntu-resolute`) builds stemcells for **Ubuntu 26.04 LTS (Resolute)**. +For other Ubuntu releases, switch to the appropriate branch (e.g. `ubuntu-noble` +for 24.04). + ## Quick Start: Building a Stemcell Locally ```bash git clone git@github.com:cloudfoundry/bosh-linux-stemcell-builder.git cd bosh-linux-stemcell-builder -git checkout ubuntu-noble/master +git checkout ubuntu-resolute/1.x mkdir -p tmp -docker build -t bosh/os-image-stemcell-builder:noble \ - ci/docker/os-image-stemcell-builder-noble/ +docker build -t bosh/os-image-stemcell-builder:resolute \ + ci/docker/os-image-stemcell-builder-resolute/ docker run \ --privileged \ -v "$(pwd):/opt/bosh" \ --workdir /opt/bosh \ --user=1000:1000 \ -it \ - bosh/os-image-stemcell-builder:noble + bosh/os-image-stemcell-builder:resolute # You're now in the the Docker container ulimit -n 16384 # only necessary if your host is Fedora gem install bundler bundle # build OS image -bundle exec rake stemcell:build_os_image[ubuntu,noble,$PWD/tmp/ubuntu_base_image.tgz] # build OS image +bundle exec rake stemcell:build_os_image[ubuntu,resolute,$PWD/tmp/ubuntu_base_image.tgz] # build vSphere stemcell -bundle exec rake stemcell:build_with_local_os_image[vsphere,esxi,ubuntu,noble,$PWD/tmp/ubuntu_base_image.tgz] +bundle exec rake stemcell:build_with_local_os_image[vsphere,esxi,ubuntu,resolute,$PWD/tmp/ubuntu_base_image.tgz] ``` When building a vSphere stemcell, you must download `VMware-ovftool-*.bundle` -and place it in the `ci/docker/os-image-stemcell-builder-noble/` directory. See +and place it in the `ci/docker/os-image-stemcell-builder-resolute/` directory. See [External Assets](#external-assets) for download instructions. ### OS image @@ -38,7 +42,7 @@ and place it in the `ci/docker/os-image-stemcell-builder-noble/` directory. See An OS image is a tarball that contains a snapshot of an OS filesystem, including the libraries and system utilities needed by the BOSH agent; however, it does not contain the BOSH agent nor the virtualization tools: [a subsequent -Rake task](#with-local-os-image) adds the BOSH agent and a set of +Rake task](#building-a-stemcell) adds the BOSH agent and a set of virtualization tools to the base OS image to produce a stemcell. The OS Image should be rebuilt when you are making changes to the packages @@ -46,7 +50,7 @@ installed in the operating system or when making changes to the configuration of those packages. ```bash -bundle exec rake stemcell:build_os_image[ubuntu,noble,$PWD/tmp/ubuntu_base_image.tgz] +bundle exec rake stemcell:build_os_image[ubuntu,resolute,$PWD/tmp/ubuntu_base_image.tgz] ``` The arguments to the `stemcell:build_os_image` rake task follow: @@ -54,9 +58,9 @@ The arguments to the `stemcell:build_os_image` rake task follow: 0. *`operating_system_name`* (`ubuntu`): identifies which type of OS to fetch. Determines which package repository and packaging tool will be used to download and assemble the files. Currently, only `ubuntu` is recognized. -0. *`operating_system_version`* (`noble`): an identifier that the system may use - to decide which release of the OS to download. Acceptable values depend on - the operating system. For `ubuntu`, use `noble`. +0. *`operating_system_version`* (`resolute`): an identifier that the system + uses to decide which release of the OS to download. For this branch, use + `resolute` (Ubuntu 26.04 LTS). 0. *`os_image_path`* (`$PWD/tmp/ubuntu_base_image.tgz`): the path to write the finished OS image tarball to. If a file exists at this path already, it will be overwritten without warning. @@ -67,7 +71,7 @@ Rebuild the stemcell when you are making and testing BOSH-specific changes such as a new BOSH agent. ```bash -bundle exec rake stemcell:build_with_local_os_image[vsphere,esxi,ubuntu,noble,$PWD/tmp/ubuntu_base_image.tgz,"0.0.8"] +bundle exec rake stemcell:build_with_local_os_image[vsphere,esxi,ubuntu,resolute,$PWD/tmp/ubuntu_base_image.tgz,"0.0.8"] ``` The arguments to `stemcell:build_with_local_os_image` are: @@ -76,10 +80,11 @@ The arguments to `stemcell:build_with_local_os_image` are: Determines which virtualization tools to package on top of the stemcell. 0. `hypervisor_name`: Depending on what the IAAS supports, which hypervisor to target: `aws` → `xen-hvm`, `azure` → `hyperv`, `google` → `kvm`, `openstack` → - `kvm`, `vsphere` → `esxi` + `kvm`, `vsphere` → `esxi`, `warden` → `warden` 0. `operating_system_name` (`ubuntu`): Type of OS. Same as -0. `stemcell:build_os_image`. Can optionally include a variant suffix (`noble-fips`) -0. `operating_system_version` (`noble`): OS release. Same as + `stemcell:build_os_image`. Can optionally include a variant suffix (e.g. `resolute-fips`) +0. `operating_system_version` (`resolute`): OS release. Same as + `stemcell:build_os_image`. 0. `os_image_path` (`$PWD/tmp/ubuntu_base_image.tgz`): Path to base OS image produced in `stemcell:build_os_image` 0. `build_number` (`0.0.8`): Stemcell version. Pro-tip: take the version number @@ -91,17 +96,15 @@ The arguments to `stemcell:build_with_local_os_image` are: You can find the resulting stemcell in the `tmp/` directory of the host, or in the `/opt/bosh/tmp` directory in the Docker container. Using the above example, the stemcell would be at -`tmp/bosh-stemcell-0.0.8-vsphere-esxi-ubuntu-noble-go_agent.tgz`. You can -upload the stemcell to a vSphere BOSH Director: +`tmp/bosh-stemcell-0.0.8-vsphere-esxi-ubuntu-resolute-go_agent.tgz`. You can +upload the stemcell to a BOSH Director: ```bash -bosh upload-stemcell tmp/bosh-stemcell-0.0.8-vsphere-esxi-ubuntu-noble-go_agent.tgz +bosh upload-stemcell tmp/bosh-stemcell-0.0.8-vsphere-esxi-ubuntu-resolute-go_agent.tgz ``` ## Testing -_[Fixme: update Testing section to noble]_ - ### How to run tests for OS Images The OS tests are meant to be run against the OS environment to which they @@ -111,12 +114,12 @@ the rake task the first time you create your docker container, but everytime after, as long as you do not destroy the container, you should be able to run the specific tests. -To run the `ubuntu_noble_spec.rb` tests (**assuming you've already built the OS +To run the OS image tests (**assuming you've already built the OS image** at the `tmp/ubuntu_base_image.tgz` and you're within the Docker container): cd /opt/bosh/bosh-stemcell - OS_IMAGE=/opt/bosh/tmp/ubuntu_base_image.tgz bundle exec rspec -fd spec/os_image/ubuntu_noble_spec.rb + OS_IMAGE=/opt/bosh/tmp/ubuntu_base_image.tgz bundle exec rspec -fd spec/os_image/ubuntu_spec.rb ### How to Run Tests for Stemcell @@ -163,7 +166,7 @@ OSX=true OS_IMAGE=/opt/bosh/tmp/ubuntu_base_image.tgz bundle exec rspec spec/ -- ### How to run tests for BOSH Linux Stemcell Builder -The BOSH Linux Stemcell Builder code itself can be tested with the following command's: +The BOSH Linux Stemcell Builder code itself can be tested with the following commands: ```shell bundle install --local @@ -189,7 +192,7 @@ If you find yourself debugging any of the above processes, here is what you need Example usage: ```shell - bundle exec rake stemcell:build_os_image[ubuntu,noble,$PWD/tmp/ubuntu_base_image.tgz] resume_from=rsyslog_config + bundle exec rake stemcell:build_os_image[ubuntu,resolute,$PWD/tmp/ubuntu_base_image.tgz] resume_from=rsyslog_config ``` ## Pro Tips @@ -199,32 +202,35 @@ If you find yourself debugging any of the above processes, here is what you need in section `How to run tests for OS Images` * If the Stemcell has been built and you are only updating tests, you do not need to re-build the stemcell. You can simply rerun the tests (without - rebuilding Stemcell. Details in section `How to run tests for Stemcell` + rebuilding Stemcell). Details in section `How to run tests for Stemcell` * It's possible to verify OS/Stemcell changes without making a deployment using - the stemcell. For a vSphere-specific Ubuntu stemcell, the filesytem is + the stemcell. For a vSphere-specific Ubuntu stemcell, the filesystem is available at `/mnt/stemcells/vsphere/esxi/ubuntu/work/work/chroot` ## External Assets -The ovftool installer from VMWare can be found at -[my.vmware.com](https://my.vmware.com/group/vmware/details?downloadGroup=OVFTOOL410&productId=489). - -The ovftool installer must be copied into the [ci/docker/os-image-stemcell-builder-noble](https://github.com/cloudfoundry/bosh-linux-stemcell-builder/tree/master/ci/docker/os-image-stemcell-builder) next to the Dockerfile or you will receive the error +The OVF Tool is only required for building **vSphere** stemcells. Download +"OVF Tool for Linux Zip" from +[Broadcom's developer portal](https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest). - Step 24/30 : ADD ${OVF_TOOL_INSTALLER} /tmp/ovftool_installer.bundle - ADD failed: stat /var/lib/docker/tmp/docker-builder389354746/VMware-ovftool-4.1.0-2459827-lin.x86_64.bundle: no such file or directory - -## Rebuilding the Docker Image +Extract the zip and place the resulting `ovftool/` directory inside the Docker +build context so that the Dockerfile's `COPY ovftool/ /usr/lib/vmware-ovftool/` +can find it: -The Docker image is published to -[`bosh/os-image-stemcell-builder`](https://hub.docker.com/r/bosh/os-image-stemcell-builder/). -You will need the ovftool installer present on your filesystem. +```bash +cd ci/docker/os-image-stemcell-builder-resolute/ +unzip ~/Downloads/VMware-ovftool-*.zip # creates ovftool/ in the current directory +``` -Rebuild the container with the `build` script... +The `ovftool/` directory is already in `.gitignore` and will not be committed. - ./build os-image-stemcell-builder +## Rebuilding the Docker Image -When ready, `push` to DockerHub and use the credentials from LastPass... +You will need the `ovftool/` directory present in +`ci/docker/os-image-stemcell-builder-resolute/` (see [External Assets](#external-assets) +above). Then build the image: - cd os-image-stemcell-builder - ./push +```bash +docker build -t bosh/os-image-stemcell-builder:resolute \ + ci/docker/os-image-stemcell-builder-resolute/ +``` diff --git a/Rakefile b/Rakefile index f668764110..776c37e002 100644 --- a/Rakefile +++ b/Rakefile @@ -12,12 +12,13 @@ namespace :stemcell do require 'bosh/stemcell/stage_collection' require 'bosh/stemcell/stage_runner' + os_image_path = File.expand_path(args.os_image_path) definition = Bosh::Stemcell::Definition.for('null', 'null', args.operating_system_name, args.operating_system_version) environment = Bosh::Stemcell::BuildEnvironment.new( ENV.to_hash, definition, '', - args.os_image_path, + os_image_path, ) collection = Bosh::Stemcell::StageCollection.new(definition) runner = Bosh::Stemcell::StageRunner.new( @@ -34,7 +35,7 @@ namespace :stemcell do runner: runner, archive_handler: archive_handler, ) - builder.build(args.os_image_path) + builder.build(os_image_path) sh(environment.os_image_rspec_command) rescue RuntimeError => e @@ -105,12 +106,13 @@ namespace :stemcell do args.with_defaults(build_number: '0000') + os_image_path = File.expand_path(args.os_image_path) definition = Bosh::Stemcell::Definition.for(args.infrastructure_name, args.hypervisor_name, args.operating_system_name, args.operating_system_version) environment = Bosh::Stemcell::BuildEnvironment.new( ENV.to_hash, definition, args.build_number, - args.os_image_path, + os_image_path, ) sh(environment.os_image_rspec_command) diff --git a/bosh-stemcell/image-metalinks/ubuntu-resolute.meta4 b/bosh-stemcell/image-metalinks/ubuntu-resolute.meta4 new file mode 100644 index 0000000000..b5538e45e5 --- /dev/null +++ b/bosh-stemcell/image-metalinks/ubuntu-resolute.meta4 @@ -0,0 +1,19 @@ + + + placeholder-update-when-resolute-os-image-is-published + placeholder + placeholder + 0 + https://storage.googleapis.com/bosh-os-images/ubuntu-resolute/ubuntu-resolute.tgz + 0.0.0 + + + placeholder + placeholder + 1 + https://storage.googleapis.com/bosh-os-images/ubuntu-resolute/usn-log.json + 0.0.0 + + metalink-repository-resource/0.0.0 + 1970-01-01T00:00:00Z + diff --git a/bosh-stemcell/lib/bosh/stemcell/build_environment.rb b/bosh-stemcell/lib/bosh/stemcell/build_environment.rb index 009804e618..58bd7c7d35 100644 --- a/bosh-stemcell/lib/bosh/stemcell/build_environment.rb +++ b/bosh-stemcell/lib/bosh/stemcell/build_environment.rb @@ -141,7 +141,7 @@ def build_time_settings end def operating_system_spec_name - "#{operating_system.name}" + operating_system.name end def prepare_build_path diff --git a/bosh-stemcell/spec/assets/dpkg-list-ubuntu-kernel.txt b/bosh-stemcell/spec/assets/dpkg-list-ubuntu-kernel.txt index 71ced9ee1e..e2f7edd49c 100644 --- a/bosh-stemcell/spec/assets/dpkg-list-ubuntu-kernel.txt +++ b/bosh-stemcell/spec/assets/dpkg-list-ubuntu-kernel.txt @@ -1,8 +1,8 @@ linux-generic -linux-headers-6.8 -linux-headers-6.8-generic +linux-headers-7.0 +linux-headers-7.0-generic linux-headers-generic -linux-image-6.8-generic +linux-image-7.0-generic linux-image-generic -linux-modules-6.8-generic -linux-modules-extra-6.8-generic +linux-main-modules-zfs-7.0-generic +linux-modules-7.0-generic diff --git a/bosh-stemcell/spec/assets/dpkg-list-ubuntu.txt b/bosh-stemcell/spec/assets/dpkg-list-ubuntu.txt index f9c3bc0e3b..181ab27721 100644 --- a/bosh-stemcell/spec/assets/dpkg-list-ubuntu.txt +++ b/bosh-stemcell/spec/assets/dpkg-list-ubuntu.txt @@ -1,10 +1,10 @@ +3cpio adduser amd64-microcode anacron apparmor apparmor-utils apt -apt-utils auditd autoconf automake @@ -30,13 +30,14 @@ chrony cloud-guest-utils cmake cmake-data +comerr-dev:amd64 console-setup console-setup-linux coreutils -cpio +coreutils-from-uutils cpp -cpp-13 -cpp-13-x86-64-linux-gnu +cpp-15 +cpp-15-x86-64-linux-gnu cpp-x86-64-linux-gnu cron cron-daemon-common @@ -61,7 +62,6 @@ distro-info distro-info-data dmidecode dmsetup -dnsutils dpkg dpkg-dev dracut-install @@ -74,30 +74,31 @@ file findutils flex g++ -g++-13 -g++-13-x86-64-linux-gnu +g++-15 +g++-15-x86-64-linux-gnu g++-x86-64-linux-gnu gcc -gcc-13 -gcc-13-base:amd64 -gcc-13-x86-64-linux-gnu -gcc-14-base:amd64 +gcc-15 +gcc-15-base:amd64 +gcc-15-x86-64-linux-gnu +gcc-16-base:amd64 gcc-x86-64-linux-gnu gdb gdisk gettext gettext-base -gir1.2-girepository-2.0:amd64 +gir1.2-girepository-3.0:amd64 gir1.2-glib-2.0:amd64 gir1.2-packagekitglib-1.0 +gnu-coreutils gpg gpg-agent gpgconf gpgv grep groff-base -grub-common grub-efi-amd64-bin +grub-efi-amd64-unsigned grub-gfxpayload-lists grub-pc grub-pc-bin @@ -106,7 +107,6 @@ grub2-common gzip hostname htop -icu-devtools ifupdown init init-system-helpers @@ -126,33 +126,35 @@ keyboard-configuration klibc-utils kmod krb5-locales +krb5-multidev:amd64 less libacl1:amd64 libaio1t64:amd64 libapparmor1:amd64 libappstream5:amd64 -libapt-pkg6.0t64:amd64 +libapt-pkg7.0:amd64 libarchive-zip-perl libarchive13t64:amd64 -libargon2-1:amd64 libasan8:amd64 -libassuan0:amd64 -libatm1t64:amd64 +libassuan9:amd64 libatomic1:amd64 libattr1:amd64 libaudit-common libaudit1:amd64 libauparse0t64:amd64 +libauplugin1:amd64 libbabeltrace1:amd64 libbinutils:amd64 libblkid1:amd64 libbpf1:amd64 +libbrotli-dev:amd64 libbrotli1:amd64 libbsd0:amd64 libbz2-1.0:amd64 libbz2-dev:amd64 libc-bin libc-dev-bin +libc-gconv-modules-extra:amd64 libc6-dev:amd64 libc6:amd64 libcap-dev:amd64 @@ -186,6 +188,7 @@ libefiboot1t64:amd64 libefivar1t64:amd64 libelf1t64:amd64 libestr0:amd64 +libevent-2.1-7t64:amd64 libexpat1:amd64 libext2fs2t64:amd64 libfastjson4:amd64 @@ -195,31 +198,39 @@ libfido2-1:amd64 libfile-stripnondeterminism-perl libfreetype6:amd64 libfribidi0:amd64 -libfuse3-3:amd64 -libgcc-13-dev:amd64 +libfuse3-4:amd64 +libfyaml0:amd64 +libgcc-15-dev:amd64 libgcc-s1:amd64 -libgcrypt20-dev +libgcrypt20-dev:amd64 libgcrypt20:amd64 libgdbm-compat4t64:amd64 libgdbm6t64:amd64 -libgirepository-1.0-1:amd64 +libgirepository-2.0-0:amd64 libglib2.0-0t64:amd64 libglib2.0-bin libglib2.0-data +libgmp-dev:amd64 libgmp10:amd64 +libgmpxx4ldbl:amd64 +libgnutls-dane0t64:amd64 +libgnutls-openssl27t64:amd64 +libgnutls28-dev:amd64 libgnutls30t64:amd64 libgomp1:amd64 -libgpg-error-dev +libgpg-error-dev:amd64 +libgpg-error-l10n libgpg-error0:amd64 libgprofng0:amd64 libgssapi-krb5-2:amd64 +libgssrpc4t64:amd64 libgstreamer1.0-0:amd64 libhogweed6t64:amd64 libhwasan0:amd64 libibverbs1:amd64 -libicu-dev:amd64 -libicu74:amd64 +libicu78:amd64 libidn2-0:amd64 +libidn2-dev:amd64 libinih1:amd64 libip4tc2:amd64 libip6tc2:amd64 @@ -227,19 +238,30 @@ libipt2 libisl23:amd64 libitm1:amd64 libjansson4:amd64 +libjemalloc2:amd64 libjson-c5:amd64 -libjsoncpp25:amd64 +libjsoncpp26:amd64 libk5crypto3:amd64 +libkadm5clnt-mit12:amd64 +libkadm5srv-mit12:amd64 +libkdb5-10t64:amd64 libkeyutils1:amd64 libklibc:amd64 libkmod2:amd64 libkrb5-3:amd64 +libkrb5-dev:amd64 libkrb5support0:amd64 +libksba8:amd64 +liblastlog2-2:amd64 +libldap-common +libldap-dev:amd64 libldap2:amd64 liblmdb0:amd64 liblocale-gettext-perl liblsan0:amd64 +liblsof0 liblz4-1:amd64 +liblzma-dev:amd64 liblzma5:amd64 libmagic-mgc libmagic1t64:amd64 @@ -260,15 +282,18 @@ libnfnetlink0:amd64 libnftables1:amd64 libnftnl11:amd64 libnghttp2-14:amd64 +libnghttp2-dev:amd64 libnl-3-200:amd64 libnl-genl-3-200:amd64 libnl-route-3-200:amd64 libnpth0t64:amd64 libnss-systemd:amd64 -libnvme1t64 +libnvme1t64:amd64 +libp11-kit-dev:amd64 libp11-kit0:amd64 libpackagekit-glib2-18:amd64 libpam-cap:amd64 +libpam-lastlog2:amd64 libpam-modules-bin libpam-modules:amd64 libpam-pwquality:amd64 @@ -278,25 +303,30 @@ libpam0g:amd64 libparted2t64:amd64 libpcap0.8t64:amd64 libpcre2-8-0:amd64 -libperl5.38t64:amd64 +libperl5.40:amd64 libpipeline1:amd64 +libpkgconf7:amd64 libpng16-16t64:amd64 libpolkit-agent-1-0:amd64 libpolkit-gobject-1-0:amd64 libpopt0:amd64 libproc2-0:amd64 +libpsl-dev:amd64 libpsl5t64:amd64 libpwquality-common libpwquality1:amd64 libpython3-stdlib:amd64 -libpython3.12-minimal:amd64 -libpython3.12-stdlib:amd64 -libpython3.12t64:amd64 +libpython3.13-minimal:amd64 +libpython3.13-stdlib:amd64 +libpython3.14-minimal:amd64 +libpython3.14-stdlib:amd64 +libpython3.14:amd64 libquadmath0:amd64 libreadline-dev:amd64 libreadline8t64:amd64 librelp0:amd64 -librhash0:amd64 +librhash1:amd64 +librtmp-dev:amd64 librtmp1:amd64 libsasl2-2:amd64 libsasl2-modules-db:amd64 @@ -307,22 +337,23 @@ libsemanage2:amd64 libsensors-config libsensors5:amd64 libsepol2:amd64 -libsframe1:amd64 +libsframe3:amd64 libslang2:amd64 libsmartcols1:amd64 libsource-highlight-common libsource-highlight4t64:amd64 libsqlite3-0:amd64 libss2:amd64 -libssh-4:amd64 +libssh2-1-dev:amd64 +libssh2-1t64:amd64 libssl-dev:amd64 libssl3t64:amd64 -libstdc++-13-dev:amd64 +libstdc++-15-dev:amd64 libstdc++6:amd64 libstemmer0d:amd64 -libsub-override-perl libsystemd-shared:amd64 libsystemd0:amd64 +libtasn1-6-dev:amd64 libtasn1-6:amd64 libtext-charwidth-perl:amd64 libtext-iconv-perl:amd64 @@ -335,26 +366,47 @@ libtsan2:amd64 libubsan1:amd64 libuchardet0:amd64 libudev1:amd64 +libunbound8:amd64 libunistring5:amd64 libunwind8:amd64 liburcu8t64:amd64 libuuid1:amd64 libuv1t64:amd64 libwrap0:amd64 +libxml2-16:amd64 libxml2-dev:amd64 -libxml2:amd64 libxmlb2:amd64 libxslt1-dev:amd64 libxslt1.1:amd64 libxtables12:amd64 libxxhash0:amd64 libyaml-0-2:amd64 +libzstd-dev:amd64 libzstd1:amd64 linux-base linux-firmware +linux-firmware-amd-graphics +linux-firmware-broadcom-wireless +linux-firmware-intel-graphics +linux-firmware-intel-misc +linux-firmware-intel-wireless +linux-firmware-marvell-prestera +linux-firmware-marvell-wireless +linux-firmware-mediatek +linux-firmware-mellanox-spectrum +linux-firmware-misc +linux-firmware-netronome +linux-firmware-nvidia-graphics +linux-firmware-qlogic +linux-firmware-qualcomm-graphics +linux-firmware-qualcomm-misc +linux-firmware-qualcomm-wireless +linux-firmware-realtek linux-libc-dev:amd64 +linux-sysctl-defaults locales login +login.defs logrotate logsave lsb-release @@ -365,7 +417,6 @@ make man-db mawk media-types -module-assistant mount ncurses-base ncurses-bin @@ -373,6 +424,7 @@ net-tools netbase netcat-openbsd netplan-generator +nettle-dev:amd64 networkd-dispatcher nftables nvme-cli @@ -380,14 +432,17 @@ openssh-client openssh-server openssh-sftp-server openssl +openssl-provider-legacy packagekit parted passwd patch perl perl-base -perl-modules-5.38 +perl-modules-5.40 pinentry-curses +pkgconf-bin +pkgconf:amd64 po-debconf polkitd procps @@ -396,6 +451,8 @@ python-apt-common python3 python3-apparmor python3-apt +python3-autocommand +python3-bcrypt python3-blinker python3-cffi-backend:amd64 python3-cryptography @@ -403,28 +460,38 @@ python3-dbus python3-distro python3-gi python3-httplib2 +python3-inflect +python3-jaraco.context +python3-jaraco.functools +python3-jaraco.text python3-jwt python3-launchpadlib python3-lazr.restfulclient python3-lazr.uri python3-libapparmor +python3-linkify-it python3-markdown-it python3-mdurl python3-minimal -python3-netifaces:amd64 +python3-more-itertools python3-netplan python3-oauthlib python3-pkg-resources python3-pygments python3-pyparsing python3-rich -python3-six +python3-setuptools python3-software-properties +python3-typeguard python3-typing-extensions +python3-uc-micro python3-wadllib python3-yaml -python3.12 -python3.12-minimal +python3-zipp +python3.13 +python3.13-minimal +python3.14 +python3.14-minimal quota readline-common rng-tools-debian @@ -435,6 +502,7 @@ rsyslog-gnutls rsyslog-openssl rsyslog-relp runit +rust-coreutils sed sensible-utils sgml-base @@ -442,20 +510,20 @@ shared-mime-info software-properties-common strace sudo +sudo-common +sudo-rs sysstat systemd -systemd-dev +systemd-cryptsetup systemd-hwe-hwdb systemd-resolved systemd-sysv -systemd-timesyncd sysuser-helper sysvinit-utils tar tcpdump traceroute tzdata -tzdata-legacy ubuntu-keyring ubuntu-pro-client ubuntu-pro-client-l10n diff --git a/bosh-stemcell/spec/bosh/stemcell/helpers_sh_spec.rb b/bosh-stemcell/spec/bosh/stemcell/helpers_sh_spec.rb index 2747362df2..fe54d7c24c 100644 --- a/bosh-stemcell/spec/bosh/stemcell/helpers_sh_spec.rb +++ b/bosh-stemcell/spec/bosh/stemcell/helpers_sh_spec.rb @@ -1,16 +1,19 @@ require 'spec_helper' +require 'open3' context 'helpers.sh' do + # Run scripts on the host (not in chroot) so they can source stemcell_builder/lib/helpers.sh + # via relative path. Chroot would require sudo and the repo paths may not exist inside chroot. + def run_script(script_basename) + script_path = File.expand_path("../../../assets/#{script_basename}", __FILE__) + stdout, _stderr, _status = Open3.capture3('bash', script_path) + stdout + end context 'add_on_exit runs cleanup commands in LIFO order' do - describe ShelloutTypes::Command.new( - File.expand_path( - '../../../assets/on_exit_with_normal_completion.sh', - __FILE__ - ), - ShelloutTypes::Chroot.new('/') - ) do - it('describes the on_exit actions in that order') { expect(subject.stdout).to match </dev/null') do + its(:stdout) { should include('Ubuntu Archive Automatic Signing Key') } end end @@ -193,6 +193,12 @@ end end + context 'display the number of unsuccessful logon/access attempts since the last successful logon/access (stig: V-51875)' do + describe file('/etc/pam.d/common-password') do + its(:content) { should match /^session\toptional\t\t\tpam_lastlog2\.so showfailed/ } + end + end + # V-38498 and V-38495 are the package defaults and cannot be configured context 'ensure auditd is installed (stig: V-38498) (stig: V-38495)' do describe package('auditd') do @@ -202,14 +208,12 @@ context 'ensure auditd file permissions and ownership (stig: V-38663) (stig: V-38664) (stig: V-38665)' do [[0o644, '/usr/share/lintian/overrides/auditd'], - [0o755, '/usr/bin/auvirt'], [0o755, '/usr/bin/ausyscall'], [0o755, '/usr/bin/aulastlog'], [0o755, '/usr/bin/aulast'], [0o750, '/var/log/audit'], [0o755, '/sbin/aureport'], [0o755, '/sbin/auditd'], - [0o755, '/sbin/autrace'], [0o755, '/sbin/ausearch'], [0o755, '/sbin/augenrules'], [0o755, '/sbin/auditctl'], @@ -290,12 +294,6 @@ end end - context 'display the number of unsuccessful logon/access attempts since the last successful logon/access (stig: V-51875)' do - describe file('/etc/pam.d/common-password') do - its(:content) { should match /session\toptional\t\t\tpam_lastlog2\.so showfailed/ } - end - end - context 'ensure whoopsie and apport are not installed (CIS-4.1)' do describe package('apport') do it { should_not be_installed } @@ -309,9 +307,15 @@ describe command('grep "^\s*auth\s*required\s*pam_wheel.so\s*use_uid" /etc/pam.d/su') do it('exits 0') { expect(subject.exit_status).to eq(0) } end + describe command('getent group wheel') do + its(:exit_status) { should eq(0) } + its(:stdout) { should match /root/ } + its(:stdout) { should match /vcap/ } + end describe user('vcap') do it { should exist } it { should be_in_group 'sudo' } + it { should be_in_group 'wheel' } end end @@ -324,7 +328,6 @@ end describe 'rsyslog modifications' do - describe file('/usr/local/bin/wait_for_var_log_to_be_mounted') do it { should be_file } its(:mode) { should eq(0o755) } @@ -353,17 +356,16 @@ _apt:x:42:65534::/nonexistent:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin -systemd-timesync:x:996:996:systemd Time Synchronization:/:/usr/sbin/nologin -dhcpcd:x:100:65534:DHCP Client Daemon,,,:/usr/lib/dhcpcd:/bin/false -messagebus:x:101:101::/nonexistent:/usr/sbin/nologin -syslog:x:102:102::/nonexistent:/usr/sbin/nologin -systemd-resolve:x:991:991:systemd Resolver:/:/usr/sbin/nologin -uuidd:x:103:104::/run/uuidd:/usr/sbin/nologin -_chrony:x:104:106:Chrony daemon,,,:/var/lib/chrony:/usr/sbin/nologin -_runit-log:x:999:990:Created by dh-sysuser for runit:/nonexistent:/usr/sbin/nologin -sshd:x:105:65534::/run/sshd:/usr/sbin/nologin -tcpdump:x:106:108::/nonexistent:/usr/sbin/nologin -polkitd:x:989:989:User for polkitd:/:/usr/sbin/nologin +dhcpcd:x:996:996:DHCP Client Daemon:/usr/lib/dhcpcd:/bin/false +messagebus:x:995:995:System Message Bus:/nonexistent:/usr/sbin/nologin +syslog:x:100:101::/nonexistent:/usr/sbin/nologin +systemd-resolve:x:989:989:systemd Resolver:/:/usr/sbin/nologin +_chrony:x:988:988:Chrony Daemon:/var/lib/chrony:/usr/sbin/nologin +uuidd:x:101:103::/run/uuidd:/usr/sbin/nologin +_runit-log:x:987:987:runit svlogd user:/nonexistent:/usr/sbin/nologin +sshd:x:986:65534:sshd user:/run/sshd:/usr/sbin/nologin +tcpdump:x:985:985:tcpdump:/nonexistent:/usr/sbin/nologin +polkitd:x:984:984:User for polkitd:/:/usr/sbin/nologin vcap:x:1000:1000:BOSH System User:/home/vcap:/bin/bash HERE end @@ -388,17 +390,16 @@ irc:\*:(\d{5}):0:99999:7::: _apt:\*:(\d{5}):0:99999:7::: nobody:\*:(\d{5}):0:99999:7::: -systemd-network:!\*:(\d{5}):::::: -systemd-timesync:!\*:(\d{5}):::::: -dhcpcd:!:(\d{5}):::::: -messagebus:!:(\d{5}):::::: +systemd-network:!\*:(\d{5}):::::1: +dhcpcd:!\*:(\d{5}):::::1: +messagebus:!\*:(\d{5}):::::: syslog:!:(\d{5}):::::: -systemd-resolve:!\*:(\d{5}):::::: +systemd-resolve:!\*:(\d{5}):::::1: +_chrony:!\*:(\d{5}):::::: uuidd:!:(\d{5}):::::: -_chrony:!:(\d{5}):::::: -_runit-log:!:(\d{5}):::::: -sshd:!:(\d{5}):::::: -tcpdump:!:(\d{5}):::::: +_runit-log:!\*:(\d{5}):::::: +sshd:!\*:(\d{5}):::::: +tcpdump:!\*:(\d{5}):::::1: polkitd:!\*:(\d{5}):::::: vcap:(.+):(\d{5}):1:99999:7::: END_SHADOW @@ -449,26 +450,28 @@ systemd-journal:x:999: systemd-network:x:998: crontab:x:997: -systemd-timesync:x:996: -input:x:995: -sgx:x:994: -kvm:x:993: -render:x:992: -messagebus:x:101: -syslog:x:102: -systemd-resolve:x:991: -netdev:x:103: -uuidd:x:104: -_ssh:x:105: -_chrony:x:106: -_runit-log:x:990: -rdma:x:107: -tcpdump:x:108: -polkitd:x:989: -admin:x:988:vcap +dhcpcd:x:996: +messagebus:x:995: +syslog:x:101: +input:x:994: +sgx:x:993: +clock:x:992: +kvm:x:991: +render:x:990: +systemd-resolve:x:989: +_chrony:x:988: +netdev:x:102: +uuidd:x:103: +_ssh:x:104: +_runit-log:x:987: +rdma:x:105: +tcpdump:x:985: +polkitd:x:984: +admin:x:986:vcap vcap:x:1000:syslog bosh_sshers:x:1001:vcap bosh_sudoers:x:1002: +wheel:x:1003:root,vcap HERE end @@ -515,26 +518,28 @@ systemd-journal:!*:: systemd-network:!*:: crontab:!*:: -systemd-timesync:!*:: +dhcpcd:!*:: +messagebus:!*:: +syslog:!:: input:!*:: sgx:!*:: +clock:!*:: kvm:!*:: render:!*:: -messagebus:!:: -syslog:!:: systemd-resolve:!*:: +_chrony:!*:: netdev:!:: uuidd:!:: _ssh:!:: -_chrony:!:: -_runit-log:!:: +_runit-log:!*:: rdma:!:: -tcpdump:!:: +tcpdump:!*:: polkitd:!*:: admin:!::vcap vcap:!::syslog bosh_sshers:!::vcap bosh_sudoers:!:: +wheel:!::root,vcap HERE end end diff --git a/bosh-stemcell/spec/stemcells/ubuntu_spec.rb b/bosh-stemcell/spec/stemcells/ubuntu_spec.rb index 9f7d58de2d..2713bb6b43 100644 --- a/bosh-stemcell/spec/stemcells/ubuntu_spec.rb +++ b/bosh-stemcell/spec/stemcells/ubuntu_spec.rb @@ -1,11 +1,10 @@ require 'spec_helper' -describe 'Ubuntu 24.04 stemcell image', stemcell_image: true do +describe 'Ubuntu 26.04 stemcell image', stemcell_image: true do it_behaves_like 'All Stemcells' it_behaves_like 'a Linux kernel based OS image' it_behaves_like 'a Linux kernel module configured OS image' - # linux_version_regex = '/linux-(.+)-([0-9]+.+)/d' linux_version_regex = 's/linux-(.+)-([0-9]+).([0-9]+).([0-9]+)-([0-9]+)/linux-\1-\2.\3/' context 'installed by image_install_grub', { @@ -119,9 +118,13 @@ subject { command('find -L / -xdev -perm /ug=s -type f') } it ('includes the correct binaries') do - # expect(subject.stdout.split).to match_array(%w(/bin/su /usr/bin/sudo /usr/bin/sudoedit)) - expect(subject.stdout.split).to match_array(%w(/bin/su /bin/sudo /bin/sudoedit /usr/bin/su /usr/bin/sudo /usr/bin/sudoedit)) - + expect(subject.stdout.split).to match_array(%w( + /bin/su /bin/su-rs /bin/sudo /bin/sudo-rs /bin/sudoedit /bin/sudoedit-rs + /etc/alternatives/sudo /etc/alternatives/sudoedit + /lib/cargo/bin/su /lib/cargo/bin/sudo + /usr/bin/su /usr/bin/su-rs /usr/bin/sudo /usr/bin/sudo-rs /usr/bin/sudoedit /usr/bin/sudoedit-rs + /usr/lib/cargo/bin/su /usr/lib/cargo/bin/sudo + )) end end end @@ -337,15 +340,39 @@ end end - context 'installed by system_kernel', exclude_on_fips: true do + context 'installed by system_kernel', exclude_on_fips: true do describe package('linux-generic') do it { should be_installed } end end + context 'installed by base_warden', { + exclude_on_alicloud: true, + exclude_on_aws: true, + exclude_on_google: true, + exclude_on_vsphere: true, + exclude_on_cloudstack: true, + exclude_on_azure: true, + exclude_on_openstack: true, + } do + describe file('/etc/sysctl.d/20-disable-apparmor-restrict.conf') do + it { should be_file } + its(:mode) { should eq(0o644) } + its(:content) { should match /^kernel\.apparmor_restrict_unprivileged_userns = 0$/ } + its(:content) { should match /^kernel\.apparmor_restrict_unprivileged_unconfined = 0$/ } + end + end + + context 'on non-warden stemcells', { + exclude_on_warden: true, + } do + describe file('/etc/sysctl.d/20-disable-apparmor-restrict.conf') do + it { should_not be_file } + end + end + describe 'installed packages' do dpkg_list_packages = "dpkg --get-selections | cut -f1 | sed -E '#{linux_version_regex}'" - # TODO: maby we can use awk "dpkg --get-selections | awk '!/linux-(.+)-([0-9]+.+)/&&/linux/{print $1}'" let(:dpkg_list_ubuntu) { File.readlines(spec_asset('dpkg-list-ubuntu.txt')).map(&:chop) } let(:dpkg_list_kernel_ubuntu) { File.readlines(spec_asset('dpkg-list-ubuntu-kernel.txt')).map(&:chop) } @@ -425,11 +452,10 @@ expect(subject.stdout.split("\n")).to match_array(dpkg_list_ubuntu.concat(dpkg_list_kernel_ubuntu, dpkg_list_cloudstack_ubuntu)) end end - end end -describe 'Ubuntu 24.04 stemcell tarball', stemcell_tarball: true do +describe 'Ubuntu 26.04 stemcell tarball', stemcell_tarball: true do context 'installed by bosh_dpkg_list stage' do describe file("#{ENV['STEMCELL_WORKDIR']}/stemcell/packages.txt", ShelloutTypes::Chroot.new('/')) do it { should be_file } diff --git a/ci/docker/os-image-stemcell-builder/.gitignore b/ci/docker/os-image-stemcell-builder/.gitignore index 9761a2e21f..c93103d575 100644 --- a/ci/docker/os-image-stemcell-builder/.gitignore +++ b/ci/docker/os-image-stemcell-builder/.gitignore @@ -1 +1,2 @@ /*.bundle +/ovftool/ diff --git a/ci/docker/os-image-stemcell-builder/Dockerfile b/ci/docker/os-image-stemcell-builder/Dockerfile index c7ec985d18..fb2925ede6 100644 --- a/ci/docker/os-image-stemcell-builder/Dockerfile +++ b/ci/docker/os-image-stemcell-builder/Dockerfile @@ -1,6 +1,6 @@ # bosh/os-image-stemcell-builder -FROM ubuntu:noble +FROM ubuntu:resolute LABEL maintainer="cf-bosh@lists.cloudfoundry.org" @@ -46,7 +46,6 @@ RUN \ parted \ qemu-utils \ rsync \ - rsync \ s3cmd \ sudo \ tar \ @@ -55,21 +54,15 @@ RUN \ yq \ && apt-get clean -# removed `groupadd -o -g ${GROUP_ID} ubuntu` as it already exists -# && useradd -u ${USER_ID} -g ${GROUP_ID} -m ubuntu \ -# && echo 'ubuntu ALL=NOPASSWD:ALL' >> /etc/sudoers RUN echo useradd -u ${USER_ID} -g ${GROUP_ID} -m ubuntu \ && echo 'ubuntu ALL=NOPASSWD:ALL' >> /etc/sudoers -# Install syft RUN curl -sL https://github.com/anchore/syft/releases/download/${SYFT_VERSION}/syft_${SYFT_VERSION#v}_linux_amd64.tar.gz \ | tar -xz -C /usr/local/bin/ syft \ && chmod +x /usr/local/bin/syft -# we install a local ruby (3.x) because Jammy is lagging at 2.7 -# TODO: noble now has ruby 3.2 do we still want to use ruby-install? -ENV RUBY_SHA256="d2f4577306e6dd932259693233141e5c3ec13622c95b75996541b8d5b68b28b4" -ENV RUBY_VERSION="3.2.0" +ENV RUBY_SHA256="a64a8a910ac2f28834b2170dedea688f06cbc6431fcd65eb18cc49ddbf3826ae" +ENV RUBY_VERSION="3.2.10" RUN \ wget -O ruby-install-0.9.3.tar.gz https://github.com/postmodern/ruby-install/archive/v0.9.3.tar.gz \ @@ -100,17 +93,9 @@ RUN \ mkdir -p /mnt/stemcells \ && chown -R ubuntu:ubuntu /mnt/stemcells -# VMware's ovftool is used to create vSphere stemcells -ENV OVF_TOOL_INSTALLER VMware-ovftool-4.4.3-18663434-lin.x86_64.bundle -ENV OVF_TOOL_INSTALLER_SHA1 6c24e473be49c961cfc3bb16774b52b48e822991 -ADD ${OVF_TOOL_INSTALLER} /tmp/ovftool_installer.bundle -RUN \ - cd /tmp \ - && echo "${OVF_TOOL_INSTALLER_SHA1} /tmp/ovftool_installer.bundle" | sha1sum -c - \ - && chmod a+x ./ovftool_installer.bundle \ - && ln -s /bin/cat /usr/local/bin/more \ - && bash ./ovftool_installer.bundle --eulas-agreed \ - && rm -rf ./ovftool_installer.bundle /tmp/vmware-root/ /usr/local/bin/more +COPY ovftool/ /usr/lib/vmware-ovftool/ +RUN chmod +x /usr/lib/vmware-ovftool/ovftool.bin /usr/lib/vmware-ovftool/ovftool \ + && ln -s /usr/lib/vmware-ovftool/ovftool /usr/local/bin/ovftool RUN \ wget -O /usr/bin/meta4 https://github.com/dpb587/metalink/releases/download/v0.2.0/meta4-0.2.0-linux-amd64 \ @@ -118,8 +103,7 @@ RUN \ && chmod +x /usr/bin/meta4 # fixes "invalid byte sequence in US-ASCII" in `spec/support/os_image_chrony_shared_examples.rb` -RUN \ - sudo locale-gen en_US.UTF-8 +RUN sudo locale-gen en_US.UTF-8 ENV LANG en_US.UTF-8 ENV LC_ALL en_US.UTF-8 diff --git a/ci/docker/os-image-stemcell-builder/README.md b/ci/docker/os-image-stemcell-builder/README.md new file mode 100644 index 0000000000..bcbcbb68f4 --- /dev/null +++ b/ci/docker/os-image-stemcell-builder/README.md @@ -0,0 +1,37 @@ +# OS image stemcell builder (Resolute host) + +Docker image for building stemcells using Ubuntu 26.04 Resolute as the **host** OS. The Resolute-based builder is required because the Noble-based builder's `debootstrap` does not include a Resolute bootstrap script. + +## Build + +```bash +docker build -t bosh/os-image-stemcell-builder:resolute . +``` + +Note: the Dockerfile expects `ubuntu:resolute` to be available from Docker Hub. You may need to `docker login` first to avoid pull rate limits. + +## Usage + +Build an OS image: + +```bash +docker run --rm --privileged \ + -v "$(pwd):/opt/bosh" --workdir /opt/bosh \ + bosh/os-image-stemcell-builder:resolute \ + bash -c 'source /usr/local/share/chruby/chruby.sh && chruby 3.2.10 && \ + bundle && bundle exec rake "stemcell:build_os_image[ubuntu,resolute,/opt/bosh/tmp/ubuntu_base_image.tgz]"' +``` + +Build: + +```bash +docker run --rm --privileged \ + -v "$(pwd):/opt/bosh" --workdir /opt/bosh \ + bosh/os-image-stemcell-builder:resolute \ + bash -c 'source /usr/local/share/chruby/chruby.sh && chruby 3.2.10 && \ + bundle && bundle exec rake "stemcell:build_with_local_os_image[warden,warden,ubuntu,resolute,/opt/bosh/tmp/ubuntu_base_image.tgz,0.0.12]"' +``` + +## Ruby version + +The image installs Ruby 3.2.10 via `ruby-install` and manages it with `chruby`. Run `source /usr/local/share/chruby/chruby.sh && chruby 3.2.10` before any `bundle` or `rake` commands. diff --git a/ci/docker/os-image-stemcell-builder/Vagrantfile b/ci/docker/os-image-stemcell-builder/Vagrantfile deleted file mode 100644 index b01294254a..0000000000 --- a/ci/docker/os-image-stemcell-builder/Vagrantfile +++ /dev/null @@ -1,54 +0,0 @@ -VAGRANTFILE_API_VERSION = '2'.freeze - -Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - required_plugins = %w[vagrant-vbguest vagrant-disksize] - should_retry = false - required_plugins.each do |plugin| - unless Vagrant.has_plugin? plugin - system "vagrant plugin install #{plugin}" - should_retry = true - end - end - - exec 'vagrant ' + ARGV.join(' ') if should_retry - - config.disksize.size = '50GB' - - config.vm.box = 'ubuntu/bionic64' - - config.vm.provider(:virtualbox) do |v| - v.name = 'bosh-os-image-stemcell-docker-builder' - v.customize ['modifyvm', :id, '--cpus', '8'] - v.customize ['modifyvm', :id, '--memory', '8192'] - end - - config.vm.synced_folder('../../../', '/opt/bosh') - - if Vagrant.has_plugin?('vagrant-proxyconf') - if ENV['http_proxy'] - config.proxy.http = ENV['http_proxy'] - config.apt_proxy.http = ENV['http_proxy'] - end - if ENV['https_proxy'] - config.proxy.https = ENV['https_proxy'] - config.apt_proxy.https = ENV['https_proxy'] - end - config.proxy.no_proxy = ENV['no_proxy'] if ENV['no_proxy'] - end - - config.vm.provision('docker') - - config.vm.provision :shell do |shell| - shell.inline = <<-BASH - # disable annoying ctrl-p docker binding - mkdir -p ~vagrant/.docker - echo '{ "detachKeys": "ctrl-q,q" }' > ~vagrant/.docker/config.json - sudo chown -R vagrant ~vagrant/.docker - - # the centos build process runs into an error if we use the default aufs; devicemapper seems to work - # see https://github.com/docker/docker/issues/6980 - echo 'DOCKER_OPTS="${DOCKER_OPTS:-} -s devicemapper "' >> /etc/default/docker - service docker restart - BASH - end -end diff --git a/docs/resolute-dev.md b/docs/resolute-dev.md new file mode 100644 index 0000000000..a73aaf6b3f --- /dev/null +++ b/docs/resolute-dev.md @@ -0,0 +1,148 @@ +# Ubuntu 26.04 Resolute stemcell development + +Branch `feat/mk/ubuntu-resolute` adds support for building BOSH stemcells based +on Ubuntu 26.04 LTS "Resolute Raccoon". + +## Current status + +Local warden stemcell builds are working (v0.0.12). OS image tests pass +(363 examples, 0 failures). No IaaS-specific builds have been tested yet. + +## Remaining work + +### Optimizations + +- [ ] **Replace `linux-firmware` with `linux-firmware-minimal` to save ~650 MB** + `linux-image-generic` has `Depends: linux-firmware | linux-firmware-minimal`. + The full `linux-firmware` meta-package pulls in 17 vendor-specific firmware + sub-packages totaling ~652 MB under `/lib/firmware/`. None are needed for + GCP, AWS, vSphere, or Warden — all use paravirtualized devices with in-kernel + drivers. `linux-firmware-minimal` is an empty 8 KB meta-package that lists + the firmware sub-packages as Recommends instead of Depends; with + `--no-install-recommends` (which `pkg_mgr` already uses), only 22 MB of base + kernel firmware remains. + **Change**: In `stemcell_builder/stages/system_kernel/apply.sh`, change + `pkg_mgr install initramfs-tools linux-generic` to + `pkg_mgr install initramfs-tools linux-firmware-minimal linux-generic`. + Also update `dpkg-list-ubuntu.txt` and `dpkg-list-ubuntu-kernel.txt`. + +### IaaS-specific validation + +- [ ] **Validate IaaS dpkg addition lists against actual IaaS builds** + The current `dpkg-list-ubuntu-{vsphere,google,azure,cloudstack}-additions.txt` + files are carried over from Noble. They need to be validated once IaaS + pipelines are available. + +### Package decisions + +- [ ] **Decide on runit inclusion** (see TODO in `base_ubuntu_packages/apply.sh`) + runit is currently included because it provides `chpst`, which many BOSH + releases depend on. Alternatives: require releases to use BPM or `setpriv`. + +### CI / Pipeline + +- [ ] **Set up Concourse pipeline for Resolute stemcell builds** +- [ ] **Publish Resolute OS image and update metalink hashes** + `bosh-stemcell/image-metalinks/ubuntu-resolute.meta4` has placeholder hashes. + +### Testing + +- [ ] **Run stemcell tests against all target IaaS variants** + Currently only Warden builds have been tested locally. + +--- + +## Build notes + +### Docker builder (required) + +The Resolute-based builder image at +`ci/docker/os-image-stemcell-builder-resolute/` is required because the +Noble-based builder's `debootstrap` does not include a Resolute bootstrap +script. See that directory's `README.md` for build and usage instructions. + +The image installs Ruby **3.2.10** via `ruby-install`, managed with `chruby`: + +```bash +source /usr/local/share/chruby/chruby.sh && chruby 3.2.10 +``` + +### Kernel + +Resolute ships **linux-generic 7.0.0-10**. `static_libraries_config` uses +`major_kernel_version="7.0"`. + +Ubuntu Resolute split the monolithic `linux-firmware` package into 17 +vendor-specific sub-packages (see optimization item above). + +### Package list (base_ubuntu_packages) + +- **Removed vs Noble**: `mg`, `module-assistant` (not in Resolute archive). +- **Re-added**: `runit` (provides `chpst`; see package decisions above). +- **Renames**: `libxml2` → `libxml2-16`. +- **Rsyslog**: `rsyslog-mmjsonparse` and `rsyslog-mmnormalize` are not in the + archive (same as Noble). We install `rsyslog rsyslog-gnutls rsyslog-openssl + rsyslog-relp` only. +- **glibc**: 2.43 in Resolute. `libm-2.43.a` has been added to + `static_libraries_list.txt`. + +### Monit compilation (bosh_monit) + +Ubuntu 26.04 moved `crypt()` from glibc to `libcrypt`. The `bosh_monit` stage +installs `libcrypt-dev` and passes `LIBS='-lcrypt'` to monit's `./configure`. + +### Sudo / sudoers + +Resolute uses **sudo-rs** (Rust rewrite) as the default `sudo`. `sudo-rs` does +not support the `tty_tickets` Defaults option, so the sudoers file uses +`Defaults !lecture,!fqdn` (drops `tty_tickets`). The `wheel` group is created +with `root` and `vcap` as members. + +### PAM / password policies + +- **common-auth.patch**: Fixed trailing newline; applies cleanly after `nullok` + is stripped. +- **common-password.patch**: Applies cleanly as long as `libpam-pwquality` is + installed before the `password_policies` stage (which it is — installed by + `base_ubuntu_packages`). Note: a `#` comment placed inside the `debs` shell + string will silently truncate the package list; keep comments outside the + string. +- **pam_lastlog2.so**: Resolute ships `libpam-lastlog2` (from util-linux 2.41). + The `session optional pam_lastlog2.so showfailed` line is active in + `common-password`. + +### AppArmor sysctl override (Warden only) + +Ubuntu 26.04 ships `/usr/lib/sysctl.d/10-apparmor.conf` which sets +`kernel.apparmor_restrict_unprivileged_userns = 1`. When `systemd-sysctl` runs +inside a privileged container it writes to the host's `/proc/sys`, breaking +unprivileged user namespaces on the host. The `base_warden` stage creates +`/etc/sysctl.d/20-disable-apparmor-restrict.conf` to override both values to 0. +This only applies to Warden stemcells; VM stemcells retain the upstream defaults. + +### apt-key deprecation + +`apt-key` is removed in Resolute. GPG keys live in `/usr/share/keyrings/` as +binary keyring files. The OS image test uses `gpg --keyring` directly. + +### auditd + +`/usr/bin/auvirt` and `/sbin/autrace` were removed from the `auditd` package +upstream. The OS image tests have been updated accordingly. + +### OS image metalinks + +`bosh-stemcell/image-metalinks/ubuntu-resolute.meta4` contains placeholder +hashes. Update when the first Resolute OS image is published to GCS. + +## Initial validation (2026-03-02) + +See [resolute-validation-results.md](resolute-validation-results.md) for the +initial package availability and PAM patch validation run against a Resolute +minbase chroot. Some findings are now outdated (e.g. runit is available, kernel +is 7.0, glibc is 2.43). + +## References + +- [resolute-validation-results.md](resolute-validation-results.md) +- [new_stemcell_line.md](new_stemcell_line.md) diff --git a/stemcell_builder/lib/prelude_bosh.bash b/stemcell_builder/lib/prelude_bosh.bash index e2cd52337d..745e11158c 100644 --- a/stemcell_builder/lib/prelude_bosh.bash +++ b/stemcell_builder/lib/prelude_bosh.bash @@ -21,11 +21,12 @@ function run_in_bosh_chroot { " } -# remove setuid binaries - except su/sudo (sudoedit is hardlinked) +# remove setuid binaries - except su/sudo (and their -rs alternates) function restrict_binary_setuid { run_in_bosh_chroot $chroot " find / -xdev -perm /ug=s -type f \ - -not \( -name sudo -o -name su -o -name sudoedit \) \ + -not \( -name sudo -o -name su -o -name sudoedit \ + -o -name sudo-rs -o -name su-rs -o -name sudoedit-rs \) \ -exec chmod ug-s {} \; " diff --git a/stemcell_builder/stages/base_ubuntu_packages/apply.sh b/stemcell_builder/stages/base_ubuntu_packages/apply.sh index 2d08184a00..ddd52ad19b 100755 --- a/stemcell_builder/stages/base_ubuntu_packages/apply.sh +++ b/stemcell_builder/stages/base_ubuntu_packages/apply.sh @@ -6,17 +6,19 @@ base_dir=$(readlink -nf $(dirname $0)/../..) source $base_dir/lib/prelude_apply.bash source $base_dir/etc/settings.bash +# TODO: Decide if we want to include runit (which provides chpst) or break a lot of releases and tell them to use BPM or setpriv debs="libssl-dev lsof strace bind9-host dnsutils tcpdump iputils-arping \ curl wget bison libreadline6-dev rng-tools \ -libxml2 libxml2-dev libxslt1.1 libxslt1-dev zip unzip \ +libxml2-16 libxml2-dev libxslt1.1 libxslt1-dev zip unzip \ flex psmisc apparmor-utils iptables nftables sysstat \ rsync openssh-server traceroute libncurses5-dev quota \ libaio1t64 gdb libcap2-bin libcap2-dev libbz2-dev \ cmake uuid-dev libgcrypt-dev ca-certificates \ -mg htop module-assistant debhelper runit parted \ +htop debhelper parted \ cloud-guest-utils anacron software-properties-common \ xfsprogs gdisk chrony dbus nvme-cli rng-tools fdisk \ -ethtool libpam-pwquality gpg-agent libcurl4 libcurl4-openssl-dev resolvconf net-tools ifupdown" +ethtool libpam-pwquality libpam-lastlog2 gpg-agent libcurl4 libcurl4-openssl-dev \ +resolvconf net-tools ifupdown runit" pkg_mgr purge netplan.io run_in_chroot $chroot " diff --git a/stemcell_builder/stages/base_warden/apply.sh b/stemcell_builder/stages/base_warden/apply.sh index 8a543c03ab..c4a2aa924c 100755 --- a/stemcell_builder/stages/base_warden/apply.sh +++ b/stemcell_builder/stages/base_warden/apply.sh @@ -16,6 +16,19 @@ sed -i 's/^local_events = yes$/local_events = no/g' $chroot/etc/audit/auditd.con # restart limit of 5 restarts in 5 seconds sed -i 's/^#DefaultStartLimitBurst=5$/DefaultStartLimitBurst=500/g' $chroot/etc/systemd/system.conf +# Override the upstream AppArmor sysctl restrictions that ship in +# /usr/lib/sysctl.d/10-apparmor.conf on Ubuntu 26.04+. When systemd-sysctl +# runs inside a privileged container it writes to the *host* /proc/sys, +# resetting kernel.apparmor_restrict_unprivileged_userns to 1 and breaking +# any host process that relies on unprivileged user namespaces. +if [ -f "$chroot/usr/lib/sysctl.d/10-apparmor.conf" ]; then + cat > "$chroot/etc/sysctl.d/20-disable-apparmor-restrict.conf" < $chroot/var/vcap/bosh/bin/restart_networking </dev/null && cracklib-update || true" + run_in_chroot $chroot " groupadd --system admin groupadd -f vcap diff --git a/stemcell_builder/stages/bosh_users/assets/sudoers b/stemcell_builder/stages/bosh_users/assets/sudoers index d2f7795cc6..e7fdcd0694 100644 --- a/stemcell_builder/stages/bosh_users/assets/sudoers +++ b/stemcell_builder/stages/bosh_users/assets/sudoers @@ -3,7 +3,7 @@ # See the man page for details on how to write a sudoers file. # Defaults -Defaults !lecture,tty_tickets,!fqdn +Defaults !lecture,!fqdn # Uncomment to allow members of group sudo to not need a password # %sudo ALL=NOPASSWD: ALL diff --git a/stemcell_builder/stages/password_policies/apply.sh b/stemcell_builder/stages/password_policies/apply.sh index bf9753b841..1a5717dd8e 100755 --- a/stemcell_builder/stages/password_policies/apply.sh +++ b/stemcell_builder/stages/password_policies/apply.sh @@ -38,4 +38,6 @@ patch $chroot/etc/pam.d/login < $assets_dir/ubuntu/login.patch # /etc/login.defs are only effective for new users sed -i -r 's/^PASS_MIN_DAYS.+/PASS_MIN_DAYS 1/' $chroot/etc/login.defs +# Ensure ENCRYPT_METHOD matches the sha512 used in pam_unix.so (Resolute defaults to YESCRYPT) +sed -i -r 's/^ENCRYPT_METHOD .+/ENCRYPT_METHOD SHA512/' $chroot/etc/login.defs run_in_chroot $chroot "chage --mindays 1 vcap" diff --git a/stemcell_builder/stages/password_policies/assets/ubuntu/common-auth.patch b/stemcell_builder/stages/password_policies/assets/ubuntu/common-auth.patch index 80fe028b9b..dd1b02b10a 100644 --- a/stemcell_builder/stages/password_policies/assets/ubuntu/common-auth.patch +++ b/stemcell_builder/stages/password_policies/assets/ubuntu/common-auth.patch @@ -8,4 +8,4 @@ +auth sufficient pam_faillock.so authsucc audit deny=3 unlock_time=604800 fail_interval=900 # here's the fallback if no module succeeds auth requisite pam_deny.so - # prime the stack with a positive return value if there isn't one already; \ No newline at end of file + # prime the stack with a positive return value if there isn't one already; diff --git a/stemcell_builder/stages/password_policies/assets/ubuntu/common-password.patch b/stemcell_builder/stages/password_policies/assets/ubuntu/common-password.patch index d1bc57e2ca..c74257f2e0 100644 --- a/stemcell_builder/stages/password_policies/assets/ubuntu/common-password.patch +++ b/stemcell_builder/stages/password_policies/assets/ubuntu/common-password.patch @@ -13,5 +13,5 @@ # since the modules above will each just jump around password required pam_permit.so # and here are more per-package modules (the "Additional" block) -+#session optional pam_lastlog2.so showfailed #NOBLE_TODO: this will only work if util-linux =>2.40 which provide pam_lastlog2.so or if users will install it manually ++session optional pam_lastlog2.so showfailed # end of pam-auth-update config diff --git a/stemcell_builder/stages/restrict_su_command/apply.sh b/stemcell_builder/stages/restrict_su_command/apply.sh index 287350f2de..208fcd859e 100755 --- a/stemcell_builder/stages/restrict_su_command/apply.sh +++ b/stemcell_builder/stages/restrict_su_command/apply.sh @@ -5,9 +5,12 @@ set -ex base_dir=$(readlink -nf $(dirname $0)/../..) source $base_dir/lib/prelude_apply.bash -# restrict Access to the su Command add the following line to the /etc/pam.d/su file. -# auth required pam_wheel.so use_uid add vcap user to 'root' group +# CIS-9.5: restrict access to the su command via pam_wheel. +# pam_wheel.so use_uid requires the calling user to be in the wheel group. +# Ubuntu does not ship a wheel group, so we create it and add root + vcap. run_in_chroot $chroot " - sudo echo 'auth required pam_wheel.so use_uid' >> /etc/pam.d/su - sudo usermod -aG sudo vcap + groupadd -f wheel + usermod -aG wheel root + usermod -aG wheel,sudo vcap + echo 'auth required pam_wheel.so use_uid' >> /etc/pam.d/su " diff --git a/stemcell_builder/stages/static_libraries_config/apply.sh b/stemcell_builder/stages/static_libraries_config/apply.sh index a7ce78e70b..a48241110d 100755 --- a/stemcell_builder/stages/static_libraries_config/apply.sh +++ b/stemcell_builder/stages/static_libraries_config/apply.sh @@ -10,7 +10,7 @@ source $base_dir/etc/settings.bash cp -p "${assets_dir}/static_libraries_list.txt" $chroot/var/vcap/bosh/etc/static_libraries_list kernel_suffix="-generic" -major_kernel_version="6.8" +major_kernel_version="7.0" if [[ "${stemcell_operating_system_variant}" == 'fips' ]]; then # TODO use iaas specific kernel diff --git a/stemcell_builder/stages/static_libraries_config/assets/static_libraries_list.txt b/stemcell_builder/stages/static_libraries_config/assets/static_libraries_list.txt index a7185b4774..92ec0497db 100644 --- a/stemcell_builder/stages/static_libraries_config/assets/static_libraries_list.txt +++ b/stemcell_builder/stages/static_libraries_config/assets/static_libraries_list.txt @@ -19,14 +19,36 @@ /usr/lib/gcc/x86_64-linux-gnu/13/libsupc++.a /usr/lib/gcc/x86_64-linux-gnu/13/libtsan.a /usr/lib/gcc/x86_64-linux-gnu/13/libubsan.a +/usr/lib/gcc/x86_64-linux-gnu/15/libasan.a +/usr/lib/gcc/x86_64-linux-gnu/15/libatomic.a +/usr/lib/gcc/x86_64-linux-gnu/15/libbacktrace.a +/usr/lib/gcc/x86_64-linux-gnu/15/libgcc.a +/usr/lib/gcc/x86_64-linux-gnu/15/libgcc_eh.a +/usr/lib/gcc/x86_64-linux-gnu/15/libgcov.a +/usr/lib/gcc/x86_64-linux-gnu/15/libgomp.a +/usr/lib/gcc/x86_64-linux-gnu/15/libhwasan.a +/usr/lib/gcc/x86_64-linux-gnu/15/libitm.a +/usr/lib/gcc/x86_64-linux-gnu/15/liblsan.a +/usr/lib/gcc/x86_64-linux-gnu/15/libquadmath.a +/usr/lib/gcc/x86_64-linux-gnu/15/libssp_nonshared.a +/usr/lib/gcc/x86_64-linux-gnu/15/libstdc++.a +/usr/lib/gcc/x86_64-linux-gnu/15/libstdc++exp.a +/usr/lib/gcc/x86_64-linux-gnu/15/libstdc++fs.a +/usr/lib/gcc/x86_64-linux-gnu/15/libsupc++.a +/usr/lib/gcc/x86_64-linux-gnu/15/libtsan.a +/usr/lib/gcc/x86_64-linux-gnu/15/libubsan.a /usr/lib/libsupp.a /usr/lib/x86_64-linux-gnu/gprofng/libgp-collectorAPI.a /usr/lib/x86_64-linux-gnu/libBrokenLocale.a /usr/lib/x86_64-linux-gnu/libanl.a +/usr/lib/x86_64-linux-gnu/libbrotlicommon.a +/usr/lib/x86_64-linux-gnu/libbrotlidec.a +/usr/lib/x86_64-linux-gnu/libbrotlienc.a /usr/lib/x86_64-linux-gnu/libbz2.a /usr/lib/x86_64-linux-gnu/libc.a /usr/lib/x86_64-linux-gnu/libc_nonshared.a /usr/lib/x86_64-linux-gnu/libcap.a +/usr/lib/x86_64-linux-gnu/libcom_err.a /usr/lib/x86_64-linux-gnu/libcrypt.a /usr/lib/x86_64-linux-gnu/libcrypto.a /usr/lib/x86_64-linux-gnu/libcurl.a @@ -36,22 +58,37 @@ /usr/lib/x86_64-linux-gnu/libformw.a /usr/lib/x86_64-linux-gnu/libg.a /usr/lib/x86_64-linux-gnu/libgcrypt.a +/usr/lib/x86_64-linux-gnu/libgmp.a +/usr/lib/x86_64-linux-gnu/libgmpxx.a +/usr/lib/x86_64-linux-gnu/libgnutls.a +/usr/lib/x86_64-linux-gnu/libgnutls-dane.a +/usr/lib/x86_64-linux-gnu/libgnutls-openssl.a /usr/lib/x86_64-linux-gnu/libgpg-error.a /usr/lib/x86_64-linux-gnu/libhistory.a +/usr/lib/x86_64-linux-gnu/libhogweed.a /usr/lib/x86_64-linux-gnu/libicudata.a /usr/lib/x86_64-linux-gnu/libicui18n.a /usr/lib/x86_64-linux-gnu/libicuio.a /usr/lib/x86_64-linux-gnu/libicutest.a /usr/lib/x86_64-linux-gnu/libicutu.a /usr/lib/x86_64-linux-gnu/libicuuc.a +/usr/lib/x86_64-linux-gnu/libidn2.a +/usr/lib/x86_64-linux-gnu/liblber.a +/usr/lib/x86_64-linux-gnu/libldap.a +/usr/lib/x86_64-linux-gnu/libldap_r.a +/usr/lib/x86_64-linux-gnu/liblzma.a /usr/lib/x86_64-linux-gnu/libm-2.35.a /usr/lib/x86_64-linux-gnu/libm-2.38.a /usr/lib/x86_64-linux-gnu/libm-2.39.a +/usr/lib/x86_64-linux-gnu/libm-2.42.a +/usr/lib/x86_64-linux-gnu/libm-2.43.a /usr/lib/x86_64-linux-gnu/libm.a /usr/lib/x86_64-linux-gnu/libmcheck.a /usr/lib/x86_64-linux-gnu/libmenu.a /usr/lib/x86_64-linux-gnu/libmenuw.a /usr/lib/x86_64-linux-gnu/libmvec.a +/usr/lib/x86_64-linux-gnu/libnettle.a +/usr/lib/x86_64-linux-gnu/libnghttp2.a /usr/lib/x86_64-linux-gnu/libncurses++.a /usr/lib/x86_64-linux-gnu/libncurses++w.a /usr/lib/x86_64-linux-gnu/libncurses.a @@ -59,21 +96,26 @@ /usr/lib/x86_64-linux-gnu/libnsl.a /usr/lib/x86_64-linux-gnu/libpanel.a /usr/lib/x86_64-linux-gnu/libpanelw.a +/usr/lib/x86_64-linux-gnu/libpsl.a /usr/lib/x86_64-linux-gnu/libpsx.a /usr/lib/x86_64-linux-gnu/libpthread.a /usr/lib/x86_64-linux-gnu/libpthread_nonshared.a /usr/lib/x86_64-linux-gnu/libreadline.a /usr/lib/x86_64-linux-gnu/libresolv.a /usr/lib/x86_64-linux-gnu/librt.a +/usr/lib/x86_64-linux-gnu/librtmp.a +/usr/lib/x86_64-linux-gnu/libssh2.a /usr/lib/x86_64-linux-gnu/libssl.a /usr/lib/x86_64-linux-gnu/libtermcap.a /usr/lib/x86_64-linux-gnu/libtic.a /usr/lib/x86_64-linux-gnu/libtinfo.a +/usr/lib/x86_64-linux-gnu/libtasn1.a /usr/lib/x86_64-linux-gnu/libtirpc.a /usr/lib/x86_64-linux-gnu/libutil.a /usr/lib/x86_64-linux-gnu/libuuid.a /usr/lib/x86_64-linux-gnu/libxml2.a /usr/lib/x86_64-linux-gnu/libz.a +/usr/lib/x86_64-linux-gnu/libzstd.a /usr/src/linux-headers-__KERNEL_VERSION__/tools/bpf/resolve_btfids/libbpf/libbpf.a /usr/src/linux-headers-__KERNEL_VERSION__/tools/bpf/resolve_btfids/libsubcmd/libsubcmd.a /usr/src/linux-headers-__KERNEL_VERSION__/tools/objtool/libsubcmd/libsubcmd.a