From 3178c3d866f2f4b4cbdd4d09f45d7b02025ff985 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 9 Oct 2020 15:26:19 +0000 Subject: [PATCH] Import dc58c20730413508f07f9c9f9ca9a5235f1b6325 --- .gitmodules | 3 + README.md | 16 +- fedora-coreos-config | 1 + group | 46 +++ image.yaml | 17 + kola-denylist.yaml | 19 ++ live/EFI/redhat/grub.cfg | 33 ++ live/README-devel.md | 13 + live/isolinux/boot.msg | 5 + live/isolinux/isolinux.cfg | 74 +++++ live/zipl.prm | 1 + manifest.yaml | 302 +++++++++++++++++ overlay.d/01fcos | 1 + overlay.d/02fcos-nouveau | 1 + .../conf.d/10-disable-default-plugins.conf | 7 + .../module-setup.sh | 12 + .../30rhcos-afterburn-checkin/module-setup.sh | 24 ++ .../rhcos-afterburn-checkin.service | 13 + .../40rhcos-fde/coreos-encrypt.service | 35 ++ .../coreos-fde-check-needsnet.service | 22 ++ .../40rhcos-fde/coreos-luks-generator | 55 ++++ .../40rhcos-fde/coreos-luks-open.service | 31 ++ .../modules.d/40rhcos-fde/module-setup.sh | 94 ++++++ .../coreos-dummy-ignition-files-run.sh | 54 ++++ .../modules.d/40rhcos-fips/module-setup.sh | 41 +++ .../40rhcos-fips/rhcos-fips-finish.service | 20 ++ .../modules.d/40rhcos-fips/rhcos-fips.service | 35 ++ .../modules.d/40rhcos-fips/rhcos-fips.sh | 132 ++++++++ .../modules.d/41rhcos-ignition-conf/base.ign | 19 ++ .../41rhcos-ignition-conf/module-setup.sh | 19 ++ .../system-preset/10-rhcos-disabled.preset | 5 + .../system-preset/43-manifest-rhcos.preset | 22 ++ ...oreos-generate-iscsi-initiatorname.service | 18 ++ .../run-every-boot.conf | 3 + .../usr/lib/systemd/system/gcp-routes.service | 16 + .../lib/systemd/system/rhcos-growpart.service | 40 +++ overlay.d/05rhcos/usr/libexec/coreos-cryptfs | 303 ++++++++++++++++++ overlay.d/05rhcos/usr/libexec/coreos-cryptlib | 30 ++ overlay.d/05rhcos/usr/libexec/rhcos-growpart | 56 ++++ overlay.d/05rhcos/usr/sbin/gcp-routes.sh | 143 +++++++++ .../50rhcos-tuned-bits/module-setup.sh | 13 + .../50rhcos-tuned-bits/tuned-workqueue.sh | 20 ++ overlay.d/20platform-chrony | 1 + overlay.d/21dhcp-chrony | 1 + overlay.d/README.md | 23 ++ passwd | 27 ++ rhcos-packages.yaml | 20 ++ scripts/ami_uncopy_regions | 28 ++ scripts/bc-is-prod.sh | 7 + scripts/download-extensions | 48 +++ scripts/install-openshift | 182 +++++++++++ scripts/upload-aliyun-image | 1 + scripts/upload-ami | 194 +++++++++++ scripts/verify-kernel-versions | 141 ++++++++ sync-sources.sh | 26 ++ .../chrony/coreos-platform-chrony-generator | 15 + tests/kola/chrony/dhcp-propagation | 73 +++++ tests/kola/luks/ignition/config.ign | 33 ++ tests/kola/luks/ignition/test.sh | 12 + tests/kola/luks/tpm/config.ign | 16 + tests/kola/luks/tpm/kola.json | 4 + tests/kola/luks/tpm/tpm-validate-encrypted | 38 +++ tests/kola/misc-ro/misc-ro.sh | 95 ++++++ tests/kola/var-mount/config.ign | 36 +++ tests/kola/var-mount/test.sh | 12 + 65 files changed, 2838 insertions(+), 9 deletions(-) create mode 100644 .gitmodules create mode 160000 fedora-coreos-config create mode 100644 group create mode 100644 image.yaml create mode 100644 kola-denylist.yaml create mode 100644 live/EFI/redhat/grub.cfg create mode 100644 live/README-devel.md create mode 100644 live/isolinux/boot.msg create mode 100644 live/isolinux/isolinux.cfg create mode 100644 live/zipl.prm create mode 100644 manifest.yaml create mode 120000 overlay.d/01fcos create mode 120000 overlay.d/02fcos-nouveau create mode 100644 overlay.d/05rhcos/usr/lib/NetworkManager/conf.d/10-disable-default-plugins.conf create mode 100644 overlay.d/05rhcos/usr/lib/dracut/modules.d/29rhcos-need-network-manager/module-setup.sh create mode 100644 overlay.d/05rhcos/usr/lib/dracut/modules.d/30rhcos-afterburn-checkin/module-setup.sh create mode 100644 overlay.d/05rhcos/usr/lib/dracut/modules.d/30rhcos-afterburn-checkin/rhcos-afterburn-checkin.service create mode 100644 overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-encrypt.service create mode 100644 overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-fde-check-needsnet.service create mode 100755 overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-luks-generator create mode 100644 overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-luks-open.service create mode 100755 overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/module-setup.sh create mode 100755 overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/coreos-dummy-ignition-files-run.sh create mode 100755 overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/module-setup.sh create mode 100644 overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips-finish.service create mode 100644 overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips.service create mode 100755 overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips.sh create mode 100644 overlay.d/05rhcos/usr/lib/dracut/modules.d/41rhcos-ignition-conf/base.ign create mode 100755 overlay.d/05rhcos/usr/lib/dracut/modules.d/41rhcos-ignition-conf/module-setup.sh create mode 100644 overlay.d/05rhcos/usr/lib/systemd/system-preset/10-rhcos-disabled.preset create mode 100644 overlay.d/05rhcos/usr/lib/systemd/system-preset/43-manifest-rhcos.preset create mode 100644 overlay.d/05rhcos/usr/lib/systemd/system/coreos-generate-iscsi-initiatorname.service create mode 100644 overlay.d/05rhcos/usr/lib/systemd/system/coreos-update-ca-trust.service.d/run-every-boot.conf create mode 100644 overlay.d/05rhcos/usr/lib/systemd/system/gcp-routes.service create mode 100644 overlay.d/05rhcos/usr/lib/systemd/system/rhcos-growpart.service create mode 100755 overlay.d/05rhcos/usr/libexec/coreos-cryptfs create mode 100755 overlay.d/05rhcos/usr/libexec/coreos-cryptlib create mode 100755 overlay.d/05rhcos/usr/libexec/rhcos-growpart create mode 100755 overlay.d/05rhcos/usr/sbin/gcp-routes.sh create mode 100755 overlay.d/15rhcos-tuned-bits/usr/lib/dracut/modules.d/50rhcos-tuned-bits/module-setup.sh create mode 100755 overlay.d/15rhcos-tuned-bits/usr/lib/dracut/modules.d/50rhcos-tuned-bits/tuned-workqueue.sh create mode 120000 overlay.d/20platform-chrony create mode 120000 overlay.d/21dhcp-chrony create mode 100644 overlay.d/README.md create mode 100644 passwd create mode 100644 rhcos-packages.yaml create mode 100644 scripts/ami_uncopy_regions create mode 100755 scripts/bc-is-prod.sh create mode 100755 scripts/download-extensions create mode 100755 scripts/install-openshift create mode 120000 scripts/upload-aliyun-image create mode 100755 scripts/upload-ami create mode 100755 scripts/verify-kernel-versions create mode 100755 sync-sources.sh create mode 100755 tests/kola/chrony/coreos-platform-chrony-generator create mode 100755 tests/kola/chrony/dhcp-propagation create mode 100644 tests/kola/luks/ignition/config.ign create mode 100755 tests/kola/luks/ignition/test.sh create mode 100644 tests/kola/luks/tpm/config.ign create mode 100644 tests/kola/luks/tpm/kola.json create mode 100755 tests/kola/luks/tpm/tpm-validate-encrypted create mode 100755 tests/kola/misc-ro/misc-ro.sh create mode 100644 tests/kola/var-mount/config.ign create mode 100755 tests/kola/var-mount/test.sh diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..909318808 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "fedora-coreos-config"] + path = fedora-coreos-config + url = https://github.com/coreos/fedora-coreos-config diff --git a/README.md b/README.md index 80450fab6..428affa8a 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,9 @@ -Please see https://github.com/openshift/installer to install -an OpenShift cluster which uses Red Hat CoreOS. +This repository is the "config" repository used to build +RHEL CoreOS using [coreos-assembler](https://github.com/coreos/coreos-assembler/). -This repository provides a place to report issues about Red Hat CoreOS, in -addition to [the Bugzilla product](https://bugzilla.redhat.com/enter_bug.cgi?product=OpenShift%20Container%20Platform&component=RHCOS). +There was a previous git repository inside the Red Hat +firewall never published. The history of that repository +is entangled with various private things and is omitted. -For more information (RHT internal): https://url.corp.redhat.com/redhat-coreos - -You may also be interested in [Fedora CoreOS](https://coreos.fedoraproject.org/) -and the [coreos-assembler](https://github.com/coreos/coreos-assembler/) project -for example. +Going forward, this repository will be canonical; more +to come. \ No newline at end of file diff --git a/fedora-coreos-config b/fedora-coreos-config new file mode 160000 index 000000000..16da48078 --- /dev/null +++ b/fedora-coreos-config @@ -0,0 +1 @@ +Subproject commit 16da480786222d407a33d944952b5c8e6312028b diff --git a/group b/group new file mode 100644 index 000000000..e86d91b24 --- /dev/null +++ b/group @@ -0,0 +1,46 @@ +root:x:0: +bin:x:1: +daemon:x:2: +sys:x:3: +adm:x:4: +tty:x:5: +disk:x:6: +lp:x:7: +mem:x:8: +kmem:x:9: +wheel:x:10: +cdrom:x:11: +mail:x:12: +man:x:15: +sudo:x:16: +dialout:x:18: +floppy:x:19: +games:x:20: +tape:x:30: +video:x:39: +ftp:x:50: +lock:x:54: +audio:x:63: +nobody:x:99: +users:x:100: +utmp:x:22: +utempter:x:35: +ssh_keys:x:999: +systemd-journal:x:190: +dbus:x:81: +polkitd:x:998: +etcd:x:997: +dip:x:40: +cgred:x:996: +tss:x:59: +avahi-autoipd:x:170: +rpc:x:32: +sssd:x:993: +dockerroot:x:986: +rpcuser:x:29: +nfsnobody:x:65534: +kube:x:994: +sshd:x:74: +chrony:x:992: +openvswitch:x:800: +hugetlbfs:x:801: diff --git a/image.yaml b/image.yaml new file mode 100644 index 000000000..314343c7d --- /dev/null +++ b/image.yaml @@ -0,0 +1,17 @@ +# See https://github.com/coreos/coreos-assembler/pull/298 +size: 16 + +# Enable LUKS root volume +# Disabled due to https://gitlab.cee.redhat.com/coreos/redhat-coreos/merge_requests/632 +luks_rootfs: "yes" +# This pairs with the above so we can easily detect in the initrd +extra-kargs: + - rhcos.root=crypt_rootfs + # https://bugzilla.redhat.com/show_bug.cgi?id=1830280 + - random.trust_cpu=on +# https://bugzilla.redhat.com/show_bug.cgi?id=1812276 +squashfs-compression: gzip + +# Disable networking by default on firstboot. We can drop this once cosa stops +# defaulting to `ip=dhcp,dhcp6 rd.neednet=1` when it doesn't see this key. +ignition-network-kcmdline: [] diff --git a/kola-denylist.yaml b/kola-denylist.yaml new file mode 100644 index 000000000..289bc3903 --- /dev/null +++ b/kola-denylist.yaml @@ -0,0 +1,19 @@ +# This file documents currently known-to-fail kola tests. It is consumed by +# coreos-assembler to automatically skip some tests. For more information, +# see: https://github.com/coreos/coreos-assembler/pull/866. +- pattern: fips.enable* + tracker: https://bugzilla.redhat.com/show_bug.cgi?id=1782026 + arches: + - s390x +- pattern: crio.base + tracker: https://github.com/kubernetes/kubernetes/issues/87325 + arches: + - s390x + - ppc64le +# for s390x by-partlabel can't be used and even if that is avoided by using part-uuid, still depends on the cpi fix below +- pattern: ext.config.var-mount + tracker: https://github.com/ibm-s390-tools/s390-tools/pull/82 + arches: + - s390x +- pattern: coreos.ignition.journald-log + tracker: https://github.com/coreos/coreos-assembler/issues/1173 diff --git a/live/EFI/redhat/grub.cfg b/live/EFI/redhat/grub.cfg new file mode 100644 index 000000000..bdd36ed53 --- /dev/null +++ b/live/EFI/redhat/grub.cfg @@ -0,0 +1,33 @@ +# Note this file mostly matches the grub.cfg file from within the +# efiboot.img on the Fedora Server DVD iso. Diff this file with that +# file in the future to pick up changes. +# +# One diff to note is we use linux and initrd instead of linuxefi and +# initrdefi. We do this because it works and allows us to use this same +# file on other architecutres. https://github.com/coreos/fedora-coreos-config/issues/63 +# +# This file gets embedded into the efiboot.img +set default="1" + +function load_video { + insmod efi_gop + insmod efi_uga + insmod video_bochs + insmod video_cirrus + insmod all_video +} + +load_video +set gfxpayload=keep +insmod gzio +insmod part_gpt +insmod ext2 + +set timeout=5 +### END /etc/grub.d/00_header ### + +### BEGIN /etc/grub.d/10_linux ### +menuentry 'RHEL CoreOS (Live)' --class fedora --class gnu-linux --class gnu --class os { + linux /images/pxeboot/vmlinuz @@KERNEL-ARGS@@ ignition.firstboot ignition.platform.id=metal + initrd /images/pxeboot/initrd.img /images/ignition.img +} diff --git a/live/README-devel.md b/live/README-devel.md new file mode 100644 index 000000000..6a123986f --- /dev/null +++ b/live/README-devel.md @@ -0,0 +1,13 @@ +These files will be copied to the target live ISO +via the CoreOS Assembler buildextend-live call. It +picks up all files in the coreos/fedora-coreos-config/live/ +directory and copies them to the base of the ISO. + +Files currently copied are: + +- isolinux/boot.msg +- isolinux/isolinux.cfg + +Files that get copied into efiboot.img in the ISO: + +- EFI/grub.cfg diff --git a/live/isolinux/boot.msg b/live/isolinux/boot.msg new file mode 100644 index 000000000..362e9e5eb --- /dev/null +++ b/live/isolinux/boot.msg @@ -0,0 +1,5 @@ + +splash.lss + + - Press the 0107 key to boot. + diff --git a/live/isolinux/isolinux.cfg b/live/isolinux/isolinux.cfg new file mode 100644 index 000000000..a614af160 --- /dev/null +++ b/live/isolinux/isolinux.cfg @@ -0,0 +1,74 @@ +# Note this file mostly matches the isolinux.cfg file from the Fedora +# Server DVD iso. Diff this file with that file in the future to pick up +# changes. +serial 0 +default vesamenu.c32 +# timeout in units of 1/10s. 50 == 5 seconds +timeout 50 + +display boot.msg + +# Clear the screen when exiting the menu, instead of leaving the menu displayed. +# For vesamenu, this means the graphical background is still displayed without +# the menu itself for as long as the screen remains in graphics mode. +menu clear +menu background splash.png +menu title RHEL CoreOS +menu vshift 8 +menu rows 18 +menu margin 8 +#menu hidden +menu helpmsgrow 15 +menu tabmsgrow 13 + +# Border Area +menu color border * #00000000 #00000000 none + +# Selected item +menu color sel 0 #ffffffff #00000000 none + +# Title bar +menu color title 0 #ff7ba3d0 #00000000 none + +# Press [Tab] message +menu color tabmsg 0 #ff3a6496 #00000000 none + +# Unselected menu item +menu color unsel 0 #84b8ffff #00000000 none + +# Selected hotkey +menu color hotsel 0 #84b8ffff #00000000 none + +# Unselected hotkey +menu color hotkey 0 #ffffffff #00000000 none + +# Help text +menu color help 0 #ffffffff #00000000 none + +# A scrollbar of some type? Not sure. +menu color scrollbar 0 #ffffffff #ff355594 none + +# Timeout msg +menu color timeout 0 #ffffffff #00000000 none +menu color timeout_msg 0 #ffffffff #00000000 none + +# Command prompt text +menu color cmdmark 0 #84b8ffff #00000000 none +menu color cmdline 0 #ffffffff #00000000 none + +# Do not display the actual menu unless the user presses a key. All that is displayed is a timeout message. + +menu tabmsg Press Tab for full configuration options on menu items. + +menu separator # insert an empty line +menu separator # insert an empty line + +label linux + menu label ^RHEL CoreOS (Live) + menu default + kernel /images/pxeboot/vmlinuz + append initrd=/images/pxeboot/initrd.img,/images/ignition.img @@KERNEL-ARGS@@ ignition.firstboot ignition.platform.id=metal + +menu separator # insert an empty line + +menu end diff --git a/live/zipl.prm b/live/zipl.prm new file mode 100644 index 000000000..56a2c07e8 --- /dev/null +++ b/live/zipl.prm @@ -0,0 +1 @@ +@@KERNEL-ARGS@@ ignition.firstboot ignition.platform.id=metal diff --git a/manifest.yaml b/manifest.yaml new file mode 100644 index 000000000..908d4a8df --- /dev/null +++ b/manifest.yaml @@ -0,0 +1,302 @@ +rojig: + license: MIT + name: rhcos + summary: OpenShift 4 + +# We inherit from Fedora CoreOS' base configuration +include: + - fedora-coreos-config/manifests/ignition-and-ostree.yaml + - fedora-coreos-config/manifests/file-transfer.yaml + # RHCOS owned packages + - rhcos-packages.yaml + +arch-include: + x86_64: fedora-coreos-config/manifests/grub2-removals.yaml + ppc64le: fedora-coreos-config/manifests/grub2-removals.yaml + aarch64: fedora-coreos-config/manifests/grub2-removals.yaml + +repos: + # Base RHEL + - rhel8-baseos + - rhel8-appstream + - rhel8-fast-datapath + # ART RHAOS repos + - art-rhaos-4.4 + - art-rhaos-4.5 + - art-rhaos-4.6 + - art-rhaos-4.7 + +# We include hours/minutes to avoid version number reuse +automatic-version-prefix: "47.82." +# This ensures we're semver-compatible which OpenShift wants +automatic-version-suffix: "-" +mutate-os-release: "4.7" + +documentation: false +initramfs-args: + - "--no-hostonly" + - "--add-drivers" + - "mptspi vmw_pvscsi" + - "--omit-drivers" + - "nouveau" + - "--omit" + # we don't need root-on-NFS + # see upstream: https://github.com/coreos/fedora-coreos-config/pull/60 + - "nfs" + - "--add" + - "iscsi" + - "ignition" + - "--add" + - "ifcfg" + - "--add" + - "fips" + # The current default in RHEL8 is network-legacy + ## XXX: This does not work for now: https://github.com/dracutdevs/dracut/issues/798 + ## XXX: Temporarily use overlay.d/05rhcos/usr/lib/dracut/modules.d/29rhcos-need-network-manager/module-setup.sh + #- "--add" + #- "network-manager" + - "--omit" + - "network-legacy" + +postprocess: + - | + #!/usr/bin/env bash + set -xeo pipefail + + # Disable PasswordAuthentication in SSH + sed -i "s|^PasswordAuthentication yes$|PasswordAuthentication no|g" /etc/ssh/sshd_config + # Disable root login because don't do that. + sed -i "s|^PermitRootLogin yes$|PermitRootLogin no|g" /etc/ssh/sshd_config + # Enable ClientAliveInterval and set to 180 per https://bugzilla.redhat.com/show_bug.cgi?id=1701050 + sed -i "s|^#ClientAliveInterval 0$|ClientAliveInterval 180|g" /etc/ssh/sshd_config + + # TEMPORARY: Create /etc/vmware-tools/tools.conf to ensure RHCOS shows up properly in VMWare + # See https://jira.coreos.com/browse/RHCOS-258 + if [ "$(uname -m)" == "x86_64" ]; then + cat > /etc/vmware-tools/tools.conf <<'EOF' + [guestosinfo] + short-name = rhel8-64 + EOF + fi + + # Nuke network.service from orbit + # https://github.com/openshift/os/issues/117 + rm -rf /etc/rc.d/init.d/network /etc/rc.d/rc*.d/*network + + # We're not using resolved yet + rm -f /usr/lib/systemd/system/systemd-resolved.service + + # Enable tmp-on-tmpfs by default because we don't want to have things + # leak across reboots, it increases alignment with FCOS, and also fixes + # the Live ISO. First, verify that RHEL is still disabling. + grep -q '# RHEL-only: Disable /tmp on tmpfs' /usr/lib/systemd/system/basic.target + echo '# RHCOS-only: we follow the Fedora/upstream default' >> /usr/lib/systemd/system/basic.target + echo 'Wants=tmp.mount' >> /usr/lib/systemd/system/basic.target + + # Let's have a non-boring motd, just like CL (although theirs is more subdued + # nowadays compared to early versions with ASCII art). One thing we do here + # is add --- as a "separator"; the idea is that any "dynamic" information should + # be below that. + # See: https://projects.engineering.redhat.com/browse/COREOS-1029 + . /etc/os-release + cat > /etc/motd < /etc/nsswitch.conf + for pam_file in system-auth password-auth smartcard-auth fingerprint-auth postlogin; do + authselect test sssd --${pam_file} | tail -n +2 > /etc/pam.d/${pam_file} + done + rm -f $(which authselect) + + # Stop shipping a baked initiator name in the image; this should be generated + # at runtime. We have a service which does this + # (coreos-generate-iscsi-initiatorname.service) until it's done properly + # upstream (see https://bugzilla.redhat.com/show_bug.cgi?id=1493296). + - | + #!/usr/bin/env bash + set -xeuo pipefail + + # NB: we don't use -f here so we break when this is no longer needed + rm -v /etc/iscsi/initiatorname.iscsi + +etc-group-members: + - wheel + - sudo + - systemd-journal + - adm +ignore-removed-users: + - root +ignore-removed-groups: + - root +check-passwd: + type: "file" + filename: "passwd" +check-groups: + type: "file" + filename: "group" + +exclude-packages: + # https://bugzilla.redhat.com/show_bug.cgi?id=1798278 + - subscription-manager + # And this one shouldn't come in + - dnf + # https://github.com/coreos/rpm-ostree/pull/1789/files/a0cd999a8acd5b40ec1024a794a642916fbc8ff8#diff-fc2076dc46933204a7a798f544ce3734 + # People need to use `rpm-ostree kargs` instead. + - grubby + +# Try to maintain this list ordering by "in RHEL, then not in RHEL". +# To verify, disable all repos except the ootpa ones and then comment +# out the bottom and run `coreos-assembler build`. +packages: + # Dependency of iscsi + - hostname + # For growing root partition + - cloud-utils-growpart + # Contains SCTP (https://bugzilla.redhat.com/show_bug.cgi?id=1718049) + # and it's not really going to be worth playing the "where's my kernel module" + # game long term. If we ship it we support it, etc. + - kernel-modules-extra + # Audit + - audit + # SELinux + - selinux-policy-targeted + # System setup + - passwd + # SSH + - openssh-server openssh-clients + # Containers + - podman + - containernetworking-plugins + - runc + - skopeo + # Pinned due to cosa on Fedora not honoring RHEL 8 modules as expected + - container-selinux + - cri-o cri-tools + # Networking + - nfs-utils + - openvswitch2.13 + - NetworkManager dnsmasq + - NetworkManager-ovs + - NetworkManager-team teamd + - lvm2 iscsi-initiator-utils sg3_utils + - device-mapper-multipath + - xfsprogs e2fsprogs mdadm + - cryptsetup + - cifs-utils + # Interactive Networking configuration during coreos-install + - NetworkManager-tui + # Time sync + - chrony + # Extra runtime + - logrotate + - sssd shadow-utils + # Common tools used by scripts and admins interactively + - sudo coreutils less tar xz gzip bzip2 rsync tmux jq + - nmap-ncat net-tools bind-utils strace + - bash-completion + # Editors + - vim-minimal nano + # Red Hat CA certs + - subscription-manager-rhsm-certificates + # rdma-core cleanly covers some key bare metal use cases + - rdma-core + # Used on the bootstrap node + - systemd-journal-remote + # Extras + - systemd-journal-gateway + # RHEL7 compatibility + - compat-openssl10 + # LUKS/Encryption support + - clevis clevis-luks clevis-dracut cryptsetup-reencrypt tpm2-tools + # Used to update PAM configuration to work with SSSD + # https://bugzilla.redhat.com/show_bug.cgi?id=1774154 + - authselect + # Dracut module dependencies + - bsdtar + # BELOW HERE ARE PACKAGES NOT IN RHEL + # OpenShift OKD + #- origin-node origin-hyperkube origin-clients + # OpenShift + - openshift-hyperkube openshift-clients + # Gluster - Used for Openshift e2e gluster testcases + # Reverts https://gitlab.cee.redhat.com/coreos/redhat-coreos/merge_requests/367 and add it for all arches + - glusterfs-fuse + # Needed for kernel-devel extension: https://bugzilla.redhat.com/show_bug.cgi?id=1885408 + # x86_64 and s390x have these packages installed as dependencies of other packages, ppc64le does not + # FIXME: once the below BZs have been resolved to remove perl dependencies, this can be done in the extensions script + # https://bugzilla.redhat.com/show_bug.cgi?id=1877905 + # https://bugzilla.redhat.com/show_bug.cgi?id=1886201 + - perl-interpreter + +packages-x86_64: + # Temporary add of open-vm-tools. Should be removed when containerized + - open-vm-tools + - irqbalance + # Until we sort out 4.2 -> 4.3 upgrades, we need to carry this. + # See also https://github.com/ostreedev/ostree/pull/1929 + - ostree-grub2 + +packages-ppc64le: + - irqbalance + +remove-from-packages: + - - filesystem + - "/usr/share/backgrounds" + # https://bugzilla.redhat.com/show_bug.cgi?id=1762509 + # https://bugzilla.redhat.com/show_bug.cgi?id=1727058 + - - initscripts + - "/" + # In newer dracut-network dhclient isn't required if you have NM 1.20 + # https://github.com/dracutdevs/dracut/commit/e863807 + # Let's go ahead and get rid of it now. + - - dhcp-client + # we want to delete all files ("/") but can't because + # `remove-from-packages` is being overzealous: + # https://github.com/coreos/rpm-ostree/issues/2068 + - "/etc/dhcp/dhclient.conf" + - "/etc/NetworkManager/dispatcher.d/11-dhclient" + - "/usr/lib64/pm-utils/sleep.d/56dhclient" + - "/usr/sbin/dhclient" + - "/usr/sbin/dhclient-script" diff --git a/overlay.d/01fcos b/overlay.d/01fcos new file mode 120000 index 000000000..96f178b27 --- /dev/null +++ b/overlay.d/01fcos @@ -0,0 +1 @@ +../fedora-coreos-config/overlay.d/05core \ No newline at end of file diff --git a/overlay.d/02fcos-nouveau b/overlay.d/02fcos-nouveau new file mode 120000 index 000000000..26e682b7f --- /dev/null +++ b/overlay.d/02fcos-nouveau @@ -0,0 +1 @@ +../fedora-coreos-config/overlay.d/08nouveau \ No newline at end of file diff --git a/overlay.d/05rhcos/usr/lib/NetworkManager/conf.d/10-disable-default-plugins.conf b/overlay.d/05rhcos/usr/lib/NetworkManager/conf.d/10-disable-default-plugins.conf new file mode 100644 index 000000000..5cd7ee520 --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/NetworkManager/conf.d/10-disable-default-plugins.conf @@ -0,0 +1,7 @@ +# Prefer keyfiles by listing the keyfile plugin first in the plugin list. This +# overrides the default plugins and will cause any new networking configuration +# written by NetworkManager in RHCOS to be written out to keyfiles instead of +# ifcfg files. User's can still bring their own ifcfg files and they will still +# work. This just changes the default format/location of generated configuration. +[main] +plugins=keyfile,ifcfg-rh diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/29rhcos-need-network-manager/module-setup.sh b/overlay.d/05rhcos/usr/lib/dracut/modules.d/29rhcos-need-network-manager/module-setup.sh new file mode 100644 index 000000000..e385cbc3a --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/29rhcos-need-network-manager/module-setup.sh @@ -0,0 +1,12 @@ +# We need a module that runs early (before any module that claims +# it depends on `network`) that pulls in network-manager to +# workaround https://github.com/dracutdevs/dracut/issues/798 which +# means we can't call `dracut --add network-manager` and have it +# properly override the default of `network-legacy` in `40network`. +depends() { + echo network-manager +} + +check() { + return 0 +} diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/30rhcos-afterburn-checkin/module-setup.sh b/overlay.d/05rhcos/usr/lib/dracut/modules.d/30rhcos-afterburn-checkin/module-setup.sh new file mode 100644 index 000000000..0aa6c3f9a --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/30rhcos-afterburn-checkin/module-setup.sh @@ -0,0 +1,24 @@ +# RHCOS specific initramfs checkin for Azure. Linked to +# initrd.target much like what we do for ignition +# +# Context: this is for installer UX considerations. The provision +# success check masks issues with Ignition configs because it runs +# after Ignition (which may never conclude). Terraform will also +# report that nothing is progressing (as it is waiting for the checkin +# even though things are. Kube will do the actual health handling +# for the machine. + +depends() { + echo network systemd +} + +check() { + return 0 +} + +install() { + local unit=rhcos-afterburn-checkin.service + mkdir -p "$initdir/$systemdsystemunitdir/ignition-files.service.requires" + inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit" + ln_r "../$unit" "$systemdsystemunitdir/ignition-files.service.requires/$unit" +} diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/30rhcos-afterburn-checkin/rhcos-afterburn-checkin.service b/overlay.d/05rhcos/usr/lib/dracut/modules.d/30rhcos-afterburn-checkin/rhcos-afterburn-checkin.service new file mode 100644 index 000000000..4d4e8e2df --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/30rhcos-afterburn-checkin/rhcos-afterburn-checkin.service @@ -0,0 +1,13 @@ +[Unit] +Description=Afterburn (Check In - from the initramfs) +ConditionKernelCommandLine=ignition.platform.id=azure + +# Since we don't care about the actual success of the boot +# from the OS perspective, check in as soon as we are able. +After=network.target + +[Service] +Environment=AFTERBURN_OPT_PROVIDER=--cmdline +ExecStart=/usr/bin/afterburn ${AFTERBURN_OPT_PROVIDER} --check-in +Type=oneshot +RemainAfterExit=yes diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-encrypt.service b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-encrypt.service new file mode 100644 index 000000000..107a75c0a --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-encrypt.service @@ -0,0 +1,35 @@ +[Unit] +Description=CoreOS Firstboot encryption of root device +DefaultDependencies=false + +# We need to fetch Ingition first +After=ignition-fetch.service + +# Also run after the disks stage, which might play around with the partition +# table, udev, etc.. +After=ignition-disks.service + +# Enforce FIPS before, otherwise the crypto will not be FIPS compliant. +After=rhcos-fips.service +Requires=rhcos-fips.service + +# Execute before the FIPS finish. +Before=rhcos-fips-finish.service + +# Run only on first boot and conflict with N boot. +Before=ignition-ostree-mount-firstboot-sysroot.service +Conflicts=ignition-ostree-mount-subsequent-sysroot.service + +# Make sure if ExecStart= fails, the boot fails +OnFailure=emergency.target +OnFailureJobMode=isolate + +[Service] +Type=oneshot +TimeoutSec=1800 +EnvironmentFile=/run/ignition.env +ExecStartPre=/bin/mkdir -p /run/coreos +ExecStart=/usr/libexec/coreos-cryptfs encrypt +# If changing this, please also change coreos-fde-check-needsnet.service +TemporaryFileSystem=/run/coreos-cryptfs-tmp /usr/lib/ignition +RemainAfterExit=yes diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-fde-check-needsnet.service b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-fde-check-needsnet.service new file mode 100644 index 000000000..b40cf41c7 --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-fde-check-needsnet.service @@ -0,0 +1,22 @@ +[Unit] +Description=CoreOS Firstboot Check If Encryption Requires Networking +DefaultDependencies=false + +# We need to fetch Ignition first +After=ignition-fetch-offline.service + +# But before we request networking +Before=coreos-enable-network.service + +# Make sure if ExecStart= fails, the boot fails +OnFailure=emergency.target +OnFailureJobMode=isolate + +[Service] +Type=oneshot +EnvironmentFile=/run/ignition.env +ExecStartPre=/bin/mkdir -p /run/coreos +ExecStart=/usr/libexec/coreos-cryptfs check-needsnet +# If changing this, please also change coreos-encrypt.service +TemporaryFileSystem=/run/coreos-cryptfs-tmp /usr/lib/ignition +RemainAfterExit=yes diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-luks-generator b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-luks-generator new file mode 100755 index 000000000..977b516e3 --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-luks-generator @@ -0,0 +1,55 @@ +#!/bin/bash +# ex: ts=8 sw=4 sts=4 et filetype=sh + +source /lib/dracut-lib.sh +# Can't do this with dracut-lib... :cry: +#set -e + +UNIT_DIR="${1:-/tmp}" + +add_requires() { + local name="$1" + shift + local target="$1" + shift + local requires_dir="${UNIT_DIR}/${target}.requires" + mkdir -p "${requires_dir}" + ln -sf "../${name}" "${requires_dir}/${name}" +} + +# In 4.4+, we only activate if rhcos.root=crypt_rootfs as set on the +# kernel cmdline by image.yaml. This will allow us to go back +# to matching FCOS and supporting full rootfs reprovisioning. +root="$(getargs rhcos.root)" +if [ "${root}" != "crypt_rootfs" ]; then + exit 0 +fi + +add_requires coreos-luks-open.service ignition-diskful.target +add_requires coreos-luks-open.service ignition-diskful-subsequent.target + +svc=ignition-ostree-growfs.service +svcd="${UNIT_DIR}/${svc}.d" +mkdir -p "${svcd}" +cat > "${svcd}/rhcos.conf" < ${dropin} << EOF +[Unit] +# Support Tang/NBDE: Network bound disk encryption +After=network-online.target +Wants=network-online.target +EOF +fi diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-luks-open.service b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-luks-open.service new file mode 100644 index 000000000..19bb9c605 --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/coreos-luks-open.service @@ -0,0 +1,31 @@ +[Unit] +Description=CoreOS LUKS Opener + +# Don't run this on systems upgraded from 4.2 or below. +# See also https://github.com/coreos/fedora-coreos-config/blob/832ed20b86272f26f6ec4450b3b839fb60d9e822/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-mount-subsequent-sysroot.service#L7 +ConditionKernelCommandLine=!root +ConditionPathExists=/etc/initrd-release + +# We only open after encryption +After=coreos-encrypt.service + +# Also run after the disks stage, which might play around with the partition +# table, udev, etc.. +After=ignition-disks.service + +# This is our luks root label +Requires=dev-disk-by\x2dlabel-crypt_rootfs.device +After=dev-disk-by\x2dlabel-crypt_rootfs.device + +# Run before locating the root device. +Before=ignition-ostree-mount-firstboot-sysroot.service +Before=ignition-ostree-mount-subsequent-sysroot.service + +# Fail the boot if the disk opening fails. +OnFailure=emergency.target +OnFailureJobMode=isolate + +[Service] +Type=oneshot +ExecStart=/usr/libexec/coreos-cryptfs open +RemainAfterExit=yes diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/module-setup.sh b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/module-setup.sh new file mode 100755 index 000000000..fff732b75 --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fde/module-setup.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +check() { + return 0 +} + +install_unit() { + local unit=$1; shift + local target=${1:-ignition-complete.target} + inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit" + local targetpath="$systemdsystemunitdir/${target}.requires/" + mkdir -p "${initdir}/${targetpath}" + ln_r "../$unit" "${targetpath}/${unit}" +} + +depends() { + echo bash crypt clevis fips systemd network +} + +installkernel() { + [[ $arch == x86_64 ]] && arch=x86 + [[ $arch == s390x ]] && arch=s390 + + # Force installation of the required modules. + hostonly='' instmods dm_crypt =crypto =drivers/crypto =arch/$arch/crypto =drivers/char/tpm sg +} + +install() { + # clevis should be provided by clevis, but put here explicitly + bins=( + blockdev + base64 + chmod + clevis + clevis-decrypt + clevis-decrypt-sss + clevis-decrypt-tpm2 + clevis-encrypt-sss + clevis-encrypt-tang + clevis-encrypt-tpm2 + clevis-luks-bind + clevis-luks-common-functions + clevis-luks-unbind + clevis-luks-unlock + cryptsetup + cryptsetup-reencrypt + curl + cut + dd + dirname + growpart + head + jose + jq + luksmeta + mktemp + nc + pwmake + sfdisk + sync + systemd-detect-virt + touch + tpm2_create + tpm2_createpolicy + tpm2_createprimary + tpm2_load + tpm2_pcrlist + tpm2_unseal + tr + umount + ) + inst_multiple ${bins[@]} + + # Needed for clevis binding + inst_dir /usr/share/cracklib + for x in /usr/share/cracklib/*; do + inst $x + done + + # Needed for TPM2 devices + inst_libdir_file "libtss2-tcti-device.so*" + + inst_script /usr/libexec/coreos-cryptfs + inst_script /usr/libexec/coreos-growpart + inst_script /usr/libexec/coreos-cryptlib + + # Service for first-boot encryption. + install_unit "coreos-fde-check-needsnet.service" "ignition-diskful.target" + install_unit "coreos-encrypt.service" "ignition-diskful.target" + inst_simple "$moddir/coreos-luks-open.service" "$systemdsystemunitdir/coreos-luks-open.service" + # The generator enables the opening service. + inst_simple "$moddir/coreos-luks-generator" \ + "$systemdutildir/system-generators/coreos-luks-generator" +} diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/coreos-dummy-ignition-files-run.sh b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/coreos-dummy-ignition-files-run.sh new file mode 100755 index 000000000..a16874b6a --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/coreos-dummy-ignition-files-run.sh @@ -0,0 +1,54 @@ +#!/bin/bash +set -euo pipefail + +outputdir=$1; shift +ign_config=$1; shift +wanted_path=$1; shift + +# Hack: we ask Ignition to write out the files in a temporary rootfs so we can +# extract the one file we want from there. We don't want to actually run after +# ignition-files because by then it'll be much too late. + +# Note this won't work if the file you're interested in might possibly be on a +# separate partition. `/etc/*` is safe, but e.g. `/var/lib/containers/foo.json` +# will fail hard if someone wants a partition for `/var/lib/containers`. This is +# a problem intrinsic to the Ignition v2 spec. + +tmpsysroot=${outputdir}/sysroot +tmpconfig=${outputdir}/tmpconfig.json +mkdir -p "${tmpsysroot}" + +# print out the logs only if something went wrong +trap "cat ${outputdir}/ignition.log" ERR + +# select just the entry we care about, and scrub out user/group, which would +# require passwd lookups too +(jq ".storage.files[] | select(.path==\"${wanted_path}\") | del(.user, .group)" 2>/dev/null || :) \ + < "${ign_config}" > ${tmpconfig}.fragment +if [ ! -s ${tmpconfig}.fragment ]; then + exit 0 +fi + +# make a super minimal Ignition config that just has that, so there are no +# other side-effects (e.g. requirements on passwd, or partitions) +cat > "${tmpconfig}" < ${tmpsysroot}/etc/selinux/config +echo -e '/.*\tsystem_u:object_r:default_t:s0' > "${tmpsysroot}/etc/selinux/targeted/contexts/files/file_contexts" + +/usr/bin/ignition \ + --config-cache "${tmpconfig}" \ + --root="${tmpsysroot}" --platform="${PLATFORM_ID}" --stage=files \ + --log-to-stdout &> "${outputdir}/ignition.log" diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/module-setup.sh b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/module-setup.sh new file mode 100755 index 000000000..4858ba48b --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/module-setup.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +check() { + return 0 +} + +depends() { + echo fips ignition +} + +install() { + inst_multiple \ + jq \ + tee \ + chroot \ + sync \ + bwrap \ + env + + inst_script "$moddir/rhcos-fips.sh" \ + "/usr/sbin/rhcos-fips" + inst_script "$moddir/coreos-dummy-ignition-files-run.sh" \ + "/usr/sbin/coreos-dummy-ignition-files-run" + inst_simple "$moddir/rhcos-fips.service" \ + "$systemdsystemunitdir/rhcos-fips.service" + inst_simple "$moddir/rhcos-fips-finish.service" \ + "$systemdsystemunitdir/rhcos-fips-finish.service" + + # Unconditionally include /etc/system-fips in the initrd. This has no + # practical effect if fips=1 isn't also enabled. OTOH, it is a *requirement* + # for a true FIPS boot: https://bugzilla.redhat.com/show_bug.cgi?id=1778940 + echo "# RHCOS FIPS mode installation complete" > "$initdir/etc/system-fips" + + # We don't support FIPS in diskless cases currently + target=ignition-diskful + mkdir -p "$initdir/$systemdsystemunitdir/${target}.target.requires" + ln_r "$moddir/rhcos-fips.service" \ + "$systemdsystemunitdir/${target}.target.requires/rhcos-fips.service" + ln_r "$moddir/rhcos-fips-finish.service" \ + "$systemdsystemunitdir/${target}.target.requires/rhcos-fips-finish.service" +} diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips-finish.service b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips-finish.service new file mode 100644 index 000000000..9eb604cdb --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips-finish.service @@ -0,0 +1,20 @@ +[Unit] +Description=Finish FIPS mode setup +DefaultDependencies=false +# we run in the second boot after the one where we set fips=1 +ConditionKernelCommandLine=ignition.firstboot +ConditionKernelCommandLine=fips +Before=initrd.target + +# we want to run after Ignition drops its files +After=ignition-files.service + +# See comment about this in ignition-complete.target. +OnFailure=emergency.target +OnFailureJobMode=isolate + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/sbin/rhcos-fips finish +MountFlags=slave diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips.service b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips.service new file mode 100644 index 000000000..db0421de0 --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips.service @@ -0,0 +1,35 @@ +[Unit] +Description=Check for FIPS mode +DefaultDependencies=false +ConditionKernelCommandLine=ignition.firstboot + +# Any services looking at mounts should generally order after the +# GPT regenerator. +# This is technically already guaranteed by After=ignition-fetch.service +# but just as a sanity-check let's add it here too. +After=coreos-gpt-setup@dev-disk-by\x2dlabel-root.service +# we need to be able to mount /boot +After=dev-disk-by\x2dlabel-boot.device +Requires=dev-disk-by\x2dlabel-boot.device + +# we need the fetched Ignition config, but before disks start +After=ignition-fetch.service +Before=ignition-disks.service + +# We want to run to completion before check-in: if we immediately reboot for +# FIPS, it'd be more appropriate to say we're up on that second boot. Also on +# some platforms (like Azure), check-in "ejects" the user-data drive, so +# Ignition can't fetch the config again. +Before=rhcos-afterburn-checkin.service + +# See comment about this in ignition-complete.target. +OnFailure=emergency.target +OnFailureJobMode=isolate + +[Service] +Type=oneshot +RemainAfterExit=yes +EnvironmentFile=/run/ignition.env +ExecStart=/usr/sbin/rhcos-fips firstboot +TemporaryFileSystem=/run/rhcos-fips /usr/lib/ignition +MountFlags=slave diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips.sh b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips.sh new file mode 100755 index 000000000..f1071819c --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/40rhcos-fips/rhcos-fips.sh @@ -0,0 +1,132 @@ +#!/bin/bash +set -euo pipefail + +IGNITION_CONFIG=/run/ignition.json +# https://github.com/openshift/machine-config-operator/pull/868 +MACHINE_CONFIG_ENCAPSULATED=/etc/ignition-machine-config-encapsulated.json + +main() { + mode=$1; shift + case "$mode" in + firstboot) firstboot;; + finish) finish;; + *) fatal "Invalid mode $mode";; + esac +} + +firstboot() { + if [ "$(> $tmpfile + done + done + zipl --verbose \ + --target "${tmpsysroot}/boot" \ + --image $tmpsysroot/boot/"$(grep linux $tmpfile | cut -d' ' -f2)" \ + --ramdisk $tmpsysroot/boot/"$(grep initrd $tmpfile | cut -d' ' -f2)" \ + --parmfile $tmpfile + fi + + echo "Rebooting" + systemctl --force reboot +} + +finish() { + # This is analogous to Anaconda's `chroot /sysroot fips-mode-setup`. Though + # of course, since our approach is "Ignition replaces Anaconda", we have to + # do it on firstboot ourselves. The key part here is that we do this + # *before* the initial switch root. + sysroot_bwrap fips-mode-setup --enable --no-bootcfg +} + +sysroot_bwrap() { + # Need to work around the initrd `rootfs` / filesystem not being a valid + # mount to pivot out of. See: + # https://github.com/torvalds/linux/blob/26bc672134241a080a83b2ab9aa8abede8d30e1c/fs/namespace.c#L3605 + # See similar code in: https://gist.github.com/jlebon/fb6e7c6dcc3ce17d3e2a86f5938ec033 + mkdir -p /mnt/bwrap + mount --bind / /mnt/bwrap + mount --make-private /mnt/bwrap + mount --bind /mnt/bwrap /mnt/bwrap + for mnt in proc sys dev; do + mount --bind /$mnt /mnt/bwrap/$mnt + done + touch /mnt/bwrap/run/ostree-booted + mount --bind /sysroot /mnt/bwrap/sysroot + chroot /mnt/bwrap env --chdir /sysroot bwrap \ + --unshare-pid --unshare-uts --unshare-ipc --unshare-net \ + --unshare-cgroup-try --dev /dev --proc /proc --chdir / \ + --ro-bind usr /usr --bind etc /etc --dir /tmp --tmpfs /var/tmp \ + --tmpfs /run --ro-bind /run/ostree-booted /run/ostree-booted \ + --symlink usr/lib /lib \ + --symlink usr/lib64 /lib64 \ + --symlink usr/bin /bin \ + --symlink usr/sbin /sbin -- "$@" +} + +noop() { + echo "$@" + exit 0 +} + +fatal() { + echo "$@" + exit 1 +} + +main "$@" diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/41rhcos-ignition-conf/base.ign b/overlay.d/05rhcos/usr/lib/dracut/modules.d/41rhcos-ignition-conf/base.ign new file mode 100644 index 000000000..3ddac11f3 --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/41rhcos-ignition-conf/base.ign @@ -0,0 +1,19 @@ +{ + "ignition": { + "version": "3.0.0" + }, + "passwd": { + "users": [ + { + "name": "core", + "gecos": "CoreOS Admin", + "groups": [ + "adm", + "sudo", + "systemd-journal", + "wheel" + ] + } + ] + } +} diff --git a/overlay.d/05rhcos/usr/lib/dracut/modules.d/41rhcos-ignition-conf/module-setup.sh b/overlay.d/05rhcos/usr/lib/dracut/modules.d/41rhcos-ignition-conf/module-setup.sh new file mode 100755 index 000000000..ea4c0f42c --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/dracut/modules.d/41rhcos-ignition-conf/module-setup.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +depends() { + echo ignition +} + +# FCOS carries the `base.ign` file in +# https://github.com/coreos/fedora-coreos-config/blob/testing-devel/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-conf/base.ign +# RHCOS doesn't need `afterburn-sshkeys@core.service`. Therefore, RHCOS +# maintains its own copy of `base.ign`, and changes to one copy need to +# be synced to the other copy. +# See https://github.com/coreos/fedora-coreos-config/pull/626 +install() { + test -f $initdir/usr/lib/ignition/base.ign + inst "$moddir/base.ign" \ + "/usr/lib/ignition/base.ign" +} diff --git a/overlay.d/05rhcos/usr/lib/systemd/system-preset/10-rhcos-disabled.preset b/overlay.d/05rhcos/usr/lib/systemd/system-preset/10-rhcos-disabled.preset new file mode 100644 index 000000000..6becefc31 --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/systemd/system-preset/10-rhcos-disabled.preset @@ -0,0 +1,5 @@ +# Disable bits primarily from fedora-coreos-config + +# https://github.com/coreos/afterburn/issues/405 +# When we changed to inherit from FCOS we started enabling this service +disable afterburn-sshkeys@.service diff --git a/overlay.d/05rhcos/usr/lib/systemd/system-preset/43-manifest-rhcos.preset b/overlay.d/05rhcos/usr/lib/systemd/system-preset/43-manifest-rhcos.preset new file mode 100644 index 000000000..9f8e16c66 --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/systemd/system-preset/43-manifest-rhcos.preset @@ -0,0 +1,22 @@ +# These presets come from the RHCOS manifest; we +# don't currently have a really good reason why some of them +# live in the manifest and some of them from the redhat-release-coreos +# package. + +# Enable the iscsi workaround +enable coreos-regenerate-iscsi-initiatorname.service +# Enable GCP routes +enable gcp-routes.service +# Enable auditd. See https://jira.coreos.com/browse/RHCOS-536 +enable auditd.service +# Disable these services by default. See https://jira.coreos.com/browse/RHCOS-92 +disable nis-domainname.service +disable rpcbind.service +disable rpcbind.socket +# Support for LUKS disk resize. +disable coreos-growpart.service +enable rhcos-growpart.service +# Enable systemd unit required for console-login-helper-messages v0.19 +# This preset should be removed once fedora-coreos-config is updated +# to include at least commit 3fbd175b16ae2d5dbb26519b89792a590ce07565. +enable console-login-helper-messages-gensnippet-ssh-keys.service diff --git a/overlay.d/05rhcos/usr/lib/systemd/system/coreos-generate-iscsi-initiatorname.service b/overlay.d/05rhcos/usr/lib/systemd/system/coreos-generate-iscsi-initiatorname.service new file mode 100644 index 000000000..ee55b780b --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/systemd/system/coreos-generate-iscsi-initiatorname.service @@ -0,0 +1,18 @@ +# Note we should rip this out once it's fixed upstream: +# https://bugzilla.redhat.com/show_bug.cgi?id=1493296 +# We have a time bomb for that in manifest.yaml. +[Unit] +Description=CoreOS Generate iSCSI Initiator Name +Documentation=https://bugzilla.redhat.com/show_bug.cgi?id=1493296 +Documentation=https://bugzilla.redhat.com/show_bug.cgi?id=1687722 +ConditionFirstBoot=true +# But only if not already written by Ignition +# https://bugzilla.redhat.com/show_bug.cgi?id=1868174 +ConditionPathExists=!/etc/iscsi/initiatorname.iscsi +Before=iscsid.service +[Service] +Type=oneshot +ExecStart=/usr/bin/sh -c 'echo "InitiatorName=`/usr/sbin/iscsi-iname`" > /etc/iscsi/initiatorname.iscsi' +RemainAfterExit=yes +[Install] +WantedBy=multi-user.target diff --git a/overlay.d/05rhcos/usr/lib/systemd/system/coreos-update-ca-trust.service.d/run-every-boot.conf b/overlay.d/05rhcos/usr/lib/systemd/system/coreos-update-ca-trust.service.d/run-every-boot.conf new file mode 100644 index 000000000..cde2df8e1 --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/systemd/system/coreos-update-ca-trust.service.d/run-every-boot.conf @@ -0,0 +1,3 @@ +# For the MCO we want to support adding/removing certs dynamically +[Unit] +ConditionFirstBoot= diff --git a/overlay.d/05rhcos/usr/lib/systemd/system/gcp-routes.service b/overlay.d/05rhcos/usr/lib/systemd/system/gcp-routes.service new file mode 100644 index 000000000..c0d3c5bab --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/systemd/system/gcp-routes.service @@ -0,0 +1,16 @@ +[Unit] +Description=Update GCP routes for forwarded IPs. +ConditionKernelCommandLine=|ignition.platform.id=gce +ConditionKernelCommandLine=|ignition.platform.id=gcp +After=network.target + +[Service] +Type=simple +ExecStart=/bin/bash /usr/sbin/gcp-routes.sh start +ExecStopPost=/bin/bash /usr/sbin/gcp-routes.sh cleanup +User=root +RestartSec=30 +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/overlay.d/05rhcos/usr/lib/systemd/system/rhcos-growpart.service b/overlay.d/05rhcos/usr/lib/systemd/system/rhcos-growpart.service new file mode 100644 index 000000000..19763b730 --- /dev/null +++ b/overlay.d/05rhcos/usr/lib/systemd/system/rhcos-growpart.service @@ -0,0 +1,40 @@ +# Note this service duplicates the FCOS growpart which is +# done in the initramfs; it will likely go away once +# we rework to use Ignition LUKS. See +# https://github.com/coreos/fedora-coreos-config/pull/503#discussion_r449240871 +[Unit] +Description=Resize root partition +ConditionPathExists=!/run/ostree-live +ConditionPathExists=!/var/lib/coreos-growpart.stamp + +Conflicts=coreos-growpart.service + +# Wait for networking since the device may be encrypted for +# NBDE via Clevis/Tang. +After=network-online.target +Wants=network-online.target + +# List a couple of space-hungry services we want to make sure we run *before*. +# This is a hack; in the future we'll just resize in the initramfs like on FCOS. + +Before=machine-config-daemon-firstboot.service +# This shouldn't be enabled in the future, though for now, make sure we run before it. See: +# https://github.com/openshift/machine-config-operator/pull/1366 +# Also https://github.com/openshift/machine-config-operator/pull/1766 +Before=machine-config-daemon-host.service +# XXX: do we actually need this? cargo-culted from 9e2d724 +Before=sshd.service + +# Also need this for newer ostree with read-only sysroot; +# see https://github.com/ostreedev/ostree/pull/2113 +After=ostree-remount.service + +[Service] +Type=oneshot +ExecStart=/usr/libexec/rhcos-growpart / +RemainAfterExit=yes +# So we can remount /sysroot writable +MountFlags=slave + +[Install] +WantedBy=multi-user.target diff --git a/overlay.d/05rhcos/usr/libexec/coreos-cryptfs b/overlay.d/05rhcos/usr/libexec/coreos-cryptfs new file mode 100755 index 000000000..2c7050623 --- /dev/null +++ b/overlay.d/05rhcos/usr/libexec/coreos-cryptfs @@ -0,0 +1,303 @@ +#!/bin/bash +# This script should be called from udev or systemd. +source /lib/dracut-lib.sh +set -e + +# this label is currently hardcoded in cosa: +# https://github.com/coreos/coreos-assembler/blob/60bb29672483cdb1cbabf08994bfd714dddaba56/src/create_disk.sh#L151 +FS_LABEL=crypt_rootfs +CLI_CMD=${1}; shift; +RUN_D="/run/coreos" +CLEVIS_JSON="${RUN_D}/clevis.json" +NET=0 + +# For the null-cipher case, we skip dm-crypt and use dm-linear. The +# header offset is used to map the start of the device mapper target. +# This is currently hardcoded; it's unlikely that cryptsetup will change, +# at least hopefully not before we replace this with Ignition. +LUKS_HEADER_OFFSET_SECTORS=32768 + +# we do realpath here since we temporarily lose the label when reencrypting +dev=$(realpath /dev/disk/by-label/${FS_LABEL}) + +# This is needed otherwise cryptsetup will fail +mkdir -p /run/cryptsetup +mkdir -p "${RUN_D}" + +msg() { + echo "coreos-cryptfs: ${@}" +} + +fatal() { + msg ${@}; + exit 1; +} + +load_kmods() { + # Load kernel modules only when required. In BZ# 1803130, + # it was discovered that virtual hardware that lacks an entrophy + # source fails to boot. Ensure that we only load the required modules + # if needed. + modprobe -a dm_crypt loop +} + +cmd_waiter() { + local c=0; + until ${@} >> /dev/null; + do + sleep 0.5; + c=$(($c + 1)) + if [ "${c}" -gt 60 ]; then + return 1 + fi + done + return +} + +net_waiter() { + if [ "${NET}" -eq 1 ]; then + return 0 + fi + + msg "Checking for default route." + cmd_waiter 'ip route show default' || + fatal "unable find default network" + msg "Waiting for DNS resolver to appear." + cmd_waiter 'test -e /etc/resolv.conf' || + fatal "failed to find /etc/resolv.conf" + NET=1 +} + +coreos_token() { + local dev="${1:?dev must be the first argument}" + + # Check if the token is in the LUKS header. + local coreos_id="$(cryptsetup luksDump ${dev} | sed -rn 's|^\s+([0-9]+): coreos|\1|p')" + if [ -z "${coreos_id}" ]; then + msg "${dev} does not have a coreos LUKS header." + exit 0 + fi + + # Read the token and parse it. + local token="$(cryptsetup token export --token-id ${coreos_id} ${dev})" + local token_type="$(jq -erM '.type //""' <<<${token})" + if [ "${token_type}" != "coreos" ]; then + cat << EOM +COREOS: DEVICE ${dev} MISSING LUKS TOKEN ${token_type}" + Tokens must be of type 'coreos' and have an 'key' + that can unlocked the device. +EOM + exit 1 + fi + echo "${token}" +} + +coreos_key() { + local dev="${1:?dev must be the first argument}" + jq -erM '.key' <<<"$(coreos_token ${dev})" +} + +try_open() { + # Determine if the volume is clevis managed or automatic unlock. + # The automatic clevis hooks will NOT work since they rely on the systemd + # crypttab generator. + local clevis_id="$(cryptsetup luksDump ${dev} | sed -rn 's|^\s+([0-9]+): clevis|\1|p')" + if [ -n "${clevis_id}" ]; then + load_kmods + local pin=$(cryptsetup token export --token-id "${cleivs_id}" "${dev}" \ + | jq -rM '.jwe.protected' | base64 -d | jq -rM '.clevis.pin') + msg "${dev} is configured for Clevis pin '${pin}'" + [ "${pin}" == "tpm2" ] || net_waiter + clevis-luks-unlock -d "${dev}" + exit $?; + fi + + local cipher=$(cryptsetup luksDump ${dev} | awk '/cipher/{print$NF;exit}') + msg "${dev} uses the '${cipher}'" + if [ "${cipher}" == "cipher_null-ecb" ]; then + # for null-cipher, us a direct dm-linear target + # this avoids the cryptsetup performance penalty. + msg "${dev} is not encrypted. Device will be mounted as device-mapper linear target." + + # We inline a growpart here since it's simpler than trying to reconfigure dm-linear + local major=$((0x$(stat -c '%t' "${dev}"))) + local minor=$((0x$(stat -c '%T' "${dev}"))) + local devpath=$(realpath "/sys/dev/block/${major}:${minor}") + local partition=$(cat "$devpath/partition") + local parent_path=$(dirname "$devpath") + local parent_device=/dev/$(basename "${parent_path}") + + # TODO: make this idempotent, and don't error out if + # we can't resize. + growpart "${parent_device}" "${partition}" || true + + local dev_size=$(($(blockdev --getsize ${dev}) - ${LUKS_HEADER_OFFSET_SECTORS})) + echo "0 ${dev_size} linear ${dev} ${LUKS_HEADER_OFFSET_SECTORS}" \ + | dmsetup create coreos-luks-root-nocrypt + else + local key="$(coreos_key ${dev})" + (echo -en "${key:-x}" | cryptsetup luksOpen "${dev}" coreos-luks-root) || + fatal "FAILED to open ${dev}" + fi +} + +token_rm() { + coreos_id=$(cryptsetup luksDump ${dev} | sed -rn 's|^\s+([0-9]+): coreos|\1|p') + cryptsetup token remove --token-id "${coreos_id}" "${dev}" + msg "Cleared token LUKS token on ${dev}" +} + +clevis_pin() { + if [ ! -f "${CLEVIS_JSON}" ]; then + # No pin specified + return + fi + + local pin="none" + # TPM configuration may be a bare JSON doc + grep --silent "\{\}" < "${CLEVIS_JSON}" \ + && [ $(jq '. | length' < "${CLEVIS_JSON}") -eq 0 ] \ + && pin="tpm2" \ + && NET=1 \ + || pin="${pin}" + + # Shamir Secret Sharing configurations have a .pins at the top level. + pin=$(jq -rM 'if .pins then "sss" else $pin end' --arg pin "${pin}" < "${CLEVIS_JSON}") + + # Tang has both a .url and .thp. Use the .thp so that the trust is established. + pin=$(jq -rM 'if .thp then "tang" else $pin end' --arg pin "${pin}" < "${CLEVIS_JSON}") + + echo "${pin}" +} + +validate_pin() { + local pin=${1} + shift + # Return success a valid clevis pin is detected. + if [[ ! "${pin}" =~ (sss|tpm2|tang) ]]; then + fatal "Clevis pin ${pin} is not supported, aborting" + fi +} + +get_clevis_cfg() { + # Be idempotent if the config was already fetched + if test -f "${CLEVIS_JSON}"; then + return + fi + + msg "Fetching clevis config" + + # Make sure the Ignition messages made it to disk before querying + # https://bugzilla.redhat.com/show_bug.cgi?id=1862957 + journalctl --sync + + # See https://github.com/coreos/fedora-coreos-config/commit/65de5e0f1676fa20537caa781937c1632eee5718 + # And see https://github.com/coreos/ignition/pull/958 for the MESSAGE_ID source. + ign_usercfg_msg=$(journalctl -q MESSAGE_ID=57124006b5c94805b77ce473e92a8aeb IGNITION_CONFIG_TYPE=user) + if [ -z "${ign_usercfg_msg}" ]; then + msg "No Ignition config provided" + return + fi + + local tmp=/run/coreos-cryptfs-tmp + local tmpsysroot="${tmp}/sysroot" + coreos-dummy-ignition-files-run "${tmp}" "/run/ignition.json" "/etc/clevis.json" + + if [ -s "${tmpsysroot}/etc/clevis.json" ]; then + msg "Detected provided Clevis config" + mv "${tmpsysroot}/etc/clevis.json" "${CLEVIS_JSON}" + jq . < "${CLEVIS_JSON}" + else + msg "No Clevis config provided" + fi +} + +encrypt() { + # This is run on first boot. The assumption here + # that the first-boot LUKS root volume is: + # 1. In a LUKS container with the label luks_root + # 2. The container is null-cipher encrypted. + # 3. The passphrase is NOT needed. + + # Skip encryption if the users requests it + get_clevis_cfg + local pin=$(clevis_pin) + if [ -z "${pin}" ]; then + msg "No Clevis pin provided, encryption is not enabled" + exit 0 + fi + + load_kmods + validate_pin "${pin}" + msg "detected pin=${pin}" + + # Strip off the build token that is set via the CoreOS installer. + token_rm "${dev}" + + # This key is transient (FIXME do we really need this) + local key_f="${RUN_D}/rootfs-luks-transient.key" + + # Prep a new random key. Clevis itself uses `pwmake` + # and using /dev/{u}random fails because Clevis pipes the + # password directly to cryptsetup. + msg "generating new key" + printf "%s%s" $(pwmake 128) $(pwmake 128) > "${key_f}" + + cat >/dev/console < /dev/null ; then + iptables -w -t "${table}" -N "${chain}"; + fi; +} + +ensure_rule() { + local table="${1}" + local chain="${2}" + shift 2 + + if ! iptables -w -t "${table}" -C "${chain}" "$@" &> /dev/null; then + iptables -w -t "${table}" -A "${chain}" "$@" + fi +} + +# set the chain, ensure entry rules, ensure ESTABLISHED rule +initialize() { + ensure_chain nat "${CHAIN_NAME}" + ensure_rule nat PREROUTING -m comment --comment 'gcp LB vip DNAT' -j ${CHAIN_NAME} + + # Need this so that existing flows (with an entry in conntrack) continue to be + # balanced, even if the DNAT entry is removed + ensure_rule filter INPUT -m comment --comment 'gcp LB vip existing' -m addrtype ! --dst-type LOCAL -m state --state ESTABLISHED,RELATED -j ACCEPT + + mkdir -p "${RUN_DIR}" +} + +remove_stale() { + ## find extra iptables rules + for ipt_vip in $(iptables -w -t nat -S "${CHAIN_NAME}" | awk '$4{print $4}' | awk -F/ '{print $1}'); do + if [[ -z "${vips[${ipt_vip}]}" ]]; then + echo removing stale vip "${ipt_vip}" + iptables -w -t nat -D "${CHAIN_NAME}" --dst "${ipt_vip}" -j REDIRECT + fi + done +} + +add_rules() { + for vip in "${vips[@]}"; do + echo "ensuring rule for ${vip}" + ensure_rule nat "${CHAIN_NAME}" --dst "${vip}" -j REDIRECT + done +} + +clear_rules() { + iptables -t nat -F "${CHAIN_NAME}" || true +} + +# out paramater: vips +list_lb_ips() { + for k in "${!vips[@]}"; do + unset vips["${k}"] + done + + local net_path="network-interfaces/" + for vif in $(curler ${net_path}); do + local hw_addr; hw_addr=$(curler "${net_path}${vif}mac") + local fwip_path; fwip_path="${net_path}${vif}forwarded-ips/" + for level in $(curler "${fwip_path}"); do + for fwip in $(curler "${fwip_path}${level}"); do + if [[ -e "${RUN_DIR}/${fwip}.down" ]]; then + echo "${fwip} is manually marked as down, skipping..." + else + echo "Processing route for NIC ${vif}${hw_addr} for ${fwip}" + vips[${fwip}]="${fwip}" + fi + done + done + done +} + +sleep_or_watch() { + if hash inotifywait &> /dev/null; then + inotifywait -t 240 -r "${RUN_DIR}" &> /dev/null || true + else + # no inotify, need to manually poll + for (( tries=0; tries<48; tries++ )); do + for vip in "${!vips[@]}"; do + if [[ -e "${RUN_DIR}/${vip}.down" ]]; then + echo "new downfile detected" + break 2 + fi + done + sleep 5 + done + fi +} + +case "$1" in + start) + initialize + while :; do + list_lb_ips + remove_stale + add_rules + echo "done applying vip rules" + sleep_or_watch + done + ;; + cleanup) + clear_rules + ;; + *) + echo $"Usage: $0 {start|cleanup}" + exit 1 +esac diff --git a/overlay.d/15rhcos-tuned-bits/usr/lib/dracut/modules.d/50rhcos-tuned-bits/module-setup.sh b/overlay.d/15rhcos-tuned-bits/usr/lib/dracut/modules.d/50rhcos-tuned-bits/module-setup.sh new file mode 100755 index 000000000..d2b8c0e36 --- /dev/null +++ b/overlay.d/15rhcos-tuned-bits/usr/lib/dracut/modules.d/50rhcos-tuned-bits/module-setup.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +check() { + return 0 +} + +depends() { + return 0 +} + +install() { + inst_hook pre-udev 00 "$moddir/tuned-workqueue.sh" +} diff --git a/overlay.d/15rhcos-tuned-bits/usr/lib/dracut/modules.d/50rhcos-tuned-bits/tuned-workqueue.sh b/overlay.d/15rhcos-tuned-bits/usr/lib/dracut/modules.d/50rhcos-tuned-bits/tuned-workqueue.sh new file mode 100755 index 000000000..2f87b8895 --- /dev/null +++ b/overlay.d/15rhcos-tuned-bits/usr/lib/dracut/modules.d/50rhcos-tuned-bits/tuned-workqueue.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# This file was adapted from +# https://raw.githubusercontent.com/redhat-performance/tuned/584f7dbe2cb56d5ba835450d3372717acc574034/profiles/cpu-partitioning/00-tuned-pre-udev.sh +# See https://gitlab.cee.redhat.com/coreos/redhat-coreos/merge_requests/727 +# Basically we want to support the same kernel argument that tuned does, +# until such time as this support lands in systemd itself. + +type getargs >/dev/null 2>&1 || . /lib/dracut-lib.sh + +function tuned_pre_udev_main() { + local cpumask="$(getargs tuned.non_isolcpus)" + local path=/sys/devices/virtual/workqueue/cpumask + if [ -n "$cpumask" ]; then + echo "tuned: setting workqueue CPU mask to $cpumask" >> /dev/kmsg + echo $cpumask > ${path} + fi +} + +tuned_pre_udev_main + diff --git a/overlay.d/20platform-chrony b/overlay.d/20platform-chrony new file mode 120000 index 000000000..2f070adb5 --- /dev/null +++ b/overlay.d/20platform-chrony @@ -0,0 +1 @@ +../fedora-coreos-config/overlay.d/20platform-chrony \ No newline at end of file diff --git a/overlay.d/21dhcp-chrony b/overlay.d/21dhcp-chrony new file mode 120000 index 000000000..5c9e295e1 --- /dev/null +++ b/overlay.d/21dhcp-chrony @@ -0,0 +1 @@ +../fedora-coreos-config/overlay.d/21dhcp-chrony \ No newline at end of file diff --git a/overlay.d/README.md b/overlay.d/README.md new file mode 100644 index 000000000..f81bab668 --- /dev/null +++ b/overlay.d/README.md @@ -0,0 +1,23 @@ +01fcos +------ + +Import `05core` overlay from fedora-coreos-config + +02fcos-nouveau +-------------- + +Blacklist the nouveau driver because it causes issues with some NVidia GPUs in +EC2, and we don't have a use case for FCOS with nouveau. + +"Cannot boot an p3.2xlarge instance with RHCOS (g3.4xlarge is working)" +https://bugzilla.redhat.com/show_bug.cgi?id=1700056 + +05rhcos +------- + +General RHCOS specific overlay. + +15rhcos-tuned-bits +------------------ + +Real Time kernel support extracted from `tuned`. diff --git a/passwd b/passwd new file mode 100644 index 000000000..673a3d56c --- /dev/null +++ b/passwd @@ -0,0 +1,27 @@ +root:x:0:0:root:/root:/bin/bash +bin:x:1:1:bin:/bin:/sbin/nologin +daemon:x:2:2:daemon:/sbin:/sbin/nologin +adm:x:3:4:adm:/var/adm:/sbin/nologin +lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin +sync:x:5:0:sync:/sbin:/bin/sync +shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown +halt:x:7:0:halt:/sbin:/sbin/halt +mail:x:8:12:mail:/var/spool/mail:/sbin/nologin +operator:x:11:0:operator:/root:/sbin/nologin +games:x:12:100:games:/usr/games:/sbin/nologin +ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin +nobody:x:99:99:Nobody:/:/sbin/nologin +dbus:x:81:81:System message bus:/:/sbin/nologin +polkitd:x:999:998:User for polkitd:/:/sbin/nologin +etcd:x:998:997:etcd user:/var/lib/etcd:/sbin/nologin +tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin +avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin +rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin +sssd:x:995:993:User for sssd:/:/sbin/nologin +dockerroot:x:997:986:Docker User:/var/lib/docker:/sbin/nologin +rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin +nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin +kube:x:996:994:Kubernetes user:/:/sbin/nologin +sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin +chrony:x:994:992::/var/lib/chrony:/sbin/nologin +openvswitch:x:800:800::/:/sbin/nologin diff --git a/rhcos-packages.yaml b/rhcos-packages.yaml new file mode 100644 index 000000000..2f89a326c --- /dev/null +++ b/rhcos-packages.yaml @@ -0,0 +1,20 @@ +# RHCOS maintained packages +# Yes, there are duplicates but this helps keep an eye on RPMs we need to keep +# updated in dist-git, etc +packages: + ## Delivered via RHAOS puddles + # Extra runtime + - afterburn + # User experience + - console-login-helper-messages-issuegen console-login-helper-messages-profile + # installer iso packages + - coreos-installer coreos-installer-bootinfra + - ignition + - redhat-release-coreos + ## Delivered via RHEL Base/Appstream (usually) + # needed by rpm-ostree for managing users + - nss-altfiles + - ostree + - rpm-ostree + # part of container-tools module + - toolbox diff --git a/scripts/ami_uncopy_regions b/scripts/ami_uncopy_regions new file mode 100644 index 000000000..80276028f --- /dev/null +++ b/scripts/ami_uncopy_regions @@ -0,0 +1,28 @@ +#!/usr/bin/python3 +import os,subprocess,json,sys + +with open(sys.argv[1]) as f: + meta = json.load(f) + +for ami in meta['amis']: + subprocess.check_call(['aws', 'ec2', f'--region={ami["name"]}', 'modify-image-attribute', '--image-id', ami['hvm'], '--launch-permission', 'Remove=[{Group=all}]']) + try: + output = subprocess.check_output(['aws', '--output=json', 'ec2', "--region", ami['name'], 'describe-images', '--image-id', ami['hvm']]) + except subprocess.CalledProcessError as e: + print("Failed to describe image {}".format(e)) + sys.exit(1) + image_description = json.loads(output) + snapshot = None + for image in image_description['Images']: + for block_device_mapping in image['BlockDeviceMappings']: + if block_device_mapping['Ebs']: + snapshot = block_device_mapping['Ebs']['SnapshotId'] + break + + if snapshot is None: + print("Failed to find SnapshotId associated with ami") + sys.exit(1) + subprocess.check_call(['aws', 'ec2', '--region', ami['name'], 'modify-snapshot-attribute', + '--snapshot-id', snapshot, '--attribute', 'createVolumePermission', + '--operation-type', 'remove', '--group-names', 'all']) + print(f"Done {ami} with snapshot ID {snapshot}") diff --git a/scripts/bc-is-prod.sh b/scripts/bc-is-prod.sh new file mode 100755 index 000000000..b46916335 --- /dev/null +++ b/scripts/bc-is-prod.sh @@ -0,0 +1,7 @@ +#!/bin/bash +PREFIX="${1:?first argument must be the prefix}" +DISTRO="${2:?second argument must be the distro}" + +out=$(oc get bc ${PREFIX}-${DISTRO} -o json 2> /dev/null \ + | jq -rM '.spec.strategy.jenkinsPipelineStrategy.env[] | select(.name== "PRODUCTION").value' 2> /dev/null) +echo ${out:-none} diff --git a/scripts/download-extensions b/scripts/download-extensions new file mode 100755 index 000000000..36574494a --- /dev/null +++ b/scripts/download-extensions @@ -0,0 +1,48 @@ +#!/bin/bash +# Download RPMs to act as extensions. +# See https://github.com/openshift/enhancements/pull/317 +# and https://github.com/coreos/fedora-coreos-tracker/issues/401 +# In the future this might live in rpm-ostree, see https://github.com/coreos/rpm-ostree/issues/2055 +set -euo pipefail +destdir=$1 +shift +reposdir=$(pwd)/src/config +cd $destdir + +# The "v2" format here is that there's an extensions/ directory, with subdirectories +# for each extension - except you should ignore "repodata/". +mkdir extensions +cd extensions + +# Stuff that's not part of the extension +mkdir dependencies + +yumdownload() { + yum --setopt=reposdir=${reposdir} --disablerepo='*' --arch=$(cosa basearch) "$@" +} + +if [ "$(arch)" = x86_64 ]; then + # https://github.com/openshift/machine-config-operator/pull/1330 + # https://github.com/openshift/enhancements/blob/master/enhancements/support-for-realtime-kernel.md + mkdir kernel-rt + # TODO: remove the rhaos-art-4.6 repo once the 8.2.z kernel is in the RHEL repo + (cd kernel-rt && yumdownload --enablerepo=rhel8-nfv --enablerepo=art-rhaos-4.6 download kernel-rt-{core,modules,modules-extra,kvm}) + # For backwards compatibility with existing MCO code, keep the kernel-rt RPMs at the toplevel too + for x in kernel-rt/*.rpm; do ln $x ..; done +fi + +# https://github.com/kmods-via-containers/kmods-via-containers/issues/3 +# https://gitlab.cee.redhat.com/coreos/redhat-coreos/merge_requests/866 +mkdir kernel-devel +# TODO: remove the rhaos-art-4.6 repo once the 8.2.z kernel is in the RHEL repo +(cd kernel-devel && yumdownload --enablerepo=rhel8-baseos --enablerepo=art-rhaos-4.6 download kernel-{core,devel,headers,modules,modules-extra}) +# For backwards compatibility with ISVs that may be trying to use kernel-devel in +# its old location. +for x in kernel-devel/*.rpm; do ln $x ..; done + +# usbguard: https://github.com/coreos/fedora-coreos-tracker/issues/326 +(cd dependencies && yumdownload --enablerepo=rhel8-baseos --enablerepo=rhel8-appstream download libqb protobuf) +mkdir usbguard +(cd usbguard && yumdownload --enablerepo=rhel8-baseos --enablerepo=rhel8-appstream download usbguard) + +createrepo_c --no-database . diff --git a/scripts/install-openshift b/scripts/install-openshift new file mode 100755 index 000000000..9bea79417 --- /dev/null +++ b/scripts/install-openshift @@ -0,0 +1,182 @@ +#!/usr/bin/python3 -u + +import argparse +import json +import tempfile +import glob +import os +import subprocess +import textwrap +import sys +import uuid + +RELEASE_IMAGE_TEMPLATE = "registry.svc.ci.openshift.org/ocp/release" + + +def install_oc(): + with tempfile.TemporaryDirectory() as output_dir: + # TODO: Use urllib3 + # Fetch oc tar + cmd = ['curl', '-LO', 'https://mirror.openshift.com/pub/openshift-v4/clients/oc/latest/linux/oc.tar.gz'] + try: + print(f"Running {' '.join(cmd)}") + subprocess.check_call(cmd, cwd=output_dir) + except subprocess.CalledProcessError as extract_err: + print(f"Failed to extract oc! Error: {extract_err}") + raise + + # Untar oc client + try: + cmd = ['sudo', 'tar', 'xzf', os.path.join(output_dir, "oc.tar.gz"), '-C', '/usr/local/bin'] + print(f"Running {' '.join(cmd)}") + subprocess.check_call(cmd, cwd=output_dir) + except Exception as tar_err: + print(f"Failed to unpack oc! Error: {tar_err}") + raise tar_err + + +def prepare_release_image(meta, build, release_image_prefix, stream): + oscontainer_image = meta["oscontainer"]["image"] + oscontainer_digest = meta["oscontainer"]["digest"] + + release_image = f"{release_image_prefix}:{build}" + + auth_file = os.environ.get("REGISTRY_AUTH_FILE") + auth_file_params = ['-a', auth_file] + if auth_file is None: + auth_file_params = [] + + # TODO: unhardcode this + # Prepare a new release + cmd = ['oc', 'adm', 'release', 'new'] + auth_file_params + [ + '-n', 'ocp', '--server', 'https://api.ci.openshift.org', + '--from-image-stream', stream, + '--to-image', release_image, + f"machine-os-content={oscontainer_image}@{oscontainer_digest}" + ] + try: + print(f"Running {' '.join(cmd)}") + subprocess.check_call(cmd) + except Exception as release_err: + print(f"Failed to create new release payload! Error: {release_err}") + raise release_err + + return release_image + + +# Run test openshift build +def run_openshift_install(region, secret_dir, release_image, buildID, log_level='debug'): + install_exception = None + + pull_secret_path = os.path.join(secret_dir, "pull_secret.json") + + with open(pull_secret_path) as f: + pull_secret = f.read() + + with open(os.path.join(secret_dir, "ssh-publickey")) as f: + ssh_publickey = f.read() + + # Create temp directory to store installer output + with tempfile.TemporaryDirectory() as output_dir: + # Write install-config.yaml + install_yaml = f"""\ + apiVersion: v1beta4 + baseDomain: devcluster.openshift.com + clusterID: {uuid.uuid1()} + metadata: + name: rhcos-test-{buildID} + networking: + networkType: OpenshiftSDN + platform: + aws: + region: {region} + pullSecret: | + {pull_secret} + sshKey: | + {ssh_publickey} + """ + install_yaml_file_path = os.path.join(output_dir, "install-config.yaml") + with open(install_yaml_file_path, 'wt', encoding='utf-8') as f: + f.write(textwrap.dedent(install_yaml)) + + # Extract installer from release image + try: + cmd = [ + '/usr/local/bin/oc', 'adm', 'release', 'extract', + '-a', pull_secret_path, + '--tools', release_image] + print(f"Running {' '.join(cmd)}") + subprocess.check_call(cmd, cwd=output_dir) + except subprocess.CalledProcessError as extract_err: + print(f"Failed to extract installer! Error: {extract_err}") + raise extract_err + + install_archive_list = glob.glob(os.path.join(output_dir, 'openshift-install-linux-*.tar.gz')) + if len(install_archive_list) == 0: + raise Exception("No installer archive found") + + # Untar the installer + try: + cmd = ['sudo', 'tar', 'xzf', install_archive_list[0], '-C', '/usr/local/bin'] + print(f"Running {' '.join(cmd)}") + subprocess.check_call(cmd, cwd=output_dir) + except Exception as tar_err: + print(f"Failed to extract oc! Error: {tar_err}") + raise tar_err + + # Create cluster + cmd = [ + 'env', + f'AWS_SHARED_CREDENTIALS_FILE={os.path.join(secret_dir, "aws-credentials")}', + f'OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE={release_image}', + '/usr/local/bin/openshift-install', + '--log-level=debug', + f"--dir={output_dir}" + ] + try: + create_cmd = cmd + ['create', 'cluster'] + print(f"Running {' '.join(create_cmd)}") + subprocess.check_call(create_cmd, cwd=output_dir) + except subprocess.CalledProcessError as create_err: + print(f"Failed to create cluster! Error: {create_err}") + if create_err is not None: + install_exception = create_err + + # Destroy cluster regardless of the error + try: + destroy_cmd = cmd + ['destroy', 'cluster'] + print(f"Running {' '.join(destroy_cmd)}") + subprocess.check_call(destroy_cmd, cwd=output_dir) + except subprocess.CalledProcessError as destroy_err: + print(f"Failed to deprovision cluster! Error: {destroy_err}") + if destroy_err is not None: + install_exception = destroy_err + + if install_exception: + raise install_exception + + +def main(): + # parse args and dispatch + parser = argparse.ArgumentParser() + parser.add_argument("--build", action='store', required=True) + parser.add_argument("--region", action='store', required=True) + parser.add_argument("--secrets", action='store', required=True) + parser.add_argument("--release-image", action='store', required=True) + parser.add_argument("--stream", action='store', required=True) + args = parser.parse_args() + + with open(f"builds/{args.build}/x86_64/meta.json") as meta_f: + meta = json.load(meta_f) + + try: + print("Running a test OpenShift install") + install_oc() + new_release_image = prepare_release_image(meta, args.build, args.release_image, args.stream) + run_openshift_install(args.region, args.secrets, new_release_image, args.build) + except subprocess.CalledProcessError: + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/scripts/upload-aliyun-image b/scripts/upload-aliyun-image new file mode 120000 index 000000000..c39a8c9b1 --- /dev/null +++ b/scripts/upload-aliyun-image @@ -0,0 +1 @@ +upload-ami \ No newline at end of file diff --git a/scripts/upload-ami b/scripts/upload-ami new file mode 100755 index 000000000..43ca0e326 --- /dev/null +++ b/scripts/upload-ami @@ -0,0 +1,194 @@ +#!/usr/bin/python3 -u + +# Wraps coreos-assembler buildextend-aws which itself wraps `ore aws upload`, +# but also supports making the images public because ore doesn't do that right +# now. Eventually we may use plume? + +import argparse +import json +import os +import subprocess +import sys + +OPENSHIFT_CI_ACCOUNT = "460538899914" +OPENSHIFT_DEV_ACCOUNT = "269733383066" +OPENSHIFT_MARKETPLACE_TEST_ACCOUNT = "125666959065" + +# Since we run all tests on QEMU, and as of today don't have really +# any tests that are specific to a cloud provider, we just run +# basic sanity checks. +SANITY_CHECK = "rhcos.basic" +# Don't need anything big +INSTANCE_TYPE = 't2.small' + +AWS = 'aws' +ALIYUN = 'aliyun' + +cloud = None + + +# Upload the given build to a bucket in a region +def upload_to_cloud(buildid, region, bucket, suffix=None, public=False): + print("Uploading {} to {} in {}...".format(buildid, bucket, region)) + ca_args = ['coreos-assembler', + f'buildextend-{cloud}', + '--upload', + f'--build={buildid}', + f'--region={region}', + f'--bucket={bucket}'] + + if suffix is not None: + ca_args.append(f'--name-suffix={suffix}') + + # If the AMI is public, grant image launch and ec2 snapshot permissions to Marketplace account. + if public and cloud == AWS: + ca_args.extend(["--grant-user", OPENSHIFT_MARKETPLACE_TEST_ACCOUNT]) + ca_args.extend(["--grant-user-snapshot", OPENSHIFT_MARKETPLACE_TEST_ACCOUNT]) + try: + print(ca_args) + subprocess.check_call(ca_args) + except subprocess.CalledProcessError as upload_err: + print("Failed to build/upload image! Error: {}".format(upload_err)) + raise + + # If the AMI isn't public, then just grant access to the dev and CI accounts. + if not public and cloud == AWS: + ca_args.extend(["--grant-user", OPENSHIFT_CI_ACCOUNT, OPENSHIFT_DEV_ACCOUNT]) + try: + print(ca_args) + subprocess.check_call(ca_args) + except subprocess.CalledProcessError as upload_err: + print("Failed to build/upload image! Error: {}".format(upload_err)) + raise + +# Run the basic kola test on an AMI +def run_kola_basic(ami_id, region): + kola_args = ['kola', '-b', 'rhcos', + '-p', 'aws', + '--ignition-version', 'v2', + '--aws-type', INSTANCE_TYPE, + '--tapfile', 'rhcos-aws.tap', + '--aws-ami', ami_id, + '--aws-region', region, + 'run', SANITY_CHECK] + + try: + subprocess.check_call(kola_args) + except subprocess.CalledProcessError as kola_err: + print("Running kola tests on AWS failed! Error: {}".format(kola_err)) + raise + +# Set all the permissions to make the AMI/snapshot public +def make_ami_public(region, ami_id): + print(f"Making {ami_id} public") + # allow the AMI to started by everyone + try: + subprocess.check_call(['aws', 'ec2', "--region", region, + 'modify-image-attribute', + '--image-id', ami_id, + '--launch-permission', + '{"Add": [{"Group":"all"}]}']) + except subprocess.CalledProcessError as pub_err: + print("Failed to make {} public! Error: {}".format(ami_id, pub_err)) + raise + + # check that the AMI is actually public + try: + output = subprocess.check_output(['aws', 'ec2', + '--region', region, + 'describe-images', + '--image-id', ami_id]) + except subprocess.CalledProcessError as pub_err: + print("Failed to describe AMI {}! Error: {}".format(ami_id, pub_err)) + raise + + image_description = json.loads(output) + snapshot = None + for image in image_description['Images']: + for block_device_mapping in image['BlockDeviceMappings']: + ebs = block_device_mapping.get('Ebs') + if ebs is not None: + snapshot = ebs['SnapshotId'] + break + + assert snapshot is not None, \ + "Failed to find SnapshotId associated with AMI {}".format(ami_id) + + # allow everyone to create volumes with the snapshot + print("Adding createVolumePermission for snapshot {}".format(snapshot) + + "in region {}".format(region)) + try: + subprocess.check_call(['aws', 'ec2', "--region", region, + 'modify-snapshot-attribute', + '--snapshot-id', snapshot, + '--attribute', 'createVolumePermission', + '--operation-type', 'add', + '--group-names', 'all']) + except subprocess.CalledProcessError as pub_err: + print("Failed to add createVolumePermission on " + + "snapshot {}! Error: {}".format(snapshot, pub_err)) + raise + + +def main(): + # the aliyun API is so close to the AWS one, we're just using the same + # script for both of them + entrypoint = os.path.basename(sys.argv[0]) + global cloud + if entrypoint == 'upload-ami': + cloud = AWS + elif entrypoint == 'upload-aliyun-image': + cloud = ALIYUN + else: + assert False, f"Bad entrypoint {entrypoint}" + + # parse args and dispatch + parser = argparse.ArgumentParser() + parser.add_argument("--build", action='store', required=True) + parser.add_argument("--region", action='store', required=True) + parser.add_argument("--bucket", action='store', required=True) + parser.add_argument("--name-suffix", action='store') + parser.add_argument("--public", action='store_true') + parser.add_argument("--skip-kola", action='store_true') + args = parser.parse_args() + + # we don't support this flag on aliyun yet, but we still want it in the + # args namespace + if cloud == ALIYUN: + assert not args.public + + try: + upload_to_cloud(args.build, args.region, + args.bucket, args.name_suffix, + args.public) + except subprocess.CalledProcessError: + sys.exit(1) + + arch = subprocess.check_output(["cosa", "basearch"], text='UTF-8').strip() + + if args.public: + with open(f"builds/{args.build}/{arch}/meta.json") as meta_f: + meta = json.load(meta_f) + ami_id = None + for region in meta['amis']: + if region['name'] == args.region: + ami_id = region['hvm'] + if ami_id is None: + print("Failed to find AMI {} in meta.json!".format(ami_id)) + sys.exit(1) + + if not args.skip_kola: + try: + run_kola_basic(ami_id, args.region) + except subprocess.CalledProcessError: + sys.exit(1) + + # Actually make the AMI/Snapshot public now + try: + make_ami_public(args.region, ami_id) + except (AssertionError, subprocess.CalledProcessError): + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/scripts/verify-kernel-versions b/scripts/verify-kernel-versions new file mode 100755 index 000000000..a73e6f987 --- /dev/null +++ b/scripts/verify-kernel-versions @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +""" +Checks to ensure the composed kernel versions and the kernel-rt extension +all have the same version. + +We want to ensure we are shipping the same feature set, kmods/drivers, +and errata are applied for those customers who chose to switch between +kernels. +""" + +import json +import os +import subprocess +import sys + +#: When set to 1, doesn't stop builds when errors are found +IGNORE_KERNEL_MISMATCH = int(os.getenv('IGNORE_KERNEL_MISMATCH', 0)) +try: + #: Jenkins provided workspace + WORKSPACE = sys.argv[1] +except Exception as ex: + print('Missing workspace path') + raise ex + +#: Path to latest builds +LATEST_BUILDS = os.path.join(WORKSPACE, 'builds/latest/') + + +def exit_on_error(errors: list, title: str): + """ + Prints errors and exists. + + :param errors: List of errors. + :raises: SystemExit + """ + if len(errors) > 0: + print(f'{title} - {len(errors)} error(s):') + for err in errors: + print(f'- {err}') + + if not IGNORE_KERNEL_MISMATCH: + raise SystemExit(1) + + +def get_nevr_from_rpm(rpm_path: str) -> list: + """ + Uses the rpm command to parse Name, Epoch, Version, and Release + from the local package. + + :param rpm_path: Path to the local rpm package + :raises: CalledProcessError, FileNotFoundError + """ + # Create a command that makes it easy to parse (-'s are deceiving) + cmd = [ + 'rpm', '-qp', '--qf', + "%{NAME}|%{EPOCH}|%{VERSION}|%{RELEASE}|%{ARCH}", rpm_path] + parts = subprocess.check_output(cmd).decode('utf8').split('|') + # If rpm says there is no epoch, it's 0 + if parts[1] == '(none)': + parts[1] = '0' + return parts + + +def get_rt_evr() -> list: + """ + Goes through the kernel-rt extensions path, verifies the kernel-rt + packages all have the same version, then returns a list of the + epoch, version, release. + + .. note:: + If the kernel-rt versions don't match eachother an error + prints and the script exits. + + :raises: SystemExit, CalledProcessError, FileNotFoundError + """ + evr = [] + errors = [] + rt_ext_path = os.path.join(WORKSPACE, 'extensions/extensions/kernel-rt/') + if not os.path.isdir(rt_ext_path): + exit_on_error([ + f'{rt_ext_path} is not a directory or does not exist'], + 'verify rt extensions directory') + for p, d, f in os.walk(rt_ext_path): + for fname in f: + if fname.endswith('.rpm'): + pkg = os.path.join(p, fname) + nevr = get_nevr_from_rpm(pkg) + # Remove the rt specific string + nevr[3] = nevr[3].replace( + nevr[3][nevr[3].index('.rt'):nevr[3].index('.el')], '') + if evr: + if evr != nevr[1:]: + errors.append( + f'{pkg} version differs from other rt packages:' + f' {evr} != {nevr[1:]}') + evr = nevr[1:] + + exit_on_error(errors, 'rt kernel version check') + if not IGNORE_KERNEL_MISMATCH: + print('rt packages have consistent versions...') + return evr + + +def main(): + """ + Main entry point. + + :raises: FileNotFoundError, SystemExit + """ + # kernel-rt is only available on x86_64. Exit early on any + # other architecture + arch = subprocess.check_output('arch')[:-1].decode() + if arch != 'x86_64': + print( + f'Skipping kernel/kernel-rt check on non x86_64 platform: {arch}') + return SystemExit() + + print('Verifying kernel versions are inline with each other ...') + rt_evr = get_rt_evr() + + # Since all the versioning should be consistent we can + # check that the kernel packages match the single kernel-rt version + errors = [] + cmj = os.path.join(LATEST_BUILDS, 'x86_64', 'commitmeta.json') + with open(cmj, 'r') as f: + commitmeta = json.load(f) + for i in commitmeta['rpmostree.rpmdb.pkglist']: + if i[0].startswith('kernel'): + if i[1:] != rt_evr: + # version-release.arch.epoch + kernel_pkg = '-'.join(i[2:-1]) + "." + i[1] + rt_kernel_pkg = '-'.join(rt_evr[1:-1]) + "." + rt_evr[0] + errors.append( + f'kernel-rt and {i[0]} version mismatch: ' + f'{kernel_pkg} != {rt_kernel_pkg}') + exit_on_error(errors, 'default kernel and rt version check') + print('<3 Kernel versions match <3') + + +if __name__ == '__main__': + main() diff --git a/sync-sources.sh b/sync-sources.sh new file mode 100755 index 000000000..6ac182d05 --- /dev/null +++ b/sync-sources.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Currently the RHT-internal `redhat-coreos` git repository +# contains both the equivalent of: +# - fedora-coreos-config +# - fedora-coreos-pipeline +# This script extracts just the first part, since the second +# part has way more internal stuff. +set -euo pipefail + +dn=$(cd $(dirname $0) && pwd) + +src=$1 +shift +files=(manifest.yaml rhcos-packages.yaml image.yaml passwd group overlay.d live scripts + kola-denylist.yaml tests) + +for f in ${files[@]}; do + rsync -rlv --delete "${src}/${f}" ${dn} +done + +fcos_rev=$(cd ${src}/fedora-coreos-config && git rev-parse HEAD) +cd ${dn}/fedora-coreos-config +git fetch origin +git reset --hard "${fcos_rev}" +cd - + diff --git a/tests/kola/chrony/coreos-platform-chrony-generator b/tests/kola/chrony/coreos-platform-chrony-generator new file mode 100755 index 000000000..98826bb6f --- /dev/null +++ b/tests/kola/chrony/coreos-platform-chrony-generator @@ -0,0 +1,15 @@ +#!/bin/bash +set -euo pipefail +# Test the coreos-platform-chrony generator. + +# kola: { "platforms": "aws,azure,gcp" } + +cd $(mktemp -d) + +platform="$(grep -Eo ' ignition.platform.id=[a-z]+' /proc/cmdline | cut -f 2 -d =)" +case "${platform}" in + aws) chronyc sources |grep '169.254.169.123'; echo "ok chrony aws" ;; + azure) chronyc sources |grep 'PHC0'; echo "ok chrony azure" ;; + gcp) chronyc sources | grep metadata.google.internal; echo "ok chrony gcp" ;; + *) echo "unhandled platform ${platform} ?"; exit 1 ;; +esac \ No newline at end of file diff --git a/tests/kola/chrony/dhcp-propagation b/tests/kola/chrony/dhcp-propagation new file mode 100755 index 000000000..90a2501d8 --- /dev/null +++ b/tests/kola/chrony/dhcp-propagation @@ -0,0 +1,73 @@ +#!/bin/bash + +# This script creates two veth interfaces i.e. one for the host machine +# and other for the container(dnsmasq server). This setup will be helpful +# to verify the DHCP propagation of NTP servers. This will also avoid any +# regression that might cause in RHCOS or FCOS when the upstream changes +# come down and obsolete the temporary work (https://github.com/coreos/fedora-coreos-config/pull/412) + +set -xeuo pipefail + +# kola: { "tags": "needs-internet" } + +test_setup() { + + # This is needed to run a container with systemd + setsebool container_manage_cgroup 1 + + # create a network namespace + ip netns add container + + # create veth pair and assign a namespace to veth-container + ip link add veth-host type veth peer name veth-container + ip link set veth-container netns container + + # assign an IP address to the `veth-container` interface and bring it up + ip netns exec container ip address add 172.16.0.1/24 dev veth-container + ip netns exec container ip link set veth-container up + + # create a static ethernet connection for the `veth-host` + nmcli dev set veth-host managed yes + ip link set veth-host up + + # run podman commands to set up dnsmasq server + pushd $(mktemp -d) + NTPHOSTIP=$(getent hosts time-c-g.nist.gov | cut -d ' ' -f 1) + cat <Dockerfile +FROM registry.fedoraproject.org/fedora:32 +RUN dnf -y install systemd dnsmasq iproute iputils \ +&& dnf clean all \ +&& systemctl enable dnsmasq +RUN echo -e 'dhcp-range=172.16.0.10,172.16.0.20,12h\nbind-interfaces\ninterface=veth-container\ndhcp-option=option:ntp-server,$NTPHOSTIP' > /etc/dnsmasq.d/dhcp +CMD [ "/sbin/init" ] +EOF + podman build -t dnsmasq . + popd + podman run -d --rm --name dnsmasq --privileged --network ns:/var/run/netns/container dnsmasq + +} + +main() { + + test_setup + + # check for NTP server information + # Name: time-c-g.nist.gov IP address: 129.6.15.30 + NTPSERVER="" + retries=300 + while [[ $retries -gt 0 && ! $NTPSERVER =~ "time-c-g.nist.gov" ]]; do + NTPSERVER=$(chronyc sources) + if [[ $NTPSERVER != *"time-c-g.nist.gov"* ]]; then + echo "waiting for ntp server to appear" + sleep 1 + retries=$((retries - 1)) + fi + done + + if [ $retries -eq 0 ]; then + echo "propagation of ntp server information via dhcp failed" + exit 1 + fi +} + +main \ No newline at end of file diff --git a/tests/kola/luks/ignition/config.ign b/tests/kola/luks/ignition/config.ign new file mode 100644 index 000000000..a4062af69 --- /dev/null +++ b/tests/kola/luks/ignition/config.ign @@ -0,0 +1,33 @@ +{ + "ignition": { + "version": "3.2.0-experimental" + }, + "storage": { + "luks": [ + { + "name": "DATA", + "device": "/dev/disk/by-id/virtio-disk1", + "keyFile": { + "source": "data:,foo" + } + } + ], + "filesystems": [ + { + "path": "/var/lib/data", + "device": "/dev/mapper/DATA", + "format": "xfs", + "label": "var" + } + ] + }, + "systemd": { + "units": [ + { + "name": "var-lib-data.mount", + "enabled": true, + "contents": "[Mount]\nWhat=/dev/mapper/DATA\nWhere=/var/lib/data\nType=xfs\n\n[Install]\nWantedBy=local-fs.target\n" + } + ] + } +} diff --git a/tests/kola/luks/ignition/test.sh b/tests/kola/luks/ignition/test.sh new file mode 100755 index 000000000..832700038 --- /dev/null +++ b/tests/kola/luks/ignition/test.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# kola: {"platforms": "qemu", "additionalDisks": ["5G"]} +set -xeuo pipefail + +srcdev=$(findmnt -nvr /var/lib/data -o SOURCE) +[[ ${srcdev} == /dev/mapper/DATA ]] + +blktype=$(lsblk -o TYPE "${srcdev}" --noheadings) +[[ ${blktype} == crypt ]] + +fstype=$(findmnt -nvr /var/lib/data -o FSTYPE) +[[ ${fstype} == xfs ]] diff --git a/tests/kola/luks/tpm/config.ign b/tests/kola/luks/tpm/config.ign new file mode 100644 index 000000000..770ef6ac5 --- /dev/null +++ b/tests/kola/luks/tpm/config.ign @@ -0,0 +1,16 @@ +{ + "ignition": { + "version": "3.0.0" + }, + "storage": { + "files": [ + { + "path": "/etc/clevis.json", + "contents": { + "source": "data:text/plain;base64,e30K" + }, + "mode": 420 + } + ] + } +} diff --git a/tests/kola/luks/tpm/kola.json b/tests/kola/luks/tpm/kola.json new file mode 100644 index 000000000..05b495104 --- /dev/null +++ b/tests/kola/luks/tpm/kola.json @@ -0,0 +1,4 @@ +{ + "architectures": "!s390x ppc64le", + "platforms": "qemu-unpriv" +} diff --git a/tests/kola/luks/tpm/tpm-validate-encrypted b/tests/kola/luks/tpm/tpm-validate-encrypted new file mode 100755 index 000000000..1d55a88a1 --- /dev/null +++ b/tests/kola/luks/tpm/tpm-validate-encrypted @@ -0,0 +1,38 @@ +#!/bin/bash +set -xeuo pipefail + +# Validate that the root filesystem is encrypted if we request +# binding to the TPM. + +boot=$(journalctl --list-boots | wc -l) +cd $(mktemp -d) +case "${AUTOPKGTEST_REBOOT_MARK:-}" in + "") + cryptsetup luksDump /dev/disk/by-partlabel/luks_root > luks.dump + # Yes, some hacky regexps. There is luksDump --debug-json but we'd have to massage the JSON + # out of other debug output and it's not clear to me it's going to be more stable. + # We're just going for a basic sanity check here. + grep -qE -e 'Cipher: *aes' luks.dump + if grep -q "Cipher: *cipher_null-ecb" luks.dump; then + echo "found null cipher" 1>&2 + exit 1 + fi + grep -qE -e '0: *clevis' luks.dump + + if grep -q '9: *coreos' luks.dump; then + echo "found default token" 1>&2 + exit 1 + fi + journalctl -q -b -u coreos-encrypt --grep=pin=tpm2 > journal.dump + grep -q pin=tpm2 journal.dump + /tmp/autopkgtest-reboot validate-encrypted + ;; + validate-encrypted) + cryptsetup luksDump /dev/disk/by-partlabel/luks_root > luks-rebooted.dump + grep -qE -e 'Cipher: *aes' luks-rebooted.dump + echo "OK" + ;; + *) echo "Unexpected reboot state" + exit 1 + ;; +esac diff --git a/tests/kola/misc-ro/misc-ro.sh b/tests/kola/misc-ro/misc-ro.sh new file mode 100755 index 000000000..6a31ed51e --- /dev/null +++ b/tests/kola/misc-ro/misc-ro.sh @@ -0,0 +1,95 @@ +#!/bin/bash +# This test is a dumping ground for quick read-only tests. +set -xeuo pipefail + +cd $(mktemp -d) + +fatal() { + echo "$@" + exit 1 +} + +# Ensure we have tmpfs on /tmp like Fedora(FCOS) +tmpfs=$(findmnt -n -o FSTYPE /tmp) +if [ "${tmpfs}" != "tmpfs" ]; then + fatal "Expected tmpfs on /tmp, found: ${tmpfs}" +fi +echo "ok tmpfs" + +# SELinux should be on + enforce=$(getenforce) +if [ "${enforce}" != "Enforcing" ]; then + fatal "Expected SELinux Enforcing, found ${enforce}" +fi +echo "ok selinux" + +# We have forgotten to chmod a+x the chrony generator, and accidentally +# omitted it entirely. +find /usr/lib/systemd/system-generators -type f | while read f; do + if ! test -x $f; then + fatal "generator is not executable: $f" + fi +done +test -x /usr/lib/systemd/system-generators/coreos-platform-chrony +echo "ok generators" + +# https://bugzilla.redhat.com/show_bug.cgi?id=1830280 +case "$(arch)" in + x86_64) + dmesg | grep ' random:' > random.txt + if ! grep -qe 'crng done.*trust.*CPU'