diff --git a/.github/actions/dockerfiles/Dockerfile.blocklist-client.debian b/.github/actions/dockerfiles/Dockerfile.blocklist-client.debian index eb174fe67..d8049caa3 100644 --- a/.github/actions/dockerfiles/Dockerfile.blocklist-client.debian +++ b/.github/actions/dockerfiles/Dockerfile.blocklist-client.debian @@ -11,6 +11,7 @@ RUN apt-get install -y --no-install-recommends \ libssl-dev \ make \ protobuf-compiler \ + gh \ npm \ default-jre \ g++ && \ diff --git a/.github/actions/dockerfiles/Dockerfile.signer.debian b/.github/actions/dockerfiles/Dockerfile.signer.debian index 31a00610a..5229798b6 100644 --- a/.github/actions/dockerfiles/Dockerfile.signer.debian +++ b/.github/actions/dockerfiles/Dockerfile.signer.debian @@ -15,6 +15,7 @@ RUN apt-get install -y --no-install-recommends \ make \ protobuf-compiler \ npm \ + gh \ default-jre \ g++ && \ apt-get clean && rm -rf /var/lib/apt/lists/* diff --git a/.github/workflows/image-build-and-draft-release.yaml b/.github/workflows/image-build-and-draft-release.yaml index 920a5966c..c58ff6a95 100644 --- a/.github/workflows/image-build-and-draft-release.yaml +++ b/.github/workflows/image-build-and-draft-release.yaml @@ -108,6 +108,29 @@ jobs: subject-name: index.docker.io/${{ env.docker-org }}/sbtc subject-digest: ${{ steps.docker_build.outputs.digest }} push-to-registry: true + + - name: Download artifact attestation + run: | + gh attestation download oci://index.docker.io/${{ env.docker-org }}/sbtc:${{ matrix.docker_target }}-${{ github.ref_name }} -R stacks-network/sbtc + + # Rename the attestation bundle (replace ":" with "_") + ATTESTATION_FILE="$(echo "${{ steps.docker_build.outputs.digest }}.jsonl" | tr ':' '_')" + mv "${{ steps.docker_build.outputs.digest }}.jsonl" "$ATTESTATION_FILE" + echo "ATTESTATION_FILE=$ATTESTATION_FILE" >> $GITHUB_ENV + + # Generate trusted root + gh attestation trusted-root > trusted_root.jsonl + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload Attestation Files as Artifacts + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 #v4.6.1 + with: + name: attestation-files + overwrite: true + path: | + ${{ env.ATTESTATION_FILE }} + trusted_root.jsonl release: name: Draft Release diff --git a/docker/mainnet/gh-attestation/README.md b/docker/mainnet/gh-attestation/README.md new file mode 100644 index 000000000..698cf4be4 --- /dev/null +++ b/docker/mainnet/gh-attestation/README.md @@ -0,0 +1,103 @@ +# **Docker Image with Attestation Verification** + +This repository provides a Docker image that can be used to run a signer application with **attestation verification**. Before running the application, the image verifies its attestation, ensuring that the image and its contents are trusted. + +## **Features** +- **Attestation Verification**: Verifies the integrity of the Docker image before execution using GitHub's attestation tools. +- **Custom Entry Point**: Uses a custom entry point script to enforce attestation verification before running the signer app. +- **Supports Local Files for Attestation**: Instead of URLs, this setup uses local file paths for the attestation bundle and trusted root. + +--- + +## **Environment Variables** + +- `TAG`: The tag of the Docker image you want to verify (e.g., `signer-test-attestation`). +- `BUNDLE_PATH`: Local path to the attestation bundle file (e.g., `/path/to/bundle.jsonl`). +- `TRUSTED_ROOT_PATH`: Local path to the trusted root file (e.g., `/path/to/trusted_root.jsonl`). + +--- + +## **Example Docker Command:** + +To run your Docker image and perform attestation verification, use the following command: + +```bash +docker run --rm \ + -e TAG="signer" \ + -e BUNDLE_PATH="/path/to/your/bundle.jsonl" \ + -e TRUSTED_ROOT_PATH="/path/to/your/trusted_root.jsonl" \ + -v /path/to/your/bundle.jsonl:/path/to/your/bundle.jsonl \ + -v /path/to/your/trusted_root.jsonl:/path/to/your/trusted_root.jsonl \ + --entrypoint /entrypoint.sh \ + image_name \ + /usr/local/bin/signer --config /signer-config.toml --migrate-db +``` + +```bash +docker run --rm \ + -e TAG="blocklist-cli" \ + -e BUNDLE_PATH="/path/to/your/bundle.jsonl" \ + -e TRUSTED_ROOT_PATH="/path/to/your/trusted_root.jsonl" \ + -v /path/to/your/bundle.jsonl:/path/to/your/bundle.jsonl \ + -v /path/to/your/trusted_root.jsonl:/path/to/your/trusted_root.jsonl \ + --entrypoint /entrypoint.sh \ + image_name \ + /usr/local/bin/blocklist-client +``` + +This command will: +1. **Set the environment variables**: `TAG`, `BUNDLE_PATH` and `TRUSTED_ROOT_PATH` + +2. **Use [/entrypoint.sh](/docker/mainnet/gh-attestation/entrypoint.sh)**: The entrypoint of the Docker image is overridden to run the `entrypoint.sh` script, which performs the attestation verification before running the application. + +3. **Run the Signer Application**: The signer application is started with the provided configuration file (`/signer-config.toml`) and the database will be migrated using the `--migrate-db` flag. + +--- + +## **Example Docker Compose Configuration:** + +```yaml +services: + signer: + image: signer + environment: + - TAG="signer" # Set your specific image tag + - BUNDLE_PATH="/path/to/your/bundle.jsonl" + - TRUSTED_ROOT_PATH="/path/to/your/trusted_root.jsonl" + volumes: + - /path/to/your/bundle.jsonl:/path/to/your/bundle.jsonl + - /path/to/your/trusted_root.jsonl:/path/to/your/trusted_root.jsonl + entrypoint: ["/entrypoint.sh"] + command: ["/usr/local/bin/signer", "--config", "/signer-config.toml", "--migrate-db"] +``` + +```yaml +services: + signer: + image: blocklist-cli + environment: + - TAG="blocklist-cli" # Set your specific image tag + - BUNDLE_PATH="/path/to/your/bundle.jsonl" + - TRUSTED_ROOT_PATH="/path/to/your/trusted_root.jsonl" + volumes: + - /path/to/your/bundle.jsonl:/path/to/your/bundle.jsonl + - /path/to/your/trusted_root.jsonl:/path/to/your/trusted_root.jsonl + entrypoint: ["/entrypoint.sh"] + command: ["/usr/local/bin/blocklist-client"] +``` + +This will: +1. **Set up the Docker container** with the required environment variables for attestation. +2. **Use [/entrypoint.sh](/docker/mainnet/gh-attestation/entrypoint.sh)**: The entry point script checks the attestation and proceeds if verified. +3. **Run the signer application** with the provided config file and migration option. + +To start the service with Docker Compose, use: + +```bash +docker-compose up +``` +--- + +## **Additional Information** + +The image requires the GitHub CLI (`gh`) to verify the attestation. \ No newline at end of file diff --git a/docker/mainnet/gh-attestation/entrypoint.sh b/docker/mainnet/gh-attestation/entrypoint.sh new file mode 100644 index 000000000..d496ac40d --- /dev/null +++ b/docker/mainnet/gh-attestation/entrypoint.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -e # Exit on error + +# Ensure required environment variables are set +if [[ -z "$BUNDLE_PATH" || -z "$TRUSTED_ROOT_PATH" ]]; then + echo "❌ ERROR: BUNDLE_PATH and TRUSTED_ROOT_PATH environment variables must be set." + exit 1 +fi + +# Define the image and repo (since they are fixed) +IMAGE="index.docker.io/blockstack/sbtc:$TAG" # You can pass $TAG as environment variable +REPO="stacks-network/sbtc" + +# Verifying attestation +echo "✅ Verifying attestation for image: $IMAGE..." +gh attestation verify \ + oci://$IMAGE \ + -R "$REPO" \ + --bundle "$BUNDLE_PATH" \ + --custom-trusted-root "$TRUSTED_ROOT_PATH" + +# If verification succeeds, run the signer app +echo "🎉 Attestation verified successfully! Running the signer..." +exec "$@" \ No newline at end of file