Remove CoreOS image folder

This commit is contained in:
Malte Poll 2022-10-13 10:57:01 +02:00 committed by Malte Poll
parent 26fdfa4bee
commit 24f3371cf6
99 changed files with 0 additions and 686 deletions

View file

@ -1,170 +0,0 @@
SRC_PATH = $(CURDIR)
BASE_PATH ?= $(SRC_PATH)
DEPENDENCIES ?= $(BASE_PATH)/dependencies
COREOS_BUILD_PATH ?= $(BASE_PATH)/build
OVERRIDES ?= $(COREOS_BUILD_PATH)/overrides
OVERRIDES_RPM ?= $(OVERRIDES)/rpm
OVERRIDES_ROOTFS ?= $(OVERRIDES)/rootfs
BOOTSTRAPPER_OVERRIDE_PATH ?= $(OVERRIDES_ROOTFS)/usr/bin/bootstrapper
KERNEL_RPM ?= $(OVERRIDES_RPM)/kernel.rpm
KERNEL_CORE_RPM ?= $(OVERRIDES_RPM)/kernel-core.rpm
KERNEL_MODULES_RPM ?= $(OVERRIDES_RPM)/kernel-modules.rpm
OVERRIDE_KERNEL ?= n
KERNEL_RPM_URL ?= "https://kojipkgs.fedoraproject.org/packages/kernel/5.17.0/0.rc3.89.fc36/x86_64/kernel-5.17.0-0.rc3.89.fc36.x86_64.rpm"
KERNEL_CORE_RPM_URL ?= "https://kojipkgs.fedoraproject.org/packages/kernel/5.17.0/0.rc3.89.fc36/x86_64/kernel-core-5.17.0-0.rc3.89.fc36.x86_64.rpm"
KERNEL_MODULES_RPM_URL ?= "https://kojipkgs.fedoraproject.org/packages/kernel/5.17.0/0.rc3.89.fc36/x86_64/kernel-modules-5.17.0-0.rc3.89.fc36.x86_64.rpm"
DOWNLOAD_BOOTSTRAPPER ?= n
BOOTSTRAPPER_BINARY ?= $(BASE_PATH)/../build/bootstrapper
DISK_MAPPER_BINARY ?= $(BASE_PATH)/../build/disk-mapper
DISK_MAPPER_OVERRIDE_PATH ?= $(OVERRIDES_ROOTFS)/usr/sbin/disk-mapper
IMAGES_PATH ?= $(BASE_PATH)/images
CONTAINER_ENGINE ?= podman
COSA_BUILDDIR ?= $(BASE_PATH)/../3rdparty/coreos-assembler
COSA_ENV ?= $(BASE_PATH)/$(CONTAINER_ENGINE).env
COSA_INIT_REPO ?= "https://github.com/edgelesssys/constellation-fedora-coreos-config"
COSA_INIT_BRANCH ?= "main"
COSA_LOCKFILE ?= $(BASE_PATH)/cosa.lock
NETRC ?= ~/.netrc
GCP_PROJECT ?= constellation-images
GCP_BUCKET ?= constellation-images
GCP_IMAGE_FAMILY ?= constellation
GCP_IMAGE_NAME ?= constellation-coreos
GCP_IMAGE_FILENAME ?= $(GCP_IMAGE_NAME)_gcp.tar.gz
GCP_IMAGE_PATH ?= $(IMAGES_PATH)/$(GCP_IMAGE_FILENAME)
GCP_REGION ?= europe-west3
AZURE_IMAGE_NAME ?= constellation-coreos
AZURE_IMAGE_FILENAME ?= $(AZURE_IMAGE_NAME)_azure.vhd
AZURE_IMAGE_PATH ?= $(IMAGES_PATH)/$(AZURE_IMAGE_FILENAME)
AZURE_RESOURCE_GROUP_NAME ?= CONSTELLATION-IMAGES
AZURE_REGION ?= northeurope
AZURE_REPLICATION_REGIONS ?= northeurope eastus westeurope westus
AZURE_GALLERY_NAME ?= Constellation
AZURE_IMAGE_DEFINITION ?= $(AZURE_IMAGE_NAME)
AZURE_IMAGE_OFFER ?= $(AZURE_IMAGE_DEFINITION)
AZURE_IMAGE_VERSION ?= 0.0.1
AZURE_PUBLISHER ?= edgelesssys
AZURE_SKU ?= constellation-coreos
-include $(CURDIR)/config.mk
.PHONY: clean all kernel coreos run shell cosa-init cosa-fetch images image-gcp upload-gcp image-azure upload-azure-non-cvm $(BOOTSTRAPPER_OVERRIDE_PATH) $(DISK_MAPPER_OVERRIDE_PATH)
SHELL := /bin/bash
all: coreos images
ifeq ($(DOWNLOAD_BOOTSTRAPPER), y)
$(BOOTSTRAPPER_BINARY):
wget -q $(BOOTSTRAPPER_URL) -O $@
endif
$(BOOTSTRAPPER_OVERRIDE_PATH): $(BOOTSTRAPPER_BINARY) | cosa-init
mkdir -p $(COREOS_BUILD_PATH)/overrides/rootfs/usr/bin
cp $(BOOTSTRAPPER_BINARY) $@
chmod +x $@
$(DISK_MAPPER_OVERRIDE_PATH): $(DISK_MAPPER_BINARY) | cosa-init
mkdir -p $(COREOS_BUILD_PATH)/overrides/rootfs/usr/sbin
cp $(DISK_MAPPER_BINARY) $@
chmod +x $@
cosa-image:
-make -j 1 -C $(COSA_BUILDDIR) clean
make -j 1 -C $(COSA_BUILDDIR)
cosa-init:
mkdir -p $(COREOS_BUILD_PATH)
-flock $(COSA_LOCKFILE) -c '. $(COSA_ENV) && cd $(COREOS_BUILD_PATH) && NETRC=$(NETRC) cosa init --branch $(COSA_INIT_BRANCH) $(COSA_INIT_REPO)'
cosa-fetch: cosa-init kernel $(BOOTSTRAPPER_OVERRIDE_PATH) $(DISK_MAPPER_OVERRIDE_PATH)
flock $(COSA_LOCKFILE) -c '. $(COSA_ENV) && cd $(COREOS_BUILD_PATH) && NETRC=$(NETRC) cosa fetch'
coreos: cosa-fetch $(BOOTSTRAPPER_OVERRIDE_PATH) $(DISK_MAPPER_OVERRIDE_PATH)
flock $(COSA_LOCKFILE) -c '. $(COSA_ENV) && cd $(COREOS_BUILD_PATH) && NETRC=$(NETRC) cosa build'
run: $(BOOTSTRAPPER_OVERRIDE_PATH) $(DISK_MAPPER_OVERRIDE_PATH)
flock $(COSA_LOCKFILE) -c '. $(COSA_ENV) && cd $(COREOS_BUILD_PATH) && NETRC=$(NETRC) cosa run --devshell-console'
shell: $(BOOTSTRAPPER_OVERRIDE_PATH) $(DISK_MAPPER_OVERRIDE_PATH)
flock $(COSA_LOCKFILE) -c '. $(COSA_ENV) && cd $(COREOS_BUILD_PATH) && NETRC=$(NETRC) cosa shell'
$(GCP_IMAGE_PATH): coreos
flock $(COSA_LOCKFILE) -c '. $(COSA_ENV) && cd $(COREOS_BUILD_PATH) && NETRC=$(NETRC) cosa buildextend-gcp'
cp $(COREOS_BUILD_PATH)/builds/latest/x86_64/fedora-coreos-*.dev.*-gcp.x86_64.tar.gz $@
$(BASE_PATH)/dm-verity/recalculate-dm-verity.sh gcp $@
$(AZURE_IMAGE_PATH): coreos
flock $(COSA_LOCKFILE) -c '. $(COSA_ENV) && cd $(COREOS_BUILD_PATH) && NETRC=$(NETRC) cosa buildextend-azure'
cp $(COREOS_BUILD_PATH)/builds/latest/x86_64/fedora-coreos-*.dev.*-azure.x86_64.vhd $@
$(BASE_PATH)/dm-verity/recalculate-dm-verity.sh azure $@
images: image-gcp image-azure
image-gcp: $(GCP_IMAGE_PATH)
upload-gcp: $(GCP_IMAGE_PATH)
-gsutil mb -l $(GCP_REGION) gs://$(GCP_BUCKET)
gsutil pap set enforced gs://$(GCP_BUCKET)
gsutil cp $(GCP_IMAGE_PATH) gs://$(GCP_BUCKET)
gcloud compute images create $(GCP_IMAGE_NAME) \
--family $(GCP_IMAGE_FAMILY) \
--source-uri=gs://$(GCP_BUCKET)/$(GCP_IMAGE_FILENAME) \
--guest-os-features=GVNIC,SEV_CAPABLE,VIRTIO_SCSI_MULTIQUEUE,UEFI_COMPATIBLE \
--labels=bootstrapper-sha1=$$(shasum $(BOOTSTRAPPER_OVERRIDE_PATH) | cut -d " " -f 1),bootstrapper-sha512=$$(sha512sum $(BOOTSTRAPPER_OVERRIDE_PATH) | cut -d " " -f 1 | cut -c-63) \
--project $(GCP_PROJECT)
gcloud compute images add-iam-policy-binding $(GCP_IMAGE_NAME) \
--project $(GCP_PROJECT) \
--member='allAuthenticatedUsers' \
--role='roles/compute.imageUser'
gsutil rm gs://$(GCP_BUCKET)/$(GCP_IMAGE_FILENAME)
image-azure: $(AZURE_IMAGE_PATH)
# reference: https://docs.microsoft.com/en-us/azure/virtual-machines/linux/disks-upload-vhd-to-managed-disk-cli
# reference: https://docs.microsoft.com/en-us/azure/virtual-machines/linux/upload-vhd
# reference: https://docs.microsoft.com/en-us/azure/virtual-machines/image-version
upload-azure: $(AZURE_IMAGE_PATH)
$(eval SIZE := $(shell wc -c $(AZURE_IMAGE_PATH) | cut -d " " -f1))
@echo "creating disk of size $(SIZE)"
az disk create -n $(AZURE_IMAGE_NAME) -g $(AZURE_RESOURCE_GROUP_NAME) -l $(AZURE_REGION) --hyper-v-generation V2 --os-type Linux --for-upload --upload-size-bytes $(SIZE) --sku standard_lrs
@echo "waiting for disk to be created"
az disk wait --created -n $(AZURE_IMAGE_NAME) -g $(AZURE_RESOURCE_GROUP_NAME)
@echo "created disk $(AZURE_IMAGE_NAME)"
az disk list --output table --query "[?name == '$(AZURE_IMAGE_NAME)' && resourceGroup == '$(AZURE_RESOURCE_GROUP_NAME)']"
@echo "Granting temporary write access on disk $(AZURE_IMAGE_NAME)"
@echo "Copying $(AZURE_IMAGE_PATH) to disk $(AZURE_IMAGE_NAME)"
azcopy copy "$(AZURE_IMAGE_PATH)" "$$(az disk grant-access -n $(AZURE_IMAGE_NAME) -g $(AZURE_RESOURCE_GROUP_NAME) --access-level Write --duration-in-seconds 86400 | jq -r .accessSas)" --blob-type PageBlob
@echo "Revoking write access"
az disk revoke-access -n $(AZURE_IMAGE_NAME) -g $(AZURE_RESOURCE_GROUP_NAME)
az image create -g $(AZURE_RESOURCE_GROUP_NAME) -l $(AZURE_REGION) -n $(AZURE_IMAGE_NAME) --hyper-v-generation V2 --os-type Linux --source "$$(az disk list --query "[?name == '$(AZURE_IMAGE_NAME)' && resourceGroup == '$(AZURE_RESOURCE_GROUP_NAME)'] | [0].id" --output json | jq -r)"
@echo "Create shared image gallery (if it does not exist yet)"
-az sig create -l $(AZURE_REGION) --gallery-name $(AZURE_GALLERY_NAME) --resource-group $(AZURE_RESOURCE_GROUP_NAME)
@echo "Create image definition (if it does not exist yet)"
-az sig image-definition create --resource-group $(AZURE_RESOURCE_GROUP_NAME) -l $(AZURE_REGION) --gallery-name $(AZURE_GALLERY_NAME) --gallery-image-definition $(AZURE_IMAGE_DEFINITION) --publisher $(AZURE_PUBLISHER) --offer $(AZURE_IMAGE_OFFER) --sku $(AZURE_SKU) --os-type Linux --os-state generalized --hyper-v-generation V2 --features SecurityType=TrustedLaunch
az sig image-version create --resource-group $(AZURE_RESOURCE_GROUP_NAME) -l $(AZURE_REGION) --gallery-name $(AZURE_GALLERY_NAME) --gallery-image-definition $(AZURE_IMAGE_DEFINITION) --gallery-image-version $(AZURE_IMAGE_VERSION) --target-regions $(AZURE_REPLICATION_REGIONS) --replica-count 1 --managed-image "$$(az image list --query "[?name == '$(AZURE_IMAGE_NAME)' && resourceGroup == '$(AZURE_RESOURCE_GROUP_NAME)'] | [0].id" --output json | jq -r)"
@echo "Create CVM image definition (if it does not exist yet)"
-az sig image-definition create --resource-group $(AZURE_RESOURCE_GROUP_NAME) -l $(AZURE_REGION) --gallery-name $(AZURE_GALLERY_NAME)_CVM --gallery-image-definition $(AZURE_IMAGE_DEFINITION) --publisher $(AZURE_PUBLISHER) --offer $(AZURE_IMAGE_OFFER) --sku $(AZURE_SKU) --os-type Linux --os-state generalized --hyper-v-generation V2 --features SecurityType=ConfidentialVmSupported
az sig image-version create --resource-group $(AZURE_RESOURCE_GROUP_NAME) -l $(AZURE_REGION) --gallery-name $(AZURE_GALLERY_NAME)_CVM --gallery-image-definition $(AZURE_IMAGE_DEFINITION) --gallery-image-version $(AZURE_IMAGE_VERSION) --target-regions $(AZURE_REPLICATION_REGIONS) --replica-count 1 --managed-image "$$(az image list --query "[?name == '$(AZURE_IMAGE_NAME)' && resourceGroup == '$(AZURE_RESOURCE_GROUP_NAME)'] | [0].id" --output json | jq -r)"
@echo "Cleaning up resources"
az image delete --resource-group $(AZURE_RESOURCE_GROUP_NAME) -n $(AZURE_IMAGE_NAME)
az disk delete --resource-group $(AZURE_RESOURCE_GROUP_NAME) -n $(AZURE_IMAGE_NAME) --yes
ifeq ($(OVERRIDE_KERNEL), y)
kernel: $(KERNEL_RPM) $(KERNEL_CORE_RPM) $(KERNEL_MODULES_RPM)
$(KERNEL_RPM): | cosa-init
-mkdir -p $$(dirname $@)
wget -q $(KERNEL_RPM_URL) -O $@
$(KERNEL_CORE_RPM): | cosa-init
-mkdir -p $$(dirname $@)
wget -q $(KERNEL_CORE_RPM_URL) -O $@
$(KERNEL_MODULES_RPM): | cosa-init
-mkdir -p $$(dirname $@)
wget -q $(KERNEL_MODULES_RPM_URL) -O $@
else
kernel:
endif
clean:
-rm $(COSA_LOCKFILE)
-rm $(IMAGES_PATH)/*
-rm -r $(COREOS_BUILD_PATH)
mkdir -p $(COREOS_BUILD_PATH)

View file

@ -1,50 +0,0 @@
# Constellation-OS Assembler
This container image uses [coreos assembler](https://coreos.github.io/coreos-assembler/) as a base (`quay.io/coreos-assembler/coreos-assembler`) to facilitate a build environment for the Constellation-OS.
The root filesystem takes its contents (OSTree) from [constellation-fedora-coreos-config](https://github.com/edgelesssys/constellation-fedora-coreos-config).
And the Constellation-OS Assembler can be pulled from ghcr.io/edgelesssys/constellation-coreos-assembler
## Setup
Prerequisites: `podman` and `qemu-kvm` are installed, nested virtualization is enabled.
Make sure your user is allowed read and write access on `/dev/kvm`.
If the device is not mounted in the container try the following command, and restart the container:
``` shell
sudo chmod 666 /dev/kvm
```
## Using the Assembler to create a bootable operating system
1. Create the assembler image as described [here](#creating-the-assembler-image)
2. Source the `fcos/.env` file to enable the `cosa` bash alias:
```
source fcos/.env
```
3. Set the `BOOTSTRAPPER_BINARY` environment variable to a path of the compiled bootstrapper binary. It will be mounted in the cosa container and copied into the resulting coreos image.
```
BOOTSTRAPPER_BINARY="/path/to/bootstrapper"
```
4. Go into the build folder and initialize cosa:
```
cd fcos/build
cosa init https://github.com/edgelesssys/constellation-fedora-coreos-config
cosa fetch
```
5. Build the OS image:
```
cosa build
```
6. Create an image for a cloud provider
```
cosa buildextend-gcp
cosa buildextend-aws
cosa buildextend-azure
[...]
```
## Using a locally checked out git repo of the coreos-config during development
Simply set the environment variable `COREOS_ASSEMBLER_CONFIG_GIT` to the local folder and perform the rest of the steps as usual:
```
COREOS_ASSEMBLER_CONFIG_GIT=/path/to/constellation-fedora-coreos-config
```

View file

@ -1,182 +0,0 @@
#!/usr/bin/env bash
set -xeuo pipefail
# Show progress on pipes if `pv` is installed
# Otherwise use plain cat
if ! command -v pv &> /dev/null
then
PV="cat"
else
PV="pv"
fi
mount_partition () {
local partition_file=$1
local mountpoint=$2
# second, try to mount as current user
if mount -o loop "${partition_file}" "${mountpoint}"; then
return
fi
# third, try to mount with sudo
sudo mount -o loop "${partition_file}" "${mountpoint}"
# temporarily change ownership of partition files
sudo chown -R "${USER}:${USER}" "${mountpoint}"
}
umount_partition () {
sync
local mountpoint=$1
# second, try to umount as current user
if umount "${mountpoint}"; then
return
fi
# third, try to umount with sudo
# repair ownership of partition files
sudo chown -R root:root "${mountpoint}"
sudo umount "${mountpoint}"
}
# Unpacks finished cloud provider image to recalculate dm-verity hash
unpack () {
local cloudprovider=$1
local packed_image=$2
local unpacked_image=$3
case $cloudprovider in
gcp)
echo "📤 Unpacking GCP image..."
"${PV}" "$packed_image" | tar -xzf - -O > "$unpacked_image"
echo " Unpacked image stored in ${unpacked_image}"
;;
azure)
echo "📤 Unpacking Azure image..."
qemu-img convert -p -f vpc -O raw "$packed_image" "$unpacked_image"
echo " Unpacked image stored in ${unpacked_image}"
;;
*)
echo "unknown cloud provider"
exit 1
;;
esac
}
get_part_offset () {
local unpacked_image=$1
local part_number=$2
local offset
offset=$(parted -s "${unpacked_image}" unit s print | sed 's/^ //g' | grep "^${part_number}" | tr -s ' ' | cut -d ' ' -f2)
local offset=${offset::-1}
echo "${offset}"
}
get_part_size () {
local unpacked_image=$1
local part_number=$2
local size
size=$(parted -s "${unpacked_image}" unit s print | sed 's/^ //g' | grep "^${part_number}" | tr -s ' ' | cut -d ' ' -f4)
local size=${size::-1}
echo "${size}"
}
extract_partition () {
local unpacked_image=$1
local part_number=$2
local extracted_partition_path=$3
local part_offset
part_offset=$(get_part_offset "${unpacked_image}" "${part_number}")
local part_size
part_size=$(get_part_size "${unpacked_image}" "${part_number}")
dd status=progress "if=${unpacked_image}" "of=${extracted_partition_path}" bs=512 "skip=${part_offset}" "count=${part_size}" 2>/dev/null
}
overwrite_partition () {
local unpacked_image=$1
local part_number=$2
local extracted_partition_path=$3
local part_offset
part_offset=$(get_part_offset "${unpacked_image}" "${part_number}")
local part_size
part_size=$(get_part_size "${unpacked_image}" "${part_number}")
dd status=progress conv=notrunc "if=${extracted_partition_path}" "of=${unpacked_image}" bs=512 "seek=${part_offset}" "count=${part_size}" 2>/dev/null
}
update_verity () {
local tmp_dir=$1
local raw_image=$2
local boot_mountpoint=${tmp_dir}/boot.mount
local boot_partition=${tmp_dir}/part_boot.raw
local root_partition=${tmp_dir}/part_root.raw
local hashtree_partition=${tmp_dir}/part_hashtree.raw
echo "⬅️ Extracting partitions..."
extract_partition "${raw_image}" 3 "${boot_partition}"
extract_partition "${raw_image}" 4 "${root_partition}"
extract_partition "${raw_image}" 5 "${hashtree_partition}"
# recalculate verity hashtree
veritysetup_out=$(veritysetup format "${root_partition}" "${hashtree_partition}")
roothash=$(echo "${veritysetup_out}" | grep 'Root hash:' | sed --expression='s/Root hash:\s*//g')
echo "🧮 Recalculated dm-verity hashtree with roothash ${roothash}"
# update bootloader kernel cmdline
mkdir -p "${boot_mountpoint}"
mount_partition "${boot_partition}" "${boot_mountpoint}"
sed -i -r "s/verity.sysroot=[[:xdigit:]]+/verity.sysroot=${roothash}/g" "${boot_mountpoint}/loader.1/entries/ostree-1-fedora-coreos.conf"
echo "✍️ Updated bootloader kernel cmdline to include new dm-verity roothash: $(grep '^options ' "${boot_mountpoint}"/loader.1/entries/ostree-1-fedora-coreos.conf)"
umount_partition "${boot_mountpoint}"
rmdir "${boot_mountpoint}"
echo "➡️ Overwriting partitions..."
overwrite_partition "${raw_image}" 3 "${boot_partition}"
overwrite_partition "${raw_image}" 5 "${hashtree_partition}"
}
repack () {
local cloudprovider=$1
local unpacked_image=$2
local packed_image=$3
local unpacked_image_dir
unpacked_image_dir=$(dirname "${unpacked_image}")
local unpacked_image_filename
unpacked_image_filename=$(basename "${unpacked_image}")
local tmp_tar_file
tmp_tar_file=$(mktemp -t verity.XXXXXX.tar)
case $cloudprovider in
gcp)
echo "📥 Repacking GCP image..."
tar --owner=0 --group=0 -C "${unpacked_image_dir}" -Sch --format=oldgnu -f "${tmp_tar_file}" "${unpacked_image_filename}"
"${PV}" "${tmp_tar_file}" | pigz -9c > "${packed_image}"
rm "${tmp_tar_file}"
echo " Repacked image stored in ${packed_image}"
;;
azure)
echo "📥 Repacking Azure image..."
qemu-img convert -p -f raw -O vpc -o force_size,subformat=fixed "${unpacked_image}" "$packed_image"
echo " Repacked image stored in ${packed_image}"
;;
*)
echo "unknown cloud provider"
exit 1
;;
esac
}
echo "🔁 Recalculating dm-verity hashtree 🌳"
tmp_dir=$(mktemp -d -t verity-XXXXXXXXXX)
raw_image="${tmp_dir}/disk.raw"
unpack "$1" "$2" "${raw_image}"
update_verity "${tmp_dir}" "${raw_image}"
repack "$1" "${raw_image}" "${2}"
rm -r "${tmp_dir}"

View file

@ -1,15 +0,0 @@
cosa() {
env | grep COREOS_ASSEMBLER
local -r COREOS_ASSEMBLER_CONTAINER_LATEST="localhost/coreos-assembler"
test -t 1 && USE_TTY="-ti"
set -x
docker run --rm ${USE_TTY} --security-opt label=disable --privileged \
-v ${PWD}:/srv/ --device /dev/kvm --device /dev/fuse \
--tmpfs /tmp -v /var/tmp:/var/tmp --name constellation-cosa \
-v ${NETRC}:/home/builder/.netrc:ro \
${COREOS_ASSEMBLER_CONFIG_GIT:+-v $COREOS_ASSEMBLER_CONFIG_GIT:/srv/src/config/:ro} \
${COREOS_ASSEMBLER_GIT:+-v $COREOS_ASSEMBLER_GIT/src/:/usr/lib/coreos-assembler/:ro} \
${COREOS_ASSEMBLER_CONTAINER_RUNTIME_ARGS} \
${COREOS_ASSEMBLER_CONTAINER:-$COREOS_ASSEMBLER_CONTAINER_LATEST} "$@"
rc=$?; set +x; return $rc
}

View file

@ -1,208 +0,0 @@
# Fedora CoreOS Assembler
We use the [Fedora CoreOS Assembler](https://coreos.github.io/coreos-assembler/) to build the base image for Constellation nodes.
## Setup
Prerequisites: `podman` and `qemu-kvm` are installed, nested virtualization is enabled.
Make sure your user is allowed read and write access on `/dev/kvm`.
If the device is not mounted in the container try the following command, and restart the container:
``` shell
sudo chmod 666 /dev/kvm
```
* Pull the assembler container image
``` shell
podman pull quay.io/coreos-assembler/coreos-assembler
```
* Create a working directory on your host system
``` shell
mkdir fcos && cd fcos
```
* Set up a bash alias
Add the following to your `.bashrc` to easily start the image assembler using `cosa`:
``` bash
cosa() {
env | grep COREOS_ASSEMBLER
local -r COREOS_ASSEMBLER_CONTAINER_LATEST="quay.io/coreos-assembler/coreos-assembler:latest"
if [[ -z ${COREOS_ASSEMBLER_CONTAINER} ]] && $(podman image exists ${COREOS_ASSEMBLER_CONTAINER_LATEST}); then
local -r cosa_build_date_str="$(podman inspect -f "{{.Created}}" ${COREOS_ASSEMBLER_CONTAINER_LATEST} | awk '{print $1}')"
local -r cosa_build_date="$(date -d ${cosa_build_date_str} +%s)"
if [[ $(date +%s) -ge $((cosa_build_date + 60*60*24*7)) ]] ; then
echo -e "\e[0;33m----" >&2
echo "The COSA container image is more that a week old and likely outdated." >&2
echo "You should pull the latest version with:" >&2
echo "podman pull ${COREOS_ASSEMBLER_CONTAINER_LATEST}" >&2
echo -e "----\e[0m" >&2
sleep 10
fi
fi
set -x
podman run --rm -ti --security-opt label=disable --privileged \
--uidmap=1000:0:1 --uidmap=0:1:1000 --uidmap 1001:1001:64536 \
-v ${PWD}:/srv/ --device /dev/kvm --device /dev/fuse \
--tmpfs /tmp -v /var/tmp:/var/tmp --name cosa \
${COREOS_ASSEMBLER_CONFIG_GIT:+-v $COREOS_ASSEMBLER_CONFIG_GIT:/srv/src/config/:ro} \
${COREOS_ASSEMBLER_GIT:+-v $COREOS_ASSEMBLER_GIT/src/:/usr/lib/coreos-assembler/:ro} \
${COREOS_ASSEMBLER_CONTAINER_RUNTIME_ARGS} \
${COREOS_ASSEMBLER_CONTAINER:-$COREOS_ASSEMBLER_CONTAINER_LATEST} "$@"
rc=$?; set +x; return $rc
}
```
* Run the builder
``` shell
cosa shell
```
* Initialize the build
``` shell
cosa init https://github.com/coreos/fedora-coreos-config
```
* Fetch metadata and packages
``` shell
cosa fetch
```
* Build a qemu VM image
``` shell
cosa build
```
Each build will create a new directory in `$PWD/builds/`, containing the generated OSTree commit and the qemu VM image.
* Run the image
``` shell
cosa run
```
## Customization
The CoreOS Assembler offers three main customization options:
* [`manifest.yaml`](https://coreos.github.io/coreos-assembler/working/#manifestyaml)
An rpm-ostree "manifest" or "treefile", primarily, a list of RPMs and their associated repositories.
See the rpm-ostree documentation for the [treefile format reference](https://coreos.github.io/rpm-ostree/treefile/)
* [`overlay.d/`](https://coreos.github.io/coreos-assembler/working/#overlayd)
A generic way to embed architecture-independent configuration and scripts by creating subdirectories in `overlay.d/`.
Each subdirectory is added to the OSTree commit in lexicographic order.
* [`image.yaml`](https://coreos.github.io/coreos-assembler/working/#imageyaml)
Configuration for the output disk images
Additionally, one may use [`overrides`](https://coreos.github.io/coreos-assembler/working/#using-overrides) to embed local RPMs from the build environment, that should not be pulled from a remote repository:
1. Package the binary as an RPM
2. Add any dependencies of the RPM to `manifest.yaml`
3. Run `cosa fetch` to prepare dependencies
4. Place the RPM in `overrides/rpm`
5. Add the name of your RPM to `manifest.yaml`
6. Run `cosa build`. Your RPM will be added to the final image.
Example: We want to build FCOS with our own kernel
1. Follow [Kernel Building](#kernel-building) to build the kernel
You should end up with at least three RPMs: `kernel`, `kernel-core`, `kernel-modules`.
`kernel` depends on `core` and `modules`, `modules` on `core`, and `core` on common FCOS packages (`bash`, `systemd`, etc.).
These dependencies should already be in the manifest.
2. Run `cosa fetch`
3. Place the kernel RPMs in `overrides/rpm`
`kernel`, `kernel-core`, `kernel-modules` should already be in the manifest (`src/config/manifests/bootable-rpm-ostree.yaml`)
4. Run `cosa build` to create the image
5. Test the image with `cosa run`
6. Run `cosa buildextend-gcp` and `cosa buildextend-azure` to additionaly create a VM image for GCP and Azure
## RPM packaging
If we want to make the most use of CoreOS assembler we should package our applications as RPM packages.
See [creating rpm packages](https://docs.fedoraproject.org/en-US/quick-docs/creating-rpm-packages/).
Brief overview of the required steps:
1. Create a directory with your source code or binary file
2. Add a <package>.spec file
Run the following command to create a spec file template that you can update with information about your package
``` shell
rpmdev-newspec <package>
```
3. Create the RPM
``` shell
fedpkg --release f35 local
```
## Kernel Building
See the [building a custom kernel](https://docs.fedoraproject.org/en-US/quick-docs/kernel/build-custom-kernel/) from the Fedora Project documentation.
The following assumes you are running on a current release of Fedora.
We have a Fedora 35 image available on GCP, make sure you have enough space available and the VM is capable to build the kernel in a reasonable time (e2-standard-8 takes ~2h to finish the build).
1. Install dependencies and clone the kernel
``` shell
sudo dnf install fedpkg fedora-packager rpmdevtools ncurses-devel pesign grubby qt3-devel libXi-devel gcc-c++
fedpkg clone -a kernel && cd kernel
sudo dnf builddep kernel.spec
```
Optionally install `ccache` to speed up rebuilds
``` shell
sudo dnf install ccache
```
2. Check out the kernel branch you want to base your build on
Each release has its own branch. E.g. to customize the kernel for Fedora 35, check out `origin/f35`. `rawhide` tracks the latest iteration, following closely behind the mainline kernel.
``` shell
git checkout origin/f35
git checkout -b custom-kernel
```
3. Customize buildid by chaning `# define buildid .local` to `%define buildid .<your_custom_id_here>` in `kernel.spec`
4. Apply your changes and patches to the kernel
5. Build the RPMs
This will take a while
``` shell
fedpkg local
```
The built kernel RPMs will be in `./x86_64/`
6. You can now use and install the kernel packages
``` shell
sudo dnf install --nogpgcheck ./x86_64/kernel-$version.rpm
```

View file

@ -1,45 +0,0 @@
# Cloud Providers
Custom CoreOS images created here can be uploaded to supported cloud providers. This documents contains information on how to manually spawn cloud provider instances using custom CoreOS images.
## GCP
```shell
gcloud compute instances create <INSTANCE_NAME> --zone=<ZONE> --machine-type=<MACHINE_TYPE> --image <IMAGE_NAME> --maintenance-policy=TERMINATE --confidential-compute --shielded-secure-boot --shielded-vtpm --shielded-integrity-monitoring --scopes=https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/trace.append
```
## Azure
Non-CVM:
```
az image list
# copy image id from output of previous command
az vm create --resource-group <RESOURCE_GROUP> --location <LOCATION> --name <INSTANCE_NAME> --os-type linux --public-ip-sku Standard --image <IMAGE_ID>
```
### Create Marketplace offer
- Upload a vhd and image to azure portal using the Makefile
- Create (or reuse) a `shared image gallery`:
- Create image gallery if it does not exist yet
- Search for "Azure compute galleries" in azure portal
- Click "create"
- Choose "constellation-images" resource group and pick a name, then click create
- Create a VM image definition
- Search for "Azure compute galleries" in azure portal and choose the created gallery
- Click "Create a VM image definition"
- OS type: Linux
- OS state: Generalized
- VM generation: Gen 2
- Publisher: EdgelessSystems
- Offer: constellation-coreos
- SKU: constellation-coreos
- Source image: Choose image uploaded using Makefile
- Create
- Create Marketplace offer (on https://partner.microsoft.com/)
- Navigate to marketplace offers overview (https://partner.microsoft.com/en-us/dashboard/marketplace-offers/overview)
- If you want to create a new version of an existing plan, skip this section
- Click "New offer" -> "Azure Virtual Machine"
- Choose an offer id and alias
- Create a new plan on "Plan overview" -> "Create new plan", choose a plan id and plan name
- In "Technical configuration", create a generation, choose "Azure shared image gallery" and select the image created earlier

View file

View file

View file

@ -1,5 +0,0 @@
mkosi.cache
mkosi.extra
pki
image.*
mkosi.output.*

View file

@ -1,54 +0,0 @@
SHELL = /bin/bash
SRC_PATH = $(CURDIR)
BASE_PATH ?= $(SRC_PATH)
BOOTSTRAPPER_BINARY ?= $(BASE_PATH)/../../build/bootstrapper
DISK_MAPPER_BINARY ?= $(BASE_PATH)/../../build/disk-mapper
PKI ?= $(BASE_PATH)/pki
MKOSI_EXTRA ?= $(BASE_PATH)/mkosi.extra
-include $(CURDIR)/config.mk
csps := qemu gcp azure
certs := $(PKI)/PK.cer $(PKI)/KEK.cer $(PKI)/db.cer
.PHONY: all clean inject-bins $(csps)
all: $(csps)
$(csps): %: mkosi.output.%/fedora~36/image.raw
mkosi.output.%/fedora~36/image.raw: mkosi.files/mkosi.%.conf inject-bins inject-certs
mkosi --config mkosi.files/mkosi.$*.conf build
secure-boot/signed-shim.sh $@
@if [ -n $(SUDO_UID) ] && [ -n $(SUDO_GID) ]; then \
chown -R $(SUDO_UID):$(SUDO_GID) mkosi.output.$*; \
fi
@echo "Image is ready: $@"
inject-bins:
mkdir -p $(MKOSI_EXTRA)/usr/bin
mkdir -p $(MKOSI_EXTRA)/usr/sbin
cp $(BOOTSTRAPPER_BINARY) $(MKOSI_EXTRA)/usr/bin/bootstrapper
cp $(DISK_MAPPER_BINARY) $(MKOSI_EXTRA)/usr/sbin/disk-mapper
inject-certs: $(certs)
# for auto enrollment using systemd-boot (not working yet)
mkdir -p "$(MKOSI_EXTRA)/boot/loader/keys/auto"
cp $(PKI)/{PK,KEK,db}.cer "$(MKOSI_EXTRA)/boot/loader/keys/auto"
cp $(PKI)/{MicWinProPCA2011_2011-10-19,MicCorUEFCA2011_2011-06-27,MicCorKEKCA2011_2011-06-24}.crt "$(MKOSI_EXTRA)/boot/loader/keys/auto"
cp $(PKI)/{PK,KEK,db}.esl "$(MKOSI_EXTRA)/boot/loader/keys/auto"
cp $(PKI)/{PK,KEK,db}.auth "$(MKOSI_EXTRA)/boot/loader/keys/auto"
# for manual enrollment using sbkeysync
mkdir -p $(MKOSI_EXTRA)/etc/secureboot/keys/{db,dbx,KEK,PK}
cp $(PKI)/db.auth "$(MKOSI_EXTRA)/etc/secureboot/keys/db/"
cp $(PKI)/KEK.auth "$(MKOSI_EXTRA)/etc/secureboot/keys/KEK/"
cp $(PKI)/PK.auth "$(MKOSI_EXTRA)/etc/secureboot/keys/PK/"
clean-cache:
rm -rf mkosi.cache/*
clean-%:
mkosi --config mkosi.files/mkosi.$*.conf clean
clean:
rm -rf mkosi.output.*
rm -rf $(MKOSI_EXTRA)
mkdir -p $(MKOSI_EXTRA)

View file

@ -1,187 +0,0 @@
## Setup
- Install mkosi (from git):
```sh
cd /tmp/
git clone https://github.com/systemd/mkosi
cd mkosi
tools/generate-zipapp.sh
cp builddir/mkosi /usr/local/bin/
```
- Install tools:
<details>
<summary>Ubuntu / Debian</summary>
```sh
sudo apt-get update
sudo apt-get install --assume-yes --no-install-recommends \
dnf \
systemd-container \
qemu-system-x86 \
qemu-utils \
ovmf \
e2fsprogs \
squashfs-tools \
efitools \
sbsigntool \
coreutils \
curl \
jq \
util-linux \
virt-manager
```
</details>
<details>
<summary>Fedora</summary>
```sh
sudo dnf install -y \
edk2-ovmf \
systemd-container \
qemu \
e2fsprogs \
squashfs-tools \
efitools \
sbsigntools \
coreutils \
curl \
jq \
util-linux \
virt-manager
```
</details>
- Prepare secure boot PKI (see `secure-boot/genkeys.sh`)
## Build
```sh
# OPTIONAL: to create a debug image, export the following line
# export BOOTSTRAPPER_BINARY=$(realpath ${PWD}/../../build/debugd)
# OPTIONAL: specify path to secure boot PKI
# export PKI=/path/to/pki/folder
sudo make -j $(nproc)
```
Raw images will be placed in `mkosi.output.<CSP>/fedora~36/image.raw`.
## Prepare Secure Boot
The generated images are partially signed by Microsoft ([shim loader](https://github.com/rhboot/shim)), and partially signed by Edgeless Systems (systemd-boot and unified kernel images consisting of the linux kernel, initramfs and kernel commandline).
For QEMU and Azure, you can pre-generate the NVRAM variables for secure boot. This is not necessary for GCP, as you can specify secure boot parameters via the GCP API on image creation.
<details>
<summary>libvirt / QEMU / KVM</summary>
```sh
secure-boot/generate_nvram_vars.sh mkosi.output.qemu/fedora~36/image.raw
```
</details>
<details>
<summary><a id="azure-secure-boot">Azure</a></summary>
These steps only have to performed once for a fresh set of secure boot certificates.
VMGS blobs for testing and release images already exist.
First, create a disk without embedded MOK EFI variables.
```sh
# set these variables
export AZURE_SECURITY_TYPE=ConfidentialVM # or TrustedLaunch
export AZURE_RESOURCE_GROUP_NAME= # e.g. "constellation-images"
export AZURE_REGION=northeurope
export AZURE_DISK_NAME=constellation-$(date +%s)
export AZURE_SNAPSHOT_NAME=${AZURE_DISK_NAME}
export AZURE_RAW_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.raw
export AZURE_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.vhd
export AZURE_VMGS_FILENAME=${AZURE_SECURITY_TYPE}.vmgs
export BLOBS_DIR=${PWD}/blobs
upload/pack.sh azure "${AZURE_RAW_IMAGE_PATH}" "${AZURE_IMAGE_PATH}"
upload/upload_azure.sh --disk-name "${AZURE_DISK_NAME}-setup-secure-boot" ""
secure-boot/azure/launch.sh -n "${AZURE_DISK_NAME}-setup-secure-boot" -d --secure-boot true --disk-name "${AZURE_DISK_NAME}-setup-secure-boot"
```
Ignore the running launch script and connect to the serial console once available.
The console shows the message "Verification failed: (0x1A) Security Violation". You can import the MOK certificate via the UEFI shell:
Press OK, then ENTER, then "Enroll key from disk".
Select the following key: `/EFI/loader/keys/auto/db.cer`.
Press Continue, then choose "Yes" to the question "Enroll the key(s)?".
Choose reboot.
Extract the VMGS from the running VM (this includes the MOK EFI variables) and delete the VM:
```sh
secure-boot/azure/extract_vmgs.sh --name "${AZURE_DISK_NAME}-setup-secure-boot"
secure-boot/azure/delete.sh --name "${AZURE_DISK_NAME}-setup-secure-boot"
```
</details>
## Upload to CSP
<details>
<summary>GCP</summary>
- Install `gcloud` and `gsutil` (see [here](https://cloud.google.com/sdk/docs/install))
- Login to GCP (see [here](https://cloud.google.com/sdk/docs/authorizing))
- Prepare secure boot PKI (see `secure-boot/genkeys.sh`)
```sh
# set these variables
export GCP_IMAGE_FAMILY= # e.g. "constellation"
export GCP_IMAGE_NAME= # e.g. "constellation-v1.0.0"
export PKI=${PWD}/pki
export GCP_PROJECT=constellation-images
export GCP_REGION=europe-west3
export GCP_BUCKET=constellation-images
export GCP_RAW_IMAGE_PATH=${PWD}/mkosi.output.gcp/fedora~36/image.raw
export GCP_IMAGE_FILENAME=$(date +%s).tar.gz
export GCP_IMAGE_PATH=${PWD}/mkosi.output.gcp/fedora~36/image.tar.gz
upload/pack.sh gcp ${GCP_RAW_IMAGE_PATH} ${GCP_IMAGE_PATH}
upload/upload_gcp.sh
```
</details>
<details>
<summary>Azure</summary>
- Install `az` and `azcopy` (see [here](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli))
- Login to Azure (see [here](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli))
- Prepare secure boot PKI (see `secure-boot/genkeys.sh`)
- [Prepare virtual machine guest state (VMGS) with customized NVRAM or use existing VMGS blob](#azure-secure-boot)
```sh
# set these variables
export AZURE_GALLERY_NAME= # e.g. "Constellation"
export AZURE_IMAGE_DEFINITION= # e.g. "constellation"
export AZURE_IMAGE_VERSION= # e.g. "1.0.0"
export AZURE_VMGS_PATH= # e.g. "path/to/ConfidentialVM.vmgs"
export AZURE_SECURITY_TYPE=ConfidentialVM # or TrustedLaunch
export AZURE_RESOURCE_GROUP_NAME=constellation-images
export AZURE_REGION=northeurope
export AZURE_REPLICATION_REGIONS="northeurope eastus westeurope westus"
export AZURE_IMAGE_OFFER=constellation
export AZURE_SKU=constellation
export AZURE_PUBLISHER=edgelesssys
export AZURE_DISK_NAME=constellation-$(date +%s)
export AZURE_RAW_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.raw
export AZURE_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.vhd
upload/pack.sh azure "${AZURE_RAW_IMAGE_PATH}" "${AZURE_IMAGE_PATH}"
upload/upload_azure.sh -g --disk-name "${AZURE_DISK_NAME}" "${AZURE_VMGS_PATH}"
```
</details>

View file

@ -1,21 +0,0 @@
#!/usr/bin/env python
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
# This script calculates the authentihash of a PE / EFI binary.
# Install prerequisites:
# pip install lief
import sys
import lief
def authentihash(filename):
pe = lief.parse(filename)
return pe.authentihash(lief.PE.ALGORITHMS.SHA_256)
if __name__ == '__main__':
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <filename>")
sys.exit(1)
print(authentihash(sys.argv[1]).hex())

View file

@ -1,29 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
# This script contains shared functions for pcr calculation.
pcr_extend() {
local CURRENT_PCR="$1"
local EXTEND_WITH="$2"
local HASH_FUNCTION="$3"
( echo -n "$CURRENT_PCR" | xxd -r -p ; echo -n "$EXTEND_WITH" | xxd -r -p; ) | ${HASH_FUNCTION} | cut -d " " -f 1
}
extract () {
local image="$1"
local path="$2"
local output="$3"
sudo systemd-dissect --copy-from "${image}" "${path}" "${output}"
}
mktempdir () {
mktemp -d
}
cleanup () {
local dir="$1"
rm -rf "${dir}"
}

View file

@ -1,6 +0,0 @@
{
"pcr11": "0000000000000000000000000000000000000000000000000000000000000000",
"pcr12": "0000000000000000000000000000000000000000000000000000000000000000",
"pcr13": "0000000000000000000000000000000000000000000000000000000000000000",
"pcr15": "0000000000000000000000000000000000000000000000000000000000000000"
}

View file

@ -1,72 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
# This script is used to precalculate the PCR[4] value for a Constellation OS image.
# Usage: precalculate_pcr_4.sh <path to image> <path to output file>
set -euo pipefail
source "$(dirname "$0")/measure_util.sh"
ev_efi_action_sha256=3d6772b4f84ed47595d72a2c4c5ffd15f5bb72c7507fe26f2aaee2c69d5633ba
ev_efi_separator_sha256=df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119
authentihash () {
local path="$1"
"$(dirname "$0")/extract_authentihash.py" "${path}"
}
write_output () {
local out="$1"
cat > "${out}" <<EOF
{
"pcr4": "${expected_pcr_4}",
"efistages": [
{
"name": "shim",
"sha256": "${shim_authentihash}"
},
{
"name": "systemd-boot",
"sha256": "${sd_boot_authentihash}"
},
{
"name": "uki",
"sha256": "${uki_authentihash}"
}
]
}
EOF
}
DIR=$(mktempdir)
trap 'cleanup "${DIR}"' EXIT
extract "$1" "/efi/EFI/BOOT/BOOTX64.EFI" "${DIR}/01-shim.efi"
extract "$1" "/efi/EFI/BOOT/grubx64.efi" "${DIR}/02-sd-boot.efi"
extract "$1" "/efi/EFI/Linux" "${DIR}/uki"
sudo chown -R "$USER:$USER" "${DIR}/uki"
cp ${DIR}/uki/*.efi "${DIR}/03-uki.efi"
shim_authentihash=$(authentihash "${DIR}/01-shim.efi")
sd_boot_authentihash=$(authentihash "${DIR}/02-sd-boot.efi")
uki_authentihash=$(authentihash "${DIR}/03-uki.efi")
cleanup "${DIR}"
expected_pcr_4=0000000000000000000000000000000000000000000000000000000000000000
expected_pcr_4=$(pcr_extend "${expected_pcr_4}" "${ev_efi_action_sha256}" "sha256sum")
expected_pcr_4=$(pcr_extend "${expected_pcr_4}" "${ev_efi_separator_sha256}" "sha256sum")
expected_pcr_4=$(pcr_extend "${expected_pcr_4}" "${shim_authentihash}" "sha256sum")
expected_pcr_4=$(pcr_extend "${expected_pcr_4}" "${sd_boot_authentihash}" "sha256sum")
expected_pcr_4=$(pcr_extend "${expected_pcr_4}" "${uki_authentihash}" "sha256sum")
echo "Authentihashes:"
echo "Stage 1 shim: ${shim_authentihash}"
echo "Stage 2 sd-boot: ${sd_boot_authentihash}"
echo "Stage 3 Unified Kernel Image (UKI): ${uki_authentihash}"
echo ""
echo "Expected PCR[4]: ${expected_pcr_4}"
echo ""
write_output "$2"

View file

@ -1,71 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
# This script is used to precalculate the PCR[8] value for a Constellation OS image.
# PCR[8] contains the hash of the kernel command line and is measured by systemd-boot.
# This value is deprecated and will be moved to PCR[12] in the future.
# This script may produce wrong results after 2023 (when the kernel command line is only measured in PCR[12]).
# Usage: precalculate_pcr_8.sh <path to image> <path to output file>
set -euo pipefail
source "$(dirname "$0")/measure_util.sh"
get_cmdline_from_uki () {
local uki="$1"
local output="$2"
objcopy -O binary --only-section=.cmdline "${uki}" "${output}"
}
cmdline_measure () {
local path="$1"
local tmp=$(mktemp)
# convert to utf-16le and add a null terminator
iconv -f utf-8 -t utf-16le "${path}" -o "${tmp}"
truncate -s +2 "${tmp}"
sha256sum "${tmp}" | cut -d " " -f 1
rm "${tmp}"
}
write_output () {
local out="$1"
cat > "${out}" <<EOF
{
"pcr8": "${expected_pcr_8}",
"cmdline": "${cmdline}"
}
EOF
}
IMAGE="$1"
OUT="$2"
CSP="$3"
DIR=$(mktempdir)
trap 'cleanup "${DIR}"' EXIT
extract "${IMAGE}" "/efi/EFI/Linux" "${DIR}/uki"
sudo chown -R "$USER:$USER" "${DIR}/uki"
cp ${DIR}/uki/*.efi "${DIR}/03-uki.efi"
get_cmdline_from_uki "${DIR}/03-uki.efi" "${DIR}/cmdline"
cmdline=$(cat "${DIR}/cmdline")
cmdline_hash=$(cmdline_measure "${DIR}/cmdline")
cleanup "${DIR}"
expected_pcr_8=0000000000000000000000000000000000000000000000000000000000000000
expected_pcr_8=$(pcr_extend "${expected_pcr_8}" "${cmdline_hash}" "sha256sum")
if [ "${CSP}" == "azure" ]; then
# Azure displays the boot menu
# triggering an extra measurement of the kernel command line.
expected_pcr_8=$(pcr_extend "${expected_pcr_8}" "${cmdline_hash}" "sha256sum")
fi
echo "Kernel commandline: ${cmdline}"
echo "Kernel Commandline measurement ${cmdline_hash}"
echo ""
echo "Expected PCR[8]: ${expected_pcr_8}"
echo ""
write_output "${OUT}"

View file

@ -1,54 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
# This script is used to precalculate the PCR[9] value for a Constellation OS image.
# PCR[9] contains the hash of the initrd and is measured by the linux kernel after loading the initrd.
# Usage: precalculate_pcr_9.sh <path to image> <path to output file>
set -euo pipefail
source "$(dirname "$0")/measure_util.sh"
get_initrd_from_uki () {
local uki="$1"
local output="$2"
objcopy -O binary --only-section=.initrd "${uki}" "${output}"
}
initrd_measure () {
local path="$1"
sha256sum "${path}" | cut -d " " -f 1
}
write_output () {
local out="$1"
cat > "${out}" <<EOF
{
"pcr9": "${expected_pcr_9}",
"initrd": "${initrd_hash}"
}
EOF
}
DIR=$(mktempdir)
trap 'cleanup "${DIR}"' EXIT
extract "$1" "/efi/EFI/Linux" "${DIR}/uki"
sudo chown -R "$USER:$USER" "${DIR}/uki"
cp ${DIR}/uki/*.efi "${DIR}/03-uki.efi"
get_initrd_from_uki "${DIR}/03-uki.efi" "${DIR}/initrd"
initrd_hash=$(initrd_measure "${DIR}/initrd")
cleanup "${DIR}"
expected_pcr_9=0000000000000000000000000000000000000000000000000000000000000000
expected_pcr_9=$(pcr_extend "${expected_pcr_9}" "${initrd_hash}" "sha256sum")
echo "Initrd measurement ${initrd_hash}"
echo ""
echo "Expected PCR[9]: ${expected_pcr_9}"
echo ""
write_output "$2"

View file

@ -1,3 +0,0 @@
[Content]
Packages=
WALinuxAgent-udev

View file

@ -1,9 +0,0 @@
[Content]
Packages=
containerd,
containernetworking-plugins,
iptables-nft,
ethtool,
socat,
iproute-tc,
conntrack-tools

View file

@ -1,3 +0,0 @@
[Content]
Packages=
nvme-cli

View file

@ -1,22 +0,0 @@
[Distribution]
Distribution=fedora
Release=36
[Output]
Format=gpt_squashfs
ManifestFormat=json,changelog
Bootable=yes
KernelCommandLine=mitigations=auto,nosmt preempt=full
WithUnifiedKernelImages=yes
Verity=yes
CompressFs=zstd
SplitArtifacts=yes
# Enable Secure Boot with own PKI
SecureBoot=yes
SecureBootKey=pki/db.key
SecureBootCertificate=pki/db.crt
# TODO: Wait for systemd 252 to bring systemd-measure
# Measure=yes
[Host]
QemuHeadless=yes

View file

@ -1,8 +0,0 @@
[Content]
Packages=
iproute,
dbus-broker,
systemd-networkd,
systemd-resolved,
dracut-network,
dhclient, # prevent NetworkManager from being pulled in by dracut-network

View file

@ -1,8 +0,0 @@
[Content]
# Secure Boot / EFI related packages for manual enrollment / verification of Secure Boot
Packages=
e2fsprogs,
sbsigntools,
efitools,
mokutil,
tpm2-tools

View file

@ -1,8 +0,0 @@
[Content]
Packages=
passwd,
nano,
nano-default-editor,
vim,
curl,
wget

View file

@ -1,3 +0,0 @@
[Output]
KernelCommandLine=constel.csp=azure
OutputDirectory=mkosi.output.azure

View file

@ -1,3 +0,0 @@
[Output]
KernelCommandLine=constel.csp=gcp
OutputDirectory=mkosi.output.gcp

View file

@ -1,3 +0,0 @@
[Output]
KernelCommandLine=constel.csp=qemu
OutputDirectory=mkosi.output.qemu

View file

@ -1,16 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
set -euxo pipefail
# recreate kubelet systemd unit after reboot.
# tmpfile config has to be written late as it interferes with the systemd-nspawn build environment
cat >"${BUILDROOT}/usr/lib/tmpfiles.d/kubelet-service.conf" <<EOF
C /run/systemd/system/kubelet.service - - - - /run/state/systemd/system/kubelet.service
C /run/systemd/system/kubelet.service.d/10-kubeadm.conf - - - - /run/state/systemd/system/kubelet.service.d/10-kubeadm.conf
EOF
# cleanup dracut generation files (disk-mapper) to save space
rm -rf "${BUILDROOT}/usr/lib/dracut/modules.d/39constellation-mount/"

View file

@ -1,22 +0,0 @@
#!/bin/sh
set -euxo pipefail
# This will work in sd-boot 251 to auto-enroll secure boot keys.
# https://www.freedesktop.org/software/systemd/man/systemd-boot.html
# > CHANGES WITH 252 in spe:
# > [...]
# > * sd-boot can automatically enroll SecureBoot keys from files found on
# > the ESP. This enrollment can be either automatic ('force' mode) or
# > controlled by the user ('manual' mode).
# > [...]
#
# echo "secure-boot-enroll force" >> /boot/loader/loader.conf
# create mountpoints in /etc
mkdir -p /etc/{cni,kubernetes}
# move issue files away from /etc
# to allow /run/issue and /run/issue.d to take precedence
mv /etc/issue.d /usr/lib/issue.d || true
rm -f /etc/issue
rm -f /etc/issue.net

View file

@ -1,4 +0,0 @@
# enable networking in initrd (initramfs) with dracut and systemd-networkd
install_items+=" /usr/lib/systemd/network/20-wired.network "
install_items+=" /usr/lib/systemd/network/21-azure.network "
add_dracutmodules+=" systemd-networkd "

View file

@ -1,3 +0,0 @@
# add hyperv drivers to initramfs
# (important for early networking)
force_drivers+=" hv_netvsc hv_sock hv_storvsc hv_vmbus "

View file

@ -1,2 +0,0 @@
# Include NVMe driver in initrd to boot on NVMe devices.
force_drivers+=" nvme "

View file

@ -1,5 +0,0 @@
/dev/mapper/state /run/state ext4 defaults,x-systemd.makefs,x-mount.mkdir 0 0
/run/state/var /var none defaults,bind,x-mount.mkdir 0 0
/run/state/kubernetes /etc/kubernetes none defaults,bind,x-mount.mkdir 0 0
/run/state/etccni /etc/cni/ none defaults,bind,x-mount.mkdir 0 0
/run/state/opt /opt none defaults,bind,x-mount.mkdir 0 0

View file

@ -1,8 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
export PATH=/run/state/bin:${PATH}
export KUBECONFIG=/etc/kubernetes/admin.conf
alias k=kubectl

View file

@ -1,216 +0,0 @@
disabled_plugins = []
imports = []
oom_score = 0
plugin_dir = ""
required_plugins = []
root = "/var/lib/containerd"
state = "/run/containerd"
version = 2
[cgroup]
path = ""
[debug]
address = ""
format = ""
gid = 0
level = ""
uid = 0
[grpc]
address = "/run/containerd/containerd.sock"
gid = 0
max_recv_message_size = 16777216
max_send_message_size = 16777216
tcp_address = ""
tcp_tls_cert = ""
tcp_tls_key = ""
uid = 0
[metrics]
address = ""
grpc_histogram = false
[plugins]
[plugins."io.containerd.gc.v1.scheduler"]
deletion_threshold = 0
mutation_threshold = 100
pause_threshold = 0.02
schedule_delay = "0s"
startup_delay = "100ms"
[plugins."io.containerd.grpc.v1.cri"]
disable_apparmor = false
disable_cgroup = false
disable_hugetlb_controller = true
disable_proc_mount = false
disable_tcp_service = true
enable_selinux = false
enable_tls_streaming = false
ignore_image_defined_volumes = false
max_concurrent_downloads = 3
max_container_log_line_size = 16384
netns_mounts_under_state_dir = false
restrict_oom_score_adj = false
sandbox_image = "k8s.gcr.io/pause:3.5"
selinux_category_range = 1024
stats_collect_period = 10
stream_idle_timeout = "4h0m0s"
stream_server_address = "127.0.0.1"
stream_server_port = "0"
systemd_cgroup = false
tolerate_missing_hugetlb_controller = true
unset_seccomp_profile = ""
[plugins."io.containerd.grpc.v1.cri".cni]
bin_dir = "/opt/cni/bin"
conf_dir = "/etc/cni/net.d"
conf_template = ""
max_conf_num = 1
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
disable_snapshot_annotations = true
discard_unpacked_layers = false
no_pivot = false
snapshotter = "overlayfs"
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
base_runtime_spec = ""
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_root = ""
runtime_type = ""
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
base_runtime_spec = ""
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_root = ""
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
BinaryName = ""
CriuImagePath = ""
CriuPath = ""
CriuWorkPath = ""
IoGid = 0
IoUid = 0
NoNewKeyring = false
NoPivotRoot = false
Root = ""
ShimCgroup = ""
SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]
base_runtime_spec = ""
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_root = ""
runtime_type = ""
[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime.options]
[plugins."io.containerd.grpc.v1.cri".image_decryption]
key_model = "node"
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = ""
[plugins."io.containerd.grpc.v1.cri".registry.auths]
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.headers]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
tls_cert_file = ""
tls_key_file = ""
[plugins."io.containerd.internal.v1.opt"]
path = "/opt/containerd"
[plugins."io.containerd.internal.v1.restart"]
interval = "10s"
[plugins."io.containerd.metadata.v1.bolt"]
content_sharing_policy = "shared"
[plugins."io.containerd.monitor.v1.cgroups"]
no_prometheus = false
[plugins."io.containerd.runtime.v1.linux"]
no_shim = false
runtime = "runc"
runtime_root = ""
shim = "containerd-shim"
shim_debug = false
[plugins."io.containerd.runtime.v2.task"]
platforms = ["linux/amd64"]
[plugins."io.containerd.service.v1.diff-service"]
default = ["walking"]
[plugins."io.containerd.snapshotter.v1.aufs"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.btrfs"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.devmapper"]
async_remove = false
base_image_size = ""
pool_name = ""
root_path = ""
[plugins."io.containerd.snapshotter.v1.native"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.overlayfs"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.zfs"]
root_path = ""
[proxy_plugins]
[stream_processors]
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
path = "ctd-decoder"
returns = "application/vnd.oci.image.layer.v1.tar"
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
path = "ctd-decoder"
returns = "application/vnd.oci.image.layer.v1.tar+gzip"
[timeouts]
"io.containerd.timeout.shim.cleanup" = "5s"
"io.containerd.timeout.shim.load" = "5s"
"io.containerd.timeout.shim.shutdown" = "3s"
"io.containerd.timeout.task.state" = "2s"
[ttrpc]
address = ""
gid = 0
uid = 0

View file

@ -1 +0,0 @@
../../../systemd/system/configure-constel-csp.service

View file

@ -1,15 +0,0 @@
[Unit]
Description=Force symlink creation for GCP nvme disks
Before=prepare-state-disk.service
After=network-online.target
Wants=network-online.target
ConditionKernelCommandLine=constel.csp=gcp
[Service]
Type=oneshot
ExecStart=/bin/bash /usr/sbin/google-nvme-disk
RemainAfterExit=yes
StandardOutput=tty
StandardInput=tty
StandardError=tty
TimeoutSec=infinity

View file

@ -1,27 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
set -euo pipefail
shopt -s extglob nullglob
GCP_STATE_DISK_SYMLINK="/dev/disk/by-id/google-state-disk"
# hack: google nvme udev rules are never executed. Create symlinks for the nvme devices manually.
while [ ! -L "${GCP_STATE_DISK_SYMLINK}" ]
do
for nvmedisk in /dev/nvme0n+([0-9])
do
/usr/lib/udev/google_nvme_id -s -d "${nvmedisk}" || true
done
if [ -L "${GCP_STATE_DISK_SYMLINK}" ]; then
break
fi
echo "Waiting for state disk to appear.."
sleep 2
done
echo "Google state disk found"
echo ${GCP_STATE_DISK_SYMLINK}$(readlink -f "${GCP_STATE_DISK_SYMLINK}")
sleep 2

View file

@ -1,59 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
depends() {
echo systemd
}
install_and_enable_unit() {
unit="$1"; shift
target="$1"; shift
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
mkdir -p "${initdir}${systemdsystemconfdir}/${target}.wants"
ln_r "${systemdsystemunitdir}/${unit}" \
"${systemdsystemconfdir}/${target}.wants/${unit}"
}
install() {
inst_multiple \
bash
inst_script "/usr/sbin/disk-mapper" \
"/usr/sbin/disk-mapper"
inst_script "$moddir/prepare-state-disk.sh" \
"/usr/sbin/prepare-state-disk"
install_and_enable_unit "prepare-state-disk.service" \
"basic.target"
inst_script "$moddir/google-nvme-disk.sh" \
"/usr/sbin/google-nvme-disk"
install_and_enable_unit "google-nvme-disk.service" \
"basic.target"
install_and_enable_unit "configure-constel-csp.service" \
"basic.target"
# azure scsi disks
inst_multiple \
cut \
readlink
# gcp nvme disks
inst_multiple \
date \
xxd \
grep \
sed \
ln \
command \
readlink
inst_script "/usr/sbin/nvme" \
"/usr/sbin/nvme"
inst_script "/usr/lib/udev/google_nvme_id" \
"/usr/lib/udev/google_nvme_id"
inst_simple "/usr/lib/udev/rules.d/64-gce-disk-removal.rules" \
"/usr/lib/udev/rules.d/64-gce-disk-removal.rules"
inst_simple "/usr/lib/udev/rules.d/65-gce-disk-naming.rules" \
"/usr/lib/udev/rules.d/65-gce-disk-naming.rules"
}

View file

@ -1,17 +0,0 @@
[Unit]
Description=Prepare encrypted state disk
Before=initrd-fs.target
After=network-online.target configure-constel-csp.service
Wants=network-online.target
Requires=initrd-root-fs.target
FailureAction=reboot-immediate
[Service]
Type=oneshot
EnvironmentFile=/run/constellation.env
ExecStart=/bin/bash /usr/sbin/prepare-state-disk
RemainAfterExit=yes
StandardOutput=tty
StandardInput=tty
StandardError=tty
TimeoutSec=infinity

View file

@ -1,15 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
set -euo pipefail
# Prepare the encrypted volume by either initializing it with a random key or by aquiring the key from another bootstrapper.
# Store encryption key (random or recovered key) in /run/cryptsetup-keys.d/state.key
disk-mapper -csp "${CONSTEL_CSP}"
if [[ $? -ne 0 ]]; then
echo "Failed to prepare state disk"
sleep 2 # give the serial console time to print the error message
exit $? # exit with the same error code as disk-mapper
fi

View file

@ -1,2 +0,0 @@
PATH=/run/state/bin:$PATH
KUBECONFIG=/etc/kubernetes/admin.conf

View file

@ -1,2 +0,0 @@
overlay
br_netfilter

View file

@ -1,3 +0,0 @@
# See https://github.com/cilium/cilium/issues/10645
net.ipv4.conf.lxc*.rp_filter = 0
net.ipv4.conf.cilium_*.rp_filter = 0

View file

@ -1,9 +0,0 @@
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
fs.inotify.max_user_instances = 8192
fs.inotify.max_user_watches = 524288
# kubernetes hardening (protectKernelDefaults=true)
vm.overcommit_memory = 1
kernel.panic = 10
kernel.panic_on_oops = 1

View file

@ -1,5 +0,0 @@
[Match]
Name=en*
[Network]
DHCP=yes

View file

@ -1,6 +0,0 @@
# Used as a fallback rule for Azure NICs as they are not named with "en*"
[Match]
Driver=hv_netvsc
[Network]
DHCP=yes

View file

@ -1,5 +0,0 @@
enable constellation-bootstrapper.service
enable configure-constel-csp.service
enable containerd.service
enable tpm-pcrs.service
enable systemd-networkd.service

View file

@ -1,10 +0,0 @@
[Unit]
Description=Configures constellation cloud service provider environment variable
[Service]
Type=oneshot
ExecStart=/bin/bash -c "CSP=$(< /proc/cmdline tr ' ' '\n' | grep constel.csp | sed 's/constel.csp=//'); echo CONSTEL_CSP=$CSP >> /run/constellation.env"
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View file

@ -1,15 +0,0 @@
[Unit]
Description=Constellation Bootstrapper
Wants=network-online.target
After=network-online.target configure-constel-csp.service
[Service]
Type=simple
RemainAfterExit=yes
Restart=on-failure
EnvironmentFile=/run/constellation.env
Environment=PATH=/run/state/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
ExecStart=/usr/bin/bootstrapper
[Install]
WantedBy=multi-user.target

View file

@ -1,3 +0,0 @@
[Service]
ExecStart=
ExecStart=/usr/bin/containerd --config /usr/etc/containerd/config.toml

View file

@ -1,11 +0,0 @@
[Unit]
Description=Print PCR state on startup
Before=constellation-bootstrapper.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/constellation-pcrs
[Install]
WantedBy=multi-user.target

View file

@ -1,2 +0,0 @@
#Type Name ID GECOS Home directory Shell
u etcd 998:997 "etcd user" /var/lib/etcd

View file

@ -1,8 +0,0 @@
#Type Path Mode User Group Age Argument
d /var/lib/etcd 0700 998 997 - -
d /var/log/kubernetes/audit/ 0700 0 0 - -
d /run/state/bin 0755 0 0 - -
d /run/issue.d 0755 0 0 - -
C /run/issue - - - - /usr/lib/issue
# merge all CNI binaries in writable folder until containerd can use multiple CNI bins: https://github.com/containerd/containerd/issues/6600
C /opt/cni/bin - - - - /usr/libexec/cni/

View file

@ -1,245 +0,0 @@
#!/bin/bash
# Copyright 2020 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Used to generate symlinks for PD-NVMe devices using the disk names reported by
# the metadata server
# Locations of the script's dependencies
readonly nvme_cli_bin=/usr/sbin/nvme
# Bash regex to parse device paths and controller identification
readonly NAMESPACE_NUMBER_REGEX="/dev/nvme[[:digit:]]+n([[:digit:]]+).*"
readonly PARTITION_NUMBER_REGEX="/dev/nvme[[:digit:]]+n[[:digit:]]+p([[:digit:]]+)"
readonly PD_NVME_REGEX="sn[[:space:]]+:[[:space]]+nvme_card-pd"
# Globals used to generate the symlinks for a PD-NVMe disk. These are populated
# by the identify_pd_disk function and exported for consumption by udev rules.
ID_SERIAL=''
ID_SERIAL_SHORT=''
#######################################
# Helper function to log an error message to stderr.
# Globals:
# None
# Arguments:
# String to print as the log message
# Outputs:
# Writes error to STDERR
#######################################
function err() {
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
}
#######################################
# Retrieves the device name for an NVMe namespace using nvme-cli.
# Globals:
# Uses nvme_cli_bin
# Arguments:
# The path to the nvme namespace (/dev/nvme0n?)
# Outputs:
# The device name parsed from the JSON in the vendor ext of the ns-id command.
# Returns:
# 0 if the device name for the namespace could be retrieved, 1 otherwise
#######################################
function get_namespace_device_name() {
local nvme_json
nvme_json="$("$nvme_cli_bin" id-ns -b "$1" | xxd -p -seek 384 | xxd -p -r)"
if [[ $? -ne 0 ]]; then
return 1
fi
if [[ -z "$nvme_json" ]]; then
err "NVMe Vendor Extension disk information not present"
return 1
fi
local device_name
device_name="$(echo "$nvme_json" | grep device_name | sed -e 's/.*"device_name":[ \t]*"\([a-zA-Z0-9_-]\+\)".*/\1/')"
# Error if our device name is empty
if [[ -z "$device_name" ]]; then
err "Empty name"
return 1
fi
echo "$device_name"
return 0
}
#######################################
# Retrieves the nsid for an NVMe namespace
# Globals:
# None
# Arguments:
# The path to the nvme namespace (/dev/nvme0n*)
# Outputs:
# The namespace number/id
# Returns:
# 0 if the namespace id could be retrieved, 1 otherwise
#######################################
function get_namespace_number() {
local dev_path="$1"
local namespace_number
if [[ "$dev_path" =~ $NAMESPACE_NUMBER_REGEX ]]; then
namespace_number="${BASH_REMATCH[1]}"
else
return 1
fi
echo "$namespace_number"
return 0
}
#######################################
# Retrieves the partition number for a device path if it exists
# Globals:
# None
# Arguments:
# The path to the device partition (/dev/nvme0n*p*)
# Outputs:
# The value after 'p' in the device path, or an empty string if the path has
# no partition.
#######################################
function get_partition_number() {
local dev_path="$1"
local partition_number
if [[ "$dev_path" =~ $PARTITION_NUMBER_REGEX ]]; then
partition_number="${BASH_REMATCH[1]}"
echo "$partition_number"
else
echo ''
fi
return 0
}
#######################################
# Generates a symlink for a PD-NVMe device using the metadata's disk name.
# Primarily used for testing but can be used if the script is directly invoked.
# Globals:
# Uses ID_SERIAL_SHORT (can be populated by identify_pd_disk)
# Arguments:
# The device path for the disk
#######################################
function gen_symlink() {
local dev_path="$1"
local partition_number="$(get_partition_number "$dev_path")"
if [[ -n "$partition_number" ]]; then
ln -s "$dev_path" /dev/disk/by-id/google-"$ID_SERIAL_SHORT"-part"$partition_number" > /dev/null 2>&1
else
ln -s "$dev_path" /dev/disk/by-id/google-"$ID_SERIAL_SHORT" > /dev/null 2>&1
fi
return 0
}
#######################################
# Populates the ID_* global variables with a disk's device name and namespace
# Globals:
# Populates ID_SERIAL_SHORT, and ID_SERIAL
# Arguments:
# The device path for the disk
# Returns:
# 0 on success and 1 if an error occurrs
#######################################
function identify_pd_disk() {
local dev_path="$1"
local dev_name
dev_name="$(get_namespace_device_name "$dev_path")"
if [[ $? -ne 0 ]]; then
return 1
fi
ID_SERIAL_SHORT="$dev_name"
ID_SERIAL="Google_PersistentDisk_${ID_SERIAL_SHORT}"
return 0
}
function print_help_message() {
echo "Usage: google_nvme_id [-s] [-h] -d device_path"
echo " -d <device_path> (Required): Specifies the path to generate a name"
echo " for. This needs to be a path to an nvme device or namespace"
echo " -s: Create symbolic link for the disk under /dev/disk/by-id."
echo " Otherwise, the disk name will be printed to STDOUT"
echo " -h: Print this help message"
}
function main() {
local opt_gen_symlink='false'
local device_path=''
while getopts :d:sh flag; do
case "$flag" in
d) device_path="$OPTARG";;
s) opt_gen_symlink='true';;
h) print_help_message
return 0
;;
:) echo "Invalid option: ${OPTARG} requires an argument" 1>&2
return 1
;;
*) return 1
esac
done
if [[ -z "$device_path" ]]; then
echo "Device path (-d) argument required. Use -h for full usage." 1>&2
exit 1
fi
# Ensure the nvme-cli command is installed
command -v "$nvme_cli_bin" > /dev/null 2>&1
if [[ $? -ne 0 ]]; then
err "The nvme utility (/usr/sbin/nvme) was not found. You may need to run \
with sudo or install nvme-cli."
return 1
fi
# Ensure the passed device is actually an NVMe device
"$nvme_cli_bin" id-ctrl "$device_path" &>/dev/null
if [[ $? -ne 0 ]]; then
err "Passed device was not an NVMe device. (You may need to run this \
script as root/with sudo)."
return 1
fi
# Detect the type of attached nvme device
local controller_id
controller_id=$("$nvme_cli_bin" id-ctrl "$device_path")
if [[ ! "$controller_id" =~ nvme_card-pd ]] ; then
err "Device is not a PD-NVMe device"
return 1
fi
# Fill the global variables for the id command for the given disk type
# Error messages will be printed closer to error, no need to reprint here
identify_pd_disk "$device_path"
if [[ $? -ne 0 ]]; then
return $?
fi
# Gen symlinks or print out the globals set by the identify command
if [[ "$opt_gen_symlink" == 'true' ]]; then
gen_symlink "$device_path"
else
# These will be consumed by udev
echo "ID_SERIAL_SHORT=${ID_SERIAL_SHORT}"
echo "ID_SERIAL=${ID_SERIAL}"
fi
return $?
}
main "$@"

View file

@ -1,17 +0,0 @@
# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# When a disk is removed, unmount any remaining attached volumes.
ACTION=="remove", SUBSYSTEM=="block", KERNEL=="sd*|vd*|nvme*", RUN+="/bin/sh -c '/bin/umount -fl /dev/$name && /usr/bin/logger -p daemon.warn -s WARNING: hot-removed /dev/$name that was still mounted, data may have been corrupted'"

View file

@ -1,37 +0,0 @@
# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Name the attached disks as the specified by deviceName.
ACTION!="add|change", GOTO="gce_disk_naming_end"
SUBSYSTEM!="block", GOTO="gce_disk_naming_end"
# SCSI naming
KERNEL=="sd*|vd*", IMPORT{program}="scsi_id --export --whitelisted -d $tempnode"
# NVME Local SSD naming
KERNEL=="nvme*n*", ATTRS{model}=="nvme_card", PROGRAM="/bin/sh -c 'nsid=$$(echo %k|sed -re s/nvme[0-9]+n\([0-9]+\).\*/\\1/); echo $$((nsid-1))'", ENV{ID_SERIAL_SHORT}="local-nvme-ssd-%c"
KERNEL=="nvme*", ATTRS{model}=="nvme_card", ENV{ID_SERIAL}="Google_EphemeralDisk_$env{ID_SERIAL_SHORT}"
# NVME Persistent Disk IO Timeout
KERNEL=="nvme*n*", ENV{DEVTYPE}=="disk", ATTRS{model}=="nvme_card-pd", ATTR{queue/io_timeout}="4294967295"
# NVME Persistent Disk Naming
KERNEL=="nvme*n*", ATTRS{model}=="nvme_card-pd", IMPORT{program}="google_nvme_id -d $tempnode"
# Symlinks
KERNEL=="sd*|vd*|nvme*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/google-$env{ID_SERIAL_SHORT}"
KERNEL=="sd*|vd*|nvme*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/google-$env{ID_SERIAL_SHORT}-part%n"
LABEL="gce_disk_naming_end"

View file

@ -1,3 +0,0 @@
# prevent systemd udev rules from marking unformatted device mapper device as unready (SYSTEMD_READY=0)
# this is the offending rule from systemd: SUBSYSTEM=="block", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}=="", ENV{SYSTEMD_READY}="0"
SUBSYSTEM=="block", ENV{DM_NAME}=="state", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}="constellation-state"

View file

@ -1,14 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
# This script reads the PCR state of the system
# and prints the message to the serial console
main() {
pcr_state="$(tpm2_pcrread sha256)"
echo -e "PCR state:\n${pcr_state}\n" > /run/issue.d/35_constellation_pcrs.issue
}
main

Binary file not shown.

Binary file not shown.

View file

@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIID3zCCAsegAwIBAgIUHii75K8+vo3LkCUKJjGBiTVJy/8wDQYJKoZIhvcNAQEL
BQAwgYgxCzAJBgNVBAYTAkRFMRwwGgYDVQQIDBNOb3JkcmhlaW4gV2VzdGZhbGVu
MQ8wDQYDVQQHDAZCb2NodW0xHjAcBgNVBAoMFUVkZ2VsZXNzIFN5c3RlbXMgR21i
SDEqMCgGA1UEAwwhQ29uc3RlbGxhdGlvbiBUZXN0aW5nIEtFSyBDQSAyMDIyMB4X
DTIyMDkyMzE0MTYwN1oXDTIyMTAyMzE0MTYwN1owgYgxCzAJBgNVBAYTAkRFMRww
GgYDVQQIDBNOb3JkcmhlaW4gV2VzdGZhbGVuMQ8wDQYDVQQHDAZCb2NodW0xHjAc
BgNVBAoMFUVkZ2VsZXNzIFN5c3RlbXMgR21iSDEqMCgGA1UEAwwhQ29uc3RlbGxh
dGlvbiBUZXN0aW5nIEtFSyBDQSAyMDIyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEA9QnVns2kVMrbV6308MDN6xVoTLcQ91ashmpj5Zj/gDiidtguggWS
hJ8bItzH2c02AWrMuf+T5wxaPWxZPjgYI9CnoBg53rgmGWpeBeV2ZWK8wRp0iUQe
GmhaBP+aA4h6UYN7N1120kV0O4BmJg76JwecHK2VXom7H4ILD4EKvXgpiyRdKJm7
CZaJ422G1LIjzLI1Gm2yhTsihyma9iguyV4EFLukp8umGneiE0erRngKw9a6YTWP
eFfTyXtwaWVcGhA5guhkp5U/KQCY1Mr6e4+Zp3ISL8QFBneYbDpVI3nWDNfWPMAH
eLxny2rpc+zvOJ+JDCc3frkWCLV4BZD8ZQIDAQABoz8wPTAdBgNVHQ4EFgQU8iGE
QDAs7qF7LowPBQu0Tft2fbowDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAYYw
DQYJKoZIhvcNAQELBQADggEBAKF9RGT46YAFhn2CrMuMd3eOalpoLM+SllAtmq5c
7RqUGQBOhuAdf1aiucFXH8xzi7DOV6aVhQG67kv5isISqUdUL80+RpajWYcU5YaW
jEX+w/o2Jv0kzBDBTVcX6uKuid1oiQDXGVL/UaU30Smdk/9ni1RImuPBPupNEljU
AjaduiqqcJArLBmXzEizCnaGhEvdezPIiZDbzARDbkvl1WQthcghh3i6iiBiN7Vp
gGMzEecGJ4oxlxa+fycIiFbrX8h3DgVOCXeaxWtbfmIuswwFeZ3rVXHXizfOMEdr
2qWu/xQwwUfN3Z07kXigfB3akJfqDYO5/mNGNNi6fAJV2do=
-----END CERTIFICATE-----

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIID4TCCAsmgAwIBAgIUUsz90g+sTYH+2QEMZf7gKWDiDEwwDQYJKoZIhvcNAQEL
BQAwgYkxCzAJBgNVBAYTAkRFMRwwGgYDVQQIDBNOb3JkcmhlaW4gV2VzdGZhbGVu
MQ8wDQYDVQQHDAZCb2NodW0xHjAcBgNVBAoMFUVkZ2VsZXNzIFN5c3RlbXMgR21i
SDErMCkGA1UEAwwiQ29uc3RlbGxhdGlvbiBUZXN0aW5nIFVFRkkgQ0EgMjAyMjAe
Fw0yMjA5MjMxNDE2MDZaFw0yMjEwMjMxNDE2MDZaMIGJMQswCQYDVQQGEwJERTEc
MBoGA1UECAwTTm9yZHJoZWluIFdlc3RmYWxlbjEPMA0GA1UEBwwGQm9jaHVtMR4w
HAYDVQQKDBVFZGdlbGVzcyBTeXN0ZW1zIEdtYkgxKzApBgNVBAMMIkNvbnN0ZWxs
YXRpb24gVGVzdGluZyBVRUZJIENBIDIwMjIwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQC4fWmh6n3qjKmJSh0zvNc9frZnEcyfK3pDSCtdhNQh/kN59Tjd
+kg79yxPfG5v6MYiQhxva2EVPiAuMmB/zrhq75UmNU6o0WCVk58g7IrXDd4xpO+s
32+umlntT86wHWfrSAj3JduBG8ci1J1uARz0mmHl2gOzoB0dn4WOAoLLMH2bAzjS
ICX0giXiY6Q66JQya4OPMvdwSAW78H6JgTtNIsYKn2clnA3VJZWXIzYl6Bd92zjC
6RFrhzu7WYw9nmIA0HMtjpSeU9JDPUmedU7MPqLAK6kpiR+RrowzkfaFmIUqdxpj
4IlGXkqWqu/I3WzKucdt7X0Run914M5iM4xzAgMBAAGjPzA9MB0GA1UdDgQWBBQ9
/pmrY9gxhPV658NbhCfmcGWkDjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB
hjANBgkqhkiG9w0BAQsFAAOCAQEAU+4eQJXS02qof7S+vkLOGznuC4KD0yXs9+jg
Ih6ANg6YBlxNZWDWAYZeJIIrQfINnzC36dQcb4StiUOKJu4eT5YxH4Afv39L3eoZ
eKsVE2Dddt4tE+i8oEBA7XPKZZH8le2V0csnZ2cbsphxftwy72qkFukmkmcBn4Zq
fXeAsdbDHoKlnTPeTNAXcgPUyLGhxqoX5vaIsNDFPGQ3BhsHfmNgKkZ4J+BSGGnc
R4Gre/mN1eNz3LYn7RZeExOrcnwnQAvFVhtz4ZFIndxP3kSiNh2Lo/7p/ECEnnEn
jOUCkARuA3lUZiWMzGMDo/kgTi6C6kulEkCWcp417OeXmThrjA==
-----END CERTIFICATE-----

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIID2TCCAsGgAwIBAgIUQZYX6ujSb/QFL2p8BY62ydJ/HEYwDQYJKoZIhvcNAQEL
BQAwgYUxCzAJBgNVBAYTAkRFMRwwGgYDVQQIDBNOb3JkcmhlaW4gV2VzdGZhbGVu
MQ8wDQYDVQQHDAZCb2NodW0xHjAcBgNVBAoMFUVkZ2VsZXNzIFN5c3RlbXMgR21i
SDEnMCUGA1UEAwweQ29uc3RlbGxhdGlvbiBUZXN0aW5nIFBDQSAyMDIyMB4XDTIy
MDkyMzE0MTYwN1oXDTIyMTAyMzE0MTYwN1owgYUxCzAJBgNVBAYTAkRFMRwwGgYD
VQQIDBNOb3JkcmhlaW4gV2VzdGZhbGVuMQ8wDQYDVQQHDAZCb2NodW0xHjAcBgNV
BAoMFUVkZ2VsZXNzIFN5c3RlbXMgR21iSDEnMCUGA1UEAwweQ29uc3RlbGxhdGlv
biBUZXN0aW5nIFBDQSAyMDIyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAx4lZNSnqGy1Dk8hxQHgzzIpCAr2+zPtNpPKdXq8PLIZ1fBERYkVW66JHH5Dl
9pzMl8KaJkkRbv5orxzpL0g9qtM+j/JQl1Ap7S9MAXgysATwyaFWfddLW+ZOi/XS
oOhq1JXp0FFFUBQwP56JtqhUEcgaICi41L9S/XMxQaoZfRQu+9ICVlDMLurqVdI4
Or5mz7eWUqj34Xl5bpjMOZgbyI1pYN4UxvODKFIYhVTmKZOWA0np4JtI4iCA5Dkd
ckF9uwOyQUyGUs7Atar2tZr2hWK66NxhcdSfj9ltuBHwskJnoJYesWPz0QHz26xO
d+a4WwIKhKfchvv5qVq9KFkRpQIDAQABoz8wPTAdBgNVHQ4EFgQUvCP4FCxcypyU
STwBjhtgqnojgaEwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAYYwDQYJKoZI
hvcNAQELBQADggEBAAhpPWCLVl8FvWZOeZA2iOKmLen/c6W0d9WiB9qvj+mI8QBq
kLhkqkxEcXTpaOjCxJLqLU3LsA828yUdfL0zmxusrJlz+gux+KRlRn1yTsCyWqmx
9rYUXO6IFwZnSUV923uVZ1nkHydwqV9hqIgrKYrppzDXOsm+ugz+NP2lxFNp6q8u
MyMsClaTdfPT+EUucp7g1lPVdtWV4RbWK/v3/rp2l5jzs7F0Roa3zc/+YquwB/AA
ZasNpDInz6RlEzhA/GkXEO5Rssem4a1NBwGrvs9mCIm5sKLaxLUnlM7SLCAeEBdS
qxLwUVTOtnQzWEM04I978V3zfKNPBtl2mvhuXYw=
-----END CERTIFICATE-----

Binary file not shown.

View file

@ -1,74 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
if [ -z "${CONFIG_FILE-}" ] && [ -f "${CONFIG_FILE-}" ]; then
. "${CONFIG_FILE}"
fi
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
-n|--name)
AZURE_VM_NAME="$2"
shift # past argument
shift # past value
;;
-*|--*)
echo "Unknown option $1"
exit 1
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
AZ_VM_INFO=$(az vm show --name "${AZURE_VM_NAME}" --resource-group "${AZURE_RESOURCE_GROUP_NAME}" -o json)
NIC=$(echo "${AZ_VM_INFO}" | jq -r '.networkProfile.networkInterfaces[0].id')
NIC_INFO=$(az network nic show --ids "${NIC}" -o json)
PUBIP=$(echo "${NIC_INFO}" | jq -r '.ipConfigurations[0].publicIpAddress.id')
NSG=$(echo "${NIC_INFO}" | jq -r '.networkSecurityGroup.id')
SUBNET=$(echo "${NIC_INFO}" | jq -r '.ipConfigurations[0].subnet.id')
VNET=$(echo $SUBNET | sed 's#/subnets/.*##')
DISK=$(echo "${AZ_VM_INFO}" | jq -r '.storageProfile.osDisk.managedDisk.id')
delete_vm () {
az vm delete -y --name "${AZURE_VM_NAME}" \
--resource-group "${AZURE_RESOURCE_GROUP_NAME}" || true
}
delete_vnet () {
az network vnet delete --ids "${VNET}" || true
}
delete_subnet () {
az network vnet subnet delete --ids "${SUBNET}" || true
}
delete_nsg () {
az network nsg delete --ids "${NSG}" || true
}
delete_pubip () {
az network public-ip delete --ids "${PUBIP}" || true
}
delete_disk () {
az disk delete -y --ids "${DISK}" || true
}
delete_nic () {
az network nic delete --ids "${NIC}" || true
}
delete_vm
delete_disk
delete_nic
delete_nsg
delete_subnet
delete_vnet
delete_pubip

View file

@ -1,65 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
if [ -z "${CONFIG_FILE-}" ] && [ -f "${CONFIG_FILE-}" ]; then
. "${CONFIG_FILE}"
fi
AZURE_SUBSCRIPTION=$(az account show --query id -o tsv)
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
-n|--name)
AZURE_VM_NAME="$2"
shift # past argument
shift # past value
;;
-*|--*)
echo "Unknown option $1"
exit 1
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
VM_DISK=$(az vm show -g "${AZURE_RESOURCE_GROUP_NAME}" --name "${AZURE_VM_NAME}" --query "storageProfile.osDisk.managedDisk.id" -o tsv)
LOCATION=$(az disk show --ids "${VM_DISK}" --query "location" -o tsv)
az snapshot create \
-g "${AZURE_RESOURCE_GROUP_NAME}" \
--source "${VM_DISK}" \
--name "${AZURE_SNAPSHOT_NAME}" \
-l "${LOCATION}"
# Azure CLI does not implement getSecureVMGuestStateSAS for snapshots yet
# az snapshot grant-access \
# --duration-in-seconds 3600 \
# --access-level Read \
# --name "${AZURE_SNAPSHOT_NAME}" \
# -g "${AZURE_RESOURCE_GROUP_NAME}"
BEGIN=$(az rest \
--method post \
--url "https://management.azure.com/subscriptions/${AZURE_SUBSCRIPTION}/resourceGroups/${AZURE_RESOURCE_GROUP_NAME}/providers/Microsoft.Compute/snapshots/${AZURE_SNAPSHOT_NAME}/beginGetAccess" \
--uri-parameters api-version="2021-12-01" \
--body '{"access": "Read", "durationInSeconds": 3600, "getSecureVMGuestStateSAS": true}' \
--verbose 2>&1)
ASYNC_OPERATION_URI=$(echo "${BEGIN}" | grep Azure-AsyncOperation | cut -d ' ' -f 7 | tr -d "'")
sleep 10
ACCESS=$(az rest --method get --url "${ASYNC_OPERATION_URI}")
VMGS_URL=$(echo "${ACCESS}" | jq -r '.properties.output.securityDataAccessSAS')
curl -L -o "${AZURE_VMGS_FILENAME}" "${VMGS_URL}"
az snapshot revoke-access \
--name "${AZURE_SNAPSHOT_NAME}" \
-g "${AZURE_RESOURCE_GROUP_NAME}"
az snapshot delete \
--name "${AZURE_SNAPSHOT_NAME}" \
-g "${AZURE_RESOURCE_GROUP_NAME}"
echo "VMGS saved to ${AZURE_VMGS_FILENAME}"

View file

@ -1,101 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
if [ -z "${CONFIG_FILE-}" ] && [ -f "${CONFIG_FILE-}" ]; then
. "${CONFIG_FILE}"
fi
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
-n|--name)
AZURE_VM_NAME="$2"
shift # past argument
shift # past value
;;
-g|--gallery)
CREATE_FROM_GALLERY=YES
shift # past argument
;;
-d|--disk)
CREATE_FROM_GALLERY=NO
shift # past argument
;;
--secure-boot)
AZURE_SECURE_BOOT="$2"
shift # past argument
shift # past value
;;
--disk-name)
AZURE_DISK_NAME="$2"
shift # past argument
shift # past value
;;
-*|--*)
echo "Unknown option $1"
exit 1
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
if [[ "${AZURE_SECURITY_TYPE}" == "ConfidentialVM" ]]; then
VMSIZE="Standard_DC2as_v5"
elif [[ "${AZURE_SECURITY_TYPE}" == "TrustedLaunch" ]]; then
VMSIZE="standard_D2as_v5"
else
echo "Unknown security type: ${AZURE_SECURITY_TYPE}"
exit 1
fi
create_vm_from_disk () {
AZURE_DISK_REFERENCE=$(az disk show --resource-group ${AZURE_RESOURCE_GROUP_NAME} --name ${AZURE_DISK_NAME} --query id -o tsv)
az vm create --name "${AZURE_VM_NAME}" \
--resource-group "${AZURE_RESOURCE_GROUP_NAME}" \
-l ${AZURE_REGION} \
--size "${VMSIZE}" \
--public-ip-sku Standard \
--os-type Linux \
--attach-os-disk "${AZURE_DISK_REFERENCE}" \
--security-type "${AZURE_SECURITY_TYPE}" \
--os-disk-security-encryption-type VMGuestStateOnly \
--enable-vtpm true \
--enable-secure-boot "${AZURE_SECURE_BOOT}" \
--boot-diagnostics-storage "" \
--no-wait
}
create_vm_from_sig () {
AZURE_IMAGE_REFERENCE=$(az sig image-version show \
--gallery-image-definition "${AZURE_IMAGE_DEFINITION}" \
--gallery-image-version "${AZURE_IMAGE_VERSION}" \
--gallery-name "${AZURE_GALLERY_NAME}" \
-g "${AZURE_RESOURCE_GROUP_NAME}" \
--query id -o tsv)
az vm create --name "${AZURE_VM_NAME}" \
--resource-group "${AZURE_RESOURCE_GROUP_NAME}" \
-l ${AZURE_REGION} \
--size "${VMSIZE}" \
--public-ip-sku Standard \
--image "${AZURE_IMAGE_REFERENCE}" \
--security-type "${AZURE_SECURITY_TYPE}" \
--os-disk-security-encryption-type VMGuestStateOnly \
--enable-vtpm true \
--enable-secure-boot "${AZURE_SECURE_BOOT}" \
--boot-diagnostics-storage "" \
--no-wait
}
if [ "$CREATE_FROM_GALLERY" = "YES" ]; then
create_vm_from_sig
else
create_vm_from_disk
fi
sleep 30
az vm boot-diagnostics enable --name "${AZURE_VM_NAME}" --resource-group "${AZURE_RESOURCE_GROUP_NAME}"

View file

@ -1,92 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
BASE_DIR=$(realpath "${SCRIPT_DIR}/..")
# Set to qemu+tcp://localhost:16599/system for dockerized libvirt setup
if [[ -z "${LIBVIRT_SOCK}" ]]; then
LIBVIRT_SOCK=qemu:///system
fi
libvirt_nvram_gen () {
local image_path="${1}"
if test -f "${BASE_DIR}/image.nvram.template"; then
echo "NVRAM template already generated: $(realpath "--relative-to=$(pwd)" ${BASE_DIR}/image.nvram.template)"
return
fi
if ! test -f "${image_path}"; then
echo "Image \"${image_path}\" does not exist yet. To generate nvram, create disk image first."
return
fi
OVMF_CODE=/usr/share/OVMF/OVMF_CODE_4M.ms.fd
OVMF_VARS=/usr/share/OVMF/OVMF_VARS_4M.ms.fd
if ! test -f "${OVMF_CODE}"; then
OVMF_CODE=/usr/share/OVMF/OVMF_CODE.secboot.fd
fi
if ! test -f "${OVMF_VARS}"; then
OVMF_VARS=/usr/share/OVMF/OVMF_VARS.secboot.fd
fi
echo "Using OVMF_CODE: ${OVMF_CODE}"
echo "Using OVMF_VARS: ${OVMF_VARS}"
# generate nvram file using libvirt
virt-install --name constell-nvram-gen \
--connect ${LIBVIRT_SOCK} \
--nonetworks \
--description 'Constellation' \
--ram 1024 \
--vcpus 1 \
--osinfo detect=on,require=off \
--disk "${image_path},format=raw" \
--boot "machine=q35,menu=on,loader=${OVMF_CODE},loader.readonly=yes,loader.type=pflash,nvram.template=${OVMF_VARS},nvram=${BASE_DIR}/image.nvram,loader_secure=yes" \
--features smm.state=on \
--noautoconsole
echo -e 'connect using'
echo -e ' \u001b[1mvirsh console constell-nvram-gen\u001b[0m'
echo -e ''
echo -e 'Load db cert with MokManager or enroll full PKI with firmware setup'
echo -e ''
echo -e ' \u001b[1mMokManager\u001b[0m'
echo -e ' For mokmanager, try to boot as usual. You will see this message:'
echo -e ' > "Verification failed: (0x1A) Security Violation"'
echo -e ' Press OK, then ENTER, then "Enroll key from disk"'
echo -e ' Select the following key:'
echo -e ' > \u001b[1m/EFI/loader/keys/auto/db.cer\u001b[0m'
echo -e ' Press Continue, then choose "Yes" to the question "Enroll the key(s)?"'
echo -e ' Choose reboot and continue this script.'
echo -e ''
echo -e ' \u001b[1mFirmware setup\u001b[0m'
echo -e ' For firmware setup, press F2.'
echo -e ' Go to "Device Manager">"Secure Boot Configuration">"Secure Boot Mode"'
echo -e ' Choose "Custom Mode"'
echo -e ' Go to "Custom Securee Boot Options"'
echo -e ' Go to "PK Options">"Enroll PK", Press "Y" if queried, "Enroll PK using File"'
echo -e ' Select the following cert: \u001b[1m/EFI/loader/keys/auto/PK.cer\u001b[0m'
echo -e ' Choose "Commit Changes and Exit"'
echo -e ' Go to "KEK Options">"Enroll KEK", Press "Y" if queried, "Enroll KEK using File"'
echo -e ' Select the following cert: \u001b[1m/EFI/loader/keys/auto/KEK.cer\u001b[0m'
echo -e ' Choose "Commit Changes and Exit"'
echo -e ' Go to "DB Options">"Enroll Signature">"Enroll Signature using File"'
echo -e ' Select the following cert: \u001b[1m/EFI/loader/keys/auto/db.cer\u001b[0m'
echo -e ' Choose "Commit Changes and Exit"'
echo -e ' Repeat the last step for the following certs:'
echo -e ' > \u001b[1m/EFI/loader/keys/auto/MicWinProPCA2011_2011-10-19.crt\u001b[0m'
echo -e ' > \u001b[1m/EFI/loader/keys/auto/MicCorUEFCA2011_2011-06-27.crt\u001b[0m'
echo -e ' Reboot and continue this script.'
echo -e ''
echo -e 'Press ENTER to continue after you followed one of the guides from above.'
read
sudo cp "${BASE_DIR}/image.nvram" "${BASE_DIR}/image.nvram.template"
virsh --connect "${LIBVIRT_SOCK}" destroy --domain constell-nvram-gen
virsh --connect "${LIBVIRT_SOCK}" undefine --nvram constell-nvram-gen
rm -f "${BASE_DIR}/image.nvram"
echo "NVRAM template generated: $(realpath "--relative-to=$(pwd)" ${BASE_DIR}/image.nvram.template)"
}
libvirt_nvram_gen $1

View file

@ -1,68 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
# This script generates a PKI for secure boot.
# It is based on the example from https://github.com/systemd/systemd/blob/main/man/loader.conf.xml
# This is meant to be used for development purposes only.
# Release images are signed using a different set of keys.
# Set PKI to an empty folder and PKI_SET to "dev".
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
TEMPLATES=${SCRIPT_DIR}/templates
BASE_DIR=$(realpath "${SCRIPT_DIR}/..")
if [ -z "${PKI}" ]; then
PKI=${BASE_DIR}/pki
fi
if [ -z "${PKI_SET}" ]; then
PKI_SET=dev
fi
gen_pki () {
# Only use for non-production images.
# Use real PKI for production images instead.
count=$(ls -1 ${PKI}/*.{key,crt,cer,esl,auth} 2>/dev/null | wc -l)
if [ $count != 0 ]
then
echo PKI files $(ls -1 $(realpath "--relative-to=$(pwd)" ${PKI})/*.{key,crt,cer,esl,auth}) already exist
return
fi
mkdir -p "${PKI}"
pushd "${PKI}"
uuid=$(systemd-id128 new --uuid)
for key in PK KEK db; do
openssl req -new -x509 -config "${TEMPLATES}/${PKI_SET}_${key}.conf" -keyout "${key}.key" -out "${key}.crt" -nodes
openssl x509 -outform DER -in "${key}.crt" -out "${key}.cer"
cert-to-efi-sig-list -g "${uuid}" "${key}.crt" "${key}.esl"
done
for key in MicWinProPCA2011_2011-10-19.crt MicCorUEFCA2011_2011-06-27.crt MicCorKEKCA2011_2011-06-24.crt; do
curl -sL "https://www.microsoft.com/pkiops/certs/${key}" --output "${key}"
sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output "${key%crt}esl" "${key}"
done
# Optionally add Microsoft Windows Production CA 2011 (needed to boot into Windows).
cat MicWinProPCA2011_2011-10-19.esl >> db.esl
# Optionally add Microsoft Corporation UEFI CA 2011 (for firmware drivers / option ROMs
# and third-party boot loaders (including shim). This is highly recommended on real
# hardware as not including this may soft-brick your device (see next paragraph).
cat MicCorUEFCA2011_2011-06-27.esl >> db.esl
# Optionally add Microsoft Corporation KEK CA 2011. Recommended if either of the
# Microsoft keys is used as the official UEFI revocation database is signed with this
# key. The revocation database can be updated with [fwupdmgr(1)](https://www.freedesktop.org/software/systemd/man/fwupdmgr.html#).
cat MicCorKEKCA2011_2011-06-24.esl >> KEK.esl
sign-efi-sig-list -c PK.crt -k PK.key PK PK.esl PK.auth
sign-efi-sig-list -c PK.crt -k PK.key KEK KEK.esl KEK.auth
sign-efi-sig-list -c KEK.crt -k KEK.key db db.esl db.auth
popd
}
# gen_pki generates a PKI for testing purposes only.
# if keys/certs are already present in the pki folder, they are not regenerated.
gen_pki

View file

@ -1,49 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
set -euo pipefail
# This script is used to add a signed shim to the image.raw file EFI partition after running `mkosi build`.
if (( $# != 1 ))
then
echo "Usage: $0 <image.raw>"
exit 1
fi
# SOURCE is the URL used to download the signed shim RPM
SOURCE=https://kojipkgs.fedoraproject.org/packages/shim/15.6/2/x86_64/shim-x64-15.6-2.x86_64.rpm
# EXPECTED_SHA512 is the SHA512 checksum of the signed shim RPM
EXPECTED_SHA512=971978bddee95a6a134ef05c4d88cf5df41926e631de863b74ef772307f3e106c82c8f6889c18280d47187986abd774d8671c5be4b85b1b0bb3d1858b65d02cf
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
BASE_DIR=$(realpath "${SCRIPT_DIR}/..")
TMPDIR=$(mktemp -d)
pushd "${TMPDIR}"
curl -sL -o shim.rpm "${SOURCE}"
echo "Checking SHA512 checksum of signed shim..."
sha512sum -c <<< "${EXPECTED_SHA512} shim.rpm"
rpm2cpio shim.rpm | cpio -idmv
echo $TMPDIR
popd
MOUNTPOINT=$(mktemp -d)
sectoroffset=$(sfdisk -J "${1}" | jq -r '.partitiontable.partitions[0].start')
byteoffset=$((sectoroffset * 512))
mount -o offset="${byteoffset}" "${1}" "${MOUNTPOINT}"
mkdir -p "${MOUNTPOINT}/EFI/BOOT/"
cp "${TMPDIR}/boot/efi/EFI/BOOT/BOOTX64.EFI" "${MOUNTPOINT}/EFI/BOOT/"
cp "${TMPDIR}/boot/efi/EFI/fedora/mmx64.efi" "${MOUNTPOINT}/EFI/BOOT/"
cp "${MOUNTPOINT}/EFI/systemd/systemd-bootx64.efi" "${MOUNTPOINT}/EFI/BOOT/grubx64.efi"
# Remove unused kernel and initramfs from EFI to save space
# We boot from unified kernel image anyway
rm -f "${MOUNTPOINT}"/*/*/{linux,initrd}
umount "${MOUNTPOINT}"
rm -rf ${MOUNTPOINT}
rm -rf "${TMPDIR}"

View file

@ -1,20 +0,0 @@
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_req
req_extensions = v3_req
prompt = no
dirstring_type = nobmp
[ req_distinguished_name ]
C = DE
ST = Nordrhein Westfalen
L = Bochum
O = Edgeless Systems GmbH
CN = Constellation Development KEK CA 2022
[ v3_req ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:true
keyUsage = digitalSignature,keyCertSign,cRLSign

View file

@ -1,20 +0,0 @@
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_req
req_extensions = v3_req
prompt = no
dirstring_type = nobmp
[ req_distinguished_name ]
C = DE
ST = Nordrhein Westfalen
L = Bochum
O = Edgeless Systems GmbH
CN = Constellation Development UEFI CA 2022
[ v3_req ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:true
keyUsage = digitalSignature,keyCertSign,cRLSign

View file

@ -1,20 +0,0 @@
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_req
req_extensions = v3_req
prompt = no
dirstring_type = nobmp
[ req_distinguished_name ]
C = DE
ST = Nordrhein Westfalen
L = Bochum
O = Edgeless Systems GmbH
CN = Constellation Development PCA 2022
[ v3_req ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:true
keyUsage = digitalSignature,keyCertSign,cRLSign

View file

@ -1,20 +0,0 @@
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_req
req_extensions = v3_req
prompt = no
dirstring_type = nobmp
[ req_distinguished_name ]
C = DE
ST = Nordrhein Westfalen
L = Bochum
O = Edgeless Systems GmbH
CN = Constellation KEK CA 2022
[ v3_req ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:true
keyUsage = digitalSignature,keyCertSign,cRLSign

View file

@ -1,20 +0,0 @@
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_req
req_extensions = v3_req
prompt = no
dirstring_type = nobmp
[ req_distinguished_name ]
C = DE
ST = Nordrhein Westfalen
L = Bochum
O = Edgeless Systems GmbH
CN = Constellation UEFI CA 2022
[ v3_req ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:true
keyUsage = digitalSignature,keyCertSign,cRLSign

View file

@ -1,20 +0,0 @@
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_req
req_extensions = v3_req
prompt = no
dirstring_type = nobmp
[ req_distinguished_name ]
C = DE
ST = Nordrhein Westfalen
L = Bochum
O = Edgeless Systems GmbH
CN = Constellation Production PCA 2022
[ v3_req ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:true
keyUsage = digitalSignature,keyCertSign,cRLSign

View file

@ -1,20 +0,0 @@
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_req
req_extensions = v3_req
prompt = no
dirstring_type = nobmp
[ req_distinguished_name ]
C = DE
ST = Nordrhein Westfalen
L = Bochum
O = Edgeless Systems GmbH
CN = Constellation Testing KEK CA 2022
[ v3_req ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:true
keyUsage = digitalSignature,keyCertSign,cRLSign

View file

@ -1,20 +0,0 @@
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_req
req_extensions = v3_req
prompt = no
dirstring_type = nobmp
[ req_distinguished_name ]
C = DE
ST = Nordrhein Westfalen
L = Bochum
O = Edgeless Systems GmbH
CN = Constellation Testing UEFI CA 2022
[ v3_req ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:true
keyUsage = digitalSignature,keyCertSign,cRLSign

View file

@ -1,20 +0,0 @@
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
x509_extensions = v3_req
req_extensions = v3_req
prompt = no
dirstring_type = nobmp
[ req_distinguished_name ]
C = DE
ST = Nordrhein Westfalen
L = Bochum
O = Edgeless Systems GmbH
CN = Constellation Testing PCA 2022
[ v3_req ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:true
keyUsage = digitalSignature,keyCertSign,cRLSign

View file

@ -1,61 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
set -euo pipefail
# Show progress on pipes if `pv` is installed
# Otherwise use plain cat
if ! command -v pv &> /dev/null
then
PV="cat"
else
PV="pv"
fi
pack () {
local cloudprovider=$1
local unpacked_image=$2
local packed_image=$3
local unpacked_image_dir
unpacked_image_dir=$(mktemp -d)
local unpacked_image_filename
unpacked_image_filename=disk.raw
local tmp_tar_file
tmp_tar_file=$(mktemp -t verity.XXXXXX.tar)
cp ${unpacked_image} "${unpacked_image_dir}/${unpacked_image_filename}"
case $cloudprovider in
gcp)
echo "📥 Packing GCP image..."
tar --owner=0 --group=0 -C "${unpacked_image_dir}" -Sch --format=oldgnu -f "${tmp_tar_file}" "${unpacked_image_filename}"
"${PV}" "${tmp_tar_file}" | pigz -9c > "${packed_image}"
rm "${tmp_tar_file}"
echo " Repacked image stored in ${packed_image}"
;;
azure)
echo "📥 Packing Azure image..."
truncate -s %1MiB "${unpacked_image_dir}/${unpacked_image_filename}"
qemu-img convert -p -f raw -O vpc -o force_size,subformat=fixed "${unpacked_image_dir}/${unpacked_image_filename}" "$packed_image"
echo " Repacked image stored in ${packed_image}"
;;
*)
echo "unknown cloud provider"
exit 1
;;
esac
rm -r ${unpacked_image_dir}
}
if [ $# -ne 3 ]; then
echo "Usage: $0 <cloudprovider> <unpacked_image> <packed_image>"
exit 1
fi
pack "${1}" "${2}" "${3}"

View file

@ -1,194 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
set -euo pipefail
if [ -z "${CONFIG_FILE-}" ] && [ -f "${CONFIG_FILE-}" ]; then
. "${CONFIG_FILE}"
fi
CREATE_SIG_VERSION=NO
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
-g|--gallery)
CREATE_SIG_VERSION=YES
shift # past argument
;;
--disk-name)
AZURE_DISK_NAME="$2"
shift # past argument
shift # past value
;;
-*|--*)
echo "Unknown option $1"
exit 1
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
if [[ "${AZURE_SECURITY_TYPE}" == "ConfidentialVM" ]]; then
AZURE_DISK_SECURITY_TYPE=ConfidentialVM_VMGuestStateOnlyEncryptedWithPlatformKey
AZURE_SIG_VERSION_ENCRYPTION_TYPE=EncryptedVMGuestStateOnlyWithPmk
elif [[ "${AZURE_SECURITY_TYPE}" == "ConfidentialVMSupported" ]]; then
AZURE_DISK_SECURITY_TYPE=""
elif [[ "${AZURE_SECURITY_TYPE}" == "TrustedLaunch" ]]; then
AZURE_DISK_SECURITY_TYPE=TrustedLaunch
else
echo "Unknown security type: ${AZURE_SECURITY_TYPE}"
exit 1
fi
AZURE_CVM_ENCRYPTION_ARGS=""
if [[ -n "${AZURE_SIG_VERSION_ENCRYPTION_TYPE-}" ]]; then
AZURE_CVM_ENCRYPTION_ARGS=" --target-region-cvm-encryption "
for region in ${AZURE_REPLICATION_REGIONS}; do
AZURE_CVM_ENCRYPTION_ARGS=" ${AZURE_CVM_ENCRYPTION_ARGS} ${AZURE_SIG_VERSION_ENCRYPTION_TYPE}, "
done
fi
echo "Replicating image in ${AZURE_REPLICATION_REGIONS}"
AZURE_VMGS_PATH=$1
if [[ -z "${AZURE_VMGS_PATH}" ]] && [[ "${AZURE_SECURITY_TYPE}" == "ConfidentialVM" ]]; then
echo "No VMGS path provided - using default ConfidentialVM VMGS"
AZURE_VMGS_PATH="${BLOBS_DIR}/cvm-vmgs.vhd"
elif [[ -z "${AZURE_VMGS_PATH}" ]] && [[ "${AZURE_SECURITY_TYPE}" == "TrustedLaunch" ]]; then
echo "No VMGS path provided - using default TrsutedLaunch VMGS"
AZURE_VMGS_PATH="${BLOBS_DIR}/trusted-launch-vmgs.vhd"
fi
SIZE=$(wc -c "${AZURE_IMAGE_PATH}" | cut -d " " -f1)
create_disk_with_vmgs () {
az disk create \
-n "${AZURE_DISK_NAME}" \
-g "${AZURE_RESOURCE_GROUP_NAME}" \
-l "${AZURE_REGION}" \
--hyper-v-generation V2 \
--os-type Linux \
--upload-size-bytes "${SIZE}" \
--sku standard_lrs \
--upload-type UploadWithSecurityData \
--security-type "${AZURE_DISK_SECURITY_TYPE}"
az disk wait --created -n "${AZURE_DISK_NAME}" -g "${AZURE_RESOURCE_GROUP_NAME}"
az disk list --output table --query "[?name == '${AZURE_DISK_NAME}' && resourceGroup == '${AZURE_RESOURCE_GROUP_NAME^^}']"
DISK_SAS=$(az disk grant-access -n ${AZURE_DISK_NAME} -g ${AZURE_RESOURCE_GROUP_NAME} \
--access-level Write --duration-in-seconds 86400 \
${AZURE_VMGS_PATH+"--secure-vm-guest-state-sas"})
azcopy copy "${AZURE_IMAGE_PATH}" \
"$(echo $DISK_SAS | jq -r .accessSas)" \
--blob-type PageBlob
if [[ -z "${AZURE_VMGS_PATH}" ]]; then
echo "No VMGS path provided - skipping VMGS upload"
else
azcopy copy "${AZURE_VMGS_PATH}" \
"$(echo $DISK_SAS | jq -r .securityDataAccessSas)" \
--blob-type PageBlob
fi
az disk revoke-access -n "${AZURE_DISK_NAME}" -g "${AZURE_RESOURCE_GROUP_NAME}"
}
create_disk_without_vmgs () {
az disk create \
-n "${AZURE_DISK_NAME}" \
-g "${AZURE_RESOURCE_GROUP_NAME}" \
-l "${AZURE_REGION}" \
--hyper-v-generation V2 \
--os-type Linux \
--upload-size-bytes "${SIZE}" \
--sku standard_lrs \
--upload-type Upload
az disk wait --created -n "${AZURE_DISK_NAME}" -g "${AZURE_RESOURCE_GROUP_NAME}"
az disk list --output table --query "[?name == '${AZURE_DISK_NAME}' && resourceGroup == '${AZURE_RESOURCE_GROUP_NAME^^}']"
DISK_SAS=$(az disk grant-access -n ${AZURE_DISK_NAME} -g ${AZURE_RESOURCE_GROUP_NAME} \
--access-level Write --duration-in-seconds 86400)
azcopy copy "${AZURE_IMAGE_PATH}" \
"$(echo $DISK_SAS | jq -r .accessSas)" \
--blob-type PageBlob
az disk revoke-access -n "${AZURE_DISK_NAME}" -g "${AZURE_RESOURCE_GROUP_NAME}"
}
create_disk () {
if [[ -z "${AZURE_VMGS_PATH}" ]]; then
create_disk_without_vmgs
else
create_disk_with_vmgs
fi
}
delete_disk () {
az disk delete -y -n "${AZURE_DISK_NAME}" -g "${AZURE_RESOURCE_GROUP_NAME}"
}
create_image () {
if [[ -n "${AZURE_VMGS_PATH}" ]]; then
return
fi
az image create \
--resource-group ${AZURE_RESOURCE_GROUP_NAME} \
-l ${AZURE_REGION} \
-n ${AZURE_DISK_NAME} \
--hyper-v-generation V2 \
--os-type Linux \
--source "$(az disk list --query "[?name == '${AZURE_DISK_NAME}' && resourceGroup == '${AZURE_RESOURCE_GROUP_NAME^^}'] | [0].id" --output tsv)"
}
delete_image () {
if [[ -n "${AZURE_VMGS_PATH}" ]]; then
return
fi
az image delete -n "${AZURE_DISK_NAME}" -g "${AZURE_RESOURCE_GROUP_NAME}"
}
create_sig_version () {
if [[ -n "${AZURE_VMGS_PATH}" ]]; then
local DISK="$(az disk list --query "[?name == '${AZURE_DISK_NAME}' && resourceGroup == '${AZURE_RESOURCE_GROUP_NAME^^}'] | [0].id" --output tsv)"
local SOURCE="--os-snapshot ${DISK}"
else
local IMAGE="$(az image list --query "[?name == '${AZURE_DISK_NAME}' && resourceGroup == '${AZURE_RESOURCE_GROUP_NAME^^}'] | [0].id" --output tsv)"
local SOURCE="--managed-image ${IMAGE}"
fi
az sig create -l "${AZURE_REGION}" --gallery-name "${AZURE_GALLERY_NAME}" --resource-group "${AZURE_RESOURCE_GROUP_NAME}" || true
az sig image-definition create \
--resource-group "${AZURE_RESOURCE_GROUP_NAME}" \
-l "${AZURE_REGION}" \
--gallery-name "${AZURE_GALLERY_NAME}" \
--gallery-image-definition "${AZURE_IMAGE_DEFINITION}" \
--publisher "${AZURE_PUBLISHER}" \
--offer "${AZURE_IMAGE_OFFER}" \
--sku "${AZURE_SKU}" \
--os-type Linux \
--os-state generalized \
--hyper-v-generation V2 \
--features SecurityType="${AZURE_SECURITY_TYPE}" || true
az sig image-version create \
--resource-group "${AZURE_RESOURCE_GROUP_NAME}" \
-l "${AZURE_REGION}" \
--gallery-name "${AZURE_GALLERY_NAME}" \
--gallery-image-definition "${AZURE_IMAGE_DEFINITION}" \
--gallery-image-version "${AZURE_IMAGE_VERSION}" \
--target-regions ${AZURE_REPLICATION_REGIONS} \
${AZURE_CVM_ENCRYPTION_ARGS} \
--replica-count 1 \
--replication-mode Full \
${SOURCE}
}
create_disk
if [ "$CREATE_SIG_VERSION" = "YES" ]; then
create_image
create_sig_version
delete_image
delete_disk
fi

View file

@ -1,31 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
set -euo pipefail
if [ -z "${CONFIG_FILE-}" ] && [ -f "${CONFIG_FILE-}" ]; then
. "${CONFIG_FILE}"
fi
PK_FILE=${PKI}/PK.cer
KEK_FILES=${PKI}/KEK.cer,${PKI}/MicCorKEKCA2011_2011-06-24.crt
DB_FILES=${PKI}/db.cer,${PKI}/MicWinProPCA2011_2011-10-19.crt,${PKI}/MicCorUEFCA2011_2011-06-27.crt
gsutil mb -l "${GCP_REGION}" "gs://${GCP_BUCKET}" || true
gsutil pap set enforced "gs://${GCP_BUCKET}" || true
gsutil cp "${GCP_IMAGE_PATH}" "gs://${GCP_BUCKET}/${GCP_IMAGE_FILENAME}"
gcloud compute images create "${GCP_IMAGE_NAME}" \
"--family=${GCP_IMAGE_FAMILY}" \
"--source-uri=gs://${GCP_BUCKET}/${GCP_IMAGE_FILENAME}" \
"--guest-os-features=GVNIC,SEV_CAPABLE,VIRTIO_SCSI_MULTIQUEUE,UEFI_COMPATIBLE" \
"--platform-key-file=${PK_FILE}" \
"--key-exchange-key-file=${KEK_FILES}" \
"--signature-database-file=${DB_FILES}" \
"--project=${GCP_PROJECT}"
gcloud compute images add-iam-policy-binding "${GCP_IMAGE_NAME}" \
"--project=${GCP_PROJECT}" \
--member='allAuthenticatedUsers' \
--role='roles/compute.imageUser'
gsutil rm "gs://${GCP_BUCKET}/${GCP_IMAGE_FILENAME}"

View file

@ -1,16 +0,0 @@
cosa() {
env | grep COREOS_ASSEMBLER
local -r COREOS_ASSEMBLER_CONTAINER_LATEST="localhost/coreos-assembler"
test -t 1 && USE_TTY="-ti"
set -x
podman run --rm ${USE_TTY} --security-opt label=disable --privileged \
--uidmap=1000:0:1 --uidmap=0:1:1000 --uidmap 1001:1001:64536 \
-v ${PWD}:/srv/ --device /dev/kvm --device /dev/fuse \
--tmpfs /tmp -v /var/tmp:/var/tmp --name constellation-cosa \
-v ${NETRC}:/home/builder/.netrc:ro \
${COREOS_ASSEMBLER_CONFIG_GIT:+-v $COREOS_ASSEMBLER_CONFIG_GIT:/srv/src/config/:ro} \
${COREOS_ASSEMBLER_GIT:+-v $COREOS_ASSEMBLER_GIT/src/:/usr/lib/coreos-assembler/:ro} \
${COREOS_ASSEMBLER_CONTAINER_RUNTIME_ARGS} \
${COREOS_ASSEMBLER_CONTAINER:-$COREOS_ASSEMBLER_CONTAINER_LATEST} "$@"
rc=$?; set +x; return $rc
}