Add TDX dockerfile & CI for asterinas

This commit is contained in:
Hsy-Intel 2024-05-08 15:58:56 +08:00 committed by Tate, Hongliang Tian
parent a997785166
commit 8c39309381
10 changed files with 339 additions and 107 deletions

View File

@ -29,17 +29,38 @@ jobs:
echo "aster_version=$( cat VERSION )" >> "$GITHUB_OUTPUT"
echo "rust_version=$( grep -m1 -o 'nightly-[0-9]\+-[0-9]\+-[0-9]\+' rust-toolchain.toml )" >> "$GITHUB_OUTPUT"
- name: Generate Dockerfile
run: |
pip install Jinja2
python3 ./tools/docker/gen_dockerfile.py
- name: Build and push development image
uses: docker/build-push-action@v4
with:
context: .
file: ./tools/docker/Dockerfile.ubuntu22.04
file: ./tools/docker/Dockerfile
platforms: linux/amd64
push: true
tags: asterinas/asterinas:${{ steps.fetch-versions.outputs.aster_version }}
build-args: |
"ASTER_RUST_VERSION=${{ steps.fetch-versions.outputs.rust_version }}"
- name: Generate Dockerfile for Intel TDX
run: |
pip install Jinja2
python3 ./tools/docker/gen_dockerfile.py
- name: Build and push development image for Intel TDX
uses: docker/build-push-action@v4
with:
context: .
file: ./tools/docker/Dockerfile
platforms: linux/amd64
push: true
tags: asterinas/asterinas:${{ steps.fetch-versions.outputs.aster_version }}-tdx
build-args: |
"ASTER_RUST_VERSION=${{ steps.fetch-versions.outputs.rust_version }}"
- name: Generate OSDK Dockerfile
run: |
python3 ./osdk/tools/docker/gen_dockerfile.py

View File

@ -46,6 +46,8 @@ CARGO_OSDK_ARGS += --release
endif
ifeq ($(INTEL_TDX), 1)
BOOT_PROTOCOL = linux-efi-handover64
CARGO_OSDK_ARGS += --scheme tdx
CARGO_OSDK_ARGS += --features intel_tdx
endif

View File

@ -6,6 +6,7 @@
* [Getting Started](kernel/README.md)
* [Advanced Build and Test Instructions](kernel/advanced-instructions.md)
* [Intel TDX](kernel/intel_tdx.md)
* [The Framekernel Architecture](kernel/the-framekernel-architecture.md)
* [Linux Compatibility](kernel/linux-compatibility.md)
* [Roadmap](kernel/roadmap.md)

View File

@ -0,0 +1,116 @@
# Intel TDX
Asterinas can serve as a secure guest OS for Intel TDX-protected virtual machines (VMs).
This documentation describes
how Asterinas can be run and tested easily on a TDX-enabled Intel server.
Intel TDX (Trust Domain Extensions) is a Trusted Execution Environment (TEE) technology
that enhances VM security
by creating isolated, hardware-enforced trust domains
with encrypted memory, secure initialization, and attestation mechanisms.
For more information about Intel TDX, jump to the last section.
## Why choose Asterinas for Intel TDX
VM TEEs such as Intel TDX deserve a more secure option for its guest OS than Linux.
Linux,
with its inherent memory safety issues and large Trusted Computing Base (TCB),
has long suffered from security vulnerabilities due to memory safety bugs.
Additionally,
when Linux is used as the guest kernel inside a VM TEE,
it must process untrusted inputs
(over 1500 instances in Linux, per Intel's estimation)
from the host (via hypercalls, MMIO, and etc.).
These untrusted inputs create new attack surfaces
that can be exploited through memory safety vulnerabilities,
known as Iago attacks.
Asterinas offers greater memory safety than Linux,
particularly against Iago attacks.
Thanks to its framekernel architecture,
the memory safety of Asterinas relies solely on the Asterinas Framework,
excluding the safe device drivers built on top of the Asterinas Framework
that may handle untrusted inputs from the host.
For more information, see [our talk on OC3'24](https://www.youtube.com/watch?v=3AQ5lpXujGo).
## Prepare the Intel TDX Environment
Please make sure your server supports Intel TDX.
See [this guide](https://github.com/canonical/tdx/tree/noble-24.04?tab=readme-ov-file#4-setup-host-os)
or other materials to enable Intel TDX in host OS.
To verify the TDX host status,
you can type:
```bash
dmesg | grep "TDX module initialized"
```
The following result is an example:
```bash
[ 20.507296] tdx: TDX module initialized.
```
`TDX module initialized` means TDX module is loaded successfully.
## Build and run Asterinas
1. Download the latest source code.
```bash
git clone https://github.com/asterinas/asterinas
```
2. Run a Docker container as the development environment.
```bash
docker run -it --privileged --network=host --device=/dev/kvm -v ./asterinas:/root/asterinas asterinas/asterinas:0.4.2_tdx
```
3. Inside the container,
go to the project folder to build and run Asterinas.
```bash
make run INTEL_TDX=1
```
If everything goes well,
Asterinas is now up and running inside a TDVM.
## About Intel TDX
Intel® Trust Domain Extensions (Intel® TDX)
is Intel's newest confidential computing technology.
This hardware-based trusted execution environment (TEE)
facilitates the deployment of trust domains (TD),
which are hardware-isolated virtual machines (VM) designed to
protect sensitive data and applications from unauthorized access.
A CPU-measured Intel TDX module enables Intel TDX.
This software module runs in a new CPU Secure Arbitration Mode (SEAM)
as a peer virtual machine manager (VMM),
and supports TD entry and exit
using the existing virtualization infrastructure.
The module is hosted in a reserved memory space
identified by the SEAM Range Register (SEAMRR).
Intel TDX uses hardware extensions for managing and encrypting memory
and protects both the confidentiality and integrity
of the TD CPU state from non-SEAM mode.
Intel TDX uses architectural elements such as SEAM,
a shared bit in Guest Physical Address (GPA),
secure Extended Page Table (EPT),
physical-address-metadata table,
Intel® Total Memory Encryption Multi-Key (Intel® TME-MK),
and remote attestation.
Intel TDX ensures data integrity, confidentiality, and authenticity,
which empowers engineers and tech professionals
to create and maintain secure systems,
enhancing trust in virtualized environments.
For more information,
please refer to [Intel TDX website](https://www.intel.com/content/www/us/en/developer/tools/trust-domain-extensions/overview.html).

View File

@ -86,6 +86,7 @@ validate_bump_type() {
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
ASTER_SRC_DIR=${SCRIPT_DIR}/..
DOCS_DIR=${ASTER_SRC_DIR}/docs
CARGO_TOML_PATH=${ASTER_SRC_DIR}/Cargo.toml
OSDK_CARGO_TOML_PATH=${ASTER_SRC_DIR}/osdk/Cargo.toml
VERSION_PATH=${ASTER_SRC_DIR}/VERSION
@ -112,6 +113,7 @@ cargo update -p asterinas --precise $new_version
update_image_versions ${ASTER_SRC_DIR}/README.md
update_image_versions ${ASTER_SRC_DIR}/README_CN.md
update_image_versions ${SCRIPT_DIR}/docker/README.md
update_image_versions ${DOCS_DIR}/src/kernel/intel_tdx.md
# Update Docker image versions in workflows
WORKFLOWS=$(find "${ASTER_SRC_DIR}/.github/workflows/" -type f -name "*.yml")

1
tools/docker/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
**/Dockerfile

View File

@ -2,7 +2,7 @@
#= Install packages for Docker building ====================================
FROM ubuntu:22.04 as build-base
FROM {{ base_image }} as build-base
SHELL ["/bin/bash", "-c"]
@ -80,6 +80,7 @@ WORKDIR /root/syscall_test
RUN export BUILD_DIR=build && \
make ${BUILD_DIR}/syscall_test_bins
{% if not intel_tdx %}
#= Build QEMU =================================================================
FROM build-base as build-qemu
@ -180,6 +181,7 @@ RUN echo depends bli part_gpt > grub-core/extra_deps.lst \
&& make install
WORKDIR /root
RUN rm -rf /root/grub
{% endif %}
#= Build busybox ==============================================================
@ -230,13 +232,15 @@ RUN apt update && apt-get install -y --no-install-recommends \
file \
gdb \
grub-efi-amd64 \
{% if not intel_tdx %}
grub-efi-amd64-bin \
grub-efi-amd64-dbg \
ovmf `# provide an alternative stable firmware` \
{% endif %}
libpixman-1-dev `# running dependency for QEMU` \
mtools `# used by grub-mkrescue` \
net-tools \
openssh-server \
ovmf `# provide an alternative stable firmware`\
pkg-config \
strace \
sudo \
@ -251,6 +255,7 @@ RUN apt clean && rm -rf /var/lib/apt/lists/*
COPY --from=syscall_test /root/syscall_test/build/syscall_test_bins /root/syscall_test_bins
ENV ASTER_PREBUILT_SYSCALL_TEST=/root/syscall_test_bins
{% if not intel_tdx %}
# Install QEMU built from the previous stages
COPY --from=qemu /usr/local/qemu /usr/local/qemu
ENV PATH="/usr/local/qemu/bin:${PATH}"
@ -265,6 +270,7 @@ COPY --from=grub /usr/local/grub /usr/local/grub
ENV PATH="/usr/local/grub/bin:${PATH}"
# Make a symbolic link for `unicode.pf2` from Ubuntu 22.04 package
RUN ln -sf /usr/share/grub/unicode.pf2 /usr/local/grub/share/grub/unicode.pf2
{% endif %}
# Install Busybox built from the previous stages
COPY --from=busybox /root/busybox/busybox /bin/busybox

View File

@ -7,17 +7,37 @@ Asterinas development Docker images are provided to facilitate developing and te
To build a Docker image for Asterinas and test it on your local machine, navigate to the root directory of the Asterinas source code tree and execute the following command:
```bash
cd <asterinas dir>/tools/docker
# Generate Dockerfile
python3 gen_dockerfile.py
cd <asterinas dir>
# Build Docker image
docker buildx build \
-f tools/docker/Dockerfile.ubuntu22.04 \
--build-arg ASTER_RUST_VERSION=$RUST_VERSION \
-t asterinas/asterinas:$ASTER_VERSION \
-f tools/docker/Dockerfile \
--build-arg ASTER_RUST_VERSION=${RUST_VERSION} \
-t asterinas/asterinas:${ASTER_VERSION} \
.
```
The meanings of the two environment variables in the command are as follows:
- `$ASTER_VERSION`: Represents the version number of Asterinas. You can find this in the `VERSION` file.
- `$RUST_VERSION`: Denotes the required Rust toolchain version, as specified in the `rust-toolchain` file.
- `${ASTER_VERSION}`: Represents the version number of Asterinas. You can find this in the `VERSION` file.
- `${RUST_VERSION}`: Denotes the required Rust toolchain version, as specified in the `rust-toolchain` file.
For Intel TDX Docker Image, you can execute the following command:
```bash
cd <asterinas dir>/tools/docker
# Generate Dockerfile for Intel TDX
python3 gen_dockerfile.py --intel-tdx
cd <asterinas dir>
# Build Docker image
docker buildx build \
-f tools/docker/Dockerfile \
--build-arg ASTER_RUST_VERSION=${RUST_VERSION} \
-t asterinas/asterinas:${ASTER_VERSION}-tdx \
.
```
## Tagging Docker Images

View File

@ -0,0 +1,58 @@
# SPDX-License-Identifier: MPL-2.0
import argparse
import os
import sys
import logging
from jinja2 import Environment, FileSystemLoader
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
def parse_arguments():
parser = argparse.ArgumentParser(description='The Dockerfile generator for OSDK.')
parser.add_argument('--intel-tdx', action='store_true', help='Include Intel TDX support')
parser.add_argument(
'--out-dir',
type=str,
default='.',
help='Output the Dockerfile under this directory. \
By default, the output directory is the current working directory.'
)
return parser.parse_args()
def setup_output_directory(out_dir):
if os.path.isabs(out_dir):
logging.error("The --out-dir argument must be a relative path.")
sys.exit(1)
template_dir = os.path.dirname(os.path.abspath(__file__))
if out_dir == '.':
return template_dir
output_directory_path = os.path.join(template_dir, out_dir)
if not os.path.exists(output_directory_path):
os.makedirs(output_directory_path)
return output_directory_path
def load_template():
template_dir = os.path.dirname(os.path.abspath(__file__))
env = Environment(loader=FileSystemLoader(template_dir), trim_blocks=True, lstrip_blocks=True)
template = env.get_template('Dockerfile.jinja')
return template
def write_dockerfile(output_directory, content):
output_path = os.path.join(output_directory, 'Dockerfile')
with open(output_path, 'w') as file:
file.write(content)
logging.info(f'Dockerfile has been generated at {output_path}.')
def main():
args = parse_arguments()
output_dir = setup_output_directory(args.out_dir)
base_image = "intelcczoo/tdvm:ubuntu22.04-mvp_2023ww15" if args.intel_tdx else "ubuntu:22.04"
template = load_template()
rendered_content = template.render(base_image=base_image, intel_tdx=args.intel_tdx)
write_dockerfile(output_dir, rendered_content)
if __name__ == '__main__':
main()

View File

@ -8,6 +8,11 @@ SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
ASTER_SRC_DIR=${SCRIPT_DIR}/../..
CARGO_TOML_PATH=${SCRIPT_DIR}/../../Cargo.toml
VERSION=$( cat ${ASTER_SRC_DIR}/VERSION )
IMAGE_NAME=asterinas/asterinas:${VERSION}
if [ "$1" = "intel-tdx" ]; then
IMAGE_NAME="asterinas/asterinas:${VERSION}-tdx"
else
IMAGE_NAME="asterinas/asterinas:${VERSION}"
fi
docker run -it --privileged --network=host --device=/dev/kvm -v ${ASTER_SRC_DIR}:/root/asterinas ${IMAGE_NAME}