diff --git a/.arg.template b/.arg.template index c72706a..4d914e1 100644 --- a/.arg.template +++ b/.arg.template @@ -10,4 +10,9 @@ HTTPS_PROXY= HTTP_PROXY= PROXY_CERT_PATH= UPDATE_KERNEL=false -CLUSTERCONFIG=spc.tgz \ No newline at end of file +CLUSTERCONFIG=spc.tgz +CIS_HARDENING=true +IS_UKI=false +UKI_SELF_SIGNED_KEYS=true +INCLUDE_MS_SECUREBOOT_KEYS=true +AUTO_ENROLL_SECUREBOOT_KEYS=false \ No newline at end of file diff --git a/.earthlyignore b/.earthlyignore new file mode 100644 index 0000000..c6fb21c --- /dev/null +++ b/.earthlyignore @@ -0,0 +1,2 @@ +local/ +build/* \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8291286..b7b0497 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,9 @@ content-*/* *.arg .idea -.DS_Store \ No newline at end of file +.DS_Store + +build/ +local/ +keys/ +secure-boot/ diff --git a/Dockerfile b/Dockerfile index 9e1655a..f0f9e18 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,18 @@ RUN if [ "${OS_DISTRIBUTION}" = "opensuse-leap" ] && [ "${PROXY_CERT_PATH}" != " ### To install the nginx package for Ubuntu ### +#TODO: Remove the following line. This is only for dev purpose. +# RUN useradd -m kairos && echo "kairos:kairos" | chpasswd +# RUN adduser kairos sudo +# RUN echo '%sudo ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers + +# sbctl and mokutil are useful tools to check secure boot status, manage secure boot keys. +RUN curl -Ls https://github.com/Foxboron/sbctl/releases/download/0.13/sbctl-0.13-linux-amd64.tar.gz | tar -xvzf - && mv sbctl/sbctl /usr/bin/sbctl +RUN chmod +x /usr/bin/sbctl +RUN apt-get update && apt-get install -y \ + mokutil \ + && apt-get clean + # RUN apt-get update && apt-get install nginx -y ### or diff --git a/Earthfile b/Earthfile index 2ddfb51..93e9c7f 100644 --- a/Earthfile +++ b/Earthfile @@ -3,34 +3,39 @@ ARG TARGETOS ARG TARGETARCH ## Default Image Repos Used in the Builds. +ARG ALPINE_IMG=gcr.io/spectro-images-public/alpine:3.16.2 ARG SPECTRO_PUB_REPO=gcr.io/spectro-images-public ARG SPECTRO_LUET_REPO=gcr.io/spectro-dev-public -ARG KAIROS_BASE_IMAGE_URL=gcr.io/spectro-images-public +ARG KAIROS_BASE_IMAGE_URL=quay.io/kairos ARG ETCD_REPO=https://github.com/etcd-io FROM $SPECTRO_PUB_REPO/canvos/alpine-cert:v1.0.0 ## Spectro Cloud and Kairos Tags ## ARG PE_VERSION=v4.3.0 ARG SPECTRO_LUET_VERSION=v1.2.7 -ARG KAIROS_VERSION=v2.4.5 +ARG KAIROS_VERSION=v3.0.7 ARG K3S_FLAVOR_TAG=k3s1 ARG RKE2_FLAVOR_TAG=rke2r1 -ARG OSBUILDER_VERSION=v0.7.11 -ARG OSBUILDER_IMAGE=$KAIROS_BASE_IMAGE_URL/osbuilder-tools:$OSBUILDER_VERSION -ARG K3S_PROVIDER_VERSION=v4.2.1 -ARG KUBEADM_PROVIDER_VERSION=v4.3.1 -ARG RKE2_PROVIDER_VERSION=v4.1.1 +ARG BASE_IMAGE_URL=quay.io/kairos +ARG OSBUILDER_VERSION=v0.200.11 +ARG OSBUILDER_IMAGE=quay.io/kairos/osbuilder-tools:$OSBUILDER_VERSION +ARG K3S_PROVIDER_VERSION=v4.4.0-alpha1 +ARG KUBEADM_PROVIDER_VERSION=v4.4.0-alpha1 +ARG RKE2_PROVIDER_VERSION=v4.4.0-alpha1 # Variables used in the builds. Update for ADVANCED use cases only Modify in .arg file or via CLI arguements ARG OS_DISTRIBUTION ARG OS_VERSION +ARG K8S_VERSION ARG IMAGE_REGISTRY ARG IMAGE_REPO=$OS_DISTRIBUTION +ARG ISO_NAME=installer ARG K8S_DISTRIBUTION ARG CUSTOM_TAG ARG CLUSTERCONFIG ARG ARCH ARG DISABLE_SELINUX=true +ARG CIS_HARDENING=true ARG FIPS_ENABLED=false ARG HTTP_PROXY @@ -41,17 +46,27 @@ ARG https_proxy=${HTTPS_PROXY} ARG no_proxy=${NO_PROXY} ARG PROXY_CERT_PATH - - ARG UPDATE_KERNEL=false +# UKI Variables +ARG IS_UKI=false +ARG INCLUDE_MS_SECUREBOOT_KEYS=true +ARG AUTO_ENROLL_SECUREBOOT_KEYS=false +ARG UKI_SELF_SIGNED_KEYS=true + +ARG CMDLINE="stylus.registration" +ARG BRANDING="Palette eXtended Kubernetes Edge" ARG ETCD_VERSION="v3.5.13" IF [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$BASE_IMAGE" = "" ] IF [ "$OS_VERSION" == 22 ] || [ "$OS_VERSION" == 20 ] ARG BASE_IMAGE_TAG=kairos-$OS_DISTRIBUTION:$OS_VERSION.04-core-$ARCH-generic-$KAIROS_VERSION ELSE - ARG BASE_IMAGE_TAG=kairos-$OS_DISTRIBUTION:$OS_VERSION-core-$ARCH-generic-$KAIROS_VERSION + IF [ "$IS_UKI" = "true" ] + ARG BASE_IMAGE_TAG=$OS_DISTRIBUTION:$OS_VERSION-core-$ARCH-generic-$KAIROS_VERSION-uki + ELSE + ARG BASE_IMAGE_TAG=$OS_DISTRIBUTION:$OS_VERSION-core-$ARCH-generic-$KAIROS_VERSION + END END ARG BASE_IMAGE=$KAIROS_BASE_IMAGE_URL/$BASE_IMAGE_TAG ELSE IF [ "$OS_DISTRIBUTION" = "opensuse-leap" ] && [ "$BASE_IMAGE" = "" ] @@ -62,10 +77,25 @@ ELSE IF [ "$OS_DISTRIBUTION" = "rhel" ] || [ "$OS_DISTRIBUTION" = "sles" ] ARG BASE_IMAGE END -IF [[ "$BASE_IMAGE" =~ "20.04-arm64-nvidia-jetson-agx-orin" ]] +IF [[ "$BASE_IMAGE" =~ "nvidia-jetson-agx-orin" ]] ARG IS_JETSON=true END +IF [ "$FIPS_ENABLED" = "true" ] + ARG STYLUS_BASE=gcr.io/spectro-images-public/stylus-framework-fips-linux-$ARCH:$PE_VERSION + ARG STYLUS_PACKAGE_BASE=gcr.io/spectro-images-public/stylus-fips-linux-$ARCH:$PE_VERSION +ELSE + ARG STYLUS_BASE=gcr.io/spectro-images-public/stylus-framework-linux-$ARCH:$PE_VERSION + ARG STYLUS_PACKAGE_BASE=gcr.io/spectro-images-public/stylus-linux-$ARCH:$PE_VERSION +END + +IF [ "$CUSTOM_TAG" != "" ] + ARG IMAGE_PATH=$IMAGE_REGISTRY/$IMAGE_REPO:$K8S_DISTRIBUTION-$K8S_VERSION-$PE_VERSION-$CUSTOM_TAG +ELSE + ARG IMAGE_PATH=$IMAGE_REGISTRY/$IMAGE_REPO:$K8S_DISTRIBUTION-$K8S_VERSION-$PE_VERSION +END +ARG CMDLINE="stylus.registration" + build-all-images: IF $FIPS_ENABLED BUILD +build-provider-images-fips @@ -73,39 +103,48 @@ build-all-images: BUILD +build-provider-images END IF [ "$ARCH" = "arm64" ] - BUILD --platform=linux/arm64 +iso-image - BUILD --platform=linux/arm64 +iso + BUILD --platform=linux/arm64 +iso-image + BUILD --platform=linux/arm64 +iso ELSE IF [ "$ARCH" = "amd64" ] - BUILD --platform=linux/amd64 +iso-image - BUILD --platform=linux/amd64 +iso + BUILD --platform=linux/amd64 +iso-image + BUILD --platform=linux/amd64 +iso END build-provider-images: - BUILD +provider-image --K8S_VERSION=1.24.6 - BUILD +provider-image --K8S_VERSION=1.25.2 - BUILD +provider-image --K8S_VERSION=1.26.4 - BUILD +provider-image --K8S_VERSION=1.27.2 - BUILD +provider-image --K8S_VERSION=1.25.13 - BUILD +provider-image --K8S_VERSION=1.26.8 - BUILD +provider-image --K8S_VERSION=1.27.5 - BUILD +provider-image --K8S_VERSION=1.27.7 - BUILD +provider-image --K8S_VERSION=1.26.10 - BUILD +provider-image --K8S_VERSION=1.25.15 - BUILD +provider-image --K8S_VERSION=1.28.2 - BUILD +provider-image --K8S_VERSION=1.29.0 - BUILD +provider-image --K8S_VERSION=1.27.9 - BUILD +provider-image --K8S_VERSION=1.26.12 - BUILD +provider-image --K8S_VERSION=1.28.5 - IF [ "$K8S_DISTRIBUTION" = "rke2" ] - BUILD +provider-image --K8S_VERSION=1.26.14 - BUILD +provider-image --K8S_VERSION=1.27.11 - BUILD +provider-image --K8S_VERSION=1.28.7 - BUILD +provider-image --K8S_VERSION=1.29.3 - ELSE IF [ "$K8S_DISTRIBUTION" = "k3s" ] - BUILD +provider-image --K8S_VERSION=1.26.14 - BUILD +provider-image --K8S_VERSION=1.27.11 - BUILD +provider-image --K8S_VERSION=1.28.7 - BUILD +provider-image --K8S_VERSION=1.29.2 + IF [ "$IS_UKI" = "true" ] + ARG TARGET=uki-provider-image + ELSE + ARG TARGET=provider-image + END + IF [ "$K8S_VERSION" = "" ] + BUILD +$TARGET --K8S_VERSION=1.24.6 + BUILD +$TARGET --K8S_VERSION=1.25.2 + BUILD +$TARGET --K8S_VERSION=1.26.4 + BUILD +$TARGET --K8S_VERSION=1.27.2 + BUILD +$TARGET --K8S_VERSION=1.25.13 + BUILD +$TARGET --K8S_VERSION=1.26.8 + BUILD +$TARGET --K8S_VERSION=1.27.5 + BUILD +$TARGET --K8S_VERSION=1.27.7 + BUILD +$TARGET --K8S_VERSION=1.26.10 + BUILD +$TARGET --K8S_VERSION=1.25.15 + BUILD +$TARGET --K8S_VERSION=1.28.2 + BUILD +$TARGET --K8S_VERSION=1.29.0 + BUILD +$TARGET --K8S_VERSION=1.27.9 + BUILD +$TARGET --K8S_VERSION=1.26.12 + BUILD +$TARGET --K8S_VERSION=1.28.5 + IF [ "$K8S_DISTRIBUTION" = "rke2" ] + BUILD +$TARGET --K8S_VERSION=1.26.14 + BUILD +$TARGET --K8S_VERSION=1.27.11 + BUILD +$TARGET --K8S_VERSION=1.28.7 + BUILD +$TARGET --K8S_VERSION=1.29.3 + ELSE IF [ "$K8S_DISTRIBUTION" = "k3s" ] + BUILD +$TARGET --K8S_VERSION=1.26.14 + BUILD +$TARGET --K8S_VERSION=1.27.11 + BUILD +$TARGET --K8S_VERSION=1.28.7 + BUILD +$TARGET --K8S_VERSION=1.29.2 + END + ELSE + BUILD +$TARGET --K8S_VERSION="$K8S_VERSION" END build-provider-images-fips: @@ -165,15 +204,126 @@ iso-image-rootfs: FROM --platform=linux/${ARCH} +iso-image SAVE ARTIFACT --keep-own /. rootfs +uki-iso: + WORKDIR /build + COPY --platform=linux/${ARCH} +build-uki-iso/ . + SAVE ARTIFACT /build/* AS LOCAL ./build/ + +uki-provider-image: + FROM gcr.io/spectro-images-public/ubuntu-systemd:22.04 + WORKDIR / + COPY +luet/luet /usr/bin/luet + COPY +kairos-agent/kairos-agent /usr/bin/kairos-agent + COPY --platform=linux/${ARCH} +trust-boot-unpack/ /trusted-boot + COPY --platform=linux/${ARCH} +install-k8s/ /k8s + SAVE IMAGE --push $IMAGE_PATH + +trust-boot-unpack: + COPY +luet/luet /usr/bin/luet + COPY --platform=linux/${ARCH} +build-provider-trustedboot-image/ /image + RUN FILE="file:/$(find /image -type f -name "*.tar" | head -n 1)" && \ + luet util unpack $FILE /trusted-boot + SAVE ARTIFACT /trusted-boot/* + +stylus-image-pack: + COPY +luet/luet /usr/bin/luet + COPY --platform=linux/${ARCH} +stylus-package-image/ /stylus + RUN cd stylus && tar -czf ../stylus.tar * + RUN luet util pack $STYLUS_BASE stylus.tar stylus-image.tar + SAVE ARTIFACT stylus-image.tar AS LOCAL ./build/ + +luet: + FROM quay.io/luet/base:latest + SAVE ARTIFACT /usr/bin/luet /luet + +kairos-agent: + FROM $BASE_IMAGE + SAVE ARTIFACT /usr/bin/kairos-agent /kairos-agent + +install-k8s: + FROM alpine + COPY +luet/luet /usr/bin/luet + + IF [ "$K8S_DISTRIBUTION" = "kubeadm" ] || [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ] + ARG BASE_K8S_VERSION=$K8S_VERSION + ELSE IF [ "$K8S_DISTRIBUTION" = "k3s" ] + ARG K8S_DISTRIBUTION_TAG=$K3S_FLAVOR_TAG + ARG BASE_K8S_VERSION=$K8S_VERSION-$K8S_DISTRIBUTION_TAG + ELSE IF [ "$K8S_DISTRIBUTION" = "rke2" ] + ARG K8S_DISTRIBUTION_TAG=$RKE2_FLAVOR_TAG + ARG BASE_K8S_VERSION=$K8S_VERSION-$K8S_DISTRIBUTION_TAG + END + + WORKDIR /output + RUN mkdir -p /etc/luet/repos.conf.d && \ + luet repo add spectro --type docker --url gcr.io/spectro-dev-public/luet-repo --priority 1 -y && \ + luet repo update + IF [ "$K8S_DISTRIBUTION" = "kubeadm" ] + RUN luet install -y container-runtime/containerd --system-target /output + END + + IF [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ] + RUN luet install -y container-runtime/containerd-fips --system-target /output + END + RUN luet install -y k8s/$K8S_DISTRIBUTION@$BASE_K8S_VERSION --system-target /output && luet cleanup + RUN rm -rf /output/var/cache/* + SAVE ARTIFACT /output/* + +internal-slink: + FROM alpine + COPY internal/slink/slink /slink + RUN chmod +x /slink + SAVE ARTIFACT /slink + +build-uki-iso: + FROM --platform=linux/${ARCH} $OSBUILDER_IMAGE + ENV ISO_NAME=${ISO_NAME} + COPY overlay/files-iso/ /overlay/ + COPY --if-exists user-data /overlay/config.yaml + COPY --if-exists user-data /overlay/data/config.yaml + COPY --platform=linux/${ARCH} +stylus-image-pack/stylus-image.tar /overlay/data/stylus-image.tar + COPY --platform=linux/${ARCH} +luet/luet /overlay/data/luet + + COPY --if-exists content-*/*.zst /overlay/opt/spectrocloud/content/ + #check if clusterconfig is passed in + IF [ "$CLUSTERCONFIG" != "" ] + COPY --if-exists "$CLUSTERCONFIG" /overlay/opt/spectrocloud/clusterconfig/spc.tgz + END + + COPY --if-exists ui.tar /overlay/opt/spectrocloud/emc/ + RUN if [ -f /overlay/opt/spectrocloud/emc/ui.tar ]; then \ + tar -xf /overlay/opt/spectrocloud/emc/ui.tar -C /overlay/opt/spectrocloud/emc && \ + rm -f /overlay/opt/spectrocloud/emc/ui.tar; \ + fi + + WORKDIR /build + COPY --platform=linux/${ARCH} --keep-own +iso-image-rootfs/rootfs /build/image + IF [ "$ARCH" = "arm64" ] + RUN /entrypoint.sh --name $ISO_NAME build-iso --date=false --overlay-iso /overlay dir:/build/image --debug --output /iso/ --arch $ARCH + ELSE IF [ "$ARCH" = "amd64" ] + COPY secure-boot/enrollment/ secure-boot/private-keys/ secure-boot/public-keys/ /keys + RUN ls -liah /keys + RUN mkdir /iso + IF [ "$AUTO_ENROLL_SECUREBOOT_KEYS" = "true" ] + RUN enki --config-dir /config build-uki dir:/build/image --extend-cmdline "$CMDLINE" --overlay-iso /overlay --overlay-iso /overlay/data --secure-boot-enroll force -t iso -d /iso -k /keys --boot-branding "$BRANDING" + ELSE + RUN enki --config-dir /config build-uki dir:/build/image --extend-cmdline "$CMDLINE" --overlay-iso /overlay --overlay-iso /overlay/data -t iso -d /iso -k /keys --boot-branding "$BRANDING" + END + END + WORKDIR /iso + RUN mv /iso/*.iso $ISO_NAME.iso + SAVE ARTIFACT /iso/* + iso: - ARG ISO_NAME=installer WORKDIR /build - COPY --platform=linux/${ARCH} (+build-iso/ --ISO_NAME=$ISO_NAME) . + IF [ "$IS_UKI" = "true" ] + COPY --platform=linux/${ARCH} +build-uki-iso/ . + ELSE + COPY --platform=linux/${ARCH} +build-iso/ . + END SAVE ARTIFACT /build/* AS LOCAL ./build/ build-iso: - ARG ISO_NAME - FROM --platform=linux/${ARCH} $OSBUILDER_IMAGE ENV ISO_NAME=${ISO_NAME} COPY overlay/files-iso/ /overlay/ @@ -204,20 +354,46 @@ build-iso: RUN sha256sum $ISO_NAME.iso > $ISO_NAME.iso.sha256 SAVE ARTIFACT /iso/* +### UKI targets +## Generate UKI keys +# Default Expiry 15 years +## earthly +uki-genkey --MY_ORG="ACME Corp" --EXPIRATION_IN_DAYS=5475 +uki-genkey: + ARG MY_ORG="ACME Corp" + ARG EXPIRATION_IN_DAYS=5475 + FROM --platform=linux/${ARCH} $OSBUILDER_IMAGE + + IF [ "$UKI_SELF_SIGNED_KEYS" = "false" ] + RUN --no-cache mkdir -p /custom-keys + COPY secure-boot/exported-keys/ /custom-keys + RUN --no-cache /entrypoint.sh genkey "$MY_ORG" --custom-cert-dir /custom-keys --skip-microsoft-certs-I-KNOW-WHAT-IM-DOING --expiration-in-days $EXPIRATION_IN_DAYS -o /keys + ELSE + IF [ "$INCLUDE_MS_SECUREBOOT_KEYS" = "false" ] + RUN --no-cache /entrypoint.sh genkey "$MY_ORG" --skip-microsoft-certs-I-KNOW-WHAT-IM-DOING --expiration-in-days $EXPIRATION_IN_DAYS -o /keys + ELSE + RUN --no-cache /entrypoint.sh genkey "$MY_ORG" --expiration-in-days $EXPIRATION_IN_DAYS -o /keys + END + END + RUN --no-cache mkdir -p /private-keys + RUN --no-cache mkdir -p /public-keys + RUN --no-cache cd /keys; mv *.key tpm2-pcr-private.pem /private-keys + RUN --no-cache cd /keys; mv *.pem /public-keys + + SAVE ARTIFACT /keys AS LOCAL ./secure-boot/enrollment + SAVE ARTIFACT /private-keys AS LOCAL ./secure-boot/private-keys + SAVE ARTIFACT /public-keys AS LOCAL ./secure-boot/public-keys + # Used to create the provider images. The --K8S_VERSION will be passed in the earthly build -provider-image: +provider-image: FROM --platform=linux/${ARCH} +base-image # added PROVIDER_K8S_VERSION to fix missing image in ghcr.io/kairos-io/provider-* - ARG K8S_VERSION=1.26.4 ARG IMAGE_REPO - IF [ "$CUSTOM_TAG" != "" ] - ARG IMAGE_PATH=$IMAGE_REGISTRY/$IMAGE_REPO:$K8S_DISTRIBUTION-$K8S_VERSION-$PE_VERSION-$CUSTOM_TAG - ELSE - ARG IMAGE_PATH=$IMAGE_REGISTRY/$IMAGE_REPO:$K8S_DISTRIBUTION-$K8S_VERSION-$PE_VERSION - END IF [ "$K8S_DISTRIBUTION" = "kubeadm" ] || [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ] ARG BASE_K8S_VERSION=$K8S_VERSION + IF [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] + RUN kernel=$(ls /lib/modules | tail -n1) && if ! ls /usr/src | grep linux-headers-$kernel; then apt-get update && apt-get install -y "linux-headers-${kernel}"; fi + END ELSE IF [ "$K8S_DISTRIBUTION" = "k3s" ] ARG K8S_DISTRIBUTION_TAG=$K3S_FLAVOR_TAG ARG BASE_K8S_VERSION=$K8S_VERSION-$K8S_DISTRIBUTION_TAG @@ -230,15 +406,18 @@ provider-image: COPY +stylus-image/etc/kairos/branding /etc/kairos/branding COPY +stylus-image/oem/stylus_config.yaml /etc/kairos/branding/stylus_config.yaml COPY +stylus-image/etc/elemental/config.yaml /etc/elemental/config.yaml - IF [ "$K8S_DISTRIBUTION" = "kubeadm" ] - RUN luet install -y container-runtime/containerd - END - IF [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ] - RUN luet install -y container-runtime/containerd-fips + IF [ "$IS_UKI" = "true" ] + COPY +internal-slink/slink /usr/bin/slink + COPY +install-k8s/ /k8s + RUN slink --source /k8s/ --target /opt/k8s + RUN rm -f /usr/bin/slink + RUN rm -rf /k8s + RUN ln -sf /opt/spectrocloud/bin/agent-provider-stylus /usr/local/bin/agent-provider-stylus + ELSE + COPY +install-k8s/ / END - RUN luet install -y k8s/$K8S_DISTRIBUTION@$BASE_K8S_VERSION && luet cleanup RUN rm -f /etc/ssh/ssh_host_* /etc/ssh/moduli COPY (+download-etcdctl/etcdctl) /usr/bin/ @@ -248,17 +427,28 @@ provider-image: SAVE IMAGE --push $IMAGE_PATH + +provider-image-rootfs: + FROM --platform=linux/${ARCH} +provider-image + SAVE ARTIFACT --keep-own /. rootfs + +build-provider-trustedboot-image: + FROM --platform=linux/${ARCH} $OSBUILDER_IMAGE + COPY --platform=linux/${ARCH} --keep-own +provider-image-rootfs/rootfs /build/image + COPY secure-boot/enrollment/ secure-boot/private-keys/ secure-boot/public-keys/ /keys + RUN /entrypoint.sh build-uki dir:/build/image -t container -d /output -k /keys --boot-branding "Palette eXtended Kubernetes Edge" + SAVE ARTIFACT /output/* AS LOCAL ./trusted-boot/ + stylus-image: - IF [ "$FIPS_ENABLED" = "true" ] - ARG STYLUS_BASE=$SPECTRO_PUB_REPO/stylus-framework-fips-linux-$ARCH:$PE_VERSION - ELSE - ARG STYLUS_BASE=$SPECTRO_PUB_REPO/stylus-framework-linux-$ARCH:$PE_VERSION - END FROM $STYLUS_BASE - SAVE ARTIFACT ./* - SAVE ARTIFACT /etc/kairos/branding - SAVE ARTIFACT /etc/elemental/config.yaml - SAVE ARTIFACT /oem/stylus_config.yaml + SAVE ARTIFACT --keep-own ./* + # SAVE ARTIFACT /etc/kairos/branding + # SAVE ARTIFACT /etc/elemental/config.yaml + # SAVE ARTIFACT /oem/stylus_config.yaml + +stylus-package-image: + FROM $STYLUS_PACKAGE_BASE + SAVE ARTIFACT --keep-own ./* kairos-provider-image: IF [ "$K8S_DISTRIBUTION" = "kubeadm" ] @@ -278,11 +468,36 @@ kairos-provider-image: # base build image used to create the base image for all other image types base-image: FROM DOCKERFILE --build-arg BASE=$BASE_IMAGE --build-arg PROXY_CERT_PATH=$PROXY_CERT_PATH \ - --build-arg OS_DISTRIBUTION=$OS_DISTRIBUTION --build-arg HTTP_PROXY=$HTTP_PROXY --build-arg HTTPS_PROXY=$HTTPS_PROXY \ + --build-arg OS_DISTRIBUTION=$OS_DISTRIBUTION --build-arg OS_VERSION=$OS_VERSION \ + --build-arg HTTP_PROXY=$HTTP_PROXY --build-arg HTTPS_PROXY=$HTTPS_PROXY \ --build-arg NO_PROXY=$NO_PROXY . IF [ "$IS_JETSON" = "true" ] - COPY mount.yaml /system/oem/mount.yaml + COPY mount.yaml /system/oem/mount.yaml + END + + IF [ "$IS_UKI" = "true" ] + COPY stylus_uki.yaml /system/oem/stylus_uki.yaml + END + + IF [ "$ARCH" = "arm64" ] + RUN mkdir -p /etc/luet/repos.conf.d && \ + SPECTRO_LUET_VERSION=$SPECTRO_LUET_VERSION luet repo add spectro --type docker --url gcr.io/spectro-dev-public/luet-repo-arm --priority 1 -y && \ + luet repo update + ELSE IF [ "$ARCH" = "amd64" ] + RUN mkdir -p /etc/luet/repos.conf.d && \ + SPECTRO_LUET_VERSION=$SPECTRO_LUET_VERSION luet repo add spectro --type docker --url gcr.io/spectro-dev-public/luet-repo --priority 1 -y && \ + luet repo update + END + + IF [ "$K8S_DISTRIBUTION" = "kubeadm" ] || [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ] + ARG BASE_K8S_VERSION=$K8S_VERSION + ELSE IF [ "$K8S_DISTRIBUTION" = "k3s" ] + ARG K8S_DISTRIBUTION_TAG=$K3S_FLAVOR_TAG + ARG BASE_K8S_VERSION=$K8S_VERSION-$K8S_DISTRIBUTION_TAG + ELSE IF [ "$K8S_DISTRIBUTION" = "rke2" ] + ARG K8S_DISTRIBUTION_TAG=$RKE2_FLAVOR_TAG + ARG BASE_K8S_VERSION=$K8S_VERSION-$K8S_DISTRIBUTION_TAG END IF [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] @@ -292,29 +507,37 @@ base-image: RUN update-ca-certificates END - RUN apt update && \ - apt install --no-install-recommends zstd vim iputils-ping bridge-utils curl tcpdump ethtool -y + RUN apt-get update && \ + apt-get install --no-install-recommends kbd zstd vim iputils-ping bridge-utils curl tcpdump ethtool -y + IF [ "$UPDATE_KERNEL" = "false" ] - RUN if dpkg -l linux-image-generic-hwe-20.04 > /dev/null; then apt-mark hold linux-image-generic-hwe-20.04; fi && \ - if dpkg -l linux-image-generic-hwe-22.04 > /dev/null; then apt-mark hold linux-image-generic-hwe-22.04; fi && \ + RUN if dpkg -l "linux-image-generic-hwe-$OS_VERSION" > /dev/null; then apt-mark hold "linux-image-generic-hwe-$OS_VERSION" "linux-headers-generic-hwe-$OS_VERSION" "linux-generic-hwe-$OS_VERSION" ; fi && \ if dpkg -l linux-image-generic > /dev/null; then apt-mark hold linux-image-generic linux-headers-generic linux-generic; fi END - RUN apt update && \ - apt upgrade --no-install-recommends -y - RUN kernel=$(ls /boot/vmlinuz-* | tail -n1) && \ - ln -sf "${kernel#/boot/}" /boot/vmlinuz - RUN kernel=$(ls /lib/modules | tail -n1) && \ - dracut -f "/boot/initrd-${kernel}" "${kernel}" && \ - ln -sf "initrd-${kernel}" /boot/initrd - RUN kernel=$(ls /lib/modules | tail -n1) && \ - depmod -a "${kernel}" - - RUN if [ ! -f /usr/bin/grub2-editenv ]; then \ - ln -s /usr/sbin/grub-editenv /usr/bin/grub2-editenv; \ - fi - - RUN rm -rf /var/cache/* && \ - apt clean + + IF [ "$IS_UKI" = "false" ] + RUN apt-get update && \ + apt-get upgrade -y + RUN kernel=$(ls /boot/vmlinuz-* | tail -n1) && \ + ln -sf "${kernel#/boot/}" /boot/vmlinuz + RUN kernel=$(ls /lib/modules | tail -n1) && \ + dracut -f "/boot/initrd-${kernel}" "${kernel}" && \ + ln -sf "initrd-${kernel}" /boot/initrd + RUN kernel=$(ls /lib/modules | tail -n1) && \ + depmod -a "${kernel}" + + RUN if [ ! -f /usr/bin/grub2-editenv ]; then \ + ln -s /usr/sbin/grub-editenv /usr/bin/grub2-editenv; \ + fi + + RUN rm -rf /var/cache/* && \ + apt-get clean + END + + IF [ "$CIS_HARDENING" = "true" ] + COPY cis-harden/harden.sh /tmp/harden.sh + RUN /tmp/harden.sh && rm /tmp/harden.sh + END # IF OS Type is Opensuse ELSE IF [ "$OS_DISTRIBUTION" = "opensuse-leap" ] && [ "$ARCH" = "amd64" ] @@ -382,7 +605,13 @@ base-image: # Used to build the installer image. The installer ISO will be created from this. iso-image: FROM --platform=linux/${ARCH} +base-image - COPY --platform=linux/${ARCH} +stylus-image/ / + IF [ "$IS_UKI" = "false" ] + COPY --platform=linux/${ARCH} +stylus-image/ / + ELSE + COPY --platform=linux/${ARCH} +stylus-image/ / + RUN find /opt/spectrocloud/bin/. ! -name 'agent-provider-stylus' -type f -exec rm -f {} + + RUN rm -f /usr/bin/luet + END COPY overlay/files/ / RUN rm -f /etc/ssh/ssh_host_* /etc/ssh/moduli @@ -394,6 +623,16 @@ iso-image: SAVE IMAGE palette-installer-image:$PE_VERSION END +iso-disk-image: + FROM scratch + + COPY +iso/*.iso /disk/ + IF [ "$CUSTOM_TAG" != "" ] + SAVE IMAGE --push $IMAGE_REGISTRY/$IMAGE_REPO/$ISO_NAME:$PE_VERSION-$CUSTOM_TAG + ELSE + SAVE IMAGE --push $IMAGE_REGISTRY/$IMAGE_REPO/$ISO_NAME:$PE_VERSION + END + OS_RELEASE: COMMAND ARG OS_ID=${OS_DISTRIBUTION} @@ -406,7 +645,8 @@ OS_RELEASE: ARG OS_REPO=spectrocloud/CanvOS ARG OS_NAME=kairos-core-${OS_DISTRIBUTION} ARG ARTIFACT=kairos-core-${OS_DISTRIBUTION}-$OS_VERSION + ARG KAIROS_RELEASE=${OS_VERSION} # update OS-release file - RUN sed -i -n '/KAIROS_/!p' /etc/os-release + # RUN sed -i -n '/KAIROS_/!p' /etc/os-release RUN envsubst >>/etc/os-release
@@ -16,25 +16,25 @@ The base image definitions reside in the Earthfile located in this repo. This d ### Base Image -From the Kairos project, this is derived from the operating system distribution chosen (currently Ubuntu and OpenSuse-Leap supported). It is pulled down as the base image and some adjustments are made to better support Palette. Those adjustments are used to clean and update the image as well as install some required packages. +From the Kairos project, this is derived from the operating system distribution chosen (currently Ubuntu and OpenSuse-Leap supported). It is pulled down as the base image and some adjustments are made to better support Palette. Those adjustments are used to clean and update the image as well as install some required packages. ### Provider Image -From the Base Image, the provider image is used to package in the Kubernetes distribution and version(s) that are part of the build. This layer is required to initialize the system and prepare it for configuration to build the Kubernetes cluster. +From the Base Image, the provider image is used to package in the Kubernetes distribution and version(s) that are part of the build. This layer is required to initialize the system and prepare it for configuration to build the Kubernetes cluster. ### Installer Image -From the base image, this image is used to provide the initial flashing of a device (bare-metal or virtual machine). This image contains the user-data configuration that has been provided in `user-data`. It will also contain the contents of any content bundle for pre-staged builds. Pre-staged builds can be used to embed all of the artifacts that are required to build a cluster. These artifacts include Helm charts, manifests, and container images. These images are loaded into containerd when the cluster is initialized elminating the need for the initial download. For more information on how to build pre-loaded content checkout the Palette Docs at [Build your Own Content](https://docs.spectrocloud.com/clusters/edge/edgeforge-workflow/build-content-bundle). +From the base image, this image is used to provide the initial flashing of a device (bare-metal or virtual machine). This image contains the user-data configuration that has been provided in `user-data`. It will also contain the contents of any content bundle for pre-staged builds. Pre-staged builds can be used to embed all of the artifacts that are required to build a cluster. These artifacts include Helm charts, manifests, and container images. These images are loaded into containerd when the cluster is initialized elminating the need for the initial download. For more information on how to build pre-loaded content checkout the Palette Docs at [Build your Own Content](https://docs.spectrocloud.com/clusters/edge/edgeforge-workflow/build-content-bundle). ### Custom Configuration -For advanced use cases, there may be a need to add additional packages not included in the [Base Images](https://github.com/kairos-io/kairos/tree/master/images). If those packages or configuration elements need to be added, they can be included in the empty `Dockerfile` located in this repo and they will be included in the build process and output artifacts. +For advanced use cases, there may be a need to add additional packages not included in the [Base Images](https://github.com/kairos-io/kairos/tree/master/images). If those packages or configuration elements need to be added, they can be included in the empty `Dockerfile` located in this repo and they will be included in the build process and output artifacts. ### Basic Usage 1. Clone the repo at [CanvOS](https://github.com/spectrocloud/CanvOS.git) -Note: If you are building the images behind a proxy server, you may need to configure your git to let it use your proxy server. +Note: If you are building the images behind a proxy server, you may need to configure your git to let it use your proxy server. ``` git config --global http.proxy @@ -108,32 +108,36 @@ cp .arg.template .arg ``` 6. To build RHEL core, RHEL FIPS or Ubuntu fips, sles base images switch to respective directories and build the base image. -The base image built can be passed as argument to build the installer and provider images. -Follow the instructions in the respective sub-folders (rhel-fips, ubuntu-fips) to create base images. -For ubuntu-fips, this image can be used as base image - `gcr.io/spectro-dev-public/ubuntu-focal-fips:v4.2_20231226` -Skip this step if your base image is ubuntu or opensuse-leap. If you are building ubuntu or opensuse-leap installer images, do not pass the BASE_IMAGE attribute as an arg to build command. + The base image built can be passed as argument to build the installer and provider images. + Follow the instructions in the respective sub-folders (rhel-fips, ubuntu-fips) to create base images. + For ubuntu-fips, this image can be used as base image - `gcr.io/spectro-dev-public/ubuntu-focal-fips:v4.2_20231226` + Skip this step if your base image is ubuntu or opensuse-leap. If you are building ubuntu or opensuse-leap installer images, do not pass the BASE_IMAGE attribute as an arg to build command. 7. Modify the `.arg` file as needed. Primarily, you must define the tag you want to use for your images. For example, if the operating system is `ubuntu` and the tag is `demo`, the image artefact will name as `ttl.sh/ubuntu:k3s-1.25.2-v3.4.3-demo`. The **.arg** file defines the following variables: -| Parameter | Description | Type | Default Value | -|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|-------------------------| -| CUSTOM_TAG | Environment name for provider image tagging. The default value is `demo`. | String | `demo` | -| IMAGE_REGISTRY | Image registry name that will store the image artifacts. The default value points to the *ttl.sh* image registry, an anonymous and ephemeral Docker image registry where images live for a maximum of 24 hours by default. If you wish to make the images exist longer than 24 hours, you can use any other image registry to suit your needs. | String | `ttl.sh` | -| OS_DISTRIBUTION | OS distribution of your choice. For example, it can be `ubuntu`, `opensuse-leap`, `rhel` or `sles` | String | `ubuntu` | -| IMAGE_REPO | Image repository name in your chosen registry. | String | `$OS_DISTRIBUTION` | -| OS_VERSION | OS version. For Ubuntu, the possible values are `20`, and `22`. Whereas for openSUSE Leap, the possible value is `15.4`. For sles, possible values are `5.4`. This example uses `22` for Ubuntu. | String | `22` | -| K8S_DISTRIBUTION | Kubernetes distribution name. It can be one of these: `k3s`, `rke2`, `kubeadm`, or `kubeadm-fips`. | String | `k3s` | -| ISO_NAME | Name of the Edge installer ISO image. In this example, the name is *palette-edge-installer*. | String | `palette-edge-installer`| -| ARCH | Type of platform to use for the build. Used for Cross Platform Build (arm64 to amd64 as example). | string | `amd64` | -| BASE_IMAGE | Base image to be used for building installer and provider images. | String | | -| FIPS_ENABLED | to generate FIPS compliant binaries. `true` or `false` | string | `false` | -| HTTP_PROXY | URL of the HTTP Proxy server to be used if needed (Optional) | string | | -| HTTPS_PROXY | URL of the HTTPS Proxy server to be used if needed (Optional) | string | | -| NO_PROXY | URLS that should be excluded from proxying (Optional) | string | | -| PROXY_CERT_PATH | Absolute path of the SSL Proxy certificate in PEM format if needed (Optional) | string | | -| UPDATE_KERNEL | Determines whether to upgrade the Kernel version to the latest from the upstream OS provider | boolean| `false` | -| DISABLE_SELINUX | Disable selinux in the operating system. Some applications (like Kubevirt) do not like selinux | boolean| `true` | -| CLUSTERCONFIG | Path of the cluster config | string | | +| Parameter | Description | Type | Default Value | +| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------ | +| CUSTOM_TAG | Environment name for provider image tagging. The default value is `demo`. | String | `demo` | +| IMAGE_REGISTRY | Image registry name that will store the image artifacts. The default value points to the _ttl.sh_ image registry, an anonymous and ephemeral Docker image registry where images live for a maximum of 24 hours by default. If you wish to make the images exist longer than 24 hours, you can use any other image registry to suit your needs. | String | `ttl.sh` | +| OS_DISTRIBUTION | OS distribution of your choice. For example, it can be `ubuntu`, `opensuse-leap`, `rhel` or `sles` | String | `ubuntu` | +| IMAGE_REPO | Image repository name in your chosen registry. | String | `$OS_DISTRIBUTION` | +| OS_VERSION | OS version. For Ubuntu, the possible values are `20`, and `22`. Whereas for openSUSE Leap, the possible value is `15.4`. For sles, possible values are `5.4`. This example uses `22` for Ubuntu. | String | `22` | +| K8S_DISTRIBUTION | Kubernetes distribution name. It can be one of these: `k3s`, `rke2`, `kubeadm`, or `kubeadm-fips`. | String | `k3s` | +| ISO_NAME | Name of the Edge installer ISO image. In this example, the name is _palette-edge-installer_. | String | `palette-edge-installer` | +| ARCH | Type of platform to use for the build. Used for Cross Platform Build (arm64 to amd64 as example). | string | `amd64` | +| BASE_IMAGE | Base image to be used for building installer and provider images. | String | | +| FIPS_ENABLED | to generate FIPS compliant binaries. `true` or `false` | string | `false` | +| HTTP_PROXY | URL of the HTTP Proxy server to be used if needed (Optional) | string | | +| HTTPS_PROXY | URL of the HTTPS Proxy server to be used if needed (Optional) | string | | +| NO_PROXY | URLS that should be excluded from proxying (Optional) | string | | +| PROXY_CERT_PATH | Absolute path of the SSL Proxy certificate in PEM format if needed (Optional) | string | | +| UPDATE_KERNEL | Determines whether to upgrade the Kernel version to the latest from the upstream OS provider | boolean | `false` | +| DISABLE_SELINUX | Disable selinux in the operating system. Some applications (like Kubevirt) do not like selinux | boolean | `true` | +| CLUSTERCONFIG | Path of the cluster config | string | | +| IS_UKI | Build UKI(Trusted boot) images | boolean | `false` | +| UKI_SELF_SIGNED_KEYS | Use self signed keys for UKI. Set to false if you want to use exported keys from hardware | boolean | `true` | +| INCLUDE_MS_SECUREBOOT_KEYS | Include Microsoft 3rd Party UEFI CA certificate in generated keys | boolean | `true` | +| AUTO_ENROLL_SECUREBOOT_KEYS | Auto enroll SecureBoot keys when device boots up and is in setup mode of secure boot | boolean | `true` | 8. (Optional) If you are building the images behind a proxy server, you may need to modify your docker daemon settings to let it use your proxy server. You can refer this [tutorial](https://docs.docker.com/config/daemon/systemd/#httphttps-proxy). @@ -191,8 +195,8 @@ system.osVersion: 22 ```shell ls build/ && docker images -palette-edge-installer.iso -palette-edge-installer.iso.sha256 +palette-edge-installer.iso +palette-edge-installer.iso.sha256 # Output REPOSITORY TAG IMAGE ID CREATED SIZE @@ -202,16 +206,16 @@ ttl.sh/ubuntu k3s-1.25.2-v4.2.3-demo ttl.sh/ubuntu k3s-1.25.2-v4.2.3-demo_linux_amd64 f6e490f53971 17 hours ago 4.62GB ``` -Earthly is a multi-architecture build tool. In this example we are building images for AMD64 hardware which is reflected by the tags above. In the future we will support ARM64 builds and those tags will be included. We only need to push the image tag that DOES NOT have the architecture reference i.e `linux_amd64` in the above example. +Earthly is a multi-architecture build tool. In this example we are building images for AMD64 hardware which is reflected by the tags above. In the future we will support ARM64 builds and those tags will be included. We only need to push the image tag that DOES NOT have the architecture reference i.e `linux_amd64` in the above example. 11. The provider images are by default not pushed to a registry. You can push the images by using the `docker push` command and reference the created images. ```shell -docker push ttl.sh/ubuntu:k3s-1.25.2-v4.2.3-demo +docker push ttl.sh/ubuntu:k3s-1.25.2-v4.2.3-demo ``` > ⚠️ The default registry, [ttl.sh](https://ttl.sh/) is a short-lived registry. Images in the ttl.sh registry have a default time to live of -24 hours. Once the time limit is up, the images will automatically be removed. To use a permanent registry, set the `.arg` file's `IMAGE_REGISTRY` parameter with the URL of your image registry. +> 24 hours. Once the time limit is up, the images will automatically be removed. To use a permanent registry, set the `.arg` file's `IMAGE_REGISTRY` parameter with the URL of your image registry. 12. Create a cluster profile using the command output. Use the [Model Edge Cluster Profile](https://docs.spectrocloud.com/clusters/edge/site-deployment/model-profile) to help you complete this step. @@ -223,15 +227,35 @@ docker push ttl.sh/ubuntu:k3s-1.25.2-v4.2.3-demo ### How-Tos -* [Building Edge Native Artifacts]([https://docs.spectrocloud.com/clusters/edge/edgeforge-workflow/palette-canvos](https://deploy-preview-1318--docs-spectrocloud.netlify.app/clusters/edge/edgeforge-workflow/palette-canvos)) - +- [Building Edge Native Artifacts](<[https://docs.spectrocloud.com/clusters/edge/edgeforge-workflow/palette-canvos](https://deploy-preview-1318--docs-spectrocloud.netlify.app/clusters/edge/edgeforge-workflow/palette-canvos)>) ### Building ARM64 Artifacts for Nvidia Jetson devices + 1. Your .arg file should contain these values + ``` BASE_IMAGE=quay.io/kairos/ubuntu:20.04-core-arm64-nvidia-jetson-agx-orin-v2.4.3 ARCH=arm64 platform=linux/arm64 ``` -2. ./earthly.sh +build-all-images \ No newline at end of file +2. ./earthly.sh +build-all-images + +### Build Trusted Boot Images + +1. Your .arg file should contain these values. + +``` +IS_UKI=true +UKI_SELF_SIGNED_KEYS=true # Set to false if you want to use exported keys from hardware +INCLUDE_MS_SECUREBOOT_KEYS=true # Include Microsoft 3rd Party UEFI CA certificate in generated keys +AUTO_ENROLL_SECUREBOOT_KEYS=false # Auto enroll SecureBoot keys when device boots up and is in setup mode of secure boot +``` + +2. Prepare keys for installer and provider image creation. If you have faactory keys exported from your hw, put them under `secure-boot/exported-keys`. The keys should be named as follows: db, KEK + +``` +./earthly.sh +uki-genkey --MY_ORG="ACME Corp" --EXPIRATION_IN_DAYS=5475 +``` + +3. ./earthly.sh +build-all-images diff --git a/cis-harden/harden.sh b/cis-harden/harden.sh new file mode 100755 index 0000000..92bcc67 --- /dev/null +++ b/cis-harden/harden.sh @@ -0,0 +1,926 @@ +#!/bin/bash + +# +# This script is to harden Kairos, use in the CanvOS Dockerfile +# Benchmark targeted: CIS Linux Benchmark +# + + +root_dir="$( cd "$( dirname $0 )" && pwd )" +echo Root dir $root_dir + + +########################################################################## +# Check for exit status and print error msg +########################################################################## +check_error() +{ + status=$1 + msg=$2 + exit_status=$3 + + if [[ ${status} -ne 0 ]]; then + echo -e "\033[31m - ${msg} \033[0m" + exit ${exit_status} + fi + + return 0 +} + + +########################################################################## +# Update the config files with specified values for hardening +########################################################################## +update_config_files() { + search_str="$1" + append_str="$2" + config_file="$3" + + if [[ ! -f ${config_file} ]]; then + check_error 1 "File ${config_file} not found" + fi + + sed -i "s/^\($search_str.*\)$/#\1/" ${config_file} + check_error $? "Failed commenting config value $search_str." 1 + + echo "$append_str" >> ${config_file} + check_error $? "Failed appending config value $append_str" 1 + + return 0 +} + + +########################################################################## +# Determine the Operating system +########################################################################## +get_os() { + if [ -f /etc/os-release ]; then + . /etc/os-release + OS=$NAME + VER=$VERSION_ID + elif type lsb_release >/dev/null 2>&1; then + OS=$(lsb_release -si) + VER=$(lsb_release -sr) + elif [ -f /etc/lsb-release ]; then + . /etc/lsb-release + OS=$DISTRIB_ID + VER=$DISTRIB_RELEASE + elif [ -f /etc/debian_version ]; then + OS=Debian + VER=$(cat /etc/debian_version) + elif [ -f /etc/SuSe-release ]; then + OS=Suse + elif [ -f /etc/centos-release ]; then + OS='CentOS Linux' + VER=$(cat /etc/centos-release | sed 's/.*\( [0-9][^ ]\+\) .*/\1/') + elif [ -f /etc/redhat-release ]; then + OS='Red Hat Enterprise Linux' + VER=$(cat /etc/redhat-release | sed 's/.*\( [0-9][^ ]\+\) .*/\1/') + else + OS=$(uname -s) + VER=$(uname -r) + fi + + if [[ $OS =~ 'Red Hat' ]]; then + OS_FLAVOUR="rhel" + elif [[ $OS =~ 'CentOS' ]]; then + OS_FLAVOUR="centos" + elif [[ $OS =~ 'Ubuntu' ]]; then + OS_FLAVOUR="ubuntu" + else + OS_FLAVOUR="linux" + fi + return 0 +} + + +########################################################################## +# Upgrade OS packages +########################################################################## +upgrade_packages() { + if [[ ${OS_FLAVOUR} == "ubuntu" ]]; then + apt-get update + apt-get -y upgrade + check_error $? "Failed upgrading packages" 1 + apt-get install -y auditd apparmor-utils libpam-pwquality + if [[ $? -ne 0 ]]; then + echo 'deb http://archive.ubuntu.com/ubuntu focal main restricted' > /etc/apt/sources.list.d/repotmp.list + apt-get update + apt-get install -y auditd apparmor-utils libpam-pwquality + check_error $? "Failed installing audit packages" 1 + rm -f /etc/apt/sources.list.d/repotmp.list + apt-get update + fi + fi + + if [[ ${OS_FLAVOUR} == "centos" ]]; then + yum -y update + yum install -y auditd apparmor-utils libpam-pwquality + check_error $? "Failed upgrading packages" 1 + fi + + if [[ ${OS_FLAVOUR} == "rhel" ]]; then + yum -y update + yum install -y auditd apparmor-utils libpam-pwquality + check_error $? "Failed upgrading packages" 1 + fi + + # Placeholder for supporting other linux OS + if [[ ${OS_FLAVOUR} == "linux" ]]; then + test 1 -eq 2 + check_error $? "OS not supported" 1 + fi + + return 0 +} + + +########################################################################## +# Harden Sysctl based parameters +########################################################################## +harden_sysctl() { + config_file='/etc/sysctl.conf' + + echo "Harden sysctl parameters" + echo "" >> ${config_file} + #Disabling IP forward related hardening as it is needed for k8s + # update_config_files 'net.ipv4.ip_forward' 'net.ipv4.ip_forward=0' ${config_file} + # update_config_files 'net.ipv4.conf.all.forwarding' 'net.ipv4.conf.all.forwarding=0' ${config_file} + # update_config_files 'net.ipv4.conf.all.mc_forwarding' 'net.ipv4.conf.all.mc_forwarding=0' ${config_file} + + update_config_files 'net.ipv4.conf.all.send_redirects' 'net.ipv4.conf.all.send_redirects=0' ${config_file} + update_config_files 'net.ipv4.conf.default.send_redirects' 'net.ipv4.conf.default.send_redirects=0' ${config_file} + + update_config_files 'net.ipv4.conf.all.accept_source_route' 'net.ipv4.conf.all.accept_source_route=0' ${config_file} + update_config_files 'net.ipv4.conf.default.accept_source_route' 'net.ipv4.conf.default.accept_source_route=0' ${config_file} + + update_config_files 'net.ipv4.conf.all.accept_redirects' 'net.ipv4.conf.all.accept_redirects=0' ${config_file} + update_config_files 'net.ipv4.conf.default.accept_redirects' 'net.ipv4.conf.default.accept_redirects=0' ${config_file} + + update_config_files 'net.ipv4.conf.all.secure_redirects' 'net.ipv4.conf.all.secure_redirects=0' ${config_file} + update_config_files 'net.ipv4.conf.default.secure_redirects' 'net.ipv4.conf.default.secure_redirects=0' ${config_file} + + + update_config_files 'net.ipv4.conf.all.log_martians' 'net.ipv4.conf.all.log_martians=1' ${config_file} + update_config_files 'net.ipv4.conf.default.log_martians' 'net.ipv4.conf.default.log_martians=1' ${config_file} + + update_config_files 'net.ipv4.icmp_echo_ignore_broadcasts' 'net.ipv4.icmp_echo_ignore_broadcasts=1' ${config_file} + update_config_files 'net.ipv4.icmp_ignore_bogus_error_responses' 'net.ipv4.icmp_ignore_bogus_error_responses=1' ${config_file} + update_config_files 'net.ipv4.conf.all.rp_filter' 'net.ipv4.conf.all.rp_filter=1' ${config_file} + update_config_files 'net.ipv4.conf.default.rp_filter' 'net.ipv4.conf.default.rp_filter=1' ${config_file} + update_config_files 'net.ipv4.tcp_syncookies' 'net.ipv4.tcp_syncookies=1' ${config_file} + update_config_files 'kernel.randomize_va_space' 'kernel.randomize_va_space=2' ${config_file} + update_config_files 'fs.suid_dumpable' 'fs.suid_dumpable=0' ${config_file} + + + update_config_files 'net.ipv6.conf.all.accept_redirects' 'net.ipv6.conf.all.accept_redirects=0' ${config_file} + update_config_files 'net.ipv6.conf.default.accept_redirects' 'net.ipv6.conf.default.accept_redirects=0' ${config_file} + update_config_files 'net.ipv6.conf.all.accept_source_route' 'net.ipv6.conf.all.accept_source_route=0' ${config_file} + update_config_files 'net.ipv6.conf.default.accept_source_route' 'net.ipv6.conf.default.accept_source_route=0' ${config_file} + update_config_files 'net.ipv6.conf.all.accept_ra' 'net.ipv6.conf.all.accept_ra=0' ${config_file} + update_config_files 'net.ipv6.conf.default.accept_ra' 'net.ipv6.conf.default.accept_ra=0' ${config_file} + + # To restrict core dumps + config_file='/etc/security/limits.conf' + echo "" >> ${config_file} + update_config_files '* hard core' '* hard core 0' ${config_file} + + return 0 +} + + +##function################################################################ +# ssh related hardening +########################################################################## +harden_ssh() { + config_file='/etc/ssh/sshd_config' + + echo "Harden ssh parameters" + # Set permissions on ssh config file + chown root:root ${config_file} + chmod og-rwx ${config_file} + + echo "" >> ${config_file} + update_config_files 'Protocol ' 'Protocol 2' ${config_file} + update_config_files 'LogLevel ' 'LogLevel INFO' ${config_file} + update_config_files 'PermitEmptyPasswords ' 'PermitEmptyPasswords no' ${config_file} + update_config_files 'X11Forwarding ' 'X11Forwarding no' ${config_file} + update_config_files 'IgnoreRhosts ' 'IgnoreRhosts yes' ${config_file} + update_config_files 'MaxAuthTries' 'MaxAuthTries 4' ${config_file} + update_config_files 'PermitRootLogin' 'PermitRootLogin no' ${config_file} + update_config_files 'ClientAliveInterval' 'ClientAliveInterval 300' ${config_file} + update_config_files 'ClientAliveCountMax' 'ClientAliveCountMax 3' ${config_file} + update_config_files 'LoginGraceTime' 'LoginGraceTime 60' ${config_file} + update_config_files 'Banner' 'Banner /etc/issue.net' ${config_file} + update_config_files 'MaxStartups' 'MaxStartups 10:30:60' ${config_file} + update_config_files 'MaxSessions' 'MaxSessions 10' ${config_file} + update_config_files 'PermitUserEnvironment' 'PermitUserEnvironment no' ${config_file} + update_config_files 'HostbasedAuthentication' 'HostbasedAuthentication no' ${config_file} + update_config_files 'Ciphers' 'Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr' ${config_file} + update_config_files 'MACs' 'MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256' ${config_file} + update_config_files 'KexAlgorithms' 'KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256' ${config_file} + + #############Shell timeout policy################## + + # Configuration lines to add to /etc/profile.d/timeout.sh + config_lines="TMOUT=900" + + # Add configuration lines to the top of the file + echo -e "$config_lines" > /etc/profile.d/timeout.sh + + echo "Configuration added to /etc/profile.d/timeout.sh" + + ############sudo command use pty################## + config_file='/etc/sudoers' + echo "" >> ${config_file} + + update_config_files 'Defaults use_pty' 'Defaults use_pty' ${config_file} + echo "Updated config file to sudo command use pty" + + return 0 +} + + +##function################################################################ +# audit related hardening +########################################################################## +harden_audit() { + + local file_path_base="/etc/audit/rules.d/audit.rules" + local file_path_timechange="/etc/audit/rules.d/50-time-change.rules" + local file_path_identityrules="/etc/audit/rules.d/50-identity.rules" + local file_path_accessrules="/etc/audit/rules.d/50-access.rules" + local file_path_deleterules="/etc/audit/rules.d/50-delete.rules" + local file_path_mountrules="/etc/audit/rules.d/50-mounts.rules" + local file_path_scoperules="/etc/audit/rules.d/50-scope.rules" + local file_path_actionsrules="/etc/audit/rules.d/50-actions.rules" + local file_path_modulesrules="/etc/audit/rules.d/50-modules.rules" + local file_path_immutablerules="/etc/audit/rules.d/99-finalize.rules" + local file_path_networkrules="/etc/audit/rules.d/50-system-locale.rules" + local file_path_MACrules="/etc/audit/rules.d/50-MAC-policy.rules" + local file_path_logineventsrules="/etc/audit/rules.d/50-logins.rules" + local file_path_DACrules="/etc/audit/rules.d/50-perm_mod.rules" + + local content_base=( + "-D" + "-b 8192" + "--backlog_wait_time 60000" + "-f 1" +) + + local content_timechange=( + "-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change" + "-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change" + "-a always,exit -F arch=b64 -S clock_settime -k time-change" + "-a always,exit -F arch=b32 -S clock_settime -k time-change" + "-w /etc/localtime -p wa -k time-change" +) + + local content_identityrules=( + "-w /etc/group -p wa -k identity" + "-w /etc/passwd -p wa -k identity" + "-w /etc/gshadow -p wa -k identity" + "-w /etc/shadow -p wa -k identity" + "-w /etc/security/opasswd -p wa -k identity" +) + + local content_accessrules=( + "-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access" + "-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access" + "-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access" + "-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access" +) + + local content_deleterules=( + "-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete" + "-a always,exit -F arch=b32 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete" +) + + local content_mountrules=( + "-a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=4294967295 -k mounts" + "-a always,exit -F arch=b32 -S mount -F auid>=1000 -F auid!=4294967295 -k mounts" +) + + local content_scoperules=( + "-w /etc/sudoers -p wa -k scope" + "-w /etc/sudoers.d/ -p wa -k scope" +) + + local content_actionsules=( + "-a always,exit -F arch=b64 -C euid!=uid -F euid=0 -Fauid>=1000 -F auid!=4294967295 -S execve -k actions" + "-a always,exit -F arch=b32 -C euid!=uid -F euid=0 -Fauid>=1000 -F auid!=4294967295 -S execve -k actions" +) + + local content_modulesrules=( + "-w /sbin/insmod -p x -k modules" + "-w /sbin/rmmod -p x -k modules" + "-w /sbin/modprobe -p x -k modules" + "-a always,exit -F arch=b64 -S init_module -S delete_module -k modules" +) + + local content_immutablerules=( + "-e 2" +) + + local content_networkrules=( + "-a always,exit -F arch=b64 -S sethostname -S setdomainname -k system-locale" + "-a always,exit -F arch=b32 -S sethostname -S setdomainname -k system-locale" + "-w /etc/issue -p wa -k system-locale" + "-w /etc/issue.net -p wa -k system-local" + "-w /etc/hosts -p wa -k system-locale" + "-w /etc/network -p wa -k system-locale" +) + + local content_MACrules=( + "-w /etc/apparmor/ -p wa -k MAC-policy" +) + + local content_logineventsrules=( + "-w /var/log/faillog -p wa -k logins" + "-w /var/log/lastlog -p wa -k logins" + "-w /var/log/tallylog -p wa -k logins" +) + + local content_DACrules=( + "-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod" + "-a always,exit -F arch=b32 -S chmod -S fchmod -S fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod" + "-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod" + "-a always,exit -F arch=b32 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod" + "-a always,exit -F arch=b64 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=1000 -F auid!=4294967295 -k perm_mod" + "-a always,exit -F arch=b32 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>=1000 -F auid!=4294967295 -k perm_mod" +) + + + # Create or append to the time change rules + echo "" > "$file_path_base" + for line in "${content_base[@]}"; do + echo "$line" | sudo tee -a "$file_path_base" >/dev/null + done + + # Create or append to the time change rules + for line in "${content_timechange[@]}"; do + echo "$line" | sudo tee -a "$file_path_timechange" >/dev/null + done + + # Create or append to the identity rules + for line in "${content_identityrules[@]}"; do + echo "$line" | sudo tee -a "$file_path_identityrules" >/dev/null + done + + # Create or append to the access rules + for line in "${content_accessrules[@]}"; do + echo "$line" | sudo tee -a "$file_path_accessrules" >/dev/null + done + + # Create or append to the delete rules + for line in "${content_deleterules[@]}"; do + echo "$line" | sudo tee -a "$file_path_deleterules" >/dev/null + done + + # Create or append to the mount rules + for line in "${content_mountrules[@]}"; do + echo "$line" | sudo tee -a "$file_path_mountrules" >/dev/null + done + + # Create or append to the scope rules + for line in "${content_scoperules[@]}"; do + echo "$line" | sudo tee -a "$file_path_scoperules" >/dev/null + done + + # Create or append to the actions rules + for line in "${content_actionsules[@]}"; do + echo "$line" | sudo tee -a "$file_path_actionsrules" >/dev/null + done + + # Create or append to the modules rules + for line in "${content_modulesrules[@]}"; do + echo "$line" | sudo tee -a "$file_path_modulesrules" >/dev/null + done + + # Create or append to the immutables rules + for line in "${content_immutablerules[@]}"; do + echo "$line" | sudo tee -a "$file_path_immutablerules" >/dev/null + done + + # Create or append to the network rules + for line in "${content_networkrules[@]}"; do + echo "$line" | sudo tee -a "$file_path_networkrules" >/dev/null + done + + # Create or append to the MAC rules + for line in "${content_MACrules[@]}"; do + echo "$line" | sudo tee -a "$file_path_MACrules" >/dev/null + done + + # Create or append to the login/logout events rules + for line in "${content_logineventsrules[@]}"; do + echo "$line" | sudo tee -a "$file_path_logineventsrules" >/dev/null + done + + # Create or append to the DAC rules + for line in "${content_DACrules[@]}"; do + echo "$line" | sudo tee -a "$file_path_DACrules" >/dev/null + done + + + # Verify if the files were created or appended successfully + if [ -f "$file_path_timechange" ] && [ -f "$file_path_identityrules" ] && [ -f "$file_path_accessrules" ] && [ -f "$file_path_deleterules" ] && [ -f "$file_path_mountrules" ] && [ -f "$file_path_scoperules" ] && [ -f "$file_path_actionsrules" ] && [ -f "$file_path_modulesrules" ] && [ -f "$file_path_immutablerules" ] && [ -f "$file_path_networkrules" ] && [ -f "$file_path_MACrules" ] && [ -f "$file_path_logineventsrules" ] && [ -f "$file_path_DACrules" ]; then + echo "Files '$file_path_timechange', '$file_path_identityrules', '$file_path_accessrules', '$file_path_deleterules', '$file_path_mountrules', '$file_path_scoperules', '$file_path_actionsrules', '$file_path_modulesrules', '$file_path_immutablerules', '$file_path_networkrules', '$file_path_MACrules', '$file_path_logineventsrules'& '$file_path_DACrules' created/appended successfully." + else + echo "Failed to create/append to files '$file_path_timechange' and/or '$file_path_identityrules' and or '$file_path_accessrules' and or '$file_path_deleterules' and or '$file_path_mountrules' and or '$file_path_scoperules' and or '$file_path_actionsrules' and or '$file_path_modulesrules' and or '$file_path_immutablerules' and or '$file_path_networkrules' and or '$file_path_MACrules' and or '$file_path_logineventsrules' and or '$file_path_DACrules'." + fi + + # Define the desired value for max_log_file + max_log_file_value=100 + + # Set the max_log_file parameter in auditd.conf + sed -i "s/^max_log_file = 8/max_log_file = ${max_log_file_value}/" /etc/audit/auditd.conf + + echo "The max_log_file parameter has been set to ${max_log_file_value}." + + # Enable auditd service + systemctl enable auditd + + return 0 +} + +##function################################################################ +# boot up related hardening +########################################################################## +harden_boot() { + echo "Disable Ctrl + Alt + Del key" + systemctl mask ctrl-alt-del.target + + grub_conf='/etc/cos/grub.cfg' + + if [[ -f ${grub_conf} ]]; then + chown root:root ${grub_conf} + chmod u-wx,go-rwx ${grub_conf} + + sed -i 's/set baseExtraArgs=""/set baseExtraArgs="audit=1"/g' /etc/cos/bootargs.cfg + + echo "Grub configuration updated successfully." + fi + + return 0 +} + +##function################################################################ +# password related hardening +########################################################################## +harden_password_files() { + + chmod 644 /etc/passwd + chown root:root /etc/passwd + chmod 644 /etc/passwd- + chown root:root /etc/passwd- + chmod 640 /etc/shadow + chown root:root /etc/shadow + chmod 000 /etc/shadow- + chown root:root /etc/shadow- + chmod 000 /etc/gshadow + chown root:root /etc/gshadow + chmod 000 /etc/gshadow- + chown root:root /etc/gshadow- + chmod 644 /etc/group + chown root:root /etc/group + chmod 644 /etc/group- + chown root:root /etc/group- + + return 0 +} + + +##function################################################################ +# os related hardening +########################################################################## +harden_system() { + + echo "Check if root user has 0 as guid , if not set it" + root_gid=$(grep '^root:' /etc/passwd | cut -d : -f 4) + if [[ ${root_gid} -ne 0 ]]; then + usermod -g 0 root + check_error $? "Failed changing root guid to 0" 1 + fi + + echo "Error out if there are users with empty password" + cat /etc/shadow |awk -F : '($2 == "" ){ exit 1}' + if [[ $? -ne 0 ]]; then + echo "Users present with empty password. Remove the user or set pasword for the users" + exit 1 + fi + + echo "Check if any user other than root has uid of 0" + root_uid_count=$(cat /etc/passwd | awk -F ":" '($3 == 0){print $3}' | wc -l) + if [[ ${root_uid_count} -ne 1 ]]; then + echo "Non root users have UID of 0.Correct the error and retry" + exit 1 + fi + + echo "Fix permission of all cron files" + for each in `echo /etc/cron.daily /etc/cron.hourly /etc/cron.d /etc/cron.monthly /etc/cron.weekly /etc/crontab` + do + if [[ -e ${each} ]]; then + stat -L -c "%a %u %g" ${each} | egrep ".00 0 0" + if [[ $? -ne 0 ]]; then + chown root:root ${each} + chmod og-rwx ${each} + fi + fi + done + + echo "Remove cron and at deny files anf have allow files in place" + rm -f /etc/cron.deny + rm -f /etc/at.deny + touch /etc/cron.allow + touch /etc/at.allow + chmod g-wx,o-rwx /etc/cron.allow + chmod g-wx,o-rwx /etc/at.allow + chown root:root /etc/cron.allow + chown root:root /etc/at.allow + + if [[ ! -f /etc/issue ]]; then + echo "### Authorized users only. All activity may be monitored and reported ###" > /etc/issue + fi + chmod 644 /etc/issue + chown root:root /etc/issue + + if [[ ! -f /etc/issue.net ]]; then + echo "### Authorized users only. All activity may be monitored and reported ###" > /etc/issue.net + fi + chmod 644 /etc/issue.net + chown root:root /etc/issue.net + + if [[ -f /etc/rsyslog.conf ]]; then + chmod 0640 /etc/rsyslog.conf + fi + + ##################users' home directories permissions are 750 or more restrictive###### + awk -F: '($1 !~ /^(halt|sync|shutdown|nfsnobody)$/ && $7 !~ /^(\/usr)?\/sbin\/nologin(\/)?$/ && $7 !~ /^(\/usr)?\/bin\/false(\/)?$/) {print $6}' /etc/passwd | while read -r dir; do + if [ -d "$dir" ]; then + dirperm=$(stat -L -c '%a' "$dir") + if [ "$(echo "$dirperm" | cut -c6)" != "-" ] || [ "$(echo "$dirperm" | cut -c8)" != "-" ] || [ "$(echo "$dirperm" | cut -c9)" != "-" ] || [ "$(echo "$dirperm" | cut -c10)" != "-" ]; then + chmod g-w,o-rwx "$dir" + fi + fi + done + + return 0 +} + +########################################################################## +# Remove unnecessary packages +########################################################################## +remove_services() { + + if [[ ${OS_FLAVOUR} == "ubuntu" ]]; then + echo "Disable setrouble shoot service if enabled" + systemctl disable setroubleshoot + + echo "Removing legacy networking services" + systemctl disable xinetd + apt-get remove -y openbsd-inetd rsh-client rsh-redone-client nis talk telnet ldap-utils gdm3 + apt-get purge -y telnet vim vim-common vim-runtime vim-tiny + + echo "Removing X packages" + apt-get remove -y xserver-xorg* + fi + + if [[ ${OS_FLAVOUR} == "centos" ]] || [[ ${OS_FLAVOUR} == "rhel" ]]; then + echo "Disable setrouble shoot service if enabled" + chkconfig setroubleshoot off + + echo "Removing legacy networking services" + yum erase -y inetd xinetd ypserv tftp-server telnet-server rsh-server gdm3 telnet vim vim-common vim-runtime vim-tiny + + echo "Removing X packages" + yum groupremove -y "X Window System" + yum remove -y xorg-x11* + fi + + # Placeholder for supporting other linux OS + if [[ ${OS_FLAVOUR} == "linux" ]]; then + test 1 -eq 2 + check_error $? "OS not supported" 1 + fi + + return 0 +} + +########################################################################## +# Block unnecessary modules +########################################################################## +disable_modules() { + + if [[ -d /etc/modprobe.d ]]; then + echo "Disabling unnecessary modules" + + echo "install dccp /bin/true" > /etc/modprobe.d/dccp.conf + echo "install sctp /bin/true" >> /etc/modprobe.d/sctp.conf + echo "install rds /bin/true" >> /etc/modprobe.d/rds.conf + echo "install tipc /bin/true" >> /etc/modprobe.d/tipc.conf + + echo "install cramfs /bin/false" > /etc/modprobe.d/cramfs.conf + echo "install freevxfs /bin/true" >> /etc/modprobe.d/freevxfs.conf + echo "install jffs2 /bin/true" >> /etc/modprobe.d/jffs2.conf + echo "install hfs /bin/true" >> /etc/modprobe.d/hfs.conf + echo "install hfsplus /bin/true" >> /etc/modprobe.d/hfsplus.conf + + # Needed for Kairos + #echo "install squashfs /bin/true" >> /etc/modprobe.d/squashfs.conf + #echo "install udf /bin/true" >> /etc/modprobe.d/udf.conf + #echo "install usb-storage /bin/false" >> /etc/modprobe.d/usb_storage.conf + fi + + return 0 +} + +########################################################################## +# Login Banner +########################################################################## + +harden_banner() { + + local file_path_locallogin="/etc/issue" + local file_path_remotelogin="/etc/issue.net" + + local content_locallogin=( + "Authorized uses only. All activity may be monitored and reported." +) + + local content_remotelogin=( + "Authorized uses only. All activity may be monitored and reported." +) + # Create or append to the local login banner + for line in "${content_locallogin[@]}"; do + echo "$line" | sudo tee -a "$file_path_locallogin" >/dev/null + done + + # Create or append to the remote login banner + for line in "${content_remotelogin[@]}"; do + echo "$line" | sudo tee -a "$file_path_remotelogin" >/dev/null + done + + # Verify if the files were created or appended successfully + if [ -f "$file_path_locallogin" ] && [ -f "$file_path_remotelogin" ]; then + echo "Files $file_path_locallogin', '$file_path_remotelogin' created/appended successfully." + else + echo "Failed to create/append to files '$file_path_locallogin' and or '$file_path_remotelogin'." + fi + + # Delete motd file + if [[ -f /etc/motd ]]; then rm /etc/motd; fi + + return 0 +} + + +############################################################# +# Log files permission +############################################################# +harden_log() { + + # Ensure permissions on all logfiles are configured + + # Find and set permissions on log files + find /var/log -type f -exec chmod g-wx,o-rwx '{}' + -o -type d -exec chmod g-w,o-rwx '{}' + + + echo "750 permission set on all log files & directories inside /var/log" + + # Ensure logrotate assigns appropriate permissions + + # Define restrictive permissiom + utmp="create 0640 root utmp" + # Modify the logrotate configuration + + if [ -e "/etc/logrotate.conf" ]; then + # Check if the logrotation restrictive permission exists + if grep -q "^create 0640" /etc/logrotate.conf; then + # Modify the existing line + sed -i "s/^create 0640.*/$utmp/" /etc/logrotate.conf + echo "Modified restrictive permission in /etc/logrotate.conf" + else + # Add the new restrictive permission at the end of the file + echo "$utmp" >> /etc/logrotate.conf + echo "Added restrictive permission to /etc/logrotate.conf" + fi + fi + + # Ensure sudo log file exists + # Define sudo log file + logfile="Defaults logfile=/var/log/sudo.log" + + if [ -e "/etc/sudoers" ]; then + # Check if the sudo log file path exists + if grep -q "$logfile" /etc/sudoers; then + echo "sudo log file path already exist in /etc/sudoers" + else + # Add the log file path at the end of the file + echo "$logfile" >> /etc/sudoers + echo "Added log file path to /etc/sudoers" + fi + fi + + return 0 +} + + +########################################################################## +# Authentication/Login Hardening +########################################################################## +harden_auth() { + + #Install the pam_pwquality module + apt-get update -y + apt-get install -y libpam-pwquality + + # Define the new values for minlen and minclass + new_minlen="minlen = 14" + new_minclass="minclass = 4" + new_difok="difok = 2" + new_dictcheck="dictcheck = 0" + new_maxrepeat="maxrepeat = 3" + + # Check if the file exists + if [ -e "/etc/security/pwquality.conf" ]; then + # Check if the minlen line already exists + if grep -q "^minlen" /etc/security/pwquality.conf; then + # Modify the existing minlen line + sed -i "s/^minlen.*/$new_minlen/" /etc/security/pwquality.conf + echo "Modified minlen in /etc/security/pwquality.conf" + else + # Add the new minlen line at the end of the file + echo "$new_minlen" >> /etc/security/pwquality.conf + echo "Added minlen to /etc/security/pwquality.conf" + fi + + # Check if the minclass line already exists + if grep -q "^minclass" /etc/security/pwquality.conf; then + # Modify the existing minclass line + sed -i "s/^minclass.*/$new_minclass/" /etc/security/pwquality.conf + echo "Modified minclass in /etc/security/pwquality.conf" + else + # Add the new minclass line at the end of the file + echo "$new_minclass" >> /etc/security/pwquality.conf + echo "Added minclass to /etc/security/pwquality.conf" + fi + + # Check if the difok line already exists + if grep -q "^difok" /etc/security/pwquality.conf; then + # Modify the existing difok line + sed -i "s/^difok.*/$new_difok/" /etc/security/pwquality.conf + echo "Modified difok in /etc/security/pwquality.conf" + else + # Add the new difok line at the end of the file + echo "$new_difok" >> /etc/security/pwquality.conf + echo "Added difok to /etc/security/pwquality.conf" + fi + + # Check if the dictcheck line already exists + if grep -q "^dictcheck" /etc/security/pwquality.conf; then + # Modify the existing dictcheck line + sed -i "s/^dictcheck.*/$new_dictcheck/" /etc/security/pwquality.conf + echo "Modified dictcheck in /etc/security/pwquality.conf" + else + # Add the new dictcheck line at the end of the file + echo "$new_dictcheck" >> /etc/security/pwquality.conf + echo "Added dictcheck to /etc/security/pwquality.conf" + fi + + # Check if the maxrepeat line already exists + if grep -q "^maxrepeat" /etc/security/pwquality.conf; then + # Modify the existing maxrepeat line + sed -i "s/^maxrepeat.*/$new_maxrepeat/" /etc/security/pwquality.conf + echo "Modified maxrepeat in /etc/security/pwquality.conf" + else + # Add the new maxrepeat line at the end of the file + echo "$new_maxrepeat" >> /etc/security/pwquality.conf + echo "Added maxrepeat to /etc/security/pwquality.conf" + fi + else + echo "File /etc/security/pwquality.conf not found." + fi + + # Configuration lines to add to /etc/pam.d/su + config_lines="auth required pam_wheel.so use_uid group=admin" + + # Add configuration lines to the top of the file + echo -e "$config_lines\n$(cat /etc/pam.d/su)" > /etc/pam.d/su + + echo "Configuration to ensure access to the su command is restricted have been made" + + ##############Password lockout policies################## + + # Configuration lines to add to the top of /etc/pam.d/common-auth + config_lines="auth required pam_faillock.so preauth silent audit deny=5 unlock_time=900" + + # Backup the original file + cp /etc/pam.d/common-auth /etc/pam.d/common-auth.bak + + # Add configuration lines to the top of the file + echo -e "$config_lines\n$(cat /etc/pam.d/common-auth)" > /etc/pam.d/common-auth + + echo "Configuration added to /etc/pam.d/common-auth" + + ##############Password reuse policy################## + + #Define the password reuse policy + reuse_policy="password required pam_pwhistory.so remember=5" + + #Check if the common-password file exists + if [ -e "/etc/pam.d/common-password" ]; then + #Check if password reuse policy already exist + if grep -q "$reuse_policy" /etc/pam.d/common-password; then + echo "Password reuse policy already exist in /etc/pam.d/common-password" + else + #Add the reuse policy at the end of file + echo "$reuse_policy" >> /etc/pam.d/common-password + echo "Added lockout policy for failed login attempts in /etc/pam.d/common-password" + fi + else + echo "File /etc/pam.d/common-password not found." + fi + + #####################Password expiry policy################# + + #Define the destination file + config_file='/etc/login.defs' + + echo "" >> ${config_file} + + update_config_files 'PASS_MIN_DAYS' 'PASS_MIN_DAYS 1' ${config_file} + update_config_files 'PASS_MAX_DAYS' 'PASS_MAX_DAYS 365' ${config_file} + + echo "Password expiry policy updated to PASS_MIN_DAYS 1 & PASS_MAX_DAYS 365" + + ####################Inactive password lock################ + + #Define the destination file + config_file='/etc/default/useradd' + + echo "" >> ${config_file} + + update_config_files 'INACTIVE' 'INACTIVE=30' ${config_file} + echo "Inactive password lock policy updated to 30 days" + + + #################Session expiry policy##################### + # Configuration lines to add to /etc/profile + config_lines="readonly TMOUT=900 ; export TMOUT" + + # Add configuration lines to the top of the file + echo "$config_lines" >> /etc/profile + + echo "Configuration added to /etc/profile for shell timeout policy" + return 0 +} + +########################################################################## +# Cleanup Package Manager Cache +########################################################################## +cleanup_cache() { + if [[ ${OS_FLAVOUR} == "ubuntu" ]]; then + apt-get clean + rm -rf /var/lib/apt/lists/* + fi + + if [[ ${OS_FLAVOUR} == "centos" ]]; then + yum clean all + rm -rf /var/cache/yum/* + fi + + if [[ ${OS_FLAVOUR} == "rhel" ]]; then + yum clean all + rm -rf /var/cache/yum/* + fi + + # Placeholder for supporting other linux OS + if [[ ${OS_FLAVOUR} == "linux" ]]; then + test 1 -eq 2 + check_error $? "OS not supported" 1 + fi + + return 0 +} + +cp /etc/os-release /etc/os-release.bak + +OS_FLAVOUR="linux" +get_os +upgrade_packages +harden_sysctl +harden_ssh +harden_boot +harden_password_files +harden_system +remove_services +disable_modules +harden_audit +harden_banner +harden_log +harden_auth +cleanup_cache + +mv /etc/os-release.bak /etc/os-release + +exit 0 \ No newline at end of file diff --git a/earthly.sh b/earthly.sh index 3f7c1b0..3b16f42 100755 --- a/earthly.sh +++ b/earthly.sh @@ -60,32 +60,36 @@ fi docker rmi gcr.io/spectro-images-public/earthly/buildkitd:$EARTHLY_VERSION docker rmi alpine:latest -# Print the output for use in Palette Profile. -echo -e '##########################################################################################################' -echo -e '\nPASTE THE CONTENT BELOW INTO YOUR CLUSTER PROFILE IN PALETTE REPLACING ALL THE CONTENTS IN THE PROFILE\n' -echo -e '##########################################################################################################' -echo -e '\n' -echo -e 'pack:' -echo -e ' content:' -echo -e ' images:' -echo -e ' - image: "{{.spectro.pack.edge-native-byoi.options.system.uri}}"' -echo -e ' # Below config is default value, please uncomment if you want to modify default values' -echo -e ' #drain:' -echo -e ' #cordon: true' -echo -e ' #timeout: 60 # The length of time to wait before giving up, zero means infinite' -echo -e ' #gracePeriod: 60 # Period of time in seconds given to each pod to terminate gracefully. If negative, the default value specified in the pod will be used' -echo -e ' #ignoreDaemonSets: true' -echo -e ' #deleteLocalData: true # Continue even if there are pods using emptyDir (local data that will be deleted when the node is drained)' -echo -e ' #force: true # Continue even if there are pods that do not declare a controller' -echo -e ' #disableEviction: false # Force drain to use delete, even if eviction is supported. This will bypass checking PodDisruptionBudgets, use with caution' -echo -e ' #skipWaitForDeleteTimeout: 60 # If pod DeletionTimestamp older than N seconds, skip waiting for the pod. Seconds must be greater than 0 to skip.' -echo -e 'options:' -echo -e ' system.uri: "{{ .spectro.pack.edge-native-byoi.options.system.registry }}/{{ .spectro.pack.edge-native-byoi.options.system.repo }}:{{ .spectro.pack.edge-native-byoi.options.system.k8sDistribution }}-{{ .spectro.system.kubernetes.version }}-{{ .spectro.pack.edge-native-byoi.options.system.peVersion }}-{{ .spectro.pack.edge-native-byoi.options.system.customTag }}"' -echo -e '\n' -echo -e " system.registry: $IMAGE_REGISTRY" -echo -e " system.repo: $IMAGE_REPO" -echo -e " system.k8sDistribution: $K8S_DISTRIBUTION" -echo -e " system.osName: $OS_DISTRIBUTION" -echo -e " system.peVersion: $PE_VERSION" -echo -e " system.customTag: $CUSTOM_TAG" -echo -e " system.osVersion: $OS_VERSION" +if [[ "$1" == "+uki-genkey" ]]; then + ./keys.sh secure-boot/ +else + # Print the output for use in Palette Profile. + echo -e '##########################################################################################################' + echo -e '\nPASTE THE CONTENT BELOW INTO YOUR CLUSTER PROFILE IN PALETTE REPLACING ALL THE CONTENTS IN THE PROFILE\n' + echo -e '##########################################################################################################' + echo -e '\n' + echo -e 'pack:' + echo -e ' content:' + echo -e ' images:' + echo -e ' - image: "{{.spectro.pack.edge-native-byoi.options.system.uri}}"' + echo -e ' # Below config is default value, please uncomment if you want to modify default values' + echo -e ' #drain:' + echo -e ' #cordon: true' + echo -e ' #timeout: 60 # The length of time to wait before giving up, zero means infinite' + echo -e ' #gracePeriod: 60 # Period of time in seconds given to each pod to terminate gracefully. If negative, the default value specified in the pod will be used' + echo -e ' #ignoreDaemonSets: true' + echo -e ' #deleteLocalData: true # Continue even if there are pods using emptyDir (local data that will be deleted when the node is drained)' + echo -e ' #force: true # Continue even if there are pods that do not declare a controller' + echo -e ' #disableEviction: false # Force drain to use delete, even if eviction is supported. This will bypass checking PodDisruptionBudgets, use with caution' + echo -e ' #skipWaitForDeleteTimeout: 60 # If pod DeletionTimestamp older than N seconds, skip waiting for the pod. Seconds must be greater than 0 to skip.' + echo -e 'options:' + echo -e ' system.uri: "{{ .spectro.pack.edge-native-byoi.options.system.registry }}/{{ .spectro.pack.edge-native-byoi.options.system.repo }}:{{ .spectro.pack.edge-native-byoi.options.system.k8sDistribution }}-{{ .spectro.system.kubernetes.version }}-{{ .spectro.pack.edge-native-byoi.options.system.peVersion }}-{{ .spectro.pack.edge-native-byoi.options.system.customTag }}"' + echo -e '\n' + echo -e " system.registry: $IMAGE_REGISTRY" + echo -e " system.repo: $IMAGE_REPO" + echo -e " system.k8sDistribution: $K8S_DISTRIBUTION" + echo -e " system.osName: $OS_DISTRIBUTION" + echo -e " system.peVersion: $PE_VERSION" + echo -e " system.customTag: $CUSTOM_TAG" + echo -e " system.osVersion: $OS_VERSION" +fi diff --git a/internal/go.mod b/internal/go.mod new file mode 100644 index 0000000..cd2d0f0 --- /dev/null +++ b/internal/go.mod @@ -0,0 +1,14 @@ +module github.com/spectrocloud/CanvOS/internal + +go 1.22.0 + +require ( + github.com/spf13/cobra v1.8.0 + github.com/twpayne/go-vfs/v5 v5.0.4 +) + +require ( + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/sys v0.17.0 // indirect +) diff --git a/internal/go.sum b/internal/go.sum new file mode 100644 index 0000000..22585c9 --- /dev/null +++ b/internal/go.sum @@ -0,0 +1,14 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/twpayne/go-vfs/v5 v5.0.4 h1:/ne3h+rW7f5YOyOFguz+3ztfUwzOLR0Vts3y0mMAitg= +github.com/twpayne/go-vfs/v5 v5.0.4/go.mod h1:zTPFJUbgsEMFNSWnWQlLq9wh4AN83edZzx3VXbxrS1w= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/slink/slink b/internal/slink/slink new file mode 100755 index 0000000..f4ea6e9 Binary files /dev/null and b/internal/slink/slink differ diff --git a/internal/slink/slink.go b/internal/slink/slink.go new file mode 100644 index 0000000..96147ff --- /dev/null +++ b/internal/slink/slink.go @@ -0,0 +1,96 @@ +package main + +import ( + "fmt" + "log/slog" + "os" + "path/filepath" + + "github.com/spf13/cobra" + "github.com/twpayne/go-vfs/v5" +) + +func slink(cmd *cobra.Command, args []string) { + source := cmd.Flag("source").Value.String() + target := cmd.Flag("target").Value.String() + slog.Info(fmt.Sprintf("Source: %s, Target: %s", source, target)) + if source == "" || target == "" { + slog.Error("Source and target must be provided") + os.Exit(1) + } + + sourceFS := vfs.NewPathFS(vfs.OSFS, source) + + if err := vfs.Walk(sourceFS, "/", func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return nil + } + + // Create symlink + linkname := path + targetname := filepath.Join(target, path) + slog.Info(fmt.Sprintf("Creating link %s to %s", linkname, targetname)) + + if err := copyDir(filepath.Dir(linkname), sourceFS, vfs.OSFS); err != nil { + slog.Error("Error copying directory: %s", err) + return err + } + + if err := os.Symlink(targetname, linkname); err != nil { + slog.Error("Error creating symlink: %s", err) + return err + } + + return nil + }); err != nil { + slog.Error("Error walking source directory: %s", err) + os.Exit(1) + } +} + +func copyDir(path string, srcFS, dstFS vfs.FS) error { + if exists, err := Exists(dstFS, path); err != nil { + return err + } else if exists { + return nil + } + + // Check if parent of path exists + if err := copyDir(filepath.Dir(path), srcFS, dstFS); err != nil { + return err + } + + // Get permission of source directory + srcInfo, err := srcFS.Stat(path) + if err != nil { + return err + } + // Create directory with same permissions as source + if err := vfs.MkdirAll(dstFS, path, srcInfo.Mode()); err != nil { + return err + } + return nil +} + +func Exists(fs vfs.FS, path string) (bool, error) { + _, err := fs.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} +func main() { + cmd := &cobra.Command{ + Use: "slink", + Run: slink, + } + cmd.Flags().StringP("source", "s", "", "source directory") + cmd.Flags().StringP("target", "t", "", "target prefix") + cmd.Execute() +} diff --git a/keys.sh b/keys.sh new file mode 100755 index 0000000..ebdbb81 --- /dev/null +++ b/keys.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Define the directory to be listed; default to secure-boot if none provided +directory="${1:-secure-boot}" + +# Print the root directory +echo "$(basename "$(realpath "$directory")")/" + +# Function to generate tree view and add comments to specific files +generate_tree() { + find "$directory" -mindepth 1 -print | sort | sed 's|[^/]*/| |g' | awk ' + { + # Replace leading spaces with a combination of pipes and dashes to simulate tree branches + gsub(/ /, "| ", $0); + sub(/\| $/, "`---", $0); + print; + }' +} + +# Function to add comments to specific files +function add_comment { + while read -r line; do + # Determine filename from the indented line + filename="${line##* }" # Extract the last part after space, which should be the file name + case "$filename" in + "PK.auth"*) + echo "$line <-- Platform Key" + ;; + "KEK.auth"*) + echo "$line <-- Key Exchange Key" + ;; + "db.auth"*) + echo "$line <-- Signature Database" + ;; + "dbx.esl"*) + echo "$line <-- Forbidden Signatures Database" + ;; + "PK.key"*) + echo "$line <-- Remove me from this directory and keep me safe" + ;; + "KEK.key"*) + echo "$line <-- Remove me from this directory and keep me safe" + ;; + *) + echo "$line" + ;; + esac + done +} + +# Generate the tree and pipe it to add comments +generate_tree | add_comment diff --git a/overlay/files-iso/boot/grub2/grub.cfg b/overlay/files-iso/boot/grub2/grub.cfg index f4a73da..9ed290b 100644 --- a/overlay/files-iso/boot/grub2/grub.cfg +++ b/overlay/files-iso/boot/grub2/grub.cfg @@ -4,14 +4,6 @@ set timeout=5 set timeout_style=menu set linux=linux set initrd=initrd -if [ "${grub_cpu}" = "x86_64" -o "${grub_cpu}" = "i386" -o "${grub_cpu}" = "arm64" ];then - if [ "${grub_platform}" = "efi" ]; then - if [ "${grub_cpu}" != "arm64" ]; then - set linux=linuxefi - set initrd=initrdefi - fi - fi -fi if [ "${grub_platform}" = "efi" ]; then echo "Please press 't' to show the boot menu on this console" fi diff --git a/rhel-core-images/Dockerfile.rhel8 b/rhel-core-images/Dockerfile.rhel8 index b0e1ad9..44bfe21 100644 --- a/rhel-core-images/Dockerfile.rhel8 +++ b/rhel-core-images/Dockerfile.rhel8 @@ -56,7 +56,7 @@ RUN uuidgen > /etc/machine-id && dnf install -y \ kernel kernel-modules kernel-modules-extra \ rsync jq && dnf clean all -COPY --from=quay.io/kairos/framework:v2.4.5 / / +COPY --from=quay.io/kairos/framework:v2.7.28 / / RUN mkdir -p /run/lock RUN touch /usr/libexec/.keep diff --git a/rhel-fips/Dockerfile b/rhel-fips/Dockerfile index 55289f7..839beb7 100644 --- a/rhel-fips/Dockerfile +++ b/rhel-fips/Dockerfile @@ -5,7 +5,7 @@ ARG PASSWORD FROM $BASE_IMAGE as base # Generate os-release file -FROM quay.io/kairos/osbuilder-tools:v0.7.11 as osbuilder +FROM quay.io/kairos/osbuilder-tools:v0.200.11 as osbuilder RUN zypper install -y gettext && zypper clean RUN mkdir /workspace COPY --from=base /etc/os-release /workspace/os-release @@ -83,7 +83,7 @@ RUN mkdir -p /run/lock && \ # Copy the os-release file to identify the OS COPY --from=osbuilder /workspace/os-release /etc/os-release -COPY --from=quay.io/kairos/framework:v2.4.5-fips / / +COPY --from=quay.io/kairos/framework:v2.7.28-fips / / COPY overlay/rhel8 / diff --git a/slem/Dockerfile b/slem/Dockerfile index c19a09f..5e4477e 100644 --- a/slem/Dockerfile +++ b/slem/Dockerfile @@ -28,7 +28,7 @@ RUN mkdir -p /run/lock RUN mkdir -p /usr/libexec RUN touch /usr/libexec/.keep -COPY --from=quay.io/kairos/framework:v2.4.5 / / +COPY --from=quay.io/kairos/framework:v2.7.28 / / # Remove file below to allow dracut to build initrd without dhcp-client RUN rm -rf /usr/lib/dracut/modules.d/35network-legacy diff --git a/stylus_uki.yaml b/stylus_uki.yaml new file mode 100644 index 0000000..ffdd938 --- /dev/null +++ b/stylus_uki.yaml @@ -0,0 +1,29 @@ +#cloud-config +stages: + initramfs: + - if: '[ -e "/run/cos/uki_boot_mode" ] && [ ! -f "/run/cos/live_mode" ]' + name: link agent provider stylus + commands: + - echo "Linking agent provider" + - mkdir -p /usr/local/bin/ + - ln -sf /opt/spectrocloud/bin/agent-provider-stylus /usr/local/bin/agent-provider-stylus + - if: '[ -e "/run/cos/uki_boot_mode" ] && [ ! -f "/run/cos/live_mode" ] && [ ! -f "/opt/spectrocloud/bin/stylus-agent" ]' + name: unpack stylus package + commands: + - echo "Unpacking stylus package" + - ln -sf /oem/opt.bind/luet /usr/local/bin/luet + - /oem/opt.bind/luet util unpack file://oem/opt.bind/stylus-image.tar / + after-install: + - name: uki stylus package persist + if: '[ -e "/run/cos/uki_install_mode" ]' + commands: + - echo "Copying files to persistent path" + - if mount | grep /oem >/dev/null; then umount /oem; fi + - if [ -e /dev/mapper/oem ]; then cryptsetup close /dev/mapper/oem; fi + - /usr/lib/systemd/systemd-cryptsetup attach oem $(findfs PARTLABEL=oem) - tpm2-device=auto + - mount /dev/mapper/oem /oem + - mkdir -p /oem/opt.bind + - cp -rfv /run/initramfs/live/luet /oem/opt.bind/ + - cp -rfv /run/initramfs/live/stylus-image.tar /oem/opt.bind/ + - umount /dev/mapper/oem + - if [ -e /dev/mapper/oem ]; then cryptsetup close /dev/mapper/oem; fi diff --git a/ubuntu-fips/Dockerfile b/ubuntu-fips/Dockerfile index 67dae7e..1e34d4e 100644 --- a/ubuntu-fips/Dockerfile +++ b/ubuntu-fips/Dockerfile @@ -1,12 +1,12 @@ # Kairos framework packages for ubuntu fips -FROM quay.io/kairos/framework:v2.4.5-fips as kairos-fips +FROM quay.io/kairos/framework:v2.7.28-fips as kairos-fips # Base ubuntu image (focal) FROM ubuntu:focal as base # Generate os-release file -FROM quay.io/kairos/osbuilder-tools:v0.7.11 as osbuilder +FROM quay.io/kairos/osbuilder-tools:v0.200.11 as osbuilder RUN zypper install -y gettext && zypper clean RUN mkdir /workspace COPY --from=base /etc/os-release /workspace/os-release