-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 70bbb42
Showing
13 changed files
with
545 additions
and
0 deletions.
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,112 @@ | ||
name: Build and Release | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
pull_request: | ||
branches: [main] | ||
|
||
permissions: | ||
contents: write | ||
|
||
jobs: | ||
build-and-release: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Set up Python | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: '3.11' | ||
|
||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v2 | ||
|
||
- name: Build Docker image | ||
uses: docker/build-push-action@v4 | ||
with: | ||
context: . | ||
load: true | ||
tags: | | ||
my-proof:${{ github.run_number }} | ||
my-proof:latest | ||
cache-from: type=gha | ||
cache-to: type=gha,mode=max | ||
|
||
- name: Clone and set up GSC | ||
run: | | ||
git clone https://github.com/gramineproject/gsc.git | ||
cd gsc | ||
python3 -m pip install --no-cache-dir 'docker>=7.1.0' 'jinja2>=3.1.4' 'tomli>=2.0.1' 'tomli-w>=1.0.0' 'pyyaml>=6.0.2' | ||
- name: Create signing key | ||
run: | | ||
echo "${{ secrets.SIGNING_KEY }}" > signing_key.pem | ||
chmod 600 signing_key.pem | ||
- name: Build GSC image | ||
run: | | ||
cd gsc | ||
./gsc build my-proof ../my-proof.manifest.template -c ../config.yaml | ||
- name: Sign GSC image | ||
run: | | ||
cd gsc | ||
./gsc sign-image my-proof ../signing_key.pem -c ../config.yaml | ||
- name: Export GSC image to file | ||
run: | | ||
docker save gsc-my-proof:latest | gzip > gsc-my-proof-${{ github.run_number }}.tar.gz | ||
- name: Generate verification data | ||
run: | | ||
cd gsc | ||
./gsc info-image gsc-my-proof > ../sigstruct.txt | ||
- name: Upload image | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: gsc-my-proof-image | ||
path: gsc-my-proof-${{ github.run_number }}.tar.gz | ||
|
||
- name: Upload verification data | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: gsc-my-proof-sigstruct | ||
path: sigstruct.txt | ||
|
||
- name: Generate release body | ||
run: | | ||
echo "MRSIGNER: $(grep -oP 'mr_signer = "\K[^"]*' sigstruct.txt)" >> release_body.txt | ||
echo "MRENCLAVE: $(grep -oP 'mr_enclave = "\K[^"]*' sigstruct.txt)" >> release_body.txt | ||
echo "Image SHA256: $(sha256sum gsc-my-proof-${{ github.run_number }}.tar.gz | cut -d' ' -f1)" >> release_body.txt | ||
- name: Create Release and Upload Assets | ||
uses: softprops/action-gh-release@v1 | ||
if: github.event_name == 'push' && github.ref == 'refs/heads/main' | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
with: | ||
tag_name: v${{ github.run_number }} | ||
name: Release v${{ github.run_number }} | ||
body_path: release_body.txt | ||
draft: false | ||
prerelease: false | ||
files: | | ||
./gsc-my-proof-${{ github.run_number }}.tar.gz | ||
./sigstruct.txt | ||
- name: Cleanup signing key | ||
if: always() | ||
run: | | ||
rm -f signing_key.pem | ||
- name: Log build result | ||
if: always() | ||
run: | | ||
if [ ${{ job.status }} == "success" ]; then | ||
echo "Build and release completed successfully" | ||
else | ||
echo "Build and release failed" | ||
fi |
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,9 @@ | ||
*.pem | ||
*.tar.gz | ||
__pycache__/ | ||
*.pyc | ||
|
||
demo/* | ||
!demo/input/ | ||
|
||
.idea/ |
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,15 @@ | ||
FROM python:3.12-slim | ||
|
||
# Install any Python dependencies your application needs, e.g.: | ||
RUN pip install --no-cache-dir requests | ||
|
||
RUN mkdir /sealed && chmod 777 /sealed | ||
|
||
WORKDIR /app | ||
|
||
COPY . /app | ||
|
||
# Install any needed packages specified in requirements.txt | ||
RUN pip install --no-cache-dir -r requirements.txt | ||
|
||
CMD ["python", "-m", "my_proof"] |
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,8 @@ | ||
The MIT License (MIT) | ||
Copyright © 2024 Corsali, Inc. dba Vana | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
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,144 @@ | ||
# VanaTensor Satya Proof of Contribution | ||
|
||
This repository creating a [proof of contribution](https://docs.vana.org/vana/core-concepts/key-elements/proof-of-contribution) tasks using Python. It is executed on Vana's Satya Network, a group of highly confidential and secure compute nodes that can validate data without revealing its contents to the node operator. | ||
|
||
## Overview | ||
|
||
This poc provides a basic structure for building proof tasks that: | ||
|
||
1. Read input files from the `/input` directory. | ||
2. Process the data securely, running any necessary validations to prove the data authentic, unique, high quality, etc. | ||
3. Write proof results to the `/output/results.json` file in the following format: | ||
|
||
```json | ||
{ | ||
"dlp_id": 1234, // DLP ID is found in the Root Network contract after the DLP is registered | ||
"valid": false, // A single boolean to summarize if the file is considered valid in this DLP | ||
"score": 0.7614457831325301, // A score between 0 and 1 for the file, used to determine how valuable the file is. This can be an aggregation of the individual scores below. | ||
"authenticity": 1.0, // A score between 0 and 1 to rate if the file has been tampered with | ||
"ownership": 1.0, // A score between 0 and 1 to verify the ownership of the file | ||
"quality": 0.6024096385542169, // A score between 0 and 1 to show the quality of the file | ||
"uniqueness": 0, // A score between 0 and 1 to show unique the file is, compared to others in the DLP | ||
"attributes": { // Custom attributes that can be added to the proof to provide extra context about the encrypted file | ||
"total_score": 0.5, | ||
"score_threshold": 0.83, | ||
"email_verified": true | ||
} | ||
} | ||
``` | ||
|
||
The project is designed to work with [Gramine](https://gramine.readthedocs.io/en/latest/), a lightweight library OS that enables running unmodified applications in secure enclaves, such as Intel SGX (Software Guard Extensions). This allows the code to run in a trusted execution environment, ensuring confidentiality and integrity of the computation. | ||
|
||
## Project Structure | ||
|
||
- `my_proof/`: Contains the main proof logic | ||
- `proof.py`: Implements the proof generation logic | ||
- `__main__.py`: Entry point for the proof execution | ||
- `demo/`: Contains sample input and output for testing | ||
- `.github/workflows/`: CI/CD pipeline for building and releasing | ||
- `Dockerfile`: Defines the container image for the proof task | ||
- `my-proof.manifest.template`: Gramine manifest template for running securely in an Intel SGX enclave | ||
- `config.yaml`: Configuration file for Gramine Shielded Containers (GSC) | ||
|
||
## Customizing the Proof Logic | ||
|
||
The main proof logic is implemented in `my_proof/proof.py`. To customize it, update the `Proof.generate()` function to change how input files are processed. | ||
|
||
The proof can be configured using environment variables. When running in an enclave, the environment variables must be defined in the `my-proof.manifest.template` file as well. The following environment variables are used for the VanaTensor DLP dataset proof: | ||
|
||
- `USER_EMAIL`: The email address of the data contributor, to verify data ownership | ||
|
||
## Local Development | ||
|
||
To run the proof locally, without Gramine, you can use Docker: | ||
|
||
``` | ||
docker build -t my-proof . | ||
docker run \ | ||
--rm \ | ||
--volume $(pwd)/demo/sealed:/sealed \ | ||
--volume $(pwd)/demo/input:/input \ | ||
--volume $(pwd)/demo/output:/output \ | ||
--env [email protected] \ | ||
my-proof | ||
``` | ||
|
||
## Building and Releasing | ||
|
||
This includes a GitHub Actions workflow that automatically: | ||
|
||
1. Builds a Docker image with your code | ||
2. Creates a Gramine-shielded container (GSC) image | ||
3. Publishes the GSC image as a GitHub release | ||
|
||
**Important:** To use this workflow, you must generate a signing key and add it to your GitHub secrets. Follow these steps: | ||
|
||
1. Generate a signing key (see instructions below) | ||
2. Add the key as a GitHub secret named `SIGNING_KEY` | ||
3. Push your changes to the `main` branch or create a pull request | ||
|
||
### Generating the Gramine Signing Key (Required) | ||
|
||
Before building and signing your graminized Docker image, you must generate a signing key. This key is crucial for creating secure SGX enclaves. Here's how to generate it: | ||
|
||
1. If you have Gramine installed: | ||
|
||
``` | ||
gramine-sgx-gen-private-key enclave-key.pem | ||
``` | ||
|
||
2. If you don't have Gramine, use OpenSSL: | ||
|
||
``` | ||
openssl genrsa -3 -out enclave-key.pem 3072 | ||
``` | ||
|
||
After generating the key: | ||
|
||
1. Keep this key secure, as it will be used to sign your enclaves. | ||
2. Add the contents of `enclave-key.pem` as a GitHub secret named `SIGNING_KEY`. | ||
|
||
This key is essential for the `gsc sign-image` step in the GSC workflow. | ||
|
||
## Running with SGX | ||
|
||
Intel SGX (Software Guard Extensions) is a set of security-related instruction codes built into modern Intel CPUs. It allows parts of a program to be executed in a secure enclave, isolated from the rest of the system. | ||
|
||
To load a released image with docker, copy the URL from the release and run: | ||
|
||
``` | ||
curl -L https://address/of/gsc-my-proof.tar.gz | docker load | ||
``` | ||
|
||
To run the image: | ||
|
||
``` | ||
docker run \ | ||
--rm \ | ||
--volume /gsc-my-proof/input:/input \ | ||
--volume /gsc-my-proof/output:/output \ | ||
--device /dev/sgx_enclave:/dev/sgx_enclave \ | ||
--volume /var/run/aesmd:/var/run/aesmd \ | ||
--volume /mnt/gsc-my-proof/sealed:/sealed \ | ||
--env [email protected] \ | ||
gsc-my-proof | ||
``` | ||
|
||
Remember to populate the `/input` directory with the files you want to process. | ||
|
||
## Security Features | ||
|
||
This proof leverages several security features: | ||
|
||
1. **Secure Enclaves**: The proof runs inside an SGX enclave, isolating it from the rest of the system. | ||
2. **Encrypted Storage**: The `/sealed` directory is automatically encrypted/decrypted by Gramine, providing secure storage for sensitive data. | ||
3. **Input/Output Isolation**: Input and output directories are mounted separately, ensuring clear data flow boundaries. | ||
4. **Minimal Attack Surface**: The Gramine manifest limits the files and resources accessible to the enclave, reducing potential vulnerabilities. | ||
|
||
## Contributing | ||
|
||
If you have suggestions for improving this poc, please open an issue or submit a pull request. | ||
|
||
## License | ||
|
||
[MIT License](LICENSE) |
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,55 @@ | ||
# NOTE: This file was copied from https://github.com/gramineproject/gsc/blob/fcf96546f4a23a4e6bcc6a14d80cf1521c018fc9/config.yaml.template | ||
|
||
# | ||
# Specify the OS distro that is used to build Gramine, i.e., the distro from where the Gramine build | ||
# gets all tools and dependencies from. This distro should match the distro underlying the | ||
# application's Docker image; otherwise the results may be unpredictable (if you specify `"auto"`, | ||
# which is recommended, you don't need to worry about the mismatch). | ||
# | ||
# Currently supported distros are: | ||
# - ubuntu:20.04, ubuntu:21.04, ubuntu:22.04, ubuntu:23.04 | ||
# - debian:10, debian:11, debian:12 | ||
# - centos:8 | ||
# - quay.io/centos/centos:stream9 | ||
# - redhat/ubi8:8.8, redhat/ubi9:9.4 | ||
# - redhat/ubi8-minimal:8.8, redhat/ubi9-minimal:9.4 | ||
|
||
# If Distro is set to "auto", GSC detects the distro automatically by examining the supplied | ||
# Docker image. Alternatively, Distro can be set to one of the supported distros mentioned above. | ||
Distro: "auto" | ||
|
||
# If the image has a specific registry, define it here. | ||
# Empty by default; example value: "registry.access.redhat.com/ubi8". | ||
Registry: "" | ||
|
||
# If you're using your own fork and branch of Gramine, specify the GitHub link and the branch name | ||
# below; typically, you want to keep the default values though. | ||
# | ||
# It is also possible to specify the prebuilt Gramine Docker image (that was built previously via | ||
# the `gsc build-gramine` command). For this, remove Repository and Branch and instead write: | ||
# Image: "<prebuilt Gramine Docker image>" | ||
# | ||
# GSC releases are guaranteed to work with corresponding Gramine releases (and GSC `master` | ||
# branch is guaranteed to work with current Gramine `master` branch). | ||
Gramine: | ||
Repository: "https://github.com/gramineproject/gramine.git" | ||
Branch: "master" | ||
|
||
# Specify the Intel SGX driver installed on your machine (more specifically, on the machine where | ||
# the graminized Docker container will run); there are several variants of the SGX driver: | ||
# | ||
# - upstream (in-kernel) driver: use empty values like below | ||
# Repository: "" | ||
# Branch: "" | ||
# | ||
# - DCAP out-of-tree driver: same as above, use empty values | ||
# Repository: "" | ||
# Branch: "" | ||
# | ||
# - legacy out-of-tree driver: use something like the below values, but adjust the branch name | ||
# Repository: "https://github.com/01org/linux-sgx-driver.git" | ||
# Branch: "sgx_driver_1.9" | ||
# | ||
SGXDriver: | ||
Repository: "" | ||
Branch: "" |
Binary file not shown.
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,31 @@ | ||
# Adjust this as needed. | ||
sgx.enclave_size = "256M" | ||
|
||
# Increase this as needed, e.g., if you run a web server. | ||
sgx.max_threads = 4 | ||
|
||
# Whitelist ENV variables that get passed to the enclave | ||
# Using { passthrough = true } allows values to be passed in from the Satya node's /RunProof endpoint | ||
loader.env.USER_EMAIL = { passthrough = true } | ||
|
||
# Gramine gives a warning that allowed_files is not safe in production, but it | ||
# should generally be fine for our use case which inherently assumes that input | ||
# files are untrusted until proven otherwise. | ||
sgx.allowed_files = [ | ||
"file:/input/", | ||
"file:/output/", | ||
# Required for internet access from inside the enclave | ||
"file:/etc/hosts", | ||
"file:/etc/resolv.conf", | ||
] | ||
|
||
# These directories are mounted from the host, which will be a temporary directory from the Satya node that's running the proof. | ||
fs.mounts = [ | ||
{ type = "encrypted", path = "/sealed", uri = "file:/sealed", key_name = "_sgx_mrenclave" }, | ||
{ path = "/input", uri = "file:/input" }, | ||
{ path = "/output", uri = "file:/output" }, | ||
] | ||
|
||
# You can add other Gramine-manifest-compatible options as needed, see the | ||
# Gramine documentation for more details: https://gramine.readthedocs.io. Note | ||
# that gsc defines a number of manifest settings by default. |
Empty file.
Oops, something went wrong.