From 6f9b8e0b4bb6652fd88aa28dfe74ae2e63b2b5a3 Mon Sep 17 00:00:00 2001 From: Leechael Yim Date: Sun, 29 Mar 2026 14:23:01 +0800 Subject: [PATCH] feat(key-provider): single-container image with systemd lifecycle management Consolidate aesmd and gramine-sealing-key-provider into a single container to eliminate cross-container startup ordering issues that caused cascading failures after power outage reboots. Move config to /etc so it no longer depends on external disk mounts. --- .github/workflows/key-provider-release.yml | 59 +++++++++++++++++++ key-provider-build/Dockerfile | 55 +++++++++++++++++ .../dstack-key-provider.service | 22 +++++++ key-provider-build/entrypoint.sh | 39 ++++++++++++ 4 files changed, 175 insertions(+) create mode 100644 .github/workflows/key-provider-release.yml create mode 100644 key-provider-build/Dockerfile create mode 100644 key-provider-build/dstack-key-provider.service create mode 100644 key-provider-build/entrypoint.sh diff --git a/.github/workflows/key-provider-release.yml b/.github/workflows/key-provider-release.yml new file mode 100644 index 00000000..1c852e8f --- /dev/null +++ b/.github/workflows/key-provider-release.yml @@ -0,0 +1,59 @@ +# SPDX-FileCopyrightText: © 2025 Phala Network +# +# SPDX-License-Identifier: Apache-2.0 + +name: Key Provider Release + +on: + workflow_dispatch: + push: + tags: + - 'key-provider-v*' + +permissions: + attestations: write + id-token: write + contents: write + packages: write + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Parse version from tag + run: | + VERSION=${GITHUB_REF#refs/tags/key-provider-v} + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "Parsed version: $VERSION" + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@v5 + with: + context: key-provider-build + push: true + tags: | + ghcr.io/${{ github.repository }}/gramine-sealing-key-provider:${{ env.VERSION }} + ghcr.io/${{ github.repository }}/gramine-sealing-key-provider:latest + platforms: linux/amd64 + provenance: false + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v1 + with: + subject-name: "ghcr.io/${{ github.repository }}/gramine-sealing-key-provider" + subject-digest: ${{ steps.build-and-push.outputs.digest }} + push-to-registry: true diff --git a/key-provider-build/Dockerfile b/key-provider-build/Dockerfile new file mode 100644 index 00000000..e7740005 --- /dev/null +++ b/key-provider-build/Dockerfile @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: © 2024-2025 Phala Network +# +# SPDX-License-Identifier: Apache-2.0 + +# Stage 1: Build +FROM gramineproject/gramine:1.9-jammy@sha256:84b3d222e0bd9ab941f0078a462af0dbc5518156b99b147c10a7b83722ac0c38 AS builder + +RUN apt-get update && apt-get install -y \ + git \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain 1.85 -y +ENV PATH="/root/.cargo/bin:${PATH}" + +ENV SGX=1 DEBUG=0 DEV_MODE=0 RUST_LOG=info + +RUN git clone https://github.com/MoeMahhouk/gramine-sealing-key-provider && \ + cd gramine-sealing-key-provider && \ + git checkout 180ff4691dce5aae7cd7d6c1344c3e1ec872f174 + +WORKDIR /gramine-sealing-key-provider +COPY Cargo.lock . + +RUN make target/release/gramine-sealing-key-provider && \ + gramine-sgx-gen-private-key && \ + make RUST_LOG=info + +# Stage 2: Runtime +# Same base image = same /lib/x86_64-linux-gnu/ (except libgcc-s1 from build-essential) +FROM gramineproject/gramine:1.9-jammy@sha256:84b3d222e0bd9ab941f0078a462af0dbc5518156b99b147c10a7b83722ac0c38 + +# libgcc-s1: only /lib/x86_64-linux-gnu/ addition from build-essential, needed for manifest hash match +# libsgx-dcap-default-qpl: not in base image, needed by aesmd for DCAP +RUN curl -fsSL https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key \ + | gpg --dearmor -o /usr/share/keyrings/intel-sgx-deb.gpg && \ + echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/intel-sgx-deb.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu jammy main' \ + > /etc/apt/sources.list.d/intel-sgx.list && \ + apt-get update && apt-get install -y \ + libgcc-s1 \ + libsgx-dcap-default-qpl \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /gramine-sealing-key-provider/target/release/gramine-sealing-key-provider /gramine-sealing-key-provider/target/release/gramine-sealing-key-provider +COPY --from=builder /gramine-sealing-key-provider/gramine-sealing-key-provider.manifest.sgx /gramine-sealing-key-provider/ +COPY --from=builder /gramine-sealing-key-provider/gramine-sealing-key-provider.sig /gramine-sealing-key-provider/ + +WORKDIR /gramine-sealing-key-provider + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +EXPOSE 3443 + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/key-provider-build/dstack-key-provider.service b/key-provider-build/dstack-key-provider.service new file mode 100644 index 00000000..a7622e9c --- /dev/null +++ b/key-provider-build/dstack-key-provider.service @@ -0,0 +1,22 @@ +[Unit] +Description=Gramine Sealing Key Provider +After=docker.service +Requires=docker.service + +[Service] +Type=simple +ExecStartPre=-/usr/bin/docker rm -f gramine-sealing-key-provider +ExecStart=/usr/bin/docker run --rm \ + --name gramine-sealing-key-provider \ + --privileged \ + --device /dev/sgx_enclave:/dev/sgx_enclave \ + --device /dev/sgx_provision:/dev/sgx_provision \ + -v /etc/dstack-key-provider/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf \ + -p 127.0.0.1:3443:3443 \ + ghcr.io/dstack-tee/dstack/gramine-sealing-key-provider:latest +ExecStop=/usr/bin/docker stop gramine-sealing-key-provider +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target diff --git a/key-provider-build/entrypoint.sh b/key-provider-build/entrypoint.sh new file mode 100644 index 00000000..96b3d5bc --- /dev/null +++ b/key-provider-build/entrypoint.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +# SPDX-FileCopyrightText: © 2025 Phala Network +# +# SPDX-License-Identifier: Apache-2.0 + +set -e + +# Start AESM service in background +echo "Starting AESM service..." +mkdir -p /var/run/aesmd +chmod 755 /var/run/aesmd +export AESM_PATH=/opt/intel/sgx-aesm-service/aesm +export LD_LIBRARY_PATH=/opt/intel/sgx-aesm-service/aesm +/opt/intel/sgx-aesm-service/aesm/aesm_service --no-daemon & +AESM_PID=$! + +# Clean up aesmd on exit +trap "kill $AESM_PID 2>/dev/null; exit" INT TERM EXIT + +# Wait for AESM socket +echo "Waiting for AESM socket..." +AESM_SOCKET="/var/run/aesmd/aesm.socket" +while [ ! -S "$AESM_SOCKET" ]; do + if ! kill -0 "$AESM_PID" 2>/dev/null; then + echo "Error: AESM service exited unexpectedly" + exit 1 + fi + sleep 1 +done +echo "AESM socket is available." + +# Show enclave info +echo "Enclave info:" +gramine-sgx-sigstruct-view --output-format json gramine-sealing-key-provider.sig + +# Replace shell with gramine-sgx so it receives signals directly as PID 1 +echo "Starting Gramine Sealing Key Provider" +exec gramine-sgx gramine-sealing-key-provider