Skip to content

Commit

Permalink
upgrade process
Browse files Browse the repository at this point in the history
  • Loading branch information
mudler committed Feb 2, 2024
1 parent 04cde4e commit 0a4afc2
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 156 deletions.
8 changes: 0 additions & 8 deletions content/en/docs/Architecture/trustedboot.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,8 @@ It is required in order to generate USI images to have a set of keys and certifi

The keys are used to sign the UKI file, and to generate a PCR policy keypair required later on by the system in order to decrypt the encrypted partitions. The keys and certificates are generated with the `enki` tool, that is available in the `enki` container image.



### Considerations

#### Security considerations

TODO: Design choices (no pivot, no grub,)

#### systemd-boot

#### Booting command lines

UKI file's signatures are including also the kernel command line, so any change to the kernel command line will require a new UKI file to be generated and the installer image to be rebuilt. This implies that you cannot change the booting options once the system is installed (and the system won't be able to access the encrypted data)
60 changes: 23 additions & 37 deletions content/en/docs/Installation/trustedboot.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ The Hardware that will run Kairos needs to have the following requirements:
- Secure boot available in the system
- The Hardware should have a TPM chip or fTPM enabled
- The Hardware should be capable of booting large EFI files (>32MB)
- Base image of the OS needs to have at least systemd 252 or newer ( for example ubuntu >=23.04 or fedora >=38 )
- Base image of the OS needs to have at least systemd 252 or newer ( for example ubuntu >=23.10 or fedora >=38 )

To build the installable medium you need the following installed in the system you use to build the installable medium:

Expand Down Expand Up @@ -53,12 +53,14 @@ docker build -t enki --target tools-image .
To generate the Secure boot certificates and keys run the following commands:

```bash
MY_ORG="Acme Corp"
# Generate the keys
docker run -v $PWD/keys:/work/keys -ti --rm enki genkey "$MY_ORG" -o /work/keys
```
{{% alert title="Warning" %}}
Substitute `$MY_ORG` for your own string, this can be anything but it help identifying the Keys
{{% /alert %}}

{{% alert title="Warning" %}}
It is very important to preserve the keys generated in this process in a safe place. Loosing the keys will prevent you to generate new images that can be used for upgrades.
{{% /alert %}}
Expand All @@ -67,59 +69,47 @@ It is very important to preserve the keys generated in this process in a safe pl

To build the installable medium you need to run the following commands:

{{% alert title="Warning" %}}

This method is still a work in progress.
For now build the testing Kairos iso with:

{{< tabpane text=true >}}
{{% tab header="From a container image" %}}
```bash
# clone the repo
git clone https://github.com/kairos-io/kairos

# cd into the repo
cd kairos

IMAGE=quay.io/kairos/fedora:38-core-amd64-generic-v3.0.0-alpha1

# build the iso with Earthly
earthly +uki-iso --BASE_IMAGE=$IMAGE

# resulting ISO is in: build/kairos-fedora-38-core-amd64-generic-v3.0.0-alpha1.uki.iso

# Multiple boot options
earthly +uki-iso --BASE_IMAGE=$IMAGE --ENKI_FLAGS="--cmdline rd.blacklist=i915"
CONTAINER_IMAGE=quay.io/kairos/fedora:38-core-amd64-generic-v3.0.0-alpha1
# ubuntu:
# CONTAINER_IMAGE=quay.io/kairos/ubuntu:23.10-core-amd64-generic-v3.0.0-alpha1
docker run -ti --rm -v $PWD/build:/result -v $PWD/keys/:/keys enki build-uki $CONTAINER_IMAGE -t iso -d /result/ -k /keys
```

{{% /alert %}}

{{% /tab %}}
{{% tab header="From a directory" %}}
```bash
CONTAINER_IMAGE=quay.io/kairos/fedora:38-core-amd64-generic-v3.0.0-alpha1
docker run --rm -v $PWD/build:/result -v $PWD/keys/:/keys enki build-uki $CONTAINER_IMAGE -o /result/trustedboot.iso -k /keys
# Assuming you have a "rootfs" directory with the content of the OS
# If the image is in a directory ($PWD/rootfs) you can use the following command
docker run -ti --rm -v $PWD/build:/result -v $PWD/rootfs:/rootfs -v $PWD/keys/:/keys enki build-uki dir:/rootfs/ -t iso -d /result/ -k /keys
```
{{% /tab %}}
{{< /tabpane >}}

## Installation

The installation process is performed as usual and the [Installation instructions]({{< relref "../installation" >}}) can be followed, however the difference is that user-data will be automatically encrypted (both the OEM and the persistent partition) by using the TPM chip and the Trusted Boot mechanism.

### Enroll the keys in Secure Boot

If your machine is in UEFI setup mode Secure Boot keys will be automatically enrolled.
If your machine is in UEFI setup mode Secure Boot keys will be automatically enrolled. To enter UEFI Setup mode you need to clear the Secure Boot keys (PKs) from the BIOS/UEFI.

If UEFI setup mode is not available, you need to enroll the keys manually in the BIOS/UEFI.
If UEFI setup mode is not available, you need to enroll the keys manually in the BIOS/UEFI.

This process can vary depending on the vendor, but in general you need to enter the BIOS/UEFI setup during early boot and import the keys, for an example outline you can check the steps for [HPE Hardware](https://techlibrary.hpe.com/docs/iss/proliant-gen10-uefi/GUID-E4427875-D123-4BBF-9056-342168478A02.html).

A video of the process in QEMU is available [here](https://github.com/kairos-io/kairos/assets/2420543/e45f6a08-ec74-4cfd-bdf0-aeb7b23ac9bc).
A video of the process of importing keys in QEMU is available [here](https://github.com/kairos-io/kairos/assets/2420543/e45f6a08-ec74-4cfd-bdf0-aeb7b23ac9bc).

## Upgrades

See the [Trusted Boot Upgrade]({{< relref "../upgrade/trustedboot" >}}) page.

## Testing the images locally

To test the ISO file locally QEMU can be used. In order to test Secure Boot components you need an ed2k firmware with secureboot in QEMU. If you don't have QEMU locally and/or you don't have the correct dependencies you can follow the steps below that build a container image with QEMU and the needed dependencies and uses it to run the ISO file.
To test the ISO file locally QEMU can be used. In order to test Secure Boot components you need an ed2k firmware with secureboot in QEMU. If you don't have QEMU locally and/or you don't have the correct dependencies you can follow the steps below that build a container image with QEMU and the needed dependencies and use that container to run the ISO file in a VM with Docker.

1. Build the container image with the dependencies (note to replace disk, VM size and ISO file name):
1. Build the container image with the QEMU/Secure Boot dependencies (note to replace disk, VM size and ISO file name):

```bash
docker build -t fedora-qemu -<<DOCKER
Expand All @@ -129,7 +119,7 @@ RUN dnf config-manager --add-repo http://www.kraxel.org/repos/firmware.repo
RUN dnf install -y edk2.git-ovmf-x64 qemu
RUN dnf install -y swtpm wget
WORKDIR /
RUN wget https://github.com/kairos-io/kairos/raw/master/tests/assets/efivars.fd
RUN wget -q https://github.com/mudler/cos-demo-labs/raw/tests/efivars.fd -O /efivars.fd
WORKDIR /work
RUN <<EOF
Expand All @@ -143,15 +133,11 @@ ENTRYPOINT [ "/entrypoint.sh" ]
DOCKER
```

2. Run the container image with the ISO file:
2. Run the container image with the ISO file (replace the iso file name with yours):

```bash
# console only
docker run --privileged -v $PWD:/work -v /dev/kvm:/dev/kvm --rm -ti fedora-qemu -cdrom /work/kairos-fedora-38-core-amd64-generic-v3.0.0-alpha1.uki.iso -nographic

# GTK (insecure)
# xhost si:localuser:root # give access to root account to connect to the X server socket
# docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --privileged -v $PWD:/work -v /dev/kvm:/dev/kvm --rm -ti fedora-qemu -cdrom /work/kairos-fedora-38-core-amd64-generic-v3.0.0-alpha1.uki.iso
```

Note: To stop the QEMU container you can use `Ctrl-a x` or `Ctrl-a c` to enter the QEMU console and then `quit` to exit.
Expand Down
139 changes: 28 additions & 111 deletions content/en/docs/Upgrade/trustedboot.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ See the [Trusted Boot Installation]({{< relref "../installation/trustedboot" >}}

In order to upgrade a node to a new version of the OS, you need to generate again the installable medium with the same keys used in the steps before.

Follow the process in [Trusted Boot Installation]({{< relref "../installation/trustedboot" >}}) to generate the installable medium, and then follow the steps below to create an image that can be used for upgrades.

{{% alert title="Note" %}}
The resulting container image can be used for upgrades with `kairos-agent`.
{{% /alert %}}
Expand All @@ -33,137 +31,56 @@ First we need to extract the EFI file from the ISO file generated with what expl
This step is required until [#2171](https://github.com/kairos-io/kairos/issues/2171) is implemented.
{{% /alert %}}

```bash
mkdir iso
mkdir efiboot
#### Generate the upgrade image

sudo mount -o loop *.iso iso
sudo mount iso/efiboot.img efiboot
1. Build the container image used to generate the upgrade image

cp efiboot/EFI/kairos/*.efi .
```bash
# Build the container image that will be used to generate the keys and installable medium
git clone https://github.com/kairos-io/enki.git
cd enki
docker build -t enki --target tools-image .
```

To generate the upgrade image you need to create a naked container image containing containing the EFI files and the `systemd-boot` configuration, for example:

{{% alert title="Warning" %}}
Flow not entirely tested/validated yet
{{% /alert %}}
2. Build the Container image used for upgrades

```bash
VERSION=v3.0.0-alpha2
EFI_FILE=$PWD/*.efi
UKI=kairos-fedora-38-core-amd64-generic-${VERSION}.efi
UPGRADE_IMAGE=ttl.sh/kairos-uki-tests/upgrade-image
CONTAINER_IMAGE=quay.io/kairos/fedora:38-core-amd64-generic-v3.0.0-alpha1

mkdir upgrade-image
mkdir -p upgrade-image/loader/entries
mkdir -p upgrade-image/EFI/kairos/
# ubuntu:
# CONTAINER_IMAGE=quay.io/kairos/ubuntu:23.10-core-amd64-generic-v3.0.0-alpha1
docker run --rm -v $PWD/keys:/keys -v $PWD:/work -ti enki build-uki $CONTAINER_IMAGE -t uki -d /work/upgrade-image -k /keys

cp -rfv $EFI_FILE upgrade-image/EFI/kairos/${UKI}

# default @saved
CONF=$(basename $(ls -1 $PWD/upgrade-image/loader/entries/*.conf))
# Replace with the version of the OS you are upgrading to (next boot auto selection)
cat <<EOF > upgrade-image/loader/loader.conf
default kairos-$VERSION.conf
default $CONF
timeout 5
console-mode max
editor no
EOF

cat <<EOF > upgrade-image/loader/entries/kairos-$VERSION.conf
title Kairos $VERSION
efi /EFI/kairos/$UKI
version $VERSION
EOF
## Generate the container image
docker run --rm -v $PWD:/work --entrypoint /bin/tar -ti enki -cf /work/src.tar /work/upgrade-image

cd upgrade-image
docker build -t $UPGRADE_IMAGE -<<DOCKER
FROM scratch
COPY . /
DOCKER
CONTAINER_IMAGE_NAME="my-upgrade-image"
docker run -ti -v $PWD:/work quay.io/luet/base:latest util pack $CONTAINER_IMAGE_NAME /work/src.tar /work/upgrade_image.tar

```

{{% alert title="Upgrades with Kubernetes" %}}

In order to upgrade with Kubernetes using system upgrade controller plans you can use the image used to generate the installable medium, and use it as a base image for the upgrade image.
When invoking `kairos-agent` in the plan however, you need to specify the `--source` flag to point to the image that contains the UKI file.

{{% /alert %}}


### Example: e2e image generation
3. Push the upgrade image to a registry

```bash
# Now you can load upgrade_image.tar to a registry and use it with kairos-agent
docker load -i upgrade_image.tar

IMAGE=ttl.sh/uki-kairos-test:awesome
UPSTREAM_IMAGE=quay.io/kairos/fedora:38-core-amd64-generic-v3.0.0-alpha1

docker build -t $IMAGE -<<DOCKER
FROM $UPSTREAM_IMAGE
RUN <<EOF
echo "wow" >> /wow
EOF
DOCKER

docker push $IMAGE

# TODO: this is temporary
# clone the repo
git clone https://github.com/kairos-io/kairos

# cd into the repo
cd kairos


# build the iso with Earthly
earthly +uki-iso --BASE_IMAGE=$IMAGE

# Extract the EFI file from the ISO
cd build/

mkdir iso
mkdir efiboot

sudo mount -o loop *.iso iso
sudo mount iso/efiboot.img efiboot

cp efiboot/EFI/kairos/*.efi .

ls
# efiboot iso kairos-fedora-38-core-amd64-generic-v3.0.0-alpha1.uki.iso v3.0.0-alpha1.efi

# Generate the upgrade image

VERSION=v3.0.0-alpha2
UKI=kairos-fedora-38-core-amd64-generic-${VERSION}.efi
UPGRADE_IMAGE=ttl.sh/kairos-uki-tests/upgrade-image
EFI_FILE=$PWD/v3.0.0-alpha1.efi

mkdir upgrade-image
mkdir -p upgrade-image/loader/entries
mkdir -p upgrade-image/EFI/kairos/

cp -rfv $EFI_FILE upgrade-image/EFI/kairos/${UKI}

# default @saved
cat <<EOF > upgrade-image/loader/loader.conf
default kairos-$VERSION.conf
timeout 5
console-mode max
editor no
EOF
docker push $CONTAINER_IMAGE_NAME
```

cat <<EOF > upgrade-image/loader/entries/kairos-$VERSION.conf
title Kairos $VERSION
efi /EFI/kairos/$UKI
version $VERSION
EOF
{{% alert title="Upgrades with Kubernetes" %}}

cd upgrade-image
docker build -t $UPGRADE_IMAGE -<<DOCKER
FROM scratch
COPY . /
DOCKER
In order to upgrade with Kubernetes using system upgrade controller plans you can use the image used to generate the installable medium, and use it as a base image for the upgrade image.
When invoking `kairos-agent` in the plan however, you need to specify the `--source` flag to point to the image that contains the UKI file.

docker push $UPGRADE_IMAGE
```
{{% /alert %}}

0 comments on commit 0a4afc2

Please sign in to comment.