-
Notifications
You must be signed in to change notification settings - Fork 215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gramine-SGX Container TEE support #1140
Merged
MasterSkepticista
merged 20 commits into
securefederatedai:develop
from
MasterSkepticista:dockerize_gramine
Nov 15, 2024
Merged
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
c23d7e8
Download src only for packages that exist on pip
MasterSkepticista ec25130
Install Gramine in base image
MasterSkepticista b70e4e1
Install Gramine in base image
MasterSkepticista b3297c0
Merge branch 'develop' into dockerize_gramine
MasterSkepticista 004e99f
Add enclave template
MasterSkepticista 1965115
SGX option in dockerize
MasterSkepticista 8bafc05
Remove /keys
MasterSkepticista 9be298c
Remove /host_save_path
MasterSkepticista 382151f
Simplify variables and constants
MasterSkepticista e0e95f9
Cleanup manifest and makefile; less hardcode
MasterSkepticista fe91455
Make venv default
MasterSkepticista 80e34ec
Remove --sgx-ready flag
MasterSkepticista 5952ef0
Store enclave measurement in file
MasterSkepticista f76875e
Rename dockerization.yml to tr_docker_native.yml
MasterSkepticista 31c209a
Add TaskRunner Gramine-Direct CI E2E test
MasterSkepticista ff1619c
Update command help
MasterSkepticista 12756b1
Rename tests
MasterSkepticista d5f3f0a
Merge branch 'develop' into dockerize_gramine
MasterSkepticista e4139ae
Add README.md
MasterSkepticista 9d9a624
Merge branch 'develop' into dockerize_gramine
MasterSkepticista File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# Tests an FL experiment in a Dockerized environment. | ||
name: TaskRunner (docker/gramine-direct) | ||
|
||
on: | ||
pull_request: | ||
branches: [ develop ] | ||
types: [opened, synchronize, reopened, ready_for_review] | ||
|
||
permissions: | ||
contents: read | ||
|
||
jobs: | ||
build: | ||
if: github.event.pull_request.draft == false | ||
runs-on: ubuntu-latest | ||
timeout-minutes: 10 | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Set up Python 3.8 | ||
uses: actions/setup-python@v3 | ||
with: | ||
python-version: "3.8" | ||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install . | ||
|
||
- name: Create workspace image | ||
run: | | ||
fx workspace create --prefix example_workspace --template keras_cnn_mnist | ||
cd example_workspace | ||
fx plan initialize -a localhost | ||
fx workspace dockerize --save --revision https://github.com/${GITHUB_REPOSITORY}.git@${{ github.event.pull_request.head.sha }} | ||
|
||
- name: Create certificate authority for workspace | ||
run: | | ||
cd example_workspace | ||
fx workspace certify | ||
|
||
- name: Create signed cert for collaborator | ||
run: | | ||
cd example_workspace | ||
fx collaborator create -d 1 -n charlie --silent | ||
fx collaborator generate-cert-request -n charlie --silent | ||
fx collaborator certify --request-pkg col_charlie_to_agg_cert_request.zip --silent | ||
|
||
# Pack the collaborator's private key, signed cert, and data.yaml into a tarball | ||
tarfiles="plan/data.yaml agg_to_col_charlie_signed_cert.zip" | ||
for entry in cert/client/*; do | ||
if [[ "$entry" == *.key ]]; then | ||
tarfiles="$tarfiles $entry" | ||
fi | ||
done | ||
|
||
tar -cf cert_col_charlie.tar $tarfiles | ||
|
||
# Clean up | ||
rm -f $tarfiles | ||
rm -f col_charlie_to_agg_cert_request.zip | ||
|
||
- name: Create signed cert for aggregator | ||
run: | | ||
cd example_workspace | ||
fx aggregator generate-cert-request --fqdn localhost | ||
fx aggregator certify --fqdn localhost --silent | ||
|
||
# Pack all files that aggregator needs to start training | ||
tar -cf cert_agg.tar plan cert save | ||
|
||
# Remove the directories after archiving | ||
rm -rf plan cert save | ||
|
||
- name: Load workspace image | ||
run: | | ||
cd example_workspace | ||
docker load -i example_workspace.tar | ||
|
||
- name: Run aggregator and collaborator | ||
run: | | ||
cd example_workspace | ||
|
||
set -x | ||
docker run --rm \ | ||
--network host \ | ||
--security-opt seccomp=unconfined \ | ||
--mount type=bind,source=./cert_agg.tar,target=/certs.tar \ | ||
--env KERAS_HOME=/tmp \ | ||
example_workspace bash -c "tar -xf /certs.tar && gramine-direct fx aggregator start" & | ||
|
||
# TODO: Run with two collaborators instead. | ||
docker run --rm \ | ||
--network host \ | ||
--security-opt seccomp=unconfined \ | ||
--mount type=bind,source=./cert_col_charlie.tar,target=/certs.tar \ | ||
--env KERAS_HOME=/tmp \ | ||
example_workspace bash -c "tar -xf /certs.tar && fx collaborator certify --import agg_to_col_charlie_signed_cert.zip && gramine-direct fx collaborator start -n charlie" |
2 changes: 1 addition & 1 deletion
2
.github/workflows/dockerization.yml → .github/workflows/tr_docker_native.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
# Copyright (C) 2024 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
# ------------------------------------ | ||
# OpenFL Base Image | ||
# OpenFL Base Image w/ Gramine support | ||
# $> docker build . -t openfl -f Dockerfile.base [--build-arg OPENFL_REVISION=GIT_URL@COMMIT_ID] | ||
# ------------------------------------ | ||
FROM ubuntu:22.04 AS base | ||
|
@@ -15,25 +15,41 @@ RUN --mount=type=cache,id=apt-dev,target=/var/cache/apt \ | |
apt-get update && \ | ||
apt-get install -y \ | ||
git \ | ||
curl \ | ||
python3-pip \ | ||
python3.10-dev \ | ||
python3.10-venv \ | ||
ca-certificates \ | ||
build-essential \ | ||
--no-install-recommends && \ | ||
apt-get purge -y linux-libc-dev && \ | ||
rm -rf /var/lib/apt/lists/* | ||
|
||
# Create a python virtual environment. | ||
RUN python3.10 -m venv /opt/venv && \ | ||
/opt/venv/bin/pip install --no-cache-dir --upgrade pip setuptools wheel | ||
ENV PATH=/opt/venv/bin:$PATH | ||
|
||
# Install Gramine | ||
RUN --mount=type=cache,id=apt-dev,target=/var/cache/apt \ | ||
curl -fsSLo /usr/share/keyrings/gramine-keyring.gpg https://packages.gramineproject.io/gramine-keyring.gpg && \ | ||
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/gramine-keyring.gpg] https://packages.gramineproject.io/ jammy main" \ | ||
| tee /etc/apt/sources.list.d/gramine.list && \ | ||
curl -fsSLo /usr/share/keyrings/intel-sgx-deb.asc https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key && \ | ||
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/intel-sgx-deb.asc] https://download.01.org/intel-sgx/sgx_repo/ubuntu jammy main" \ | ||
| tee /etc/apt/sources.list.d/intel-sgx.list && \ | ||
apt-get update && \ | ||
apt-get install -y gramine --no-install-recommends && \ | ||
rm -rf /var/lib/apt/lists/* | ||
|
||
# Install OpenFL. | ||
ARG OPENFL_REVISION=https://github.com/securefederatedai/[email protected] | ||
RUN pip install --no-cache-dir git+${OPENFL_REVISION} && \ | ||
INSTALL_SOURCES=yes /opt/venv/lib/python3.10/site-packages/openfl-docker/licenses.sh | ||
|
||
# Create an unprivileged user. | ||
RUN groupadd -g 1001 default && \ | ||
useradd -m -u 1001 -g default user | ||
USER user | ||
WORKDIR /home/user | ||
ENV PATH=/home/user/.local/bin:$PATH | ||
|
||
# Install OpenFL. | ||
ARG OPENFL_REVISION=https://github.com/securefederatedai/[email protected] | ||
RUN pip install --no-cache-dir -U pip setuptools wheel && \ | ||
pip install --no-cache-dir git+${OPENFL_REVISION} && \ | ||
INSTALL_SOURCES=yes /home/user/.local/lib/python3.10/site-packages/openfl-docker/licenses.sh | ||
|
||
CMD ["/bin/bash"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,33 @@ | ||
# Copyright (C) 2024 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
# ------------------------------------ | ||
# Workspace Image | ||
# Gramine-ready Workspace Image | ||
# Usage: | ||
# $> docker build . -t openfl-workspace -f Dockerfile.workspace \ | ||
# [--build-arg BASE_IMAGE=openfl:latest] \ | ||
# [--build-arg WORKSPACE_NAME=WORKSPACE_NAME] \ | ||
# [--secret id=signer-key,src=signer-key.pem] | ||
# ------------------------------------ | ||
ARG BASE_IMAGE=openfl:latest | ||
FROM ${BASE_IMAGE} | ||
|
||
USER root | ||
SHELL ["/bin/bash", "-o", "pipefail", "-c"] | ||
|
||
USER user | ||
# Import workspace | ||
WORKDIR / | ||
ARG WORKSPACE_NAME | ||
COPY ${WORKSPACE_NAME}.zip . | ||
RUN fx workspace import --archive ${WORKSPACE_NAME}.zip && \ | ||
pip install --no-cache-dir -r ${WORKSPACE_NAME}/requirements.txt | ||
COPY ${WORKSPACE_NAME}.zip /workspace.zip | ||
RUN fx workspace import --archive /workspace.zip && \ | ||
pip install --no-cache-dir -r /workspace/requirements.txt | ||
|
||
# Build enclaves | ||
WORKDIR /workspace | ||
RUN --mount=type=secret,id=signer-key,dst=/key.pem \ | ||
cp -r /opt/venv/lib/python3.10/site-packages/openfl-docker/gramine_app/* /workspace/ && \ | ||
make SGX=1 SGX_SIGNER_KEY=/key.pem >> fx.mr_enclave && \ | ||
echo "$(cat fx.mr_enclave)" && \ | ||
chown -R user /workspace | ||
|
||
WORKDIR /home/user/${WORKSPACE_NAME} | ||
USER user | ||
CMD ["/bin/bash"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Using OpenFL within a Container | ||
|
||
OpenFL can be used within a container for simulating Federated Learning experiments, or to deploy real-world experiments within Trusted Execution Environments (TEEs). | ||
|
||
## Base Image | ||
|
||
To develop or simulate experiments within a container, build the base image (or pull one from docker hub). | ||
|
||
```shell | ||
# Pull latest stable base image | ||
$> docker pull intel/openfl | ||
|
||
# Or, build a base image from the latest source code | ||
$> docker build . -t openfl -f Dockerfile.base \ | ||
--build-arg OPENFL_REVISION=https://github.com/securefederatedai/openfl.git@develop | ||
``` | ||
|
||
Run the container: | ||
```shell | ||
user@vm:~/openfl$ docker run -it --rm openfl:latest bash | ||
user@7b40624c207a:/$ fx | ||
OpenFL - Open Federated Learning | ||
|
||
BASH COMPLETE ACTIVATION | ||
|
||
Run in terminal: | ||
_FX_COMPLETE=bash_source fx > ~/.fx-autocomplete.sh | ||
source ~/.fx-autocomplete.sh | ||
If ~/.fx-autocomplete.sh has already exist: | ||
source ~/.fx-autocomplete.sh | ||
|
||
CORRECT USAGE | ||
|
||
fx [options] [command] [subcommand] [args] | ||
``` | ||
|
||
## Deployment | ||
This section assumes familiarity with the [TaskRunner API](https://openfl.readthedocs.io/en/latest/about/features_index/taskrunner.html#running-the-task-runner). | ||
|
||
### Building a workspace image | ||
OpenFL supports [Gramine-based](https://gramine.readthedocs.io/en/stable/) TEEs that run within SGX. | ||
|
||
To build a TEE-ready workspace image, run the following command from an existing workspace directory. Ensure PKI setup and plan confirmations are done before this step. | ||
|
||
```shell | ||
# Optional, generate an enclave signing key (auto-generated otherwise) | ||
user@vm:~/example_workspace$ openssl genrsa -out key.pem -3 3072 | ||
user@vm:~/example_workspace$ fx workspace dockerize --enclave-key ./key.pem --save | ||
``` | ||
This command builds the base image and a TEE-ready workspace image. Refer to `fx workspace dockerize --help` for more details. | ||
|
||
A signed docker image named `example_workspace.tar` will be saved in the workspace. This image (along with respective PKI certificates) can be shared across participating entities. | ||
|
||
### Running without a TEE | ||
Using native `fx` command within the image will run the experiment without TEEs. | ||
|
||
```shell | ||
# Aggregator | ||
docker run --rm \ | ||
--network host \ | ||
--mount type=bind,source=./certs.tar,target=/certs.tar \ | ||
example_workspace bash -c "fx aggregator start ..." | ||
|
||
# Collaborator(s) | ||
docker run --rm \ | ||
--network host \ | ||
--mount type=bind,source=./certs.tar,target=/certs.tar \ | ||
example_workspace bash -c "fx collaborator start ..." | ||
``` | ||
|
||
### Running within a TEE | ||
To run `fx` within a TEE, mount SGX device and AESMD volumes. In addition, prefix the `fx` command with `gramine-sgx` directive. | ||
```shell | ||
# Aggregator | ||
docker run --rm \ | ||
--network host \ | ||
--device=/dev/sgx_enclave \ | ||
-v /var/run/aesmd/aesm.socket:/var/run/aesmd/aesm.socket \ | ||
--mount type=bind,source=./certs.tar,target=/certs.tar \ | ||
example_workspace bash -c "gramine-sgx fx aggregator start ..." | ||
|
||
# Collaborator(s) | ||
docker run --rm \ | ||
--network host \ | ||
--device=/dev/sgx_enclave \ | ||
-v /var/run/aesmd/aesm.socket:/var/run/aesmd/aesm.socket \ | ||
--mount type=bind,source=./certs.tar,target=/certs.tar \ | ||
example_workspace bash -c "gramine-sgx fx collaborator start ..." | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Copyright (C) 2024 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
# ------------------------------------ | ||
# Makefile for Gramine application within a container | ||
# Usage: | ||
# 1. Activate the python venv. | ||
# 2. Provide paths VENV_ROOT and WORKSPACE_ROOT. | ||
# 3. make SGX=0/1 [SGX_SIGNER_KEY=<path_to_sgx_signer_key>] | ||
# ------------------------------------ | ||
VENV_ROOT ?= $(shell dirname $(shell dirname $(shell which python))) | ||
WORKSPACE_ROOT ?= $(shell pwd) | ||
ARCH_LIBDIR ?= /lib/$(shell $(CC) -dumpmachine) | ||
SGX_SIGNER_KEY ?= /key.pem | ||
|
||
ifeq ($(DEBUG),1) | ||
GRAMINE_LOG_LEVEL = debug | ||
else | ||
GRAMINE_LOG_LEVEL = error | ||
endif | ||
|
||
.PHONY: all | ||
all: fx.manifest | ||
ifeq ($(SGX),1) | ||
all: fx.manifest.sgx fx.sig | ||
endif | ||
|
||
fx.manifest: fx.manifest.template | ||
@echo "Making fx.manifest file" | ||
gramine-manifest \ | ||
-Dlog_level=$(GRAMINE_LOG_LEVEL) \ | ||
-Darch_libdir=$(ARCH_LIBDIR) \ | ||
-Dvenv_root=$(VENV_ROOT) \ | ||
-Dentrypoint=$(VENV_ROOT)/bin/fx \ | ||
-Dworkspace_root=$(WORKSPACE_ROOT) \ | ||
$< >$@ | ||
|
||
fx.manifest.sgx: fx.manifest | ||
@echo "Making fx.manifest.sgx file" | ||
@test -s $(SGX_SIGNER_KEY) || \ | ||
{ echo "SGX signer private key was not found, please specify SGX_SIGNER_KEY!"; exit 1; } | ||
@gramine-sgx-sign \ | ||
--key $(SGX_SIGNER_KEY) \ | ||
--manifest $< \ | ||
--output $@ | tail -n 1 | tr -d ' ' | xargs -I {} echo "fx.mr_enclave={}" | ||
|
||
fx.sig: fx.manifest.sgx | ||
|
||
.PHONY: clean | ||
clean: | ||
$(RM) *.manifest *.manifest.sgx *.token *.sig OUTPUT* *.PID TEST_STDOUT TEST_STDERR | ||
$(RM) -r scripts/__pycache__ | ||
|
||
.PHONY: distclean | ||
distclean: clean |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this image automatically uploaded on each OpenFL release?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the scripts here are used to publish latest wheels and images.
Following 1.7, OpenFL base image will come bundled with Gramine (and ability to build SGX-ready workspaces).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, the
intel/openfl
image seems relatively up to date. The one I just pulled is marked as created "27 hours ago" - likely by some automated workflow. I guess I'm a little worried because those scripts are really old (3-4 years), and I don't understand the publishing workflow. But maybe you have better confidence in this process.Just in case, have you tested the graminization workflow with this image, rather than the one built locally?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure of the publishing workflow either. We should revisit this.
Dockerize with Gramine won't work with any older commits/tags/releases for graminized workspaces. Part of the process is copying manifest/makefiles from the source code (which means it must be at least the latest commit that this PR points to).
I agree that this is a little painful as we have to wait for next major release until users can benefit from this. Best would be if users always git clone the tip of develop.