diff --git a/cloud-computing/go-hello-world/Dockerfile b/cloud-computing/go-hello-world/Dockerfile new file mode 100644 index 00000000..d72223c9 --- /dev/null +++ b/cloud-computing/go-hello-world/Dockerfile @@ -0,0 +1,10 @@ +# same version as Scone +FROM golang:1.16.0-alpine3.13 + +RUN apk --update add gcc build-base gcc-go + +COPY ./src /app + +RUN go build -compiler=gccgo -buildmode=exe -o /app/helloworld /app/helloworld.go + +ENTRYPOINT ["/app/helloworld"] diff --git a/cloud-computing/go-hello-world/README.md b/cloud-computing/go-hello-world/README.md new file mode 100644 index 00000000..19a42317 --- /dev/null +++ b/cloud-computing/go-hello-world/README.md @@ -0,0 +1,68 @@ +# Go hello-world app + +## Standard mode +By default the application is built in **Standard** mode which +does not use TEE capabilities. + +### Build +Standard mode application is built just like any other dockerized +application: +``` +docker image build -t go-hello-world . +``` + +### Run +The application can be tested locally to make sure it is well setup: +``` +rm -rf /tmp/iexec_out && \ +docker run \ + --rm \ + -e IEXEC_IN=/iexec_in \ + -e IEXEC_DATASET_FILENAME=Lorem-ipsum.txt \ + -e IEXEC_OUT=/iexec_out \ + -v /tmp/iexec_out:/iexec_out \ + -v $(pwd)/resources/data:/iexec_in \ + go-hello-world Alice +``` +Once the execution ends, the result should be found in the folder +`/tmp/iexec_out`. +``` +cat /tmp/iexec_out/result.txt +``` + +## TEE (protected) mode +To convert the application into **TEE** mode, first, it needs to be +build in **Standard** mode as instructed in the section above. +Then the produced image is converted using `sconify.sh` script into +a newly created TEE enabled image `tee-go-hello-world`: + +### Build (conversion) +The script can edited to change parameters like **heap size**, new +image name, sources folder, ... + +``` +bash sconify.sh +``` + +### Run +(TODO test with CAS and session) + +First of all, Intel® SGX driver needs to be present on the host machine. +These [instructions](https://github.com/intel/linux-sgx-driver) provide +information about how to install it. +The application can be tested locally to make sure it is well setup: +``` +rm -rf /tmp/iexec_out && \ +docker run \ + --rm \ + -e IEXEC_OUT=/iexec_out \ + -e IEXEC_IN=/iexec_in \ + -v /tmp/iexec_out:/iexec_out \ + -v $(pwd)/resources/dataset:/iexec_in \ + --device /dev/isgx \ + tee-go-hello-world Alice +``` +To get the MREnclave value of the TEE application: +``` +docker run -it --rm -e SCONE_HASH=1 tee-go-hello-world +``` diff --git a/cloud-computing/go-hello-world/resources/data/Lorem-ipsum.txt b/cloud-computing/go-hello-world/resources/data/Lorem-ipsum.txt new file mode 100644 index 00000000..1b376877 --- /dev/null +++ b/cloud-computing/go-hello-world/resources/data/Lorem-ipsum.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. diff --git a/cloud-computing/go-hello-world/resources/tee/docker-compose.yml b/cloud-computing/go-hello-world/resources/tee/docker-compose.yml new file mode 100644 index 00000000..b481689f --- /dev/null +++ b/cloud-computing/go-hello-world/resources/tee/docker-compose.yml @@ -0,0 +1,33 @@ +version: '3.2' +networks: + scone-net: + external: true + +services: + las: + image: registry.scontain.com:5050/sconecuratedimages/services:las-scone5.3.0 + container_name: las + devices: + - /dev/isgx + networks: + - scone-net + cas: + image: registry.scontain.com:5050/sconecuratedimages/services:cas.preprovisioned-scone5.2.1 + container_name: cas + devices: + - /dev/isgx + depends_on: + - las + networks: + - scone-net + scone-cli: + image: registry.scontain.com:5050/sconecuratedimages/iexec-sconify-image:5.3.3 + container_name: scone-cli + command: bash -c "sleep 5 && scone session create /session.yml --cas cas --only_for_testing-disable-attestation-verification" + volumes: + - ./session.yml:/session.yml + depends_on: + - las + - cas + networks: + - scone-net diff --git a/cloud-computing/go-hello-world/resources/tee/run-scone-app b/cloud-computing/go-hello-world/resources/tee/run-scone-app new file mode 100644 index 00000000..a3294406 --- /dev/null +++ b/cloud-computing/go-hello-world/resources/tee/run-scone-app @@ -0,0 +1,24 @@ +#!/bin/bash + +### TODO on each build: update mrenclave in session + +docker-compose down > /dev/null +docker network create scone-net > /dev/null +echo "Starting CAS & LAS:" +docker-compose up -d +sleep 5 + +MY_SCONE_APP=tee-go-hello-world +echo "Starting $MY_SCONE_APP" +docker run --rm \ + --name=$MY_SCONE_APP \ + -e SCONE_VERSION=1 \ + -e SCONE_CAS_ADDR="cas" \ + -e SCONE_LAS_ADDR="las" \ + -e SCONE_CONFIG_ID="1/service" \ + --network=scone-net \ + --device=/dev/isgx \ + $MY_SCONE_APP + +docker-compose down +docker network rm scone-net diff --git a/cloud-computing/go-hello-world/resources/tee/session.yml b/cloud-computing/go-hello-world/resources/tee/session.yml new file mode 100644 index 00000000..5f26c86e --- /dev/null +++ b/cloud-computing/go-hello-world/resources/tee/session.yml @@ -0,0 +1,29 @@ +name: 1 +version: "0.3" + +# Access control: +# - only the data owner (CREATOR) can read or update the session +# - even the data owner cannot read the session secrets (i.e., the volume key and tag) or delete the session + +access_policy: + read: + - CREATOR + update: + - CREATOR + +services: + - name: service + image_name: service_image + mrenclaves: [5e0955204071b0f9d108bc7244ab25e331550046849f739f736c9536574fffb0] + command: "/app/helloworld" + environment: + IEXEC_IN: /iexec_in + IEXEC_OUT: /iexec_out + +images: + - name: service_image + +security: + attestation: + tolerate: [hyperthreading, software-hardening-needed, insecure-igpu, outdated-tcb, debug-mode] + ignore_advisories: ["INTEL-SA-00161", "INTEL-SA-00289", "INTEL-SA-00334", "INTEL-SA-00381", "INTEL-SA-00389"] diff --git a/cloud-computing/go-hello-world/sconify.args b/cloud-computing/go-hello-world/sconify.args new file mode 100644 index 00000000..827df3e7 --- /dev/null +++ b/cloud-computing/go-hello-world/sconify.args @@ -0,0 +1,12 @@ +--name=goHelloWorld \ +--from=${IMG_FROM} \ +--to=${IMG_TO} \ +--binary-fs \ +--host-path=/etc \ +--host-path=/opt \ +--binary="/app/helloworld" \ +--heap="1G" \ +--dlopen="2" \ +--no-color \ +--verbose \ +--command="/app/helloworld" diff --git a/cloud-computing/go-hello-world/src/helloworld.go b/cloud-computing/go-hello-world/src/helloworld.go new file mode 100644 index 00000000..78bd9018 --- /dev/null +++ b/cloud-computing/go-hello-world/src/helloworld.go @@ -0,0 +1,57 @@ +package main + +import ( + "fmt" + "io/ioutil" + "log" + "os" +) + +func main() { + iexecOut := os.Getenv("IEXEC_OUT") + iexecIn := os.Getenv("IEXEC_IN") + datasetFilename := os.Getenv("IEXEC_DATASET_FILENAME") + if iexecIn == "" { + panic("No value for IEXEC_IN") + } + if iexecOut == "" { + panic("No value for IEXEC_OUT") + } + + result := "" + + // Print a message + if (len(os.Args) > 1) { + result += "Hello, " + os.Args[1] + "!\n" + } else { + result += "Hello, World!\n" + } + + // Read the content of the dataset if present + if datasetFilename != "" { + datasetFilepath := iexecIn + "/" + datasetFilename + input, err := ioutil.ReadFile(datasetFilepath) + if err != nil { + log.Fatal("Error reading dataset file", err) + } else { + result += "Dataset (" + datasetFilepath + "): " + string(input) + } + } else { + result += "No dataset was found\n" + } + + fmt.Println(result) + + // Save result + err := ioutil.WriteFile(iexecOut + "/result.txt", []byte(result), 0) + if err != nil { + log.Fatal(err) + } + + // Create computed.json file + dataString := `{"deterministic-output-path": "` + iexecOut + `/result.txt"}` + err = ioutil.WriteFile(iexecOut + "/computed.json", []byte(dataString), 0) + if err != nil { + log.Fatal(err) + } +} diff --git a/cloud-computing/nodejs-hello-world/standard/Dockerfile b/cloud-computing/nodejs-hello-world/Dockerfile similarity index 85% rename from cloud-computing/nodejs-hello-world/standard/Dockerfile rename to cloud-computing/nodejs-hello-world/Dockerfile index 6a9f6bcc..dc2fd2a8 100644 --- a/cloud-computing/nodejs-hello-world/standard/Dockerfile +++ b/cloud-computing/nodejs-hello-world/Dockerfile @@ -1,4 +1,4 @@ -FROM node:10 +FROM node:14-alpine3.10 ### install your dependencies RUN mkdir /app && cd /app && npm install figlet@1.x diff --git a/cloud-computing/nodejs-hello-world/README.md b/cloud-computing/nodejs-hello-world/README.md new file mode 100644 index 00000000..54c9248b --- /dev/null +++ b/cloud-computing/nodejs-hello-world/README.md @@ -0,0 +1,70 @@ +# Node hello-world app + +## Standard mode +By default the application is built in **Standard** mode which +does not use TEE capabilities. + +### Build +Standard mode application is built just like any other dockerized +application: +``` +docker image build -t nodejs-hello-world . +``` +**IMPORTANT:** /!\ Please note that the base node image should be +alpine based if it will be converted into TEE mode. + +### Run +The application can be tested locally to make sure it is well setup: +``` +rm -rf /tmp/iexec_out && \ +docker run \ + --rm \ + -e IEXEC_IN=/iexec_in \ + -e IEXEC_DATASET_FILENAME=Lorem-ipsum.txt \ + -e IEXEC_OUT=/iexec_out \ + -v /tmp/iexec_out:/iexec_out \ + -v $(pwd)/resources/dataset:/iexec_in \ + nodejs-hello-world Alice +``` +Once the execution ends, the result should be found in the folder +`/tmp/iexec_out`. +``` +cat /tmp/iexec_out/result.txt +``` + +## TEE (protected) mode +To convert the application into **TEE** mode, first, it needs to be +built in **Standard** mode as instructed in the section above. +Then the standard image is converted using `sconify.sh` script into +a newly created TEE enabled image `tee-nodejs-hello-world`: + +### Build (conversion) +The script can edited to change parameters like **heap size**, new +image name, sources folder, ... + +``` +bash sconify.sh +``` + +### Run +(TODO test with CAS and session) + +First of all, Intel® SGX driver needs to be present on the host machine. +These [instructions](https://github.com/intel/linux-sgx-driver) provide +information about how to install it. +The application can be tested locally to make sure it is well setup: +``` +rm -rf /tmp/iexec_out && \ +docker run \ + --rm \ + -e IEXEC_OUT=/iexec_out \ + -e IEXEC_IN=/iexec_in \ + -v /tmp/iexec_out:/iexec_out \ + -v $(pwd)/resources/dataset:/iexec_in \ + --device /dev/isgx \ + tee-nodejs-hello-world Alice +``` +To get the MREnclave value of the TEE application: +``` +docker run -it --rm -e SCONE_HASH=1 tee-nodejs-hello-world +``` diff --git a/cloud-computing/nodejs-hello-world/Readme.md b/cloud-computing/nodejs-hello-world/Readme.md deleted file mode 100644 index 1e650574..00000000 --- a/cloud-computing/nodejs-hello-world/Readme.md +++ /dev/null @@ -1,20 +0,0 @@ - - -* Basic - -Build: -`./standard/build` - -Run locally: -`./standard/run` -`./standard/run Alice` - - -* Tee - -Build: -`./tee/build` - -Run locally: -`./tee/run` -`./tee/run Alice` diff --git a/cloud-computing/nodejs-hello-world/resources/data/Lorem-ipsum.txt b/cloud-computing/nodejs-hello-world/resources/data/Lorem-ipsum.txt new file mode 100644 index 00000000..1b376877 --- /dev/null +++ b/cloud-computing/nodejs-hello-world/resources/data/Lorem-ipsum.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. diff --git a/cloud-computing/nodejs-hello-world/resources/tee/docker-compose.yml b/cloud-computing/nodejs-hello-world/resources/tee/docker-compose.yml new file mode 100644 index 00000000..b481689f --- /dev/null +++ b/cloud-computing/nodejs-hello-world/resources/tee/docker-compose.yml @@ -0,0 +1,33 @@ +version: '3.2' +networks: + scone-net: + external: true + +services: + las: + image: registry.scontain.com:5050/sconecuratedimages/services:las-scone5.3.0 + container_name: las + devices: + - /dev/isgx + networks: + - scone-net + cas: + image: registry.scontain.com:5050/sconecuratedimages/services:cas.preprovisioned-scone5.2.1 + container_name: cas + devices: + - /dev/isgx + depends_on: + - las + networks: + - scone-net + scone-cli: + image: registry.scontain.com:5050/sconecuratedimages/iexec-sconify-image:5.3.3 + container_name: scone-cli + command: bash -c "sleep 5 && scone session create /session.yml --cas cas --only_for_testing-disable-attestation-verification" + volumes: + - ./session.yml:/session.yml + depends_on: + - las + - cas + networks: + - scone-net diff --git a/cloud-computing/nodejs-hello-world/resources/tee/run-scone-app b/cloud-computing/nodejs-hello-world/resources/tee/run-scone-app new file mode 100644 index 00000000..b8ff436b --- /dev/null +++ b/cloud-computing/nodejs-hello-world/resources/tee/run-scone-app @@ -0,0 +1,24 @@ +#!/bin/bash + +### TODO on each build: update mrenclave in session + +docker-compose down > /dev/null +docker network create scone-net > /dev/null +echo "Starting CAS & LAS:" +docker-compose up -d +sleep 5 + +MY_SCONE_APP=tee-nodejs-hello-world +echo "Starting $MY_SCONE_APP" +docker run --rm \ + --name=$MY_SCONE_APP \ + -e SCONE_VERSION=1 \ + -e SCONE_CAS_ADDR="cas" \ + -e SCONE_LAS_ADDR="las" \ + -e SCONE_CONFIG_ID="1/service" \ + --network=scone-net \ + --device=/dev/isgx \ + $MY_SCONE_APP + +docker-compose down +docker network rm scone-net diff --git a/cloud-computing/nodejs-hello-world/resources/tee/session.yml b/cloud-computing/nodejs-hello-world/resources/tee/session.yml new file mode 100644 index 00000000..9747a0d5 --- /dev/null +++ b/cloud-computing/nodejs-hello-world/resources/tee/session.yml @@ -0,0 +1,29 @@ +name: 1 +version: "0.3" + +# Access control: +# - only the data owner (CREATOR) can read or update the session +# - even the data owner cannot read the session secrets (i.e., the volume key and tag) or delete the session + +access_policy: + read: + - CREATOR + update: + - CREATOR + +services: + - name: service + image_name: service_image + mrenclaves: [5f7645b0f4c733c98c31f8daa2c6827c4e9bdc22b6ffac65699e10a0f1015340] + command: "node /app/app.js" + environment: + IEXEC_IN: /iexec_in + IEXEC_OUT: /iexec_out + +images: + - name: service_image + +security: + attestation: + tolerate: [hyperthreading, software-hardening-needed, insecure-igpu, outdated-tcb, debug-mode] + ignore_advisories: ["INTEL-SA-00161", "INTEL-SA-00289", "INTEL-SA-00334", "INTEL-SA-00381", "INTEL-SA-00389"] diff --git a/cloud-computing/nodejs-hello-world/sconify.sh b/cloud-computing/nodejs-hello-world/sconify.sh new file mode 100644 index 00000000..97d0037b --- /dev/null +++ b/cloud-computing/nodejs-hello-world/sconify.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Until the correct image is made available, do this workaround: +# docker image pull registry.scontain.com:5050/sconecuratedimages/iexec:node-14.4.0-alpine3.11 +# docker image tag registry.scontain.com:5050/sconecuratedimages/iexec:node-14.4.0-alpine3.11 registry.scontain.com:5050/sconecuratedimages/node:14.4.0-alpine3.11 + +docker run -it --rm \ + -v /var/run/docker.sock:/var/run/docker.sock \ + registry.scontain.com:5050/sconecuratedimages/iexec-sconify-image:5.3.3 \ + sconify_iexec \ + --name=nodejsHelloWorld \ + --from=nodejs-hello-world \ + --to=tee-nodejs-hello-world \ + --binary-fs \ + --fs-dir=/app \ + --host-path=/etc/hosts \ + --host-path=/etc/resolv.conf \ + --binary="/usr/local/bin/node" \ + --heap="1G" \ + --dlopen="2" \ + --no-color \ + --verbose \ + --command="node /app/app.js" diff --git a/cloud-computing/nodejs-hello-world/src/app.js b/cloud-computing/nodejs-hello-world/src/app.js index 9c60c945..9c9ca687 100644 --- a/cloud-computing/nodejs-hello-world/src/app.js +++ b/cloud-computing/nodejs-hello-world/src/app.js @@ -3,20 +3,22 @@ const figlet = require('figlet'); const iexecOut = process.env.IEXEC_OUT; const iexecIn = process.env.IEXEC_IN; -const confidentialFilepath = `${iexecIn}/confidential-asset.txt`; +const datasetFilename = process.env.IEXEC_DATASET_FILENAME; +const datasetFilepath = `${iexecIn}/${datasetFilename}`; (async () => { try { // Write hello to fs let text = process.argv.length > 2 ? `Hello, ${process.argv[2]}!` : 'Hello, World'; - text = `${figlet.textSync(text)}\n${text}`; // Let's add some art for e.g. + text = `${figlet.textSync(text)}\n${text}\n`; // Let's add some art for e.g. // Eventually use some confidential assets try { - const confidentialFile = await fsPromises.readFile(confidentialFilepath); - text = `${text}\nConfidential asset: ${confidentialFile}`; + const datasetContent = await fsPromises.readFile(datasetFilepath); + text += `Dataset (${datasetFilepath}): ${datasetContent}\n`; } catch (e) { // confidential asset does not exist + text += `No dataset was found\n` } // Append some results await fsPromises.writeFile(`${iexecOut}/result.txt`, text); @@ -34,11 +36,3 @@ const confidentialFilepath = `${iexecIn}/confidential-asset.txt`; process.exit(1); } })(); - -/* Try -Basic: -mkdir -p /tmp/iexec_out && IEXEC_OUT=/tmp/iexec_out IEXEC_IN=/tmp/iexec_in node app.js Alice - -Tee: -mkdir -p /tmp/iexec_out && IEXEC_OUT=/tmp/iexec_out IEXEC_IN=../tee/confidential-assets node app.js Alice -*/ diff --git a/cloud-computing/nodejs-hello-world/standard/build b/cloud-computing/nodejs-hello-world/standard/build deleted file mode 100755 index 52ca37fc..00000000 --- a/cloud-computing/nodejs-hello-world/standard/build +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -cd $(dirname $0) - -docker image build -f ../standard/Dockerfile -t node-hello-world .. $@ diff --git a/cloud-computing/nodejs-hello-world/standard/run b/cloud-computing/nodejs-hello-world/standard/run deleted file mode 100755 index 78fee211..00000000 --- a/cloud-computing/nodejs-hello-world/standard/run +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -cd $(dirname $0) - -IEXEC_OUT=/tmp/iexec_out - -rm -rf $IEXEC_OUT -mkdir -p $IEXEC_OUT - -docker run --rm -e IEXEC_OUT=/iexec_out -e IEXEC_IN=/iexec_in -v $IEXEC_OUT:/iexec_out node-hello-world $@ - -echo -find $IEXEC_OUT diff --git a/cloud-computing/nodejs-hello-world/tee/Dockerfile b/cloud-computing/nodejs-hello-world/tee/Dockerfile deleted file mode 100644 index 6369287f..00000000 --- a/cloud-computing/nodejs-hello-world/tee/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM sconecuratedimages/public-apps:node-10-alpine-scone3.0 - -### install dependencies you need -RUN apk add bash nodejs-npm -RUN mkdir /app && cd /app && SCONE_MODE=sim npm install figlet@1.x - -COPY ./src /app - -### protect file system with Scone -COPY ./tee/protect-fs.sh ./tee/Dockerfile /build/ -RUN sh /build/protect-fs.sh /app - -ENTRYPOINT [ "node", "/app/app.js"] diff --git a/cloud-computing/nodejs-hello-world/tee/build b/cloud-computing/nodejs-hello-world/tee/build deleted file mode 100755 index 11d298dd..00000000 --- a/cloud-computing/nodejs-hello-world/tee/build +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -cd $(dirname $0) -docker image build -f ../tee/Dockerfile -t tee-nodejs-hello-world .. $@ diff --git a/cloud-computing/nodejs-hello-world/tee/confidential-assets/confidential-asset.txt b/cloud-computing/nodejs-hello-world/tee/confidential-assets/confidential-asset.txt deleted file mode 100644 index 96426db1..00000000 --- a/cloud-computing/nodejs-hello-world/tee/confidential-assets/confidential-asset.txt +++ /dev/null @@ -1 +0,0 @@ -dummy confidential file diff --git a/cloud-computing/nodejs-hello-world/tee/protect-fs.sh b/cloud-computing/nodejs-hello-world/tee/protect-fs.sh deleted file mode 100644 index b23c5397..00000000 --- a/cloud-computing/nodejs-hello-world/tee/protect-fs.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh - -cd $(dirname $0) - -if [ ! -e Dockerfile ] -then - printf "\nFailed to parse Dockerfile ENTRYPOINT\n" - printf "Did you forget to add your Dockerfile in your build?\n" - printf "COPY ./tee/Dockerfile /build/\n\n" - exit 1 -fi - -ENTRYPOINT_ARSG=$(grep ENTRYPOINT ./Dockerfile | tail -1 | grep -o '"[^"]\+"' | tr -d '"') -echo $ENTRYPOINT_ARSG > ./entrypoint - -if [ -z "$ENTRYPOINT_ARSG" ] -then - printf "\nFailed to parse Dockerfile ENTRYPOINT\n" - printf "Did you forget to add an ENTRYPOINT to your Dockerfile?\n" - printf "ENTRYPOINT [\"executable\", \"param1\", \"param2\"]\n\n" - exit 1 -fi - -INTERPRETER=$(awk '{print $1}' ./entrypoint) # python -ENTRYPOINT=$(cat ./entrypoint) # /python /app/app.py - -export SCONE_MODE=sim -export SCONE_HEAP=1G - -APP_FOLDER=$1 - -printf "\n### Starting file system protection ...\n\n" - -scone fspf create /fspf.pb -scone fspf addr /fspf.pb / --not-protected --kernel / -scone fspf addr /fspf.pb /usr --authenticated --kernel /usr -scone fspf addf /fspf.pb /usr /usr -scone fspf addr /fspf.pb /bin --authenticated --kernel /bin -scone fspf addf /fspf.pb /bin /bin -scone fspf addr /fspf.pb /lib --authenticated --kernel /lib -scone fspf addf /fspf.pb /lib /lib -scone fspf addr /fspf.pb /etc/ssl --authenticated --kernel /etc/ssl -scone fspf addf /fspf.pb /etc/ssl /etc/ssl -scone fspf addr /fspf.pb /sbin --authenticated --kernel /sbin -scone fspf addf /fspf.pb /sbin /sbin -printf "\n### Protecting code found in folder \"$APP_FOLDER\"\n\n" -scone fspf addr /fspf.pb $APP_FOLDER --authenticated --kernel $APP_FOLDER -scone fspf addf /fspf.pb $APP_FOLDER $APP_FOLDER - -scone fspf encrypt /fspf.pb > ./keytag - -MRENCLAVE="$(SCONE_HASH=1 $INTERPRETER)" -FSPF_TAG=$(cat ./keytag | awk '{print $9}') -FSPF_KEY=$(cat ./keytag | awk '{print $11}') -FINGERPRINT="$FSPF_KEY|$FSPF_TAG|$MRENCLAVE|$ENTRYPOINT" -echo $FINGERPRINT > ./fingerprint - -printf "\n\n" -printf "Your application fingerprint (mrenclave) is ready:\n" -printf "#####################################################################\n" -printf "iexec.json:\n\n" -printf "%s\n" "\"app\": { " " \"owner\" : ... " " \"name\": ... " " ..." " \"mrenclave\": \"$FINGERPRINT\"" "}" -printf "#####################################################################\n" -printf "Hint: Replace 'mrenclave' before doing 'iexec app deploy' step.\n" -printf "\n\n" diff --git a/cloud-computing/nodejs-hello-world/tee/run b/cloud-computing/nodejs-hello-world/tee/run deleted file mode 100755 index f6c03b56..00000000 --- a/cloud-computing/nodejs-hello-world/tee/run +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -cd $(dirname $0) - -IEXEC_OUT=/tmp/iexec_out - -rm -rf $IEXEC_OUT -mkdir -p $IEXEC_OUT - -docker run --rm -e IEXEC_OUT=/iexec_out -e IEXEC_IN=/iexec_in -v $IEXEC_OUT:/iexec_out -v $(pwd)/confidential-assets:/iexec_in --device /dev/isgx tee-nodejs-hello-world $@ - -echo -find $IEXEC_OUT diff --git a/cloud-computing/python-hello-world/standard/Dockerfile b/cloud-computing/python-hello-world/Dockerfile similarity index 56% rename from cloud-computing/python-hello-world/standard/Dockerfile rename to cloud-computing/python-hello-world/Dockerfile index 668bc04a..9d45ef94 100644 --- a/cloud-computing/python-hello-world/standard/Dockerfile +++ b/cloud-computing/python-hello-world/Dockerfile @@ -1,8 +1,8 @@ -FROM python:3.7.3-alpine3.10 +FROM python:3.7-alpine3.10 ### install python3 dependencies you need RUN pip3 install pyfiglet COPY ./src /app -ENTRYPOINT ["python", "/app/app.py"] +ENTRYPOINT ["python3", "/app/app.py"] diff --git a/cloud-computing/python-hello-world/README.md b/cloud-computing/python-hello-world/README.md new file mode 100644 index 00000000..13f04f92 --- /dev/null +++ b/cloud-computing/python-hello-world/README.md @@ -0,0 +1,74 @@ +# Python hello-world app + +## Standard mode +By default the application is built in **Standard** mode which +does not use TEE capabilities. + +### Build +Standard mode application is built just like any other dockerized +application: +``` +docker image build -t python-hello-world . +``` +**IMPORTANT:** /!\ Please note that the base python image should be +alpine based if the application will be converted into TEE mode. + +### Run +The application can be tested locally to make sure it is well setup: +``` +rm -rf /tmp/iexec_out && \ +docker run \ + --rm \ + -e IEXEC_IN=/iexec_in \ + -e IEXEC_OUT=/iexec_out \ + -e IEXEC_DATASET_FILENAME=Lorem-ipsum.txt \ + -e IEXEC_INPUT_FILES_NUMBER=2 \ + -e IEXEC_INPUT_FILES_FOLDER=/iexec_in \ + -e IEXEC_INPUT_FILE_NAME_1=input-file1.txt \ + -e IEXEC_INPUT_FILE_NAME_2=input-file2.txt \ + -v /tmp/iexec_out:/iexec_out \ + -v $(pwd)/resources/data:/iexec_in \ + python-hello-world Alice +``` +Once the execution ends, the result should be found in the folder +`/tmp/iexec_out`. +``` +cat /tmp/iexec_out/result.txt +``` + +## TEE (protected) mode +To convert the application into **TEE** mode, first, it needs to be +built in **Standard** mode as instructed in the section above. +Then the standard image is converted using `sconify.sh` script into +a newly created TEE enabled image `tee-python-hello-world`: + +### Build (conversion) +The script can edited to change parameters like **heap size**, new +image name, sources folder, ... + +``` +bash sconify.sh +``` + +### Run +(TODO test with CAS and session) + +First of all, Intel® SGX driver needs to be present on the host machine. +These [instructions](https://github.com/intel/linux-sgx-driver) provide +information about how to install it. +The application can be tested locally to make sure it is well setup: +``` +rm -rf /tmp/iexec_out && \ +docker run \ + --rm \ + -e IEXEC_OUT=/iexec_out \ + -e IEXEC_IN=/iexec_in \ + -v /tmp/iexec_out:/iexec_out \ + -v $(pwd)/resources/data:/iexec_in \ + --device /dev/isgx \ + tee-python-hello-world Alice +``` +To get the MREnclave value of the TEE application: +``` +docker run -it --rm -e SCONE_HASH=1 tee-python-hello-world +``` diff --git a/cloud-computing/python-hello-world/Readme.md b/cloud-computing/python-hello-world/Readme.md deleted file mode 100644 index 1e650574..00000000 --- a/cloud-computing/python-hello-world/Readme.md +++ /dev/null @@ -1,20 +0,0 @@ - - -* Basic - -Build: -`./standard/build` - -Run locally: -`./standard/run` -`./standard/run Alice` - - -* Tee - -Build: -`./tee/build` - -Run locally: -`./tee/run` -`./tee/run Alice` diff --git a/cloud-computing/python-hello-world/resources/data/Lorem-ipsum.txt b/cloud-computing/python-hello-world/resources/data/Lorem-ipsum.txt new file mode 100644 index 00000000..1b376877 --- /dev/null +++ b/cloud-computing/python-hello-world/resources/data/Lorem-ipsum.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. diff --git a/cloud-computing/python-hello-world/resources/data/input-file1.txt b/cloud-computing/python-hello-world/resources/data/input-file1.txt new file mode 100644 index 00000000..4ac303fb --- /dev/null +++ b/cloud-computing/python-hello-world/resources/data/input-file1.txt @@ -0,0 +1 @@ +An input file with some very interesting content! diff --git a/cloud-computing/python-hello-world/resources/data/input-file2.txt b/cloud-computing/python-hello-world/resources/data/input-file2.txt new file mode 100644 index 00000000..3898a4d9 --- /dev/null +++ b/cloud-computing/python-hello-world/resources/data/input-file2.txt @@ -0,0 +1 @@ +Another input file with some other very interesting content! diff --git a/cloud-computing/python-hello-world/resources/tee/docker-compose.yml b/cloud-computing/python-hello-world/resources/tee/docker-compose.yml new file mode 100644 index 00000000..b481689f --- /dev/null +++ b/cloud-computing/python-hello-world/resources/tee/docker-compose.yml @@ -0,0 +1,33 @@ +version: '3.2' +networks: + scone-net: + external: true + +services: + las: + image: registry.scontain.com:5050/sconecuratedimages/services:las-scone5.3.0 + container_name: las + devices: + - /dev/isgx + networks: + - scone-net + cas: + image: registry.scontain.com:5050/sconecuratedimages/services:cas.preprovisioned-scone5.2.1 + container_name: cas + devices: + - /dev/isgx + depends_on: + - las + networks: + - scone-net + scone-cli: + image: registry.scontain.com:5050/sconecuratedimages/iexec-sconify-image:5.3.3 + container_name: scone-cli + command: bash -c "sleep 5 && scone session create /session.yml --cas cas --only_for_testing-disable-attestation-verification" + volumes: + - ./session.yml:/session.yml + depends_on: + - las + - cas + networks: + - scone-net diff --git a/cloud-computing/python-hello-world/resources/tee/run-scone-app b/cloud-computing/python-hello-world/resources/tee/run-scone-app new file mode 100644 index 00000000..e56034c0 --- /dev/null +++ b/cloud-computing/python-hello-world/resources/tee/run-scone-app @@ -0,0 +1,24 @@ +#!/bin/bash + +### TODO on each build: update mrenclave in session + +docker-compose down > /dev/null +docker network create scone-net > /dev/null +echo "Starting CAS & LAS:" +docker-compose up -d +sleep 5 + +MY_SCONE_APP=tee-python-hello-world +echo "Starting $MY_SCONE_APP" +docker run --rm \ + --name=$MY_SCONE_APP \ + -e SCONE_VERSION=1 \ + -e SCONE_CAS_ADDR="cas" \ + -e SCONE_LAS_ADDR="las" \ + -e SCONE_CONFIG_ID="1/service" \ + --network=scone-net \ + --device=/dev/isgx \ + $MY_SCONE_APP + +docker-compose down +docker network rm scone-net diff --git a/cloud-computing/python-hello-world/resources/tee/session.yml b/cloud-computing/python-hello-world/resources/tee/session.yml new file mode 100644 index 00000000..ed5a6431 --- /dev/null +++ b/cloud-computing/python-hello-world/resources/tee/session.yml @@ -0,0 +1,29 @@ +name: 1 +version: "0.3" + +# Access control: +# - only the data owner (CREATOR) can read or update the session +# - even the data owner cannot read the session secrets (i.e., the volume key and tag) or delete the session + +access_policy: + read: + - CREATOR + update: + - CREATOR + +services: + - name: service + image_name: service_image + mrenclaves: [eca3ace86f1e8a5c47123c8fd271319e9eb25356803d36666dc620f30365c0c1] + command: "python3 /app/app.py" + environment: + IEXEC_IN: /iexec_in + IEXEC_OUT: /iexec_out + +images: + - name: service_image + +security: + attestation: + tolerate: [hyperthreading, software-hardening-needed, insecure-igpu, outdated-tcb, debug-mode] + ignore_advisories: ["INTEL-SA-00161", "INTEL-SA-00289", "INTEL-SA-00334", "INTEL-SA-00381", "INTEL-SA-00389"] diff --git a/cloud-computing/python-hello-world/sconify.sh b/cloud-computing/python-hello-world/sconify.sh new file mode 100644 index 00000000..36faf833 --- /dev/null +++ b/cloud-computing/python-hello-world/sconify.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Until the correct image is made available, do this workaround: +# docker image pull registry.scontain.com:5050/sconecuratedimages/iexec:node-14.4.0-alpine3.11 +# docker image tag registry.scontain.com:5050/sconecuratedimages/iexec:node-14.4.0-alpine3.11 registry.scontain.com:5050/sconecuratedimages/node:14.4.0-alpine3.11 + +docker run -it --rm \ + -v /var/run/docker.sock:/var/run/docker.sock \ + registry.scontain.com:5050/sconecuratedimages/iexec-sconify-image:5.3.3 \ + sconify_iexec \ + --name=pythonHelloWorld \ + --from=python-hello-world \ + --to=tee-python-hello-world \ + --binary-fs \ + --fs-dir=/app \ + --host-path=/etc/hosts \ + --host-path=/etc/resolv.conf \ + --binary="/usr/local/bin/python3.7" \ + --heap="1G" \ + --dlopen="2" \ + --no-color \ + --verbose \ + --command="python3 /app/app.py" diff --git a/cloud-computing/python-hello-world/src/app.py b/cloud-computing/python-hello-world/src/app.py index f5340e17..524a4679 100644 --- a/cloud-computing/python-hello-world/src/app.py +++ b/cloud-computing/python-hello-world/src/app.py @@ -3,32 +3,79 @@ import json from pyfiglet import Figlet -iexec_out = os.environ['IEXEC_OUT'] -iexec_in = os.environ['IEXEC_IN'] - -# Do whatever you want -text = "Hello, World!" -if len(sys.argv) > 1: - text = 'Hello, {}!'.format(sys.argv[1]) -text = Figlet().renderText(text) + text # Let's add some art for e.g. - -# Eventually use some confidential assets -if os.path.exists(iexec_in + '/confidential-asset.txt'): - with open(iexec_in + '/confidential-asset.txt', 'r') as f: - text = text + '\nConfidential asset: ' + f.read() - -# Append some results -with open(iexec_out + '/result.txt', 'w+') as f: - f.write(text) - print(text) - -# Declare everything is computed -with open(iexec_out + '/computed.json', 'w+') as f: - json.dump({ "deterministic-output-path" : iexec_out + '/result.txt' }, f) - -## Try: -# Basic: -# mkdir -p /tmp/iexec_out && IEXEC_OUT=/tmp/iexec_out IEXEC_IN=/tmp/iexec_in python3 app.py Alice -# -# Tee: -# mkdir -p /tmp/iexec_out && IEXEC_OUT=/tmp/iexec_out IEXEC_IN=../tee/confidential-assets python3 app.py Alice + +def do_some_computation(): + """ + This function simulates some computation in an iExec application. Script + arguments (if provided) are accessible via "sys.argv" array. In this case, + if the first argument is present, it is used in the greeting message. + """ + name = sys.argv[1] if len(sys.argv) > 1 else "World" + greeting = f'Hello, {name}!' + # Let's add some art for e.g. + art = Figlet().renderText(greeting) + return art + greeting + + +def handle_dataset(): + """ + This function shows how to read a dataset file from an iExec application. + Datasets are public in standard mode and confidential in TEE mode. + The dataset location and filename are needed to be able to read it. Both + of which are provided in the following environment variables: + - IEXEC_IN: the path to the folder where the dataset is located. + - IEXEC_DATASET_FILENAME: the name of the dataset file. + """ + iexec_in = os.environ['IEXEC_IN'] + dataset_filename = os.environ['IEXEC_DATASET_FILENAME'] + dataset_filepath = iexec_in + '/' + dataset_filename + text = f'\nDataset ({dataset_filepath}): ' + if os.path.isfile(dataset_filepath): + with open(dataset_filepath) as f: + text = text + f.read() + return text + + +def handle_input_files(): + """ + This function demonstrates how to use input files in an iExec application. + The following environment variables are used: + - IEXEC_IN: the path to the folder where input files are located. + - IEXEC_INPUT_FILES_NUMBER: number of available input files. + - IEXEC_INPUT_FILE_NAME_N: the name of the Nth input file. N is between + 1 and IEXEC_INPUT_FILES_NUMBER. + If IEXEC_INPUT_FILES_NUMBER is 0 then no input file is available. + """ + iexec_in = os.environ['IEXEC_IN'] + iexec_input_files_number = int(os.environ['IEXEC_INPUT_FILES_NUMBER']) + text = '' + for i in range(1, iexec_input_files_number + 1): + file_path = iexec_in + "/" + os.environ['IEXEC_INPUT_FILE_NAME_' + str(i)] + if os.path.isfile(file_path): + with open(file_path) as f: + text += f'\nInput file [{i}] ({file_path}): {f.read()}' + return text + + +def save_result(text): + """ + This function shows how to save a result in an iExec application. The result + file(s) should be written in the folder indicated by the environment variable + IEXEC_OUT. After saving the result, the file "computed.json" must be created + in the same folder. It must contain, at least, the path to the determinism + file (deterministic-output-path). + """ + iexec_out = os.environ['IEXEC_OUT'] + result_filepath = iexec_out + '/result.txt' + with open(result_filepath, 'w+') as f: + f.write(text) + with open(iexec_out + '/computed.json', 'w+') as f: + json.dump({"deterministic-output-path": result_filepath}, f) + + +if __name__ == '__main__': + computation_text = do_some_computation() + dataset_text = handle_dataset() + input_files_text = handle_input_files() + result = f'{computation_text}\n{dataset_text}\n{input_files_text}\n' + save_result(result) \ No newline at end of file diff --git a/cloud-computing/python-hello-world/standard/build b/cloud-computing/python-hello-world/standard/build deleted file mode 100755 index 294fd2f6..00000000 --- a/cloud-computing/python-hello-world/standard/build +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -cd $(dirname $0) - -docker image build -f ../standard/Dockerfile -t python-hello-world .. $@ diff --git a/cloud-computing/python-hello-world/standard/run b/cloud-computing/python-hello-world/standard/run deleted file mode 100755 index b22f8443..00000000 --- a/cloud-computing/python-hello-world/standard/run +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -cd $(dirname $0) - -IEXEC_OUT=/tmp/iexec_out - -rm -rf $IEXEC_OUT -mkdir -p $IEXEC_OUT - -docker run --rm -e IEXEC_OUT=/iexec_out -e IEXEC_IN=/iexec_in -v /tmp/iexec_out:/iexec_out python-hello-world $@ - -echo -find $IEXEC_OUT diff --git a/cloud-computing/python-hello-world/tee/Dockerfile b/cloud-computing/python-hello-world/tee/Dockerfile deleted file mode 100644 index 78810fa0..00000000 --- a/cloud-computing/python-hello-world/tee/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM sconecuratedimages/public-apps:python-3.7.3-alpine3.10-scone3.0 - -### install python3 dependencies you need -RUN SCONE_MODE=sim pip3 install pyfiglet - -COPY ./src /app - -### protect file system with Scone -COPY ./tee/protect-fs.sh ./tee/Dockerfile /build/ -RUN sh /build/protect-fs.sh /app - -ENTRYPOINT ["python", "/app/app.py"] diff --git a/cloud-computing/python-hello-world/tee/build b/cloud-computing/python-hello-world/tee/build deleted file mode 100755 index 5eb88e6d..00000000 --- a/cloud-computing/python-hello-world/tee/build +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -cd $(dirname $0) -docker image build -f ../tee/Dockerfile -t tee-python-hello-world .. $@ diff --git a/cloud-computing/python-hello-world/tee/confidential-assets/confidential-asset.txt b/cloud-computing/python-hello-world/tee/confidential-assets/confidential-asset.txt deleted file mode 100644 index 96426db1..00000000 --- a/cloud-computing/python-hello-world/tee/confidential-assets/confidential-asset.txt +++ /dev/null @@ -1 +0,0 @@ -dummy confidential file diff --git a/cloud-computing/python-hello-world/tee/protect-fs.sh b/cloud-computing/python-hello-world/tee/protect-fs.sh deleted file mode 100644 index b23c5397..00000000 --- a/cloud-computing/python-hello-world/tee/protect-fs.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh - -cd $(dirname $0) - -if [ ! -e Dockerfile ] -then - printf "\nFailed to parse Dockerfile ENTRYPOINT\n" - printf "Did you forget to add your Dockerfile in your build?\n" - printf "COPY ./tee/Dockerfile /build/\n\n" - exit 1 -fi - -ENTRYPOINT_ARSG=$(grep ENTRYPOINT ./Dockerfile | tail -1 | grep -o '"[^"]\+"' | tr -d '"') -echo $ENTRYPOINT_ARSG > ./entrypoint - -if [ -z "$ENTRYPOINT_ARSG" ] -then - printf "\nFailed to parse Dockerfile ENTRYPOINT\n" - printf "Did you forget to add an ENTRYPOINT to your Dockerfile?\n" - printf "ENTRYPOINT [\"executable\", \"param1\", \"param2\"]\n\n" - exit 1 -fi - -INTERPRETER=$(awk '{print $1}' ./entrypoint) # python -ENTRYPOINT=$(cat ./entrypoint) # /python /app/app.py - -export SCONE_MODE=sim -export SCONE_HEAP=1G - -APP_FOLDER=$1 - -printf "\n### Starting file system protection ...\n\n" - -scone fspf create /fspf.pb -scone fspf addr /fspf.pb / --not-protected --kernel / -scone fspf addr /fspf.pb /usr --authenticated --kernel /usr -scone fspf addf /fspf.pb /usr /usr -scone fspf addr /fspf.pb /bin --authenticated --kernel /bin -scone fspf addf /fspf.pb /bin /bin -scone fspf addr /fspf.pb /lib --authenticated --kernel /lib -scone fspf addf /fspf.pb /lib /lib -scone fspf addr /fspf.pb /etc/ssl --authenticated --kernel /etc/ssl -scone fspf addf /fspf.pb /etc/ssl /etc/ssl -scone fspf addr /fspf.pb /sbin --authenticated --kernel /sbin -scone fspf addf /fspf.pb /sbin /sbin -printf "\n### Protecting code found in folder \"$APP_FOLDER\"\n\n" -scone fspf addr /fspf.pb $APP_FOLDER --authenticated --kernel $APP_FOLDER -scone fspf addf /fspf.pb $APP_FOLDER $APP_FOLDER - -scone fspf encrypt /fspf.pb > ./keytag - -MRENCLAVE="$(SCONE_HASH=1 $INTERPRETER)" -FSPF_TAG=$(cat ./keytag | awk '{print $9}') -FSPF_KEY=$(cat ./keytag | awk '{print $11}') -FINGERPRINT="$FSPF_KEY|$FSPF_TAG|$MRENCLAVE|$ENTRYPOINT" -echo $FINGERPRINT > ./fingerprint - -printf "\n\n" -printf "Your application fingerprint (mrenclave) is ready:\n" -printf "#####################################################################\n" -printf "iexec.json:\n\n" -printf "%s\n" "\"app\": { " " \"owner\" : ... " " \"name\": ... " " ..." " \"mrenclave\": \"$FINGERPRINT\"" "}" -printf "#####################################################################\n" -printf "Hint: Replace 'mrenclave' before doing 'iexec app deploy' step.\n" -printf "\n\n" diff --git a/cloud-computing/python-hello-world/tee/run b/cloud-computing/python-hello-world/tee/run deleted file mode 100755 index fe7f4f8d..00000000 --- a/cloud-computing/python-hello-world/tee/run +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -cd $(dirname $0) - -IEXEC_OUT=/tmp/iexec_out - -rm -rf $IEXEC_OUT -mkdir -p $IEXEC_OUT - -docker run --rm -e IEXEC_OUT=/iexec_out -e IEXEC_IN=/iexec_in -v $IEXEC_OUT:/iexec_out -v $(pwd)/confidential-assets:/iexec_in --device /dev/isgx tee-python-hello-world $@ - -echo -find $IEXEC_OUT diff --git a/offchain-computing/offchain-python-hello-world/src/app.py b/offchain-computing/offchain-python-hello-world/src/app.py index c2572ef7..54c53957 100644 --- a/offchain-computing/offchain-python-hello-world/src/app.py +++ b/offchain-computing/offchain-python-hello-world/src/app.py @@ -5,6 +5,7 @@ iexec_out = os.environ['IEXEC_OUT'] iexec_in = os.environ['IEXEC_IN'] +dataset_filepath = iexec_in + '/' + os.environ['IEXEC_DATASET_FILENAME'] # Do whatever you want data = "Hello, World!" @@ -12,9 +13,9 @@ data = 'Hello, {}!'.format(sys.argv[1]) # Eventually use some confidential assets -if os.path.exists(iexec_in + '/confidential-asset.txt'): - with open(iexec_in + '/confidential-asset.txt', 'r') as f: - print('Confidential asset: ' + f.read()) +if os.path.isfile(dataset_filepath): + with open(dataset_filepath, 'r') as f: + print('Dataset ({}): {}'.format(dataset_filepath, f.read())) # Send callback data to smart-contract callback_data = eth_abi.encode_abi([ 'string'], [ data ]).hex() diff --git a/offchain-computing/offchain-tee-kaiko-pricefeed/src/app.py b/offchain-computing/offchain-tee-kaiko-pricefeed/src/app.py index 0bd05fc3..e75b6994 100644 --- a/offchain-computing/offchain-tee-kaiko-pricefeed/src/app.py +++ b/offchain-computing/offchain-tee-kaiko-pricefeed/src/app.py @@ -7,27 +7,32 @@ iexec_out = os.environ['IEXEC_OUT'] iexec_in = os.environ['IEXEC_IN'] +dataset_filepath = iexec_in + '/' + os.environ['IEXEC_DATASET_FILENAME'] class Lib: + @staticmethod def parseValue(rawValue, ethType, power): if re.search('^u?int[0-9]*$', ethType): return round(float(rawValue) * 10 ** int(power)) else: return rawValue + @staticmethod def formatArgs(args): return '&'.join('{}={}'.format(k,v) for k,v in args.items()) + @staticmethod def getAPIKey(): try: - with open(iexec_in + '/' + 'key.txt', 'r') as dataset_file: + with open(dataset_filepath, 'r') as dataset_file: apiKey = dataset_file.read().strip() if not re.search('^[0-9a-zA-Z]{1,128}$', apiKey): raise Exception('Invalid API key') return apiKey - except FileNotFoundError: + except (FileNotFoundError, IsADirectoryError): raise Exception('Missing API key dataset') + @staticmethod def fetchMarketData(region, endpoint, params): print('Request https://{region}.market-api.kaiko.io/v1/data/trades.v1/{endpoint}?{params}'.format( region = region, @@ -51,6 +56,7 @@ def fetchMarketData(region, endpoint, params): ) class PriceFeed: + @staticmethod def fetchRate(baseAsset, quoteAsset): return Lib.fetchMarketData( 'us', @@ -61,6 +67,7 @@ def fetchRate(baseAsset, quoteAsset): }) ) + @staticmethod def run(baseAsset, quoteAsset, power): response = PriceFeed.fetchRate( baseAsset = baseAsset,