blob: 07999077e26ac36acbd4fd2a840b58f5a7cdb3b4 [file] [log] [blame]
diff --git a/.drone.yml b/.drone.yml
index fa2e4c7..19b7350 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -12,41 +12,59 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
-x-isgx-1804-image: &isgx-1804-image
- image: teaclave/teaclave-build-ubuntu-1804-sgx-2.14:0.1.5
-
kind: pipeline
-name: sgx-debug-ubuntu-1804
+name: sgx-debug-ubuntu-2004
steps:
- name: prepare
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+ environment:
+ SSH_USERNAME:
+ from_secret: SSH_USERNAME
+ SSH_PRIVATE_KEY:
+ from_secret: SSH_PRIVATE_KEY
+ SSH_SERVER_IP:
+ from_secret: SSH_SERVER_IP
commands:
+ - mkdir -p algorithm2_hash_sgx
+ - echo $SSH_PRIVATE_KEY | base64 -d > id_rsa
+ - chmod 400 id_rsa
+ - scp -i id_rsa -oStrictHostKeyChecking=no $SSH_USERNAME@$SSH_SERVER_IP:/xlabfs/ci/cleanroom-workload-devkit-ci-bot/libalgorithm2.a algorithm2_hash_sgx
- . /root/.cargo/env
- . /opt/sgxsdk/environment
+ - echo "127.0.0.1 teaclave-file-service" >> /etc/hosts
- mkdir -p build
- cd build && cmake -DCMAKE_BUILD_TYPE=Debug -DTEST_MODE=ON ..
- name: check
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make check
- name: compile
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make VERBOSE=1 -j2
-- name: tvm example
- <<: *isgx-1804-image
+- name: package-cli
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- - . ~/.cargo/env
- - cd examples/python/wasm_tvm_mnist_payload
+ - . /root/.cargo/env
+ - . /opt/sgxsdk/environment
+ - apt update
+ - apt install -y clang
+ - pip3 install pyoxidizer
+ - cd cleanroom-cli
- make
+# - name: tvm example
+# image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+# commands:
+# - . ~/.cargo/env
+# - cd examples/python/wasm_tvm_mnist_payload
+# - make
- name: test
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
environment:
AS_ALGO: sgx_epid
AS_URL: https://api.trustedservices.intel.com:443
@@ -65,6 +83,8 @@ steps:
- . /opt/sgxsdk/environment
- (cd release/tool && ./teaclave_sgx_tool status)
- (cd release/tool && ./teaclave_sgx_tool attestation --key $AS_KEY --spid $AS_SPID)
+ - export TEACLAVE_LOG=warn
+ - echo "127.0.0.1 teaclave-file-service" >> /etc/hosts
- cd build && make run-tests
volumes:
@@ -75,46 +95,65 @@ volumes:
host:
path: /var/run/aesmd/aesm.socket
+trigger:
+ ref:
+ exclude:
+ - refs/tags/cli-**
+
node:
instance: mesatee-sgx
----
-x-dcap-1804-image: &dcap-1804-image
- image: teaclave/teaclave-build-ubuntu-1804-sgx-dcap-1.11:0.1.5
+---
kind: pipeline
-name: sgx-dcap-debug-ubuntu-1804
+name: sgx-dcap-release-ubuntu-2004
steps:
- name: prepare
- <<: *dcap-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.1
+ environment:
+ SSH_USERNAME:
+ from_secret: SSH_USERNAME
+ SSH_PRIVATE_KEY:
+ from_secret: SSH_PRIVATE_KEY
+ SSH_SERVER_IP:
+ from_secret: SSH_SERVER_IP
commands:
+ - mkdir -p algorithm2_hash_sgx
+ - echo $SSH_PRIVATE_KEY | base64 -d > id_rsa
+ - chmod 400 id_rsa
+ - scp -i id_rsa -oStrictHostKeyChecking=no $SSH_USERNAME@$SSH_SERVER_IP:/xlabfs/ci/cleanroom-workload-devkit-ci-bot/libalgorithm2.a algorithm2_hash_sgx
- . /root/.cargo/env
- . /opt/sgxsdk/environment
+ - echo "127.0.0.1 teaclave-file-service" >> /etc/hosts
- mkdir -p build
- - cd build && cmake -DCMAKE_BUILD_TYPE=Debug -DTEST_MODE=ON -DDCAP=ON ..
+ - cd build && cmake -DCMAKE_BUILD_TYPE=Release -DTEST_MODE=ON -DDCAP=ON ..
- name: check
- <<: *dcap-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make check
- name: compile
- <<: *dcap-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- sed -i 's/ias_root_ca_cert/dcap_root_ca_cert/' config/build.config.toml
- cd build && make VERBOSE=1 -j2
-- name: tvm example
- <<: *dcap-1804-image
+- name: package-cli
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- - . ~/.cargo/env
- - cd examples/python/wasm_tvm_mnist_payload
+ - . /root/.cargo/env
+ - . /opt/sgxsdk/environment
+ - pip3 install pyoxidizer
+ - apt update
+ - apt install -y clang
+ - cd cleanroom-cli
- make
- name: test
- <<: *dcap-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.1
environment:
AS_ALGO: sgx_ecdsa
AS_URL: https://localhost:8080
@@ -141,6 +180,7 @@ steps:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- (cd release/dcap && ./teaclave_dcap_ref_as &)
+ - echo "127.0.0.1 teaclave-file-service" >> /etc/hosts
- cd build && make run-tests
volumes:
@@ -163,440 +203,393 @@ volumes:
host:
path: /etc/sgx_default_qcnl.conf
+trigger:
+ ref:
+ exclude:
+ - refs/tags/cli-**
+
node:
instance: mesatee-sgx-dcap
----
-x-isgx-2004-image: &isgx-2004-image
- image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.3
+---
kind: pipeline
-name: sgx-debug-ubuntu-2004
+name: sgx-dcap-release-tag-publish-ubuntu-2004
steps:
- name: prepare
- <<: *isgx-2004-image
- commands:
- - . /root/.cargo/env
- - . /opt/sgxsdk/environment
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.1
+ environment:
+ SSH_USERNAME:
+ from_secret: SSH_USERNAME
+ SSH_PRIVATE_KEY:
+ from_secret: SSH_PRIVATE_KEY
+ SSH_SERVER_IP:
+ from_secret: SSH_SERVER_IP
+ DCAP_ROOT_CA_CERT:
+ from_secret: DCAP_ROOT_CA_CERT
+ DCAP_SERVER_CERT:
+ from_secret: DCAP_SERVER_CERT
+ DCAP_SERVER_KEY:
+ from_secret: DCAP_SERVER_KEY
+ commands:
+ - mkdir -p algorithm2_hash_sgx
+ - echo $SSH_PRIVATE_KEY | base64 -d > id_rsa
+ - echo $DCAP_ROOT_CA_CERT | base64 -d > keys/dcap_root_ca_cert.pem
+ - echo $DCAP_SERVER_CERT | base64 -d > keys/dcap_server_cert.pem
+ - echo $DCAP_SERVER_KEY | base64 -d > keys/dcap_server_key.pem
+ - chmod 400 id_rsa
+ - scp -i id_rsa -oStrictHostKeyChecking=no $SSH_USERNAME@$SSH_SERVER_IP:/xlabfs/ci/cleanroom-workload-devkit-ci-bot/libalgorithm2.a algorithm2_hash_sgx
+ - . /root/.cargo/env
+ - . /opt/sgxsdk/environment
+ - echo "127.0.0.1 teaclave-file-service" >> /etc/hosts
- mkdir -p build
- - cd build && cmake -DCMAKE_BUILD_TYPE=Debug -DTEST_MODE=ON ..
+ - cd build && cmake -DCMAKE_BUILD_TYPE=Release -DTEST_MODE=OFF -DDCAP=ON ..
- name: check
- <<: *isgx-2004-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make check
- name: compile
- <<: *isgx-2004-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
+ - sed -i 's/ias_root_ca_cert/dcap_root_ca_cert/' config/build.config.toml
- cd build && make VERBOSE=1 -j2
-- name: tvm example
- <<: *isgx-2004-image
- commands:
- - . ~/.cargo/env
- - cd examples/python/wasm_tvm_mnist_payload
- - make
-- name: test
- <<: *isgx-2004-image
+- name: publish
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.1
environment:
- AS_ALGO: sgx_epid
- AS_URL: https://api.trustedservices.intel.com:443
- AS_KEY:
- from_secret: V5_KEY
- AS_SPID:
- from_secret: V5_SPID
- privileged: true
- volumes:
- - name: isgx
- path: /dev/isgx
- - name: aesmd
- path: /var/run/aesmd/aesm.socket
- commands:
- - . /root/.cargo/env
- - . /opt/sgxsdk/environment
- - (cd release/tool && ./teaclave_sgx_tool status)
- - (cd release/tool && ./teaclave_sgx_tool attestation --key $AS_KEY --spid $AS_SPID)
- - cd build && make run-tests
+ SSH_USERNAME:
+ from_secret: SSH_USERNAME
+ SSH_PRIVATE_KEY:
+ from_secret: SSH_PRIVATE_KEY
+ SSH_SERVER_IP:
+ from_secret: SSH_SERVER_IP
+ PUBLISH_DIR:
+ from_secret: PUBLISH_DIR
+ commands:
+ - release_id=${DRONE_TAG}_$(git rev-parse --short HEAD)
+ - out_service="dcap_service_release_$release_id"
+ - mkdir $out_service
+ - cp -r ./release $out_service/release
+ - cp -r ./dcap_deployment/docker $out_service/docker
+ - cp -r ./monitoring/prometheus.py $out_service
+
+ - out_sdk="dcap_sdk_release_$release_id"
+ - mkdir $out_sdk
+ - cp -r ./sdk/python $out_sdk/python
+ - cp ./release/services/enclave_info.toml $out_sdk/enclave_info.toml
+ - cp ./release/cli/teaclave_cli $out_sdk/teaclave_cli
+ - cp ./keys/dcap_root_ca_cert.pem $out_sdk/dcap_root_cert.pem
+
+ - tar czvf $out_sdk.tgz $out_sdk
+ - tar czvf $out_service.tgz $out_service
+ - scp -i id_rsa -oStrictHostKeyChecking=no $out_sdk.tgz $SSH_USERNAME@$SSH_SERVER_IP:$PUBLISH_DIR
+ - scp -i id_rsa -oStrictHostKeyChecking=no $out_service.tgz $SSH_USERNAME@$SSH_SERVER_IP:$PUBLISH_DIR
-volumes:
-- name: isgx
- host:
- path: /dev/isgx
-- name: aesmd
- host:
- path: /var/run/aesmd/aesm.socket
+
+trigger:
+ ref:
+ include:
+ - refs/tags/service-**
+
+depends_on:
+ - sgx-dcap-release-ubuntu-2004
node:
instance: mesatee-sgx
---
-x-dcap-2004-image: &dcap-2004-image
- image: teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.3
-
kind: pipeline
-name: sgx-dcap-debug-ubuntu-2004
+name: sgx-release-ubuntu-2004
steps:
- name: prepare
- <<: *dcap-2004-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+ environment:
+ SSH_USERNAME:
+ from_secret: SSH_USERNAME
+ SSH_PRIVATE_KEY:
+ from_secret: SSH_PRIVATE_KEY
+ SSH_SERVER_IP:
+ from_secret: SSH_SERVER_IP
commands:
+ - mkdir -p algorithm2_hash_sgx
+ - echo $SSH_PRIVATE_KEY | base64 -d > id_rsa
+ - chmod 400 id_rsa
+ - scp -i id_rsa -oStrictHostKeyChecking=no $SSH_USERNAME@$SSH_SERVER_IP:/xlabfs/ci/cleanroom-workload-devkit-ci-bot/libalgorithm2.a algorithm2_hash_sgx
- . /root/.cargo/env
- . /opt/sgxsdk/environment
+ - echo "127.0.0.1 teaclave-file-service" >> /etc/hosts
- mkdir -p build
- - cd build && cmake -DCMAKE_BUILD_TYPE=Debug -DTEST_MODE=ON -DDCAP=ON ..
+ - cd build && cmake -DCMAKE_BUILD_TYPE=Release -DTEST_MODE=OFF ..
- name: check
- <<: *dcap-2004-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make check
- name: compile
- <<: *dcap-2004-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- - sed -i 's/ias_root_ca_cert/dcap_root_ca_cert/' config/build.config.toml
- cd build && make VERBOSE=1 -j2
-- name: tvm example
- image: teaclave/teaclave-build-ubuntu-1804-sgx-2.14:0.1.5
+- name: package-cli
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- - . ~/.cargo/env
- - cd examples/python/wasm_tvm_mnist_payload
- - make
-- name: test
- <<: *dcap-2004-image
- environment:
- AS_ALGO: sgx_ecdsa
- AS_URL: https://localhost:8080
- AS_KEY:
- from_secret: V5_KEY
- AS_SPID:
- from_secret: V5_SPID
- privileged: true
- volumes:
- - name: sgx
- path: /dev/sgx
- - name: sgx_enclave
- path: /dev/sgx_enclave
- - name: sgx_provision
- path: /dev/sgx_provision
- - name: aesmd
- path: /var/run/aesmd/aesm.socket
- - name: aesmd-conf
- path: /etc/aesmd.conf
- - name: qcnl
- path: /etc/sgx_default_qcnl.conf
- commands:
- - echo "$(ip route | awk 'NR==1 {print $3}') pccs-server" >> /etc/hosts
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- - (cd release/dcap && ./teaclave_dcap_ref_as &)
- - cd build && make run-tests
-
-volumes:
-- name: sgx
- host:
- path: /dev/sgx
-- name: sgx_enclave
- host:
- path: /dev/sgx_enclave
-- name: sgx_provision
- host:
- path: /dev/sgx_provision
-- name: aesmd
- host:
- path: /var/run/aesmd/aesm.socket
-- name: aesmd-conf
- host:
- path: /etc/aesmd.conf
-- name: qcnl
- host:
- path: /etc/sgx_default_qcnl.conf
-
-node:
- instance: mesatee-sgx-dcap
-
----
-
-x-dcap-2004-image: &dcap-2004-image
- image: teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.3
-
-kind: pipeline
-name: sgx-dcap-coverage-ubuntu-2004
-
-steps:
-- name: prepare
- <<: *dcap-2004-image
- commands:
- - . /root/.cargo/env
- - . /opt/sgxsdk/environment
- - mkdir -p build
- - cd build && cmake -DCMAKE_BUILD_TYPE=Debug -DTEST_MODE=ON -DDCAP=ON -DCOV=ON ..
-- name: check
- <<: *dcap-2004-image
- commands:
- - . /root/.cargo/env
- - . /opt/sgxsdk/environment
- - cd build && make check
-- name: compile
- <<: *dcap-2004-image
- commands:
- - . /root/.cargo/env
- - . /opt/sgxsdk/environment
- - sed -i 's/ias_root_ca_cert/dcap_root_ca_cert/' config/build.config.toml
- - cd build && make VERBOSE=1 -j2
-- name: tvm example
- image: teaclave/teaclave-build-ubuntu-1804-sgx-2.14:0.1.5
- commands:
- - . ~/.cargo/env
- - cd examples/python/wasm_tvm_mnist_payload
+ - pip3 install pyoxidizer
+ - apt update
+ - apt install -y clang
+ - cd cleanroom-cli
- make
+# - name: tvm example
+# image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+# commands:
+# - . ~/.cargo/env
+# - cd examples/python/wasm_tvm_mnist_payload
+# - make
- name: test
- <<: *dcap-2004-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+ privileged: true
environment:
- AS_ALGO: sgx_ecdsa
- AS_URL: https://localhost:8080
+ AS_ALGO: sgx_epid
+ AS_URL: https://api.trustedservices.intel.com:443
AS_KEY:
from_secret: V5_KEY
AS_SPID:
from_secret: V5_SPID
- privileged: true
volumes:
- - name: sgx
- path: /dev/sgx
- - name: sgx_enclave
- path: /dev/sgx_enclave
- - name: sgx_provision
- path: /dev/sgx_provision
+ - name: isgx
+ path: /dev/isgx
- name: aesmd
path: /var/run/aesmd/aesm.socket
- - name: aesmd-conf
- path: /etc/aesmd.conf
- - name: qcnl
- path: /etc/sgx_default_qcnl.conf
commands:
- - echo "$(ip route | awk 'NR==1 {print $3}') pccs-server" >> /etc/hosts
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- - (cd release/dcap && ./teaclave_dcap_ref_as &)
- - cd build && make run-tests && make cov
+ - cd build && make run-examples
volumes:
-- name: sgx
- host:
- path: /dev/sgx
-- name: sgx_enclave
- host:
- path: /dev/sgx_enclave
-- name: sgx_provision
+- name: isgx
host:
- path: /dev/sgx_provision
+ path: /dev/isgx
- name: aesmd
host:
path: /var/run/aesmd/aesm.socket
-- name: aesmd-conf
- host:
- path: /etc/aesmd.conf
-- name: qcnl
- host:
- path: /etc/sgx_default_qcnl.conf
+
+trigger:
+ ref:
+ exclude:
+ - refs/tags/cli-**
node:
- instance: mesatee-sgx-dcap
----
+ instance: mesatee-sgx
-x-dcap-2004-image: &dcap-2004-image
- image: teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.3
+---
kind: pipeline
-name: sgx-dcap-release-ubuntu-2004
+name: sim-debug-ubuntu-2004
steps:
- name: prepare
- <<: *dcap-2004-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+ environment:
+ SSH_USERNAME:
+ from_secret: SSH_USERNAME
+ SSH_PRIVATE_KEY:
+ from_secret: SSH_PRIVATE_KEY
+ SSH_SERVER_IP:
+ from_secret: SSH_SERVER_IP
commands:
+ - mkdir -p algorithm2_hash_sgx
+ - echo $SSH_PRIVATE_KEY | base64 -d > id_rsa
+ - chmod 400 id_rsa
+ - scp -i id_rsa -oStrictHostKeyChecking=no $SSH_USERNAME@$SSH_SERVER_IP:/xlabfs/ci/cleanroom-workload-devkit-ci-bot/libalgorithm2.a algorithm2_hash_sgx
- . /root/.cargo/env
- . /opt/sgxsdk/environment
+ - echo "127.0.0.1 teaclave-file-service" >> /etc/hosts
- mkdir -p build
- - cd build && cmake -DCMAKE_BUILD_TYPE=Release -DTEST_MODE=OFF -DDCAP=ON ..
+ - cd build && cmake -DCMAKE_BUILD_TYPE=Debug -DSGX_SIM_MODE=ON -DTEST_MODE=ON ..
- name: check
- <<: *dcap-2004-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make check
- name: compile
- <<: *dcap-2004-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- - sed -i 's/ias_root_ca_cert/dcap_root_ca_cert/' config/build.config.toml
- cd build && make VERBOSE=1 -j2
-- name: tvm example
- <<: *dcap-2004-image
- commands:
- - . ~/.cargo/env
- - cd examples/python/wasm_tvm_mnist_payload
- - make
+- name: package-cli
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+ commands:
+ - . /root/.cargo/env
+ - . /opt/sgxsdk/environment
+ - pip3 install pyoxidizer
+ - apt update
+ - apt install -y clang
+ - cd cleanroom-cli
+ - make
+# - name: tvm example
+# image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+# commands:
+# - . ~/.cargo/env
+# - cd examples/python/wasm_tvm_mnist_payload
+# - make
- name: test
- <<: *dcap-2004-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
environment:
- AS_ALGO: sgx_ecdsa
- AS_URL: https://localhost:8080
+ AS_ALGO: sgx_epid
+ AS_URL: https://api.trustedservices.intel.com:443
AS_KEY:
from_secret: V5_KEY
AS_SPID:
from_secret: V5_SPID
- privileged: true
- volumes:
- - name: sgx
- path: /dev/sgx
- - name: sgx_enclave
- path: /dev/sgx_enclave
- - name: sgx_provision
- path: /dev/sgx_provision
- - name: aesmd
- path: /var/run/aesmd/aesm.socket
- - name: aesmd-conf
- path: /etc/aesmd.conf
- - name: qcnl
- path: /etc/sgx_default_qcnl.conf
commands:
- - echo "$(ip route | awk 'NR==1 {print $3}') pccs-server" >> /etc/hosts
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- - (cd release/dcap && ./teaclave_dcap_ref_as &)
- - cd build && make run-examples
+ - echo "127.0.0.1 teaclave-file-service" >> /etc/hosts
+ - cd build && make run-tests
-volumes:
-- name: sgx
- host:
- path: /dev/sgx
-- name: sgx_enclave
- host:
- path: /dev/sgx_enclave
-- name: sgx_provision
- host:
- path: /dev/sgx_provision
-- name: aesmd
- host:
- path: /var/run/aesmd/aesm.socket
-- name: aesmd-conf
- host:
- path: /etc/aesmd.conf
-- name: qcnl
- host:
- path: /etc/sgx_default_qcnl.conf
+trigger:
+ ref:
+ exclude:
+ - refs/tags/cli-**
node:
- instance: mesatee-sgx-dcap
+ instance: mesatee-sgx
---
-x-isgx-1804-image: &isgx-1804-image
- image: teaclave/teaclave-build-ubuntu-1804-sgx-2.14:0.1.5
-
kind: pipeline
-name: sgx-release-ubuntu-1804
+name: sim-release-ubuntu-2004
steps:
- name: prepare
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+ environment:
+ SSH_USERNAME:
+ from_secret: SSH_USERNAME
+ SSH_PRIVATE_KEY:
+ from_secret: SSH_PRIVATE_KEY
+ SSH_SERVER_IP:
+ from_secret: SSH_SERVER_IP
commands:
+ - mkdir -p algorithm2_hash_sgx
+ - echo $SSH_PRIVATE_KEY | base64 -d > id_rsa
+ - chmod 400 id_rsa
+ - scp -i id_rsa -oStrictHostKeyChecking=no $SSH_USERNAME@$SSH_SERVER_IP:/xlabfs/ci/cleanroom-workload-devkit-ci-bot/libalgorithm2.a algorithm2_hash_sgx
- . /root/.cargo/env
- . /opt/sgxsdk/environment
+ - echo "127.0.0.1 teaclave-file-service" >> /etc/hosts
- mkdir -p build
- - cd build && cmake -DCMAKE_BUILD_TYPE=Release -DTEST_MODE=OFF ..
+ - cd build && cmake -DCMAKE_BUILD_TYPE=Release -DSGX_SIM_MODE=ON -DTEST_MODE=OFF ..
- name: check
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make check
- name: compile
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make VERBOSE=1 -j2
-- name: tvm example
- <<: *isgx-1804-image
+- name: package-cli
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- - . ~/.cargo/env
- - cd examples/python/wasm_tvm_mnist_payload
+ - . /root/.cargo/env
+ - . /opt/sgxsdk/environment
+ - pip3 install pyoxidizer
+ - apt update
+ - apt install -y clang
+ - cd cleanroom-cli
- make
+# - name: tvm example
+# image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+# commands:
+# - . ~/.cargo/env
+# - cd examples/python/wasm_tvm_mnist_payload
+# - make
- name: test
- <<: *isgx-1804-image
- privileged: true
- environment:
- AS_ALGO: sgx_epid
- AS_URL: https://api.trustedservices.intel.com:443
- AS_KEY:
- from_secret: V5_KEY
- AS_SPID:
- from_secret: V5_SPID
- volumes:
- - name: isgx
- path: /dev/isgx
- - name: aesmd
- path: /var/run/aesmd/aesm.socket
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make run-examples
-volumes:
-- name: isgx
- host:
- path: /dev/isgx
-- name: aesmd
- host:
- path: /var/run/aesmd/aesm.socket
+trigger:
+ ref:
+ exclude:
+ - refs/tags/cli-**
node:
instance: mesatee-sgx
---
-x-isgx-1804-image: &isgx-1804-image
- image: teaclave/teaclave-build-ubuntu-1804-sgx-2.14:0.1.5
-
kind: pipeline
-name: sim-debug-ubuntu-1804
+name: sim-debug-ubuntu-2004-test-log
steps:
- name: prepare
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+ environment:
+ SSH_USERNAME:
+ from_secret: SSH_USERNAME
+ SSH_PRIVATE_KEY:
+ from_secret: SSH_PRIVATE_KEY
+ SSH_SERVER_IP:
+ from_secret: SSH_SERVER_IP
commands:
+ - mkdir -p algorithm2_hash_sgx
+ - echo $SSH_PRIVATE_KEY | base64 -d > id_rsa
+ - chmod 400 id_rsa
+ - scp -i id_rsa -oStrictHostKeyChecking=no $SSH_USERNAME@$SSH_SERVER_IP:/xlabfs/ci/cleanroom-workload-devkit-ci-bot/libalgorithm2.a algorithm2_hash_sgx
- . /root/.cargo/env
- . /opt/sgxsdk/environment
+ - echo "127.0.0.1 teaclave-file-service" >> /etc/hosts
- mkdir -p build
- cd build && cmake -DCMAKE_BUILD_TYPE=Debug -DSGX_SIM_MODE=ON -DTEST_MODE=ON ..
- name: check
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make check
- name: compile
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make VERBOSE=1 -j2
-- name: tvm example
- <<: *isgx-1804-image
+- name: package-cli
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- - . ~/.cargo/env
- - cd examples/python/wasm_tvm_mnist_payload
+ - . /root/.cargo/env
+ - . /opt/sgxsdk/environment
+ - pip3 install pyoxidizer
+ - apt update
+ - apt install -y clang
+ - cd cleanroom-cli
- make
+# - name: tvm example
+# image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+# commands:
+# - . ~/.cargo/env
+# - cd examples/python/wasm_tvm_mnist_payload
+# - make
- name: test
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
environment:
AS_ALGO: sgx_epid
AS_URL: https://api.trustedservices.intel.com:443
@@ -607,84 +600,59 @@ steps:
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- - cd build && make run-tests
-
-node:
- instance: mesatee-sgx
-
----
+ - cd build
+ - export TEACLAVE_LOG=warn && make run-examples
-x-isgx-1804-image: &isgx-1804-image
- image: teaclave/teaclave-build-ubuntu-1804-sgx-2.14:0.1.5
-
-kind: pipeline
-name: sim-release-ubuntu-1804
-
-steps:
-- name: prepare
- <<: *isgx-1804-image
- commands:
- - . /root/.cargo/env
- - . /opt/sgxsdk/environment
- - mkdir -p build
- - cd build && cmake -DCMAKE_BUILD_TYPE=Release -DSGX_SIM_MODE=ON -DTEST_MODE=OFF ..
-- name: check
- <<: *isgx-1804-image
- commands:
- - . /root/.cargo/env
- - . /opt/sgxsdk/environment
- - cd build && make check
-- name: compile
- <<: *isgx-1804-image
- commands:
- - . /root/.cargo/env
- - . /opt/sgxsdk/environment
- - cd build && make VERBOSE=1 -j2
-- name: tvm example
- <<: *isgx-1804-image
- commands:
- - . ~/.cargo/env
- - cd examples/python/wasm_tvm_mnist_payload
- - make
-- name: test
- <<: *isgx-1804-image
- commands:
- - . /root/.cargo/env
- - . /opt/sgxsdk/environment
- - cd build && make run-examples
+trigger:
+ ref:
+ exclude:
+ - refs/tags/cli-**
node:
instance: mesatee-sgx
---
-x-isgx-1804-image: &isgx-1804-image
- image: teaclave/teaclave-build-ubuntu-1804-sgx-2.14:0.1.5
-
kind: pipeline
name: lint
steps:
- name: prepare
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
+ environment:
+ SSH_USERNAME:
+ from_secret: SSH_USERNAME
+ SSH_PRIVATE_KEY:
+ from_secret: SSH_PRIVATE_KEY
+ SSH_SERVER_IP:
+ from_secret: SSH_SERVER_IP
commands:
+ - mkdir -p algorithm2_hash_sgx
+ - echo $SSH_PRIVATE_KEY | base64 -d > id_rsa
+ - chmod 400 id_rsa
+ - scp -i id_rsa -oStrictHostKeyChecking=no $SSH_USERNAME@$SSH_SERVER_IP:/xlabfs/ci/cleanroom-workload-devkit-ci-bot/libalgorithm2.a algorithm2_hash_sgx
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- mkdir -p build
- cd build && cmake -DRUSTFLAGS="-D warnings" -DTEST_MODE=ON ..
- name: check
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make check
- name: clippy
- <<: *isgx-1804-image
+ image: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.1
commands:
- . /root/.cargo/env
- . /opt/sgxsdk/environment
- cd build && make CLP=1
+trigger:
+ ref:
+ exclude:
+ - refs/tags/cli-**
+
node:
instance: mesatee-sgx
@@ -723,15 +691,17 @@ trigger:
- hourly
depends_on:
- - sgx-debug-ubuntu-1804
- - sgx-dcap-debug-ubuntu-1804
- sgx-debug-ubuntu-2004
- - sgx-dcap-debug-ubuntu-2004
- - sgx-dcap-coverage-ubuntu-2004
- - sgx-release-ubuntu-1804
- - sim-debug-ubuntu-1804
- - sim-release-ubuntu-1804
+ - sgx-dcap-release-ubuntu-2004
+ - sgx-release-ubuntu-2004
+ - sim-debug-ubuntu-2004
+ - sim-release-ubuntu-2004
- lint
+trigger:
+ ref:
+ exclude:
+ - refs/tags/cli-**
+
node:
- instance: mesatee-sgx
+ instance: mesatee-sgx
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index 2ca637a..0000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,170 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-name: CI
-on: [push, pull_request]
-defaults:
- run:
- shell: bash
-
-jobs:
- teaclave-client-sdk-macos:
- runs-on: macos-latest
- steps:
- - uses: actions/checkout@v2
- with:
- submodules: 'true'
- - name: Install dependencies
- run: |
- brew install cmake openssl@1.1
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
- export PATH=~/.cargo/bin:$PATH
- rustup default nightly-2020-10-25 && rustup target add aarch64-apple-ios x86_64-apple-ios
- - name: Building Teaclave Client SDK
- run: |
- export PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig:/usr/local/opt/libssh2/lib/pkgconfig/"
- export PATH=~/.cargo/bin:$PATH
- cargo +stable install cargo-lipo
- cargo build --manifest-path sdk/rust/Cargo.toml
- cargo build --manifest-path sdk/rust/Cargo.toml --target aarch64-apple-ios
- cargo lipo --manifest-path sdk/rust/Cargo.toml
- cd sdk/swift/TeaclaveClientSDK && xcodebuild -scheme TeaclaveClientSDK
- sim-debug-ubuntu-1804:
- runs-on: ubuntu-18.04
- container: teaclave/teaclave-build-ubuntu-1804-sgx-2.14:0.1.5
- steps:
- - uses: actions/checkout@v2
- - name: Setting up $HOME
- run: |
- cp /root/.bashrc $HOME/.bashrc &&
- ln -sf /root/.rustup ~/.rustup &&
- ln -sf /root/.cargo ~/.cargo
- - name: Preparing build system
- run: |
- . ~/.cargo/env &&
- . /opt/sgxsdk/environment &&
- mkdir -p build &&
- cd build &&
- cmake -DCMAKE_BUILD_TYPE=Debug -DSGX_SIM_MODE=ON -DTEST_MODE=ON ..
- - name: Building
- run: |
- . /opt/sgxsdk/environment &&
- . ~/.cargo/env &&
- cd build &&
- make VERBOSE=1
- - name: Build TVM example
- run: |
- . ~/.cargo/env &&
- cd ${GITHUB_WORKSPACE}/examples/python/wasm_tvm_mnist_payload &&
- make
- - name: Run tests and examples
- run: |
- export AS_SPID="00000000000000000000000000000000" &&
- export AS_KEY="00000000000000000000000000000000" &&
- export AS_ALGO="sgx_epid" &&
- export AS_URL="https://api.trustedservices.intel.com:443" &&
- . ~/.cargo/env &&
- cd build &&
- make run-tests
-
- sim-debug-ubuntu-2004:
- runs-on: ubuntu-20.04
- container: teaclave/teaclave-build-ubuntu-2004-sgx-2.15.1:0.1.3
- steps:
- - uses: actions/checkout@v2
- - name: Setting up $HOME
- run: |
- cp /root/.bashrc $HOME/.bashrc &&
- ln -sf /root/.rustup ~/.rustup &&
- ln -sf /root/.cargo ~/.cargo
- - name: Preparing build system
- run: |
- . ~/.cargo/env &&
- . /opt/sgxsdk/environment &&
- mkdir -p build &&
- cd build &&
- cmake -DCMAKE_BUILD_TYPE=Debug -DSGX_SIM_MODE=ON -DTEST_MODE=ON ..
- - name: Building
- run: |
- . /opt/sgxsdk/environment &&
- . ~/.cargo/env &&
- cd build &&
- make VERBOSE=1
- - name: Build TVM example
- run: |
- . ~/.cargo/env &&
- cd ${GITHUB_WORKSPACE}/examples/python/wasm_tvm_mnist_payload &&
- make
- - name: Run tests and examples
- run: |
- export AS_SPID="00000000000000000000000000000000" &&
- export AS_KEY="00000000000000000000000000000000" &&
- export AS_ALGO="sgx_epid" &&
- export AS_URL="https://api.trustedservices.intel.com:443" &&
- . ~/.cargo/env &&
- cd build &&
- make run-tests
-
- format:
- runs-on: ubuntu-18.04
- container: teaclave/teaclave-build-ubuntu-1804-sgx-2.14:0.1.5
- steps:
- - uses: actions/checkout@v2
- - name: Setting up $HOME
- run: |
- cp /root/.bashrc $HOME/.bashrc &&
- ln -sf /root/.rustup ~/.rustup &&
- ln -sf /root/.cargo ~/.cargo
- - name: Preparing build system
- run: |
- . ~/.cargo/env &&
- . /opt/sgxsdk/environment &&
- mkdir -p build &&
- cd build &&
- cmake -DRUSTFLAGS="-D warnings" -DTEST_MODE=ON ..
- - name: Checking code format
- run: |
- . /root/.cargo/env &&
- cd build && make check
- lint:
- runs-on: ubuntu-18.04
- container: teaclave/teaclave-build-ubuntu-1804-sgx-2.14:0.1.5
- steps:
- - uses: actions/checkout@v2
- - name: Setting up $HOME
- run: |
- cp /root/.bashrc $HOME/.bashrc &&
- ln -sf /root/.rustup ~/.rustup &&
- ln -sf /root/.cargo ~/.cargo
- - name: Preparing build system
- run: |
- . ~/.cargo/env &&
- . /opt/sgxsdk/environment &&
- mkdir -p build &&
- cd build &&
- cmake -DRUSTFLAGS="-D warnings" -DTEST_MODE=ON ..
- - name: Code linting with Clippy
- run: |
- . /opt/sgxsdk/environment &&
- . /root/.cargo/env &&
- cd build && make CLP=1
- license:
- runs-on: ubuntu-18.04
- steps:
- - uses: actions/checkout@v2
- - name: Check License Header
- uses: apache/skywalking-eyes@main
diff --git a/.github/workflows/cli-packaging.yml b/.github/workflows/cli-packaging.yml
new file mode 100644
index 0000000..9f42d95
--- /dev/null
+++ b/.github/workflows/cli-packaging.yml
@@ -0,0 +1,122 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: cli-packaging
+on:
+ push:
+ tags:
+ - 'cli-**'
+defaults:
+ run:
+ shell: bash
+
+
+jobs:
+ matrix-packaging:
+ runs-on: ${{ matrix.label }}
+ strategy:
+ matrix:
+ label: [ci-mac-x86_64, ci-linux-x64]
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set env
+ run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
+ - name: Test
+ run: |
+ echo $RELEASE_VERSION
+ echo $(uname) $(uname -m)
+ - name: Building Cleanroom CLI
+ run: |
+ CommitID=$(git rev-parse --short HEAD)
+ UniqID=$RELEASE_VERSION-$CommitID
+ DestBase=/xlabfs/shared/teaclave-release/tmp
+ DestDir=$DestBase/$UniqID
+ echo $DestDir
+
+ ssh node5 "mkdir -p $DestDir -m775"
+
+ cd cleanroom-cli
+ make azure > make_azure.log
+
+ os=$(uname)
+ arch=$(uname -m)
+ package_name=cleanroom-cli-$os-$arch
+
+ ls $package_name.tgz
+
+ scp $package_name.tgz node5:"$DestDir"
+
+ mac-arm64-packaging:
+ runs-on: ci-mac-arm64
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set env
+ run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
+ - name: Test
+ run: |
+ echo $RELEASE_VERSION
+ echo $(uname) $(uname -m)
+ - name: Building Cleanroom CLI
+ run: |
+ CommitID=$(git rev-parse --short HEAD)
+ UniqID=$RELEASE_VERSION-$CommitID
+ DestBase=/xlabfs/shared/teaclave-release/tmp
+ DestDir=$DestBase/$UniqID
+ echo $DestDir
+
+ ssh node5 "mkdir -p $DestDir -m775"
+
+ cd cleanroom-cli
+
+ arch -arm64 make azure > make_azure.log
+ package_name=cleanroom-cli-Darwin-arm64
+
+ ls $package_name.tgz
+
+ scp $package_name.tgz node5:"$DestDir"
+
+ archive-packages:
+ needs: [matrix-packaging, mac-arm64-packaging]
+ runs-on: ci-linux-x64
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set ENV
+ run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
+ - name: Test ENV
+ run: |
+ echo $RELEASE_VERSION
+ - name: Building Cleanroom CLI
+ run: |
+ CommitID=$(git rev-parse --short HEAD)
+ UniqID=$RELEASE_VERSION-$CommitID
+ ReleaseDir=/xlabfs/shared/teaclave-release
+ DestBase=/xlabfs/shared/teaclave-release/tmp
+ DestDir=$DestBase/$UniqID
+ echo $DestDir
+
+ cd cleanroom-cli/
+ cli_version=$(cat cleanroom-cli.py | sed -n 's/^__version__ = "\(.*\)"/\1/p')
+ echo $cli_version
+
+ echo $RELEASE_VERSION | grep -qE "$cli_version$"
+
+ echo $cli_version > version
+ cp version $DestDir
+ cp install.sh $DestDir
+
+ tar czvf cleanroom-$UniqID.tgz -C $DestBase $UniqID
+ cp cleanroom-$UniqID.tgz $ReleaseDir
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
deleted file mode 100644
index b9c5ff0..0000000
--- a/.github/workflows/codeql-analysis.yml
+++ /dev/null
@@ -1,62 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-name: "Code scanning"
-
-on:
- push:
- pull_request:
- schedule:
- - cron: '36 22 * * 3'
-
-jobs:
- analyze-cpp:
- name: Analyze cpp
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v2
- with:
- submodules: 'true'
-
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v1
- with:
- languages: cpp
-
- - name: Build C projects
- run: cd examples/c && make
-
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
-
- analyze-python:
- name: Analyze python
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v2
-
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v1
- with:
- languages: python
-
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
diff --git a/.gitmodules b/.gitmodules
index b2955f0..d861c3f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -15,5 +15,6 @@
ignore = dirty
[submodule "third_party/wasm-micro-runtime"]
path = third_party/wasm-micro-runtime
- url = https://github.com/bytecodealliance/wasm-micro-runtime
+ url = https://github.com/organization/wasm-micro-runtime
+ branch = cleanroom
ignore = dirty
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ff7b657..3d46b38 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -110,8 +110,12 @@ parse_cargo_packages(
if(NOT TEST_MODE)
list(FILTER SGX_APPS EXCLUDE REGEX "_tests$")
list(FILTER SGX_APP_CATEGORIES EXCLUDE REGEX "tests")
+ list(FILTER SGX_APPS EXCLUDE REGEX "_profiling$")
+ list(FILTER SGX_APP_CATEGORIES EXCLUDE REGEX "profiling")
list(FILTER SGX_LIBS EXCLUDE REGEX "_tests_enclave$")
list(FILTER SGX_LIB_CATEGORIES EXCLUDE REGEX "tests")
+ list(FILTER SGX_LIBS EXCLUDE REGEX "_profiling_enclave$")
+ list(FILTER SGX_LIB_CATEGORIES EXCLUDE REGEX "profiling")
endif()
if(NOT DCAP)
@@ -189,6 +193,7 @@ set(WAMR_OUTPUTS
${TEACLAVE_OUT_DIR}/libvmlib.a
)
+
if(USE_PREBUILT_MESAPY)
add_custom_command(
OUTPUT ${MESAPY_OUTPUTS}
@@ -220,22 +225,27 @@ ExternalProject_Add(wamr_teaclave
LOG_BUILD 1
)
+
add_custom_command(
OUTPUT ${WAMR_OUTPUTS}
DEPENDS wamr_teaclave
COMMAND
- cp ${WAMR_TEACLAVE_ROOT_DIR}/build/libvmlib.a ${TEACLAVE_OUT_DIR}
+ cp ${WAMR_TEACLAVE_ROOT_DIR}/build/libvmlib.a ${TEACLAVE_OUT_DIR} &&
+ cp ${ALGORITHM2_ROOT_DIR}/libalgorithm2.a ${TEACLAVE_OUT_DIR}
WORKING_DIRECTORY ${WAMR_TEACLAVE_ROOT_DIR}/build
)
+
add_custom_target(mesapy
DEPENDS ${MESAPY_OUTPUTS}
)
+
add_custom_target(wamr
DEPENDS ${WAMR_TEACLAVE_ROOT_DIR}/CMakeLists.txt ${WAMR_OUTPUTS}
)
+
# mesapy components
add_custom_command(
OUTPUT ${TEACLAVE_OUT_DIR}/acs_py_enclave.c
@@ -303,3 +313,4 @@ add_cargo_build_dylib_staticlib_target(teaclave_client_sdk
# ${TEACLAVE_EXAMPLE_INSTALL_DIR}/quickstart_c )
add_enclave_sig_target_n_hooks()
+
diff --git a/NOTICE b/NOTICE
index 8d84f50..22629d1 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
Apache Teaclave (incubating)
-Copyright 2019-2022 The Apache Software Foundation
+Copyright 2019-2021 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
index fe59a6f..4c0cbbf 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,6 @@ platform, making computation on privacy-sensitive data safe and simple.
### Contribute to Teaclave
-- [Release Guide](docs/release-guide.md)
- [Rust Development Guideline](docs/rust-guideline.md)
- [Development Tips](docs/development-tips.md)
diff --git a/attestation/Cargo.toml b/attestation/Cargo.toml
index 35bc104..85e6cc2 100644
--- a/attestation/Cargo.toml
+++ b/attestation/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_attestation"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Provides TLS-based remote attestation mechanism in Teaclave."
license = "Apache-2.0"
@@ -44,7 +44,7 @@ cfg-if = { version = "0.1.9" }
chrono = { version = "0.4.6" }
hex = { version = "0.4.0" }
httparse = { version = "1.3.2", default-features = false }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
num-bigint = { version = "0.2.2" }
percent-encoding = { version = "2.1.0" }
rustls = { version = "0.16.0", features = ["dangerous_configuration"] }
diff --git a/binder/Cargo.toml b/binder/Cargo.toml
index a427e2f..eb5b869 100644
--- a/binder/Cargo.toml
+++ b/binder/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_binder"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Abstract communication interfaces between TEE untrusted/trusted worlds."
license = "Apache-2.0"
@@ -39,7 +39,7 @@ app_unit_test = []
cfg-if = { version = "0.1.9" }
anyhow = { version = "1.0.26" }
env_logger = { version = "0.7.1" }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
serde = { version = "1.0.92", features = ["derive"] }
serde_json = { version = "1.0.39" }
thiserror = { version = "1.0.9" }
diff --git a/binder/attribute/Cargo.toml b/binder/attribute/Cargo.toml
index a4162de..538af15 100644
--- a/binder/attribute/Cargo.toml
+++ b/binder/attribute/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_binder_attribute"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Macros for binder"
license = "Apache-2.0"
diff --git a/binder/src/proto.rs b/binder/src/proto.rs
index b3e7fa7..aab5c5f 100644
--- a/binder/src/proto.rs
+++ b/binder/src/proto.rs
@@ -96,14 +96,22 @@ impl RunTestInput {
#[derive(Serialize, Deserialize, Debug)]
pub struct RunTestOutput;
-#[derive(Default, Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug)]
+pub enum SubCmd {
+ Attestation,
+ BackupDb,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
pub struct RawJsonInput {
+ pub sub_cmd: SubCmd,
pub json: String,
}
impl RawJsonInput {
- pub fn new(json: impl ToString) -> Self {
+ pub fn new(sub_cmd: SubCmd, json: impl ToString) -> Self {
Self {
+ sub_cmd,
json: json.to_string(),
}
}
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index ff36216..aa0bcf6 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_cli"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave command line tool"
license = "Apache-2.0"
diff --git a/cmake/TeaclaveGenVars.cmake b/cmake/TeaclaveGenVars.cmake
index 347ed06..966bcba 100644
--- a/cmake/TeaclaveGenVars.cmake
+++ b/cmake/TeaclaveGenVars.cmake
@@ -17,6 +17,7 @@
set(TEACLAVE_PROJECT_ROOT ${PROJECT_SOURCE_DIR})
set(TEACLAVE_BUILD_ROOT ${PROJECT_BINARY_DIR})
+set(TEACLAVE_CLEANROOMCLI_ROOT ${PROJECT_SOURCE_DIR}/cleanroom-cli)
set(TEACLAVE_OUT_DIR ${PROJECT_BINARY_DIR}/intermediate)
set(TEACLAVE_INSTALL_DIR ${PROJECT_SOURCE_DIR}/release)
set(TEACLAVE_EDL_DIR ${PROJECT_SOURCE_DIR}/edl)
@@ -45,6 +46,9 @@ set(TRUSTED_TARGET_DIR ${TEACLAVE_TARGET_DIR}/trusted)
set(WAMR_TEACLAVE_ROOT_DIR
${PROJECT_SOURCE_DIR}/third_party/wasm-micro-runtime/product-mini/platforms/teaclave-sgx
)
+set(ALGORITHM2_ROOT_DIR
+ ${PROJECT_SOURCE_DIR}/algorithm2_hash_sgx
+)
# build.rs will read ENV{ENCLAVE_OUT_DIR} for linking
set(ENCLAVE_OUT_DIR ${TEACLAVE_OUT_DIR})
set(RUST_SGX_SDK ${PROJECT_SOURCE_DIR}/third_party/rust-sgx-sdk)
@@ -123,6 +127,7 @@ set(TEACLAVE_COMMON_ENVS
TEACLAVE_EXAMPLE_INSTALL_DIR=${TEACLAVE_EXAMPLE_INSTALL_DIR}
TEACLAVE_BIN_INSTALL_DIR=${TEACLAVE_BIN_INSTALL_DIR}
TEACLAVE_CLI_INSTALL_DIR=${TEACLAVE_CLI_INSTALL_DIR}
+ TEACLAVE_CLEANROOMCLI_ROOT=${TEACLAVE_CLEANROOMCLI_ROOT}
TEACLAVE_TOOL_INSTALL_DIR=${TEACLAVE_TOOL_INSTALL_DIR}
TEACLAVE_DCAP_INSTALL_DIR=${TEACLAVE_DCAP_INSTALL_DIR}
TEACLAVE_LIB_INSTALL_DIR=${TEACLAVE_LIB_INSTALL_DIR}
diff --git a/cmake/TeaclaveUtils.cmake b/cmake/TeaclaveUtils.cmake
index 144a0f7..877a525 100644
--- a/cmake/TeaclaveUtils.cmake
+++ b/cmake/TeaclaveUtils.cmake
@@ -58,17 +58,8 @@ function(init_submodules)
)
endif()
# Patch WAMR after pulling
- if(NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/wasm-micro-runtime/product-mini/platforms/teaclave-sgx/CMakeLists.txt")
- execute_process(
- COMMAND
- patch -N -p1
- INPUT_FILE "../wamr.patch"
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/third_party/wasm-micro-runtime
- )
- endif()
endif()
endif()
-
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/crates-io"
OR NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/crates-sgx"
OR NOT EXISTS "${PROJECT_SOURCE_DIR}/third_party/mesapy"
diff --git a/cmake/UtilTargets.cmake b/cmake/UtilTargets.cmake
index 5c6cf1c..d707b95 100644
--- a/cmake/UtilTargets.cmake
+++ b/cmake/UtilTargets.cmake
@@ -74,8 +74,12 @@ if(TEST_MODE)
run-sdk-tests COMMAND ${TEACLAVE_COMMON_ENVS}
${MT_SCRIPT_DIR}/test.sh sdk)
add_custom_target(
- run-cancel-test COMMAND ${TEACLAVE_COMMON_ENVS}
+ run-cancel-tests COMMAND ${TEACLAVE_COMMON_ENVS}
${MT_SCRIPT_DIR}/test.sh cancel)
+
+ add_custom_target(
+ run-cleanroomcli-tests COMMAND ${TEACLAVE_COMMON_ENVS}
+ ${MT_SCRIPT_DIR}/test.sh cleanroomcli)
else()
add_custom_target(
run-tests
diff --git a/cmake/scripts/parse_cargo_packages.py b/cmake/scripts/parse_cargo_packages.py
index 457b9c7..3412191 100644
--- a/cmake/scripts/parse_cargo_packages.py
+++ b/cmake/scripts/parse_cargo_packages.py
@@ -95,6 +95,7 @@ def pkg_path_2_category(pkg_path):
DEFAULT_EDL_LIB = "Enclave_common_t"
PKG_NAME_TO_EDL_LIB = {
"teaclave_unit_tests_enclave": "Enclave_fa_t",
+ "teaclave_profiling_enclave": "Enclave_fa_t",
"teaclave_execution_service_enclave": "Enclave_fa_t",
}
diff --git a/cmake/scripts/prep.sh b/cmake/scripts/prep.sh
index dc87812..6fa4b21 100755
--- a/cmake/scripts/prep.sh
+++ b/cmake/scripts/prep.sh
@@ -26,7 +26,7 @@ REQUIRED_ENVS=("CMAKE_SOURCE_DIR" "CMAKE_BINARY_DIR"
"TEACLAVE_CLI_INSTALL_DIR" "TEACLAVE_TOOL_INSTALL_DIR" "TEACLAVE_DCAP_INSTALL_DIR"
"TEACLAVE_LIB_INSTALL_DIR" "TEACLAVE_TEST_INSTALL_DIR"
"TEACLAVE_AUDITORS_DIR" "TEACLAVE_EXAMPLE_AUDITORS_DIR" "DCAP" "TEACLAVE_SYMLINKS"
-"TEACLAVE_PROJECT_ROOT"
+"TEACLAVE_PROJECT_ROOT" "TEACLAVE_CLEANROOMCLI_ROOT"
)
for var in "${REQUIRED_ENVS[@]}"; do
diff --git a/cmake/scripts/sgx_link_sign.sh b/cmake/scripts/sgx_link_sign.sh
index b2e4de7..dd9a44e 100755
--- a/cmake/scripts/sgx_link_sign.sh
+++ b/cmake/scripts/sgx_link_sign.sh
@@ -46,7 +46,7 @@ fi
TEACLAVE_LINK_FLAGS="-L${TEACLAVE_OUT_DIR} -lpycomponent ffi.o -lpypy-c -lsgx_tlibc_ext -lffi"
if [ "$TEACLAVE_EXECUTOR_WAMR" == "ON" ]; then
- TEACLAVE_LINK_FLAGS+=" -lvmlib"
+ TEACLAVE_LINK_FLAGS+=" -lvmlib -lalgorithm2"
fi
# Enable the security flags
diff --git a/cmake/scripts/test.sh b/cmake/scripts/test.sh
index a8a5747..1f79e61 100755
--- a/cmake/scripts/test.sh
+++ b/cmake/scripts/test.sh
@@ -18,7 +18,6 @@
# under the License.
set -eE
-export TEACLAVE_LOG=teaclave=info
if [ -z "${TEACLAVE_PROJECT_ROOT}" ] \
|| [ -z "${SGX_SDK}" ] || [ -z "${SGX_MODE}" ]; then
@@ -69,7 +68,7 @@ cleanup() {
wait_port() {
for port in "$@"
do
- timeout 10 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' localhost "$port"
+ timeout 20 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' localhost "$port"
done
}
@@ -227,16 +226,17 @@ run_examples() {
# Run tests of execution service separately
./teaclave_execution_service &
- sleep 3 # wait for execution services
+ sleep 6 # wait for execution services
popd
# Generate WASM file for WAMR Rust example
- pushd ${TEACLAVE_PROJECT_ROOT}/examples/python/wasm_rust_psi_payload
- make
- popd
+ # pushd ${TEACLAVE_PROJECT_ROOT}/examples/python/wasm_rust_psi_payload
+ # make
+ # popd
pushd ${TEACLAVE_PROJECT_ROOT}/examples/python
export PYTHONPATH=${TEACLAVE_PROJECT_ROOT}/sdk/python
+ python3 test_default_arguments.py
python3 builtin_echo.py
python3 mesapy_echo.py
python3 mesapy_logistic_reg.py
@@ -248,24 +248,29 @@ run_examples() {
python3 builtin_rsa_sign.py
python3 builtin_face_detection.py
python3 builtin_password_check.py
- python3 wasm_c_simple_add.py
- python3 wasm_rust_psi.py
- python3 wasm_tvm_mnist.py
+ python3 cleanroom_algorithm1.py
+ python3 cleanroom_stderr.py
+ python3 builtin_cleanroom_algorithm2.py
+ # python3 cleanroom_algorithm1_repeat.py
+ # python3 cleanroom_algorithm2.py
+ # python3 wasm_c_simple_add.py
+ # python3 wasm_rust_psi.py
+ # python3 wasm_tvm_mnist.py
python3 test_disable_function.py
popd
- pushd ${TEACLAVE_PROJECT_ROOT}/examples/c
- make run
- popd
-
- pushd ${TEACLAVE_PROJECT_ROOT}/examples/rust
- pushd ./builtin_echo
- RUSTFLAGS=${RUSTFLAGS} cargo run
- popd
- pushd ./builtin_ordered_set_intersect
- RUSTFLAGS=${RUSTFLAGS} cargo run
- popd
- popd
+ # pushd ${TEACLAVE_PROJECT_ROOT}/examples/c
+ # make run
+ # popd
+
+ # pushd ${TEACLAVE_PROJECT_ROOT}/examples/rust
+ # pushd ./builtin_echo
+ # RUSTFLAGS=${RUSTFLAGS} cargo run
+ # popd
+ # pushd ./builtin_ordered_set_intersect
+ # RUSTFLAGS=${RUSTFLAGS} cargo run
+ # popd
+ # popd
# kill all background services
cleanup
@@ -301,7 +306,7 @@ run_cancel_test() {
# Run of execution services separately
./teaclave_execution_service & exe_pid1=$!
./teaclave_execution_service & exe_pid2=$!
- sleep 10 # wait for execution services
+ sleep 25 # wait for execution services
popd
echo "executor 1 pid: $exe_pid1"
@@ -312,7 +317,7 @@ run_cancel_test() {
python3 mesapy_deadloop_cancel.py
popd
- sleep 10 # Wait for executor exit
+ sleep 15 # Wait for executor exit
live_pids=0
if ps -p $exe_pid1 > /dev/null
@@ -325,6 +330,7 @@ run_cancel_test() {
live_pids=$((live_pids+1))
fi
+ echo "Current Executor: ${live_pids}"
if [ $live_pids -eq 1 ]
then
echo "only one executor is killed, test passed"
@@ -336,6 +342,46 @@ run_cancel_test() {
cleanup
}
+run_cleanroomcli_tests() {
+ trap cleanup INT TERM ERR
+
+ echo_title "cleanroom cli"
+ mkdir -p /tmp/fusion_data
+ pushd ${TEACLAVE_CLI_INSTALL_DIR}
+ ./teaclave_cli verify \
+ --enclave-info ../examples/enclave_info.toml \
+ --public-keys $(find ../examples -name "*.public.pem") \
+ --signatures $(find ../examples -name "*.sign.sha256")
+ popd
+
+ echo "initiating Teaclave..."
+
+ pushd ${TEACLAVE_SERVICE_INSTALL_DIR}
+ ./teaclave_authentication_service &
+ ./teaclave_storage_service &
+ wait_port 7776 17776 17778 # wait for authentication and storage service
+ ./teaclave_management_service &
+ ./teaclave_scheduler_service &
+ wait_port 17777 17780 # wait for management service and scheduler_service
+ ./teaclave_access_control_service &
+ ./teaclave_frontend_service &
+ wait_port 17779 7777 # wait for other services
+
+ start_storage_server
+
+ # Run of execution services separately
+ ./teaclave_execution_service & exe_pid1=$!
+ sleep 25 # wait for execution services
+ popd
+
+ pushd ${TEACLAVE_CLEANROOMCLI_ROOT}
+ ./run_test.sh
+ popd
+
+ # kill all background services
+ cleanup
+}
+
case "$1" in
"unit")
run_unit_tests
@@ -355,6 +401,9 @@ case "$1" in
"cancel")
run_cancel_test
;;
+ "cleanroomcli")
+ run_cleanroomcli_tests
+ ;;
*)
run_unit_tests
run_integration_tests
@@ -362,5 +411,6 @@ case "$1" in
run_sdk_tests
run_examples
run_cancel_test
+ run_cleanroomcli_tests
;;
esac
diff --git a/cmake/tomls/Cargo.sgx_trusted_lib.toml b/cmake/tomls/Cargo.sgx_trusted_lib.toml
index 687b4ca..4b2681e 100644
--- a/cmake/tomls/Cargo.sgx_trusted_lib.toml
+++ b/cmake/tomls/Cargo.sgx_trusted_lib.toml
@@ -26,6 +26,7 @@ members = [
"services/management/enclave",
"services/scheduler/enclave",
"tests/unit/enclave",
+ "tests/profiling/enclave",
"tests/functional/enclave",
"tests/integration/enclave",
"tool/enclave",
@@ -90,6 +91,7 @@ sct = { git = "https://github.com/mesalock-linux/sct.rs", branch =
serde = { git = "https://github.com/mesalock-linux/serde-sgx" }
serde_derive = { git = "https://github.com/mesalock-linux/serde-sgx" }
serde_json = { git = "https://github.com/mesalock-linux/serde-json-sgx" }
+bincode = { git = "https://github.com/mesalock-linux/bincode-sgx"}
threadpool = { git = "https://github.com/mesalock-linux/rust-threadpool-sgx" }
# tiff = { git = "https://github.com/mesalock-linux/image-tiff-sgx" }
toml = { git = "https://github.com/mesalock-linux/toml-rs-sgx" }
@@ -99,3 +101,6 @@ uuid = { git = "https://github.com/mesalock-linux/uuid-sgx" }
webpki = { git = "https://github.com/mesalock-linux/webpki", branch = "mesalock_sgx" }
webpki-roots = { git = "https://github.com/mesalock-linux/webpki-roots", branch = "mesalock_sgx" }
yasna = { git = "https://github.com/mesalock-linux/yasna.rs-sgx" }
+
+[profile.release]
+lto = true
diff --git a/cmake/tomls/Cargo.sgx_untrusted_app.toml b/cmake/tomls/Cargo.sgx_untrusted_app.toml
index 2fa8058..bb8c7e3 100644
--- a/cmake/tomls/Cargo.sgx_untrusted_app.toml
+++ b/cmake/tomls/Cargo.sgx_untrusted_app.toml
@@ -26,6 +26,7 @@ members = [
"services/management/app",
"services/scheduler/app",
"tests/unit/app",
+ "tests/profiling/app",
"tests/functional/app",
"tests/integration/app",
"tool/app",
@@ -40,3 +41,6 @@ sgx_urts = { git = "https://github.com/apache/teaclave-sgx-sdk", rev = "v1.1.3"
sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk", rev = "v1.1.3" }
sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk", rev = "v1.1.3" }
sgx_trts = { git = "https://github.com/apache/teaclave-sgx-sdk", rev = "v1.1.3" }
+
+[profile.release]
+lto = true
diff --git a/cmake/tomls/Cargo.unix_app.toml b/cmake/tomls/Cargo.unix_app.toml
index 718170f..f239c32 100644
--- a/cmake/tomls/Cargo.unix_app.toml
+++ b/cmake/tomls/Cargo.unix_app.toml
@@ -34,3 +34,6 @@ exclude = [
# sgx_urts = { git = "https://github.com/apache/teaclave-sgx-sdk", rev = "v1.1.3" }
sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk", rev = "v1.1.3" }
sgx_ucrypto = { git = "https://github.com/apache/teaclave-sgx-sdk", rev = "v1.1.3" }
+
+[profile.release]
+lto = true
diff --git a/common/protected_fs_rs/Cargo.lock b/common/protected_fs_rs/Cargo.lock
index 84dab3f..b0601a3 100644
--- a/common/protected_fs_rs/Cargo.lock
+++ b/common/protected_fs_rs/Cargo.lock
@@ -25,7 +25,7 @@ checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
[[package]]
name = "protected_fs_rs"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"cfg-if",
"libc",
diff --git a/common/protected_fs_rs/Cargo.toml b/common/protected_fs_rs/Cargo.toml
index 8370ae4..ab877b8 100644
--- a/common/protected_fs_rs/Cargo.toml
+++ b/common/protected_fs_rs/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "protected_fs_rs"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Ported sgx_protected_fs (Intel SGX SDK) running out side sgx with Rust bindings."
license-file = "Apache-2.0"
diff --git a/common/rusty_leveldb_sgx/Cargo.toml b/common/rusty_leveldb_sgx/Cargo.toml
index 2c09ebf..5173df2 100644
--- a/common/rusty_leveldb_sgx/Cargo.toml
+++ b/common/rusty_leveldb_sgx/Cargo.toml
@@ -24,6 +24,7 @@ integer-encoding = { version = "1.0" }
protected_fs_rs = { path = "../protected_fs_rs", optional = true }
teaclave_test_utils = { path = "../../tests/utils", optional = true }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
sgx_tstd = { version = "1.1.3", optional = true }
sgx_trts = { version = "1.1.3", optional = true }
diff --git a/common/rusty_leveldb_sgx/src/db_impl.rs b/common/rusty_leveldb_sgx/src/db_impl.rs
index 04cb757..56b6a7f 100644
--- a/common/rusty_leveldb_sgx/src/db_impl.rs
+++ b/common/rusty_leveldb_sgx/src/db_impl.rs
@@ -136,7 +136,9 @@ impl DB {
db.vset.borrow_mut().log_and_apply(ve)?;
}
+ log::warn!("delete_obsolete_files at open");
db.delete_obsolete_files()?;
+
db.maybe_do_compaction()?;
Ok(db)
}
@@ -187,8 +189,8 @@ impl DB {
// Recover from all log files not in the descriptor.
let mut max_seq = 0;
let filenames = self.opt.env.children(&self.path)?;
- let mut expected = self.vset.borrow().live_files();
let mut log_files = vec![];
+ let mut expected = self.vset.borrow().live_files();
for file in &filenames {
if let Ok((num, typ)) = parse_file_name(&file) {
@@ -201,12 +203,15 @@ impl DB {
}
}
if !expected.is_empty() {
- log!(self.opt.log, "Missing at least these files: {:?}", expected);
+ //log!(self.opt.log, "Missing at least these files: {:?}", expected);
+ //return err(StatusCode::Corruption, "missing live files (see log)");
+ log::error!("Missing at least these files: {:?}", expected);
return err(StatusCode::Corruption, "missing live files (see log)");
}
log_files.sort();
for i in 0..log_files.len() {
+ log::info!("Recover log_file: {:?}", log_files[i]);
let (save_manifest_, max_seq_) =
self.recover_log_file(log_files[i], i == log_files.len() - 1, ve)?;
if save_manifest_ {
@@ -337,7 +342,8 @@ impl DB {
if typ == FileType::Table {
let _ = self.cache.borrow_mut().evict(num);
}
- log!(self.opt.log, "Deleting file type={:?} num={}", typ, num);
+ //log!(self.opt.log, "Deleting file type={:?} num={}", typ, num);
+ log::warn!("Deleting file type={:?} num={}", typ, num);
if let Err(e) = self.opt.env.delete(&self.path.join(&name)) {
log!(self.opt.log, "Deleting file num={} failed: {}", num, e);
}
diff --git a/common/rusty_leveldb_sgx/src/lib.rs b/common/rusty_leveldb_sgx/src/lib.rs
index a5727b6..40aa59c 100644
--- a/common/rusty_leveldb_sgx/src/lib.rs
+++ b/common/rusty_leveldb_sgx/src/lib.rs
@@ -86,6 +86,79 @@ pub use crate::write_batch::WriteBatch;
pub use db_impl::DB;
pub use disk_env::PosixDiskEnv;
+use std::collections::VecDeque;
+use std::path::Path;
+use std::vec::Vec;
+
+use table_cache::TableCache;
+pub struct DBReader {
+ nums: Vec<types::FileNum>,
+ tc: TableCache,
+}
+
+impl DBReader {
+ pub fn new(db_name: impl AsRef<Path>, opt: Options) -> Result<Self> {
+ let filenames = opt.env.children(db_name.as_ref())?;
+ let tc = TableCache::new(db_name.as_ref(), opt, 1024);
+ let mut nums = vec![];
+ for name in filenames {
+ if let Ok((num, typ)) = types::parse_file_name(&name) {
+ match typ {
+ types::FileType::Table => nums.push(num),
+ _ => {}
+ }
+ }
+ }
+ Ok(DBReader { nums, tc })
+ }
+}
+
+pub struct DBReaderIntoIterator {
+ tables: VecDeque<table_reader::Table>,
+ table_iter: Option<table_reader::TableIterator>,
+}
+
+impl IntoIterator for DBReader {
+ type Item = (Vec<u8>, Vec<u8>);
+ type IntoIter = DBReaderIntoIterator;
+
+ fn into_iter(mut self) -> Self::IntoIter {
+ let mut tables: VecDeque<_> = self
+ .nums
+ .clone()
+ .into_iter()
+ .map(|num| self.tc.get_table(num).unwrap())
+ .collect();
+
+ let opt_table = tables.pop_front();
+ DBReaderIntoIterator {
+ tables,
+ table_iter: opt_table.map(|table| table.iter()),
+ }
+ }
+}
+
+impl Iterator for DBReaderIntoIterator {
+ type Item = (Vec<u8>, Vec<u8>);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.table_iter.is_none() {
+ return None;
+ }
+
+ let iter = self.table_iter.as_mut().unwrap();
+ if iter.advance() {
+ let (mut k, mut v) = (vec![], vec![]);
+ iter.current(&mut k, &mut v);
+ Some((k, v))
+ } else {
+ let opt_table = self.tables.pop_front();
+ self.table_iter = opt_table.map(|table| table.iter());
+ self.next()
+ }
+ }
+}
+
#[cfg(feature = "enclave_unit_test")]
pub mod tests {
use super::*;
diff --git a/common/rusty_leveldb_sgx/src/version_set.rs b/common/rusty_leveldb_sgx/src/version_set.rs
index 3718976..58cd5ef 100644
--- a/common/rusty_leveldb_sgx/src/version_set.rs
+++ b/common/rusty_leveldb_sgx/src/version_set.rs
@@ -647,8 +647,7 @@ impl VersionSet {
self.finalize(&mut v);
self.add_version(v);
self.manifest_num = self.next_file_num - 1;
- log!(
- self.opt.log,
+ log::info!(
"Recovered manifest with next_file={} manifest_num={} log_num={} prev_log_num={} \
last_seq={}",
self.next_file_num,
diff --git a/config/Cargo.toml b/config/Cargo.toml
index b4b29dc..8385d88 100644
--- a/config/Cargo.toml
+++ b/config/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_config"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Build and runtime configurations."
license = "Apache-2.0"
@@ -30,7 +30,7 @@ build_config = []
[dependencies]
anyhow = { version = "1.0.26" }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
serde = { version = "1.0.92", features = ["derive"] }
toml = { version = "0.5.1" }
url = { version = "2.1.1" }
diff --git a/config/config_gen/Cargo.lock b/config/config_gen/Cargo.lock
index 23b17a0..0e22458 100644
--- a/config/config_gen/Cargo.lock
+++ b/config/config_gen/Cargo.lock
@@ -329,7 +329,7 @@ dependencies = [
[[package]]
name = "teaclave_config_gen"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"askama",
"pem",
diff --git a/config/config_gen/Cargo.toml b/config/config_gen/Cargo.toml
index 31e203c..5835865 100644
--- a/config/config_gen/Cargo.toml
+++ b/config/config_gen/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_config_gen"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Generating build config."
license = "Apache-2.0"
diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml
index f1f1224..dd507f9 100644
--- a/crypto/Cargo.toml
+++ b/crypto/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_crypto"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave crypto"
license = "Apache-2.0"
diff --git a/dcap/Cargo.toml b/dcap/Cargo.toml
index 8b3012c..4affa2e 100644
--- a/dcap/Cargo.toml
+++ b/dcap/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_dcap_ref_as"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave DCAP Attestation Service (Reference Implementation)"
license = "Apache-2.0"
diff --git a/dcap_deployment/backup_db.sh b/dcap_deployment/backup_db.sh
new file mode 100755
index 0000000..4b53025
--- /dev/null
+++ b/dcap_deployment/backup_db.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+set -e
+
+orig_bak=/data/backup/database_$(date +"%Y_%m_%d_%I_%M_%p").tgz
+
+# back and tar original db
+tar czvf $orig_bak /cleanroom-demo-data/database
+
+BASE="$HOME/backup_db/"
+cd $BASE/release/tool
+
+# two working directories
+# - tool/existing/
+# - tool/converted/
+
+# ensure clean working dir
+rm -rf ./existing
+mkdir ./existing
+
+# create existing
+tar xzvf $orig_bak -C ./existing
+
+# convert existing to ./converted in docker
+
+DOCKER="teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.1"
+LOCAL_AESM="/var/run/aesmd/aesm.socket"
+DOCKER_AESM="/var/run/aesmd/aesm.socket"
+
+BuildScript=$(cat << 'EOF'
+ . /opt/sgxsdk/environment;
+ cd /teaclave/release/tool
+ rm -rf ./converted
+ mkdir ./converted
+ cd ./existing
+ for db in ./cleanroom-demo-data/database/*_db; do
+ existing_db=$(realpath $db)
+ mkdir -p "../converted/$db"
+ new_db=$(realpath ../converted/$db)
+ echo "convert $existing_db to $new_db"
+
+ key="00010203040506070f0e0d0c0b0a0908"
+
+ pushd /teaclave/release/tool
+ ./teaclave_sgx_tool backup $existing_db $new_db --key $key
+ popd
+ done
+EOF
+)
+
+docker run --device /dev/sgx/enclave:/dev/sgx/enclave --device /dev/sgx/provision:/dev/sgx/provision -v ${LOCAL_AESM}:${DOCKER_AESM} -v `pwd`:/teaclave/release/tool $DOCKER /bin/bash -c "$BuildScript"
+
+# tar converted db into the same dir as $orig_bak
+cd ./converted
+tar czvf $orig_bak.converted .
+
+
diff --git a/dcap_deployment/dcap_release_build.sh b/dcap_deployment/dcap_release_build.sh
new file mode 100755
index 0000000..0c32b4f
--- /dev/null
+++ b/dcap_deployment/dcap_release_build.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+set -e
+
+BASE=$HOME/dcap-release
+cd $BASE
+
+git clone git@github.com:organization/incubator-teaclave.git
+cd incubator-teaclave
+
+sed -i 's/https:\/\/github.com\/organization/git@github.com:organization/' .gitmodules
+sed -i 's/ias_root_ca_cert/dcap_root_ca_cert/' config/build.config.toml
+
+mkdir algorithm2_hash_sgx
+cp /xlabfs/ci/cleanroom-workload-devkit-ci-bot/libalgorithm2.a algorithm2_hash_sgx
+
+git submodule update --recursive --init
+mkdir build
+
+BuildScript=$(cat <<-END
+ . /root/.cargo/env;
+ . /opt/sgxsdk/environment;
+ cd /teaclave/build;
+ cmake -DCMAKE_BUILD_TYPE=Release -DTEST_MODE=OFF -DDCAP=ON .. &&
+ make -j4
+END
+)
+docker run -v `pwd`:/teaclave "teaclave/teaclave-build-ubuntu-2004-sgx-dcap-1.12.1:0.1.1" /bin/bash -c "$BuildScript"
+
diff --git a/dcap_deployment/docker/README.md b/dcap_deployment/docker/README.md
new file mode 100644
index 0000000..139a8c7
--- /dev/null
+++ b/dcap_deployment/docker/README.md
@@ -0,0 +1,77 @@
+# Teaclave Docker Internal DCAP Deployment
+
+## Check configuration file
+Make sure the PCCS\_URL is set correctly, and `USE_SECURE_CERT=FALSE`.
+
+```
+❯ cat /etc/sgx_default_qcnl.conf
+# PCCS server address
+PCCS_URL=https://pccs-server:8081/sgx/certification/v3/
+
+# To accept insecure HTTPS certificate, set this option to FALSE
+USE_SECURE_CERT=FALSE
+```
+
+## Check aesmd
+```
+sudo service aesmd status
+● aesmd.service - Intel(R) Architectural Enclave Service Manager
+ Loaded: loaded (/lib/systemd/system/aesmd.service; enabled; vendor preset: enabled)
+ Active: active (running) since Wed 2021-12-15 22:19:20 PST; 1h 48min ago
+ Process: 25632 ExecStartPre=/opt/intel/sgx-aesm-service/aesm/linksgx.sh (code=exited, status=0/SUCCESS)
+ Process: 25639 ExecStartPre=/bin/mkdir -p /var/run/aesmd/ (code=exited, status=0/SUCCESS)
+ Process: 25640 ExecStartPre=/bin/chown -R aesmd:aesmd /var/run/aesmd/ (code=exited, status=0/SUCCESS)
+ Process: 25641 ExecStartPre=/bin/chmod 0755 /var/run/aesmd/ (code=exited, status=0/SUCCESS)
+ Process: 25642 ExecStartPre=/bin/chown -R aesmd:aesmd /var/opt/aesmd/ (code=exited, status=0/SUCCESS)
+ Process: 25643 ExecStartPre=/bin/chmod 0750 /var/opt/aesmd/ (code=exited, status=0/SUCCESS)
+ Process: 25644 ExecStart=/opt/intel/sgx-aesm-service/aesm/aesm_service (code=exited, status=0/SUCCESS)
+ Main PID: 25645 (aesm_service)
+ Tasks: 4 (limit: 76883)
+ Memory: 3.6M
+ CGroup: /system.slice/aesmd.service
+ └─25645 /opt/intel/sgx-aesm-service/aesm/aesm_service
+
+Dec 15 22:19:20 xlab-sgx4 systemd[1]: Starting Intel(R) Architectural Enclave Service Manager...
+Dec 15 22:19:20 xlab-sgx4 systemd[1]: Started Intel(R) Architectural Enclave Service Manager.
+Dec 15 22:19:20 xlab-sgx4 aesm_service[25645]: The server sock is 0x556bdd36bad0
+```
+
+## Check pccs
+```
+sudo service pccs status
+● pccs.service - Provisioning Certificate Caching Service (PCCS)
+ Loaded: loaded (/lib/systemd/system/pccs.service; enabled; vendor preset: enabled)
+ Active: active (running) since Wed 2021-12-15 22:19:15 PST; 1h 49min ago
+ Docs: https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteGeneration/pccs/README.md
+ Main PID: 25609 (node)
+ Tasks: 11 (limit: 76883)
+ Memory: 64.0M
+ CGroup: /system.slice/pccs.service
+ └─25609 /usr/bin/node -r esm /opt/intel/sgx-dcap-pccs/pccs_server.js
+```
+
+Test pccs with the following command:
+```
+curl -v -k -G "https://127.0.0.1:8081/sgx/certification/v3/rootcacrl"
+```
+
+## Launch teaclave\_dcap\_ref\_as on host
+```
+cd release/dcap/
+./teaclave_dcap_ref_as
+```
+
+## Launch service dockers
+
+```
+$ ./run-teaclave-services.sh
+Starting teaclave-file-service ... done
+Starting teaclave-authentication-service ... done
+Starting teaclave-access-control-service ... done
+Starting teaclave-scheduler-service ... done
+Starting teaclave-management-service ... done
+Starting teaclave-execution-service ... done
+Starting teaclave-frontend-service ... done
+Attaching to ...
+```
+
diff --git a/dcap_deployment/docker/deploy_compose_build.sh b/dcap_deployment/docker/deploy_compose_build.sh
new file mode 100755
index 0000000..acd7146
--- /dev/null
+++ b/dcap_deployment/docker/deploy_compose_build.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+
+docker-compose -f docker-compose-ubuntu-2004.yml -f docker-compose-dcap-dev.override.yml -f docker-compose-aesm-socket.override.yml build
diff --git a/dcap_deployment/docker/deploy_compose_run.sh b/dcap_deployment/docker/deploy_compose_run.sh
new file mode 100755
index 0000000..ef66479
--- /dev/null
+++ b/dcap_deployment/docker/deploy_compose_run.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -e
+
+source run.env
+docker-compose -f docker-compose-ubuntu-2004.yml -f docker-compose-dcap-dev.override.yml -f docker-compose-aesm-socket.override.yml up
diff --git a/dcap_deployment/docker/docker-compose-aesm-socket.override.yml b/dcap_deployment/docker/docker-compose-aesm-socket.override.yml
new file mode 100644
index 0000000..20a7ab6
--- /dev/null
+++ b/dcap_deployment/docker/docker-compose-aesm-socket.override.yml
@@ -0,0 +1,61 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+version: '3.7'
+
+services:
+ teaclave-authentication-service:
+ volumes:
+ - type: bind
+ source: /var/run/aesmd/aesm.socket
+ target: /var/run/aesmd/aesm.socket
+
+ teaclave-frontend-service:
+ volumes:
+ - type: bind
+ source: /var/run/aesmd/aesm.socket
+ target: /var/run/aesmd/aesm.socket
+
+ teaclave-management-service:
+ volumes:
+ - type: bind
+ source: /var/run/aesmd/aesm.socket
+ target: /var/run/aesmd/aesm.socket
+
+ teaclave-storage-service:
+ volumes:
+ - type: bind
+ source: /var/run/aesmd/aesm.socket
+ target: /var/run/aesmd/aesm.socket
+
+ teaclave-access-control-service:
+ volumes:
+ - type: bind
+ source: /var/run/aesmd/aesm.socket
+ target: /var/run/aesmd/aesm.socket
+
+ teaclave-execution-service:
+ volumes:
+ - type: bind
+ source: /var/run/aesmd/aesm.socket
+ target: /var/run/aesmd/aesm.socket
+
+ teaclave-scheduler-service:
+ volumes:
+ - type: bind
+ source: /var/run/aesmd/aesm.socket
+ target: /var/run/aesmd/aesm.socket
diff --git a/dcap_deployment/docker/docker-compose-aesm-vol.override.yml b/dcap_deployment/docker/docker-compose-aesm-vol.override.yml
new file mode 100644
index 0000000..49459a0
--- /dev/null
+++ b/dcap_deployment/docker/docker-compose-aesm-vol.override.yml
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+version: '3.7'
+
+volumes:
+ aesmd-socket:
+ external: true
+
+services:
+ teaclave-authentication-service:
+ volumes:
+ - aesmd-socket:/var/run/aesmd
+
+ teaclave-frontend-service:
+ volumes:
+ - aesmd-socket:/var/run/aesmd
+
+ teaclave-management-service:
+ volumes:
+ - aesmd-socket:/var/run/aesmd
+
+ teaclave-storage-service:
+ volumes:
+ - aesmd-socket:/var/run/aesmd
+
+ teaclave-access-control-service:
+ volumes:
+ - aesmd-socket:/var/run/aesmd
+
+ teaclave-execution-service:
+ volumes:
+ - aesmd-socket:/var/run/aesmd
+
+ teaclave-scheduler-service:
+ volumes:
+ - aesmd-socket:/var/run/aesmd
diff --git a/dcap_deployment/docker/docker-compose-dcap-dev.override.yml b/dcap_deployment/docker/docker-compose-dcap-dev.override.yml
new file mode 100644
index 0000000..efb0215
--- /dev/null
+++ b/dcap_deployment/docker/docker-compose-dcap-dev.override.yml
@@ -0,0 +1,54 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+version: '3.7'
+
+services:
+ teaclave-authentication-service:
+ devices:
+ - /dev/sgx/enclave
+ - /dev/sgx/provision
+
+ teaclave-frontend-service:
+ devices:
+ - /dev/sgx/enclave
+ - /dev/sgx/provision
+
+ teaclave-management-service:
+ devices:
+ - /dev/sgx/enclave
+ - /dev/sgx/provision
+
+ teaclave-storage-service:
+ devices:
+ - /dev/sgx/enclave
+ - /dev/sgx/provision
+
+ teaclave-access-control-service:
+ devices:
+ - /dev/sgx/enclave
+ - /dev/sgx/provision
+
+ teaclave-execution-service:
+ devices:
+ - /dev/sgx/enclave
+ - /dev/sgx/provision
+
+ teaclave-scheduler-service:
+ devices:
+ - /dev/sgx/enclave
+ - /dev/sgx/provision
diff --git a/dcap_deployment/docker/docker-compose-ubuntu-2004.yml b/dcap_deployment/docker/docker-compose-ubuntu-2004.yml
new file mode 100644
index 0000000..aea234a
--- /dev/null
+++ b/dcap_deployment/docker/docker-compose-ubuntu-2004.yml
@@ -0,0 +1,230 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+version: '3.7'
+
+services:
+ teaclave-authentication-service:
+ build:
+ context: ../
+ dockerfile: docker/teaclave-rt.ubuntu-2004.Dockerfile
+ ports:
+ - 7776:7776
+ expose:
+ - 7776
+ - 17776
+ volumes:
+ - ./runtime.config.toml:/teaclave/runtime.config.toml
+ - /cleanroom-demo-data:/cleanroom-demo-data
+ - /etc/aesmd.conf:/etc/aesmd.conf
+ - ./hosts:/etc/hosts
+ working_dir: /teaclave
+ environment:
+ - AS_SPID
+ - AS_KEY
+ - AS_ALGO
+ - AS_URL
+ - TEACLAVE_LOG
+ entrypoint: ./teaclave_authentication_service
+ container_name: teaclave-authentication-service
+ networks:
+ api:
+ internal:
+
+ teaclave-frontend-service:
+ build:
+ context: ../
+ dockerfile: docker/teaclave-rt.ubuntu-2004.Dockerfile
+ ports:
+ - 7777:7777
+ expose:
+ - 7777
+ volumes:
+ - ./runtime.config.toml:/teaclave/runtime.config.toml
+ - /etc/aesmd.conf:/etc/aesmd.conf
+ - ./hosts:/etc/hosts
+ working_dir: /teaclave
+ environment:
+ - AS_SPID
+ - AS_KEY
+ - AS_ALGO
+ - AS_URL
+ - TEACLAVE_LOG
+ entrypoint: ./teaclave_frontend_service
+ depends_on:
+ - teaclave-management-service
+ container_name: teaclave-frontend-service
+ networks:
+ api:
+ internal:
+
+ teaclave-management-service:
+ build:
+ context: ../
+ dockerfile: docker/teaclave-rt.ubuntu-2004.Dockerfile
+ expose:
+ - 17777
+ volumes:
+ - ./runtime.config.toml:/teaclave/runtime.config.toml
+ - /cleanroom-demo-data:/cleanroom-demo-data
+ - /etc/aesmd.conf:/etc/aesmd.conf
+ - ./hosts:/etc/hosts
+ working_dir: /teaclave
+ environment:
+ - AS_SPID
+ - AS_KEY
+ - AS_ALGO
+ - AS_URL
+ - TEACLAVE_LOG
+ entrypoint: ./teaclave_management_service
+ depends_on:
+ - teaclave-storage-service
+ - teaclave-access-control-service
+ container_name: teaclave-management-service
+ networks:
+ internal:
+
+ teaclave-storage-service:
+ build:
+ context: ../
+ dockerfile: docker/teaclave-rt.ubuntu-2004.Dockerfile
+ expose:
+ - 17778
+ volumes:
+ - ./runtime.config.toml:/teaclave/runtime.config.toml
+ - /cleanroom-demo-data:/cleanroom-demo-data
+ - /etc/aesmd.conf:/etc/aesmd.conf
+ - ./hosts:/etc/hosts
+ working_dir: /teaclave
+ environment:
+ - AS_SPID
+ - AS_KEY
+ - AS_ALGO
+ - AS_URL
+ - TEACLAVE_LOG
+ entrypoint: ./teaclave_storage_service
+ container_name: teaclave-storage-service
+ networks:
+ internal:
+
+ teaclave-access-control-service:
+ build:
+ context: ../
+ dockerfile: docker/teaclave-rt.ubuntu-2004.Dockerfile
+ expose:
+ - 17779
+ volumes:
+ - ./runtime.config.toml:/teaclave/runtime.config.toml
+ - /etc/aesmd.conf:/etc/aesmd.conf
+ - ./hosts:/etc/hosts
+ working_dir: /teaclave
+ environment:
+ - AS_SPID
+ - AS_KEY
+ - AS_ALGO
+ - AS_URL
+ - TEACLAVE_LOG
+ container_name: teaclave-access-control-service
+ entrypoint: ./teaclave_access_control_service
+ networks:
+ internal:
+
+ teaclave-execution-service:
+ build:
+ context: ../
+ dockerfile: docker/teaclave-rt.ubuntu-2004.Dockerfile
+ expose:
+ - 17770
+ volumes:
+ - ./runtime.config.toml:/teaclave/runtime.config.toml
+ - /cleanroom-demo-data:/cleanroom-demo-data
+ - /etc/aesmd.conf:/etc/aesmd.conf
+ - ./hosts:/etc/hosts
+ working_dir: /teaclave
+ environment:
+ - AS_SPID
+ - AS_KEY
+ - AS_ALGO
+ - AS_URL
+ - TEACLAVE_LOG
+ entrypoint: ./teaclave_execution_service
+ container_name: teaclave-execution-service
+ restart: always
+ depends_on:
+ - teaclave-scheduler-service
+ networks:
+ internal:
+ fs:
+
+ teaclave-scheduler-service:
+ build:
+ context: ../
+ dockerfile: docker/teaclave-rt.ubuntu-2004.Dockerfile
+ expose:
+ - 17780
+ volumes:
+ - ./runtime.config.toml:/teaclave/runtime.config.toml
+ - /etc/aesmd.conf:/etc/aesmd.conf
+ - ./hosts:/etc/hosts
+ working_dir: /teaclave
+ environment:
+ - AS_SPID
+ - AS_KEY
+ - AS_ALGO
+ - AS_URL
+ - TEACLAVE_LOG
+ entrypoint: ./teaclave_scheduler_service
+ container_name: teaclave-scheduler-service
+ depends_on:
+ - teaclave-storage-service
+ networks:
+ internal:
+
+ teaclave-file-service:
+ image: python:3
+ container_name: teaclave-file-service
+ volumes:
+ - ../release/tests:/teaclave-file-service
+ - /cleanroom-demo-data/file:/cleanroom-demo-data/file
+ working_dir: /cleanroom-demo-data/file
+ ports:
+ - 6789:6789
+ expose:
+ - 6789
+ entrypoint: /teaclave-file-service/scripts/simple_http_server.py
+ networks:
+ fs:
+
+ teaclave-file-external-service:
+ image: python:3
+ container_name: teaclave-file-external-service
+ volumes:
+ - ../release/tests:/teaclave-file-external-service
+ - /cleanroom-demo-data/file:/cleanroom-demo-data/file
+ working_dir: /cleanroom-demo-data/file
+ ports:
+ - 7789:7789
+ expose:
+ - 7789
+ entrypoint: ["/teaclave-file-external-service/scripts/auth_http_server.py", "7789", "001dda666e88921cfa9cecd5935d387b17b16c70022fe119ce69dee0ec84e3d9"]
+ networks:
+ fs:
+
+networks:
+ internal:
+ api:
+ fs:
diff --git a/dcap_deployment/docker/hosts b/dcap_deployment/docker/hosts
new file mode 100644
index 0000000..7e5fe60
--- /dev/null
+++ b/dcap_deployment/docker/hosts
@@ -0,0 +1,2 @@
+172.17.0.1 api-as-dev.cleanroom.com
+
diff --git a/dcap_deployment/docker/run-teaclave-services.sh b/dcap_deployment/docker/run-teaclave-services.sh
new file mode 100644
index 0000000..581edcd
--- /dev/null
+++ b/dcap_deployment/docker/run-teaclave-services.sh
@@ -0,0 +1,224 @@
+#!/bin/bash
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+SGX_DEV_SEL="none"
+AESM_SEL="none"
+
+function sgx_dev_detect() {
+ local ISGX_DEV=/dev/isgx
+ local ISGX_DEV_EXIST=false
+ if [ -c "$ISGX_DEV" ]; then
+ echo "$ISGX_DEV device detected."
+ ISGX_DEV_EXIST=true
+ fi
+
+ local ENCL_DEV=/dev/sgx/enclave
+ local ENCL_DEV_EXIST=false
+ if [ -L "$ENCL_DEV" ] && [ -c $(realpath $ENCL_DEV) ]; then
+ echo "$ENCL_DEV device detected."
+ ENCL_DEV_EXIST=true
+ fi
+
+ local PROV_DEV=/dev/sgx/provision
+ local PROV_DEV_EXIST=false
+ if [ -L "$PROV_DEV" ] && [ -c $(realpath $PROV_DEV) ]; then
+ echo "$PROV_DEV device detected."
+ PROV_DEV_EXIST=true
+ fi
+
+ if ($ISGX_DEV_EXIST && $ENCL_DEV_EXIST && $PROV_DEV_EXIST); then
+ PS3='Please enter your choice: '
+ options=("ISGX device" "DCAP device" "Quit")
+ select opt in "${options[@]}"
+ do
+ case $opt in
+ "ISGX device")
+ echo "you chose $opt"
+ SGX_DEV_SEL="isgx"
+ break
+ ;;
+ "DCAP device")
+ echo "you chose $opt"
+ SGX_DEV_SEL="dcap"
+ break
+ ;;
+ "Quit")
+ exit 1
+ ;;
+ *) echo "invalid option $REPLY" ;;
+ esac
+ done
+ else
+ if $ISGX_DEV_EXIST; then
+ SGX_DEV_SEL="isgx"
+ fi
+ if ($ENCL_DEV_EXIST && $PROV_DEV_EXIST); then
+ SGX_DEV_SEL="dcap"
+ fi
+ fi
+}
+
+function aesm_detect() {
+ local AESM_SOCK=/var/run/aesmd/aesm.socket
+ local AESM_SOCK_EXIST=false
+ if [ -S "$AESM_SOCK" ]; then
+ echo "$AESM_SOCK socket detected."
+ AESM_SOCK_EXIST=true
+ fi
+
+ local AESM_VOL=aesmd-socket
+ local AESM_VOL_EXIST=false
+ if docker volume inspect $AESM_VOL 2>&1 > /dev/null ; then
+ echo "$AESM_VOL volume detected."
+ AESM_VOL_EXIST=true
+ fi
+
+ if ($AESM_SOCK_EXIST && $AESM_VOL_EXIST); then
+ PS3='Please enter your choice: '
+ options=("$AESM_SOCK socket" "$AESM_VOL volume" "Quit")
+ select opt in "${options[@]}"
+ do
+ case $opt in
+ "$AESM_SOCK socket")
+ echo "you chose $opt"
+ AESM_SEL="sock"
+ break
+ ;;
+ "$AESM_VOL volume")
+ echo "you chose $opt"
+ AESM_SEL="vol"
+ break
+ ;;
+ "Quit")
+ exit 1
+ ;;
+ *) echo "invalid option $REPLY" ;;
+ esac
+ done
+ else
+ if $AESM_SOCK_EXIST; then
+ AESM_SEL="sock"
+ fi
+ if $AESM_VOL_EXIST; then
+ AESM_SEL="vol"
+ fi
+ fi
+}
+
+function usage {
+ echo "Usage: $(basename $0) [-hdbm:]" 2>&1
+ echo ' -h shows usage'
+ echo ' -m run mode (default: sgx)'
+ echo ' -d detached mode'
+ echo ' -b build or rebuild services'
+ echo 'Available run modes: sim, sgx'
+ exit 1
+}
+
+RUN_MODE="sgx"
+DETACH_ARG=""
+optstring="hdbm:"
+while getopts ${optstring} arg; do
+ case ${arg} in
+ h)
+ echo "showing usage!"
+ usage
+ ;;
+ d)
+ DETACH_ARG="-d"
+ ;;
+ b)
+ BUILD_ARG="--build"
+ ;;
+ m)
+ RUN_MODE=$OPTARG
+ ;;
+ esac
+done
+
+shift $((OPTIND-1))
+
+case $RUN_MODE in
+ "sgx")
+ sgx_dev_detect
+ aesm_detect
+ ;;
+ "sim")
+ ;;
+ *)
+ echo "The specified run mode: $RUN_MODE is not recognized."
+ usage
+ ;;
+esac
+
+OV_PREFIX="docker-compose-"
+OV_SUFFIX=".override.yml"
+SGX_DEV_OV_FILE=""
+AESM_OV_FILE=""
+case $SGX_DEV_SEL in
+ "isgx")
+ SGX_DEV_OV_FILE="isgx-dev"
+ ;;
+ "dcap")
+ SGX_DEV_OV_FILE="dcap-dev"
+ ;;
+ "none")
+ ;;
+ *)
+ echo "Invalid SGX device."
+ exit 2
+ ;;
+esac
+SGX_DEV_OV_FILE="${OV_PREFIX}${SGX_DEV_OV_FILE}${OV_SUFFIX}"
+
+case $AESM_SEL in
+ "sock")
+ AESM_OV_FILE="aesm-socket"
+ ;;
+ "vol")
+ AESM_OV_FILE="aesm-vol"
+ ;;
+ "none")
+ ;;
+ *)
+ echo "Invalid AESM service."
+ exit 2
+ ;;
+esac
+AESM_OV_FILE="${OV_PREFIX}${AESM_OV_FILE}${OV_SUFFIX}"
+
+DOCKER_COMPOSE_FILE="docker-compose-ubuntu-1804.yml"
+DC_ARGS=""
+if [ "$RUN_MODE" == "sgx" ]; then
+ if [ "$SGX_DEV_SEL" == "none" ]; then
+ echo "Cannot find a valid sgx device."
+ exit 3
+ fi
+ if [ "$AESM_SEL" == "none" ]; then
+ echo "Cannot find a valid aesm service."
+ exit 6
+ fi
+ DC_ARGS="-f $DOCKER_COMPOSE_FILE -f $SGX_DEV_OV_FILE -f $AESM_OV_FILE"
+else
+ DC_ARGS="-f $DOCKER_COMPOSE_FILE"
+fi
+
+echo COMMAND: docker-compose ${DC_ARGS} up ${DETACH_ARG} ${BUILD_ARG}
+
+#docker-compose ${DC_ARGS} up ${DETACH_ARG} ${BUILD_ARG} --build
diff --git a/dcap_deployment/docker/run.env b/dcap_deployment/docker/run.env
new file mode 100644
index 0000000..25d16de
--- /dev/null
+++ b/dcap_deployment/docker/run.env
@@ -0,0 +1,4 @@
+export AS_ALGO=sgx_ecdsa
+export AS_URL=https://api-as-dev.cleanroom.com:8080
+export AS_KEY="00000000000000000000000000000000"
+export AS_SPID="00000000000000000000000000000000"
diff --git a/dcap_deployment/docker/runtime.config.toml b/dcap_deployment/docker/runtime.config.toml
new file mode 100644
index 0000000..e5a7297
--- /dev/null
+++ b/dcap_deployment/docker/runtime.config.toml
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Teaclave Runtime Config
+#
+# Note that this config is loaded at running time. We don't have to trust the
+# content though. Maliciously crafted config from this file will not break data
+# confidentiality/integrity.
+
+[api_endpoints]
+authentication = { listen_address = "0.0.0.0:7776" }
+frontend = { listen_address = "0.0.0.0:7777" }
+
+[internal_endpoints]
+authentication = { listen_address = "0.0.0.0:17776", advertised_address = "teaclave-authentication-service:17776" }
+management = { listen_address = "0.0.0.0:17777", advertised_address = "teaclave-management-service:17777" }
+storage = { listen_address = "0.0.0.0:17778", advertised_address = "teaclave-storage-service:17778" }
+access_control = { listen_address = "0.0.0.0:17779", advertised_address = "teaclave-access-control-service:17779" }
+execution = { listen_address = "0.0.0.0:17770", advertised_address = "teaclave-execution-service:17770" }
+scheduler = { listen_address = "0.0.0.0:17780", advertised_address = "teaclave-scheduler-service:17780" }
+
+[audit]
+enclave_info = { path = "enclave_info.toml" }
+auditor_signatures = [
+ { path = "auditors/godzilla/godzilla.sign.sha256" },
+ { path = "auditors/optimus_prime/optimus_prime.sign.sha256" },
+ { path = "auditors/albus_dumbledore/albus_dumbledore.sign.sha256" },
+]
+
+[attestation]
+algorithm = "sgx_ecdsa"
+url = "https://api-as-dev.cleanroom.com:8080"
+key = "00000000000000000000000000000000"
+spid = "00000000000000000000000000000000"
+
+[mount]
+fusion_base_dir = "/cleanroom-demo-data"
diff --git a/dcap_deployment/docker/teaclave-rt.ubuntu-2004.Dockerfile b/dcap_deployment/docker/teaclave-rt.ubuntu-2004.Dockerfile
new file mode 100644
index 0000000..5bd4261
--- /dev/null
+++ b/dcap_deployment/docker/teaclave-rt.ubuntu-2004.Dockerfile
@@ -0,0 +1,81 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+FROM ubuntu:20.04
+
+ENV VERSION 2.15.101.1-focal1
+ENV SGX_DOWNLOAD_URL_BASE "https://download.01.org/intel-sgx/sgx-linux/2.15.1/distro/ubuntu20.04-server/"
+ENV SGX_LINUX_X64_SDK sgx_linux_x64_sdk_2.15.101.1.bin
+ENV SGX_LINUX_X64_SDK_URL "$SGX_DOWNLOAD_URL_BASE/$SGX_LINUX_X64_SDK"
+
+ENV DEBIAN_FRONTEND=noninteractive
+
+RUN apt-get update && apt-get install -q -y \
+ libcurl4-openssl-dev \
+ libprotobuf-dev \
+ curl \
+ pkg-config \
+ wget \
+ build-essential \
+ gpg-agent
+
+RUN echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu focal main' | \
+ tee /etc/apt/sources.list.d/intel-sgx.list
+RUN curl -fsSL https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | apt-key add -
+
+RUN apt-get update && apt-get install -q -y \
+ libsgx-launch=$VERSION \
+ libsgx-urts=$VERSION \
+ libsgx-quote-ex=$VERSION \
+ libsgx-uae-service=$VERSION
+RUN mkdir /etc/init
+
+# Install Intel SGX SDK for libsgx_urts_sim.so
+RUN wget $SGX_LINUX_X64_SDK_URL && \
+ chmod u+x $SGX_LINUX_X64_SDK && \
+ echo -e 'no\n/opt' | ./$SGX_LINUX_X64_SDK && \
+ rm $SGX_LINUX_X64_SDK && \
+ echo 'source /opt/sgxsdk/environment' >> /etc/environment
+ENV LD_LIBRARY_PATH=/opt/sgxsdk/sdk_libs
+
+# Make a directory for fusion data. Since we are in the single machine mode,
+# there is no need to mount a network file system.
+RUN mkdir -p /tmp/fusion_data
+
+ADD release/services/teaclave_frontend_service /teaclave/
+ADD release/services/teaclave_frontend_service_enclave.signed.so /teaclave/
+
+ADD release/services/teaclave_authentication_service /teaclave/
+ADD release/services/teaclave_authentication_service_enclave.signed.so /teaclave/
+
+ADD release/services/teaclave_management_service /teaclave/
+ADD release/services/teaclave_management_service_enclave.signed.so /teaclave/
+
+ADD release/services/teaclave_scheduler_service /teaclave/
+ADD release/services/teaclave_scheduler_service_enclave.signed.so /teaclave/
+
+ADD release/services/teaclave_access_control_service /teaclave/
+ADD release/services/teaclave_access_control_service_enclave.signed.so /teaclave/
+
+ADD release/services/teaclave_storage_service /teaclave/
+ADD release/services/teaclave_storage_service_enclave.signed.so /teaclave/
+
+ADD release/services/teaclave_execution_service /teaclave/
+ADD release/services/teaclave_execution_service_enclave.signed.so /teaclave/
+
+ADD release/services/enclave_info.toml /teaclave/
+ADD release/services/auditors /teaclave/auditors
diff --git a/dcap_deployment/pack_publish.sh b/dcap_deployment/pack_publish.sh
new file mode 100755
index 0000000..9f96467
--- /dev/null
+++ b/dcap_deployment/pack_publish.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+DEFAULT_PUBLISH_DIR=/xlabfs/shared/teaclave-release
+DEFAULT_VERSION_PREFIX=="0.0.6"
+DEFAULT_REPO=$HOME/dcap-release/incubator-teaclave
+
+read -p "Enter Repo Path [$DEFAULT_REPO]: " repo
+repo=${repo:-$DEFAULT_REPO}
+
+read -p "Enter publish dir [$DEFAULT_PUBLISH_DIR]: " publish_dir
+publish_dir=${publish_dir:-$DEFAULT_PUBLISH_DIR}
+
+read -p "Enter version prefix [$DEFAULT_VERSION_PREFIX]: " version_prefix
+version_prefix=${version_prefix:-$DEFAULT_VERSION_PREFIX}
+
+commit_id=$(git rev-parse --short HEAD)
+version="$version_prefix_$commit_id"
+
+out="dcap_service_release_$version"
+mkdir $out
+cp -r $repo/release $out/release
+cp -r $repo/dcap_deployment/docker $out/docker
+tar czvf $out.tgz $out
+cp $out.tgz $publish_dir/
+rm $out.tgz
+rm -rf $out
+
+out="dcap_sdk_release_$version"
+mkdir $out
+cp -r $repo/sdk/python $out/python
+cp $repo/release/services/enclave_info.toml $out/enclave_info.toml
+cp $repo/keys/dcap_root_ca_cert.pem $out/dcap_root_cert.pem
+tar czvf $out.tgz $out
+cp $out.tgz $publish_dir/
+rm $out.tgz
+rm -rf $out
+
diff --git a/dcap_deployment/pull_latest_deploy.sh b/dcap_deployment/pull_latest_deploy.sh
new file mode 100755
index 0000000..3e2db77
--- /dev/null
+++ b/dcap_deployment/pull_latest_deploy.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+set -e
+
+DEFAULT_PUBLISH_BASE=/xlabfs/shared/teaclave-release
+DEFAULT_DEPLOY_BASE=$HOME/teaclave-dcap-deploy
+
+read -p "Confirm Publish Path [$DEFAULT_PUBLISH_BASE]: " PUBLISH_BASE
+PUBLISH_BASE=${PUBLISH_BASE:-$DEFAULT_PUBLISH_BASE}
+
+read -p "Confirm Deploy Path [$DEFAULT_DEPLOY_BASE]: " DEPLOY_BASE
+DEPLOY_BASE=${DEPLOY_BASE:-$DEFAULT_DEPLOY_BASE}
+
+mkdir -p $DEPLOY_BASE
+mkdir -p $DEPLOY_BASE/logs
+
+release_tar_path=`ls -t $PUBLISH_BASE/dcap_service_release*.tgz | head -1`
+echo "[+] Latest relase tar is : $release_tar_path ..."
+cp $release_tar_path $DEPLOY_BASE
+
+echo "[+] Copy $release_tar_path to $DEPLOY_BASE ..."
+filename=$(basename -- "$release_tar_path")
+tar_name="${filename%%.tgz}"
+
+
+echo "[+] Extract $tar_name.tgz ..."
+pushd $DEPLOY_BASE
+tar xzf $tar_name.tgz
+
+log_path=$DEPLOY_BASE/logs/$tar_name.log
+echo "[+] Start service and logging to $log_path .."
+
+pushd $DEPLOY_BASE/$tar_name/docker/
+./deploy_compose_build.sh
+popd
+
+echo "Please stop the previous depyloyment and run the following command in a tmux session ... "
+
+echo "cd $DEPLOY_BASE/$tar_name/docker/"
+echo "TEACLAVE_LOG=info ./deploy_compose_run.sh >> $log_path 2>&1"
+
+popd
diff --git a/docker/docker-compose-ubuntu-1804.yml b/docker/docker-compose-ubuntu-1804.yml
index ad718b5..bb55584 100644
--- a/docker/docker-compose-ubuntu-1804.yml
+++ b/docker/docker-compose-ubuntu-1804.yml
@@ -75,6 +75,7 @@ services:
- 17777
volumes:
- ./runtime.config.toml:/teaclave/runtime.config.toml
+ - /tmp/fusion_data:/tmp/fusion_data
working_dir: /teaclave
environment:
- AS_SPID
@@ -138,6 +139,7 @@ services:
- 17770
volumes:
- ./runtime.config.toml:/teaclave/runtime.config.toml
+ - /tmp/fusion_data:/tmp/fusion_data
working_dir: /teaclave
environment:
- AS_SPID
@@ -147,6 +149,7 @@ services:
- TEACLAVE_LOG
entrypoint: ./teaclave_execution_service
container_name: teaclave-execution-service
+ restart: always
depends_on:
- teaclave-scheduler-service
networks:
@@ -181,6 +184,10 @@ services:
volumes:
- ../tests:/teaclave-file-service
working_dir: /teaclave-file-service
+ ports:
+ - 6789:6789
+ expose:
+ - 6789
entrypoint: ./scripts/simple_http_server.py
networks:
fs:
diff --git a/docker/docker-compose-ubuntu-2004.yml b/docker/docker-compose-ubuntu-2004.yml
index a639ec7..103dc3b 100644
--- a/docker/docker-compose-ubuntu-2004.yml
+++ b/docker/docker-compose-ubuntu-2004.yml
@@ -149,6 +149,7 @@ services:
- TEACLAVE_LOG
entrypoint: ./teaclave_execution_service
container_name: teaclave-execution-service
+ restart: always
depends_on:
- teaclave-scheduler-service
networks:
diff --git a/docker/run-teaclave-services.sh b/docker/run-teaclave-services.sh
index a711fd0..d9b4fce 100755
--- a/docker/run-teaclave-services.sh
+++ b/docker/run-teaclave-services.sh
@@ -84,7 +84,7 @@ function aesm_detect() {
local AESM_VOL=aesmd-socket
local AESM_VOL_EXIST=false
- if docker volume inspect $AESM_VOL > /dev/null 2>&1; then
+ if docker volume inspect $AESM_VOL 2>&1 > /dev/null ; then
echo "$AESM_VOL volume detected."
AESM_VOL_EXIST=true
fi
diff --git a/docs/README.md b/docs/README.md
index 0366c56..875ca7c 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -25,7 +25,6 @@ permalink: /docs/
## Contribute
-- [Release Guide](release-guide.md)
- [Development Tips](development-tips.md)
- [Rust Development Guideline](rust-guideline.md)
diff --git a/docs/release-guide.md b/docs/release-guide.md
deleted file mode 100644
index 57f69f8..0000000
--- a/docs/release-guide.md
+++ /dev/null
@@ -1,282 +0,0 @@
----
-permalink: /docs/release-guide
----
-
-# Release Guide
-
-This document guide you through how to prepare and publish an official release.
-Releasing a new version in the community contains multiple steps, here is an
-overview.
-
-[[toc]]
-
-## Prepare the Release Notes
-
-For a new release, you should first prepare the release note. Release note
-contains summaries of new features, enhancements, bug fixes,
-docs, known issues, and deprecation, etc. You can see the notes of
-[past release](https://github.com/apache/incubator-teaclave/releases) as an example.
-
-## Prepare the GPG Signing Key
-
-You can skip this section if you have already uploaded your key. That is, the
-GPG signing key has been added in the following places:
- - The KEYS file in repo (<https://github.com/apache/incubator-teaclave/blob/master/KEYS>)
- - Apache release dist sever (<https://dist.apache.org/repos/dist/release/incubator/teaclave/KEYS>)
-
-If you are the first to publish a release, please follow this instruction to
-generating and uplaoding keys.
-
-To generate GPG key, please refer to
-<https://www.apache.org/dev/openpgp.html#generate-key> for details.
-
-If you want to do the release on another machine, you can transfer your GPG key
-to that machine via the `gpg --export` and `gpg --import` commands.
-
-The last step is to update the KEYS file with your code signing key. Check in
-the changes to the main branch of the repository, as well as ASF SVN,
-
-Here is an instruction of editing the KEYS file in the ASF SVN.
-
-```
-# the --depth=files will avoid checkout existing folders
-svn co --depth=files "https://dist.apache.org/repos/dist/dev/incubator/teaclave" svn-dev-teaclave
-cd svn-dev-teaclave
-# edit KEYS file
-svn ci --username $ASF_USERNAME --password "$ASF_PASSWORD" -m "Update KEYS"
-# update downloads.apache.org
-svn rm --username $ASF_USERNAME --password "$ASF_PASSWORD" https://dist.apache.org/repos/dist/release/incubator/teaclave/KEYS -m "Update KEYS"
-svn cp --username $ASF_USERNAME --password "$ASF_PASSWORD" https://dist.apache.org/repos/dist/dev/incubator/teaclave/KEYS https://dist.apache.org/repos/dist/release/incubator/teaclave/ -m "Update KEYS"
-```
-
-## Cut a Release Candidate
-
-To cut a release candidate, one needs to first cut a branch from the main branch
-using selected version string. We follow the [semantic versioning](https://semver.org/)
-guidelines for new version string. In short, x.y.z means MAJOR.MINOR.PATCH. Since we
-already have the release note, we can decide the version string to be released
-based on the changes.
-
-Note that in our workflow, the main branch should be freezed during the
-releasing period, i.e, no new features and enhancements can be merged into it.
-Only changes on this release can be merged and committed into the releasing
-branch.
-
-For example, to release version 1.0.0, let us first create a new branch
-`release-v1.0.0` from the main branch.
-
-```
-git clone https://github.com/apache/incubator-teaclave
-cd incubator-teaclave
-git checkout -b release-v1.0.0
-```
-
-The next step is to do a complete version bumping (e.g., changing files which
-contain versions and bump them from v0.9.0 to v1.0.0). Note that this affect
-multiple files in different languages. Then, commit the changes to this
-releasing branch. Other bug fixes and docs improvements can be also commited at
-this time.
-
-When cleanups are done, make sure all tests can be passed. Then, add a tag with
-the current commit in the form of "v1.0.0-rc.1" where 1 means it's the first
-release candidate. You can add the tag using git or add on GitHub.
-
-Using Git:
-```
-git tag v1.0.0-rc.1
-git push origin v1.0.0-rc.1
-```
-
-## Create Release Artifacts
-
-Create the source code artifacts, including a self-contained tarball without git
-history, a signature file signed by keys in the KEYS file, and a sha256 hash
-file.
-
-```
-git clone git@github.com:apache/incubator-teaclave.git apache-teaclave-1.0.0-rc.1-incubating
-cd apache-teaclave-1.0.0-rc.1-incubating
-git checkout v1.0.0-rc.1
-mkdir build && cd build && cmake .. && cd .. # This will init submodules and apply patches
-rm -rf build
-find . -name ".git" -print0 | xargs -0 rm -rf # Remove all .git directories
-cd ..
-tar czvf apache-teaclave-1.0.0-rc.1-incubating.tar.gz apache-teaclave-1.0.0-rc.1-incubating
-```
-
-Use your GPG key to sign the created artifact. First make sure your GPG is set
-to use the correct private key,
-
-```
-$ gpg --list-key
-/home/user/.gnupg/pubring.kbx
-------------------------------------
-pub rsa4096 2020-08-17 [SC]
- 154xxx
-uid [ unknown] XXX (CODE SIGNING KEY) <xxx@apache.org>
-sub rsa4096 2020-08-17 [E]
-```
-
-```
-gpg -u 154xxx --armor --detach-sign apache-teaclave-1.0.0-rc.1-incubating.tar.gz
-sha512sum apache-teaclave-1.0.0-rc.1-incubating.tar.gz > apache-teaclave-1.0.0-rc.1-incubating.tar.gz.sha512
-```
-
-At this point, we got three files in the release artifacts:
- - `apache-teaclave-1.0.0-rc.1-incubating.tar.gz`: source code tarball
- - `apache-teaclave-1.0.0-rc.1-incubating.tar.gz.asc`: signature
- - `apache-teaclave-1.0.0-rc.1-incubating.tar.gz.sha512`: SHA512 hash
-
-## Check the Artifacts
-
-We suggest to double check the release artifacts, e.g., verify the signature,
-hash value and build from scratch.
-There is a [checklist](https://cwiki.apache.org/confluence/display/INCUBATOR/Incubator+Release+Checklist) which can help the process.
-
-## Upload the Release Candidate Artifacts
-
-The release artifacts needs to be uploaded to ASF SVN,
-
-```
-# the --depth=files will avoid checkout existing folders
-svn co --depth=files "https://dist.apache.org/repos/dist/dev/incubator/teaclave" svn-dev-teaclave
-cd svn-dev-teaclave
-mkdir 1.0.0-rc.1
-# copy files (.tar.gz, .asc, .sha512) into it
-svn add 1.0.0-rc.1
-svn ci --username $ASF_USERNAME --password "$ASF_PASSWORD" -m "Add 1.0.0-rc.1"
-```
-
-## Publish the Pre-Release on GitHub
-
-The next step is to publish a pre-release. Go to the GitHub repo's "Releases"
-tab and click "Draft a new release".
-
-- Choose a tag and select v1.0.0-rc.1.
-- Copy and paste the release note draft into the description box.
-- Select "This is a pre-release".
-- Upload the artifacts created by the previous steps.
-- Click "Publish release".
-
-## Call a Vote on the Release Candidate
-
-There are two votes need to be done for releasing a incubating project.
-The first vote takes place on the Apache Teaclave developers list
-(`dev@teaclave.apache.org`). Once it is closed with pass, we can call for the
-second in the Apache Incubator general list
-(`general@incubator.apache.org`). Look at past voting threads to see how this
-proceeds. The email should contains these information.
-
-- Provide the link to the draft of the release notes in the email
-- Provide the link to the release candidate artifacts
-- Make sure the email is in text format and the links are correct
-
-For the dev@ vote, there must be at least 3 binding +1 votes and more +1 votes
-than -1 votes. Once the vote is done, you should also send out a summary email
-with the totals, with a subject that looks something like `[VOTE][RESULT]`.
-
-In ASF, votes are open at least 72hrs (3 days). If you don't get enough number
-of binding votes within that time, you cannot close the voting deadline. You
-need to extend it.
-
-If the voting fails, the community needs to modified the release accordingly,
-create a new release candidate and re-run the voting process.
-
-Here are some examples:
-
-**Vote in the dev@teaclave list**:
-
-- subject: [VOTE] Release Apache Teaclave (incubating) v0.3.0-rc.1
-- to: dev@teaclave.apache.org
-- link: <https://lists.apache.org/thread/9dzwv0y9l9qf9hol2rpwv85ns1xfgn7k>
-
-**Result in the dev@teaclave list**:
-
-- subject: [RESULT][VOTE] Release Apache Teaclave (incubating) v0.3.0-rc.1
-- to: dev@teaclave.apache.org
-- link: <https://lists.apache.org/thread/tyqhx2m9q0z1qg7dbxczf58nnpvxfzrn>
-
-**Vote in the general@incubator list**:
-
-- subject: [VOTE] Release Apache Teaclave (incubating) v0.3.0-rc.1
-- to: general@incubator.apache.org
-- link: <https://lists.apache.org/thread/mrwl41shgx60p432mw2lc6zcdw1lk6lk>
-
-**Result in the general@incubator list**:
-
-- subject: [RESULT][VOTE] Release Apache Teaclave (incubating) v0.3.0-rc.1
-- to: dev@teaclave.apache.org
-- link: <https://lists.apache.org/thread/gbv3f7l9bf6t1876byqm1v4stsw7g00z>
-
-## Post the Release
-
-After the vote passes, we need to crate the final release artifacts:
-
-```
-cd svn-dev-teaclave
-mkdir 1.0.0
-# copy RC files (.tar.gz, .asc, .sha512) into it and rename them
-cp 1.0.0-rc.1/apache-teaclave-1.0.0-rc.1-incubating.tar.gz 1.0.0/apache-teaclave-1.0.0-incubating.tar.gz
-cp 1.0.0-rc.1/apache-teaclave-1.0.0-rc.1-incubating.tar.gz.asc 1.0.0/apache-teaclave-1.0.0-incubating.tar.gz.asc
-cp 1.0.0-rc.1/apache-teaclave-1.0.0-rc.1-incubating.tar.gz.sha512 1.0.0/apache-teaclave-1.0.0-incubating.tar.gz.sha512
-# edit the file name (i.e., remove the rc version) in the sha512 file
-vi 1.0.0/apache-teaclave-1.0.0-incubating.tar.gz.sha512
-svn add 1.0.0
-svn ci --username $ASF_USERNAME --password "$ASF_PASSWORD" -m "Add 1.0.0"
-```
-
-To upload the binaries to Apache mirrors, you copy the binaries from the dev
-directory (this should be where they are voted) to the dist directory.
-These artifacts will be automatically propagated to the CDN service.
-
-```
-export SVN_EDITOR=vim
-svn cp https://dist.apache.org/repos/dist/dev/incubator/teaclave/1.0.0 https://dist.apache.org/repos/dist/release/incubator/teaclave/1.0.0
-
-# If you've added your signing key to the KEYS file, also update the release copy.
-svn co --depth=files "https://dist.apache.org/repos/dist/release/incubator/teaclave" svn-dist-teaclave
-curl "https://dist.apache.org/repos/dist/dev/incubator/teaclave/KEYS" > svn-dist-teaclave/KEYS
-(cd svn-dist-teaclave && svn ci --username $ASF_USERNAME --password "$ASF_PASSWORD" -m "Update KEYS")
-```
-
-Merge commits in the release branch to the main branch, create a new release tag
-(v1.0.0 in this case) on Github and remove the pre-release candidate tag.
-
-```
-git checkout master
-## merge the release branch and use --ff-only to ensure the commit hash for voting is also in the master branch
-git merge release-v1.0.0 --ff-only
-git tag v1.0.0
-git push origin v1.0.0
-git push --delete origin v1.0.0-rc.1
-git push --delete origin release-v1.0.0
-```
-
-At last update the release notes and corresponding artifacts on GitHub.
-
-## Update the Website
-
-The website repository is located at <https://github.com/apache/incubator-teaclave-website>.
-Modify the download page to include the release artifacts as well as the GPG
-signature and SHA hash. Note that only put the latest version in the download page.
-Older releases are archived in the archive site automatically
-(<https://archive.apache.org/dist/incubator/teaclave/>).
-
-Note that the links to the release artifact should start with
-`https://www.apache.org/dyn/closer.lua/incubator/teaclave` to better utilize the
-Apache CND. You can refer to the previous release link.
-
-
-## Post the Announcement
-
-Post new version release annoucement to the mailing list, blog and other
-channels (Twitter, Discord, etc.).
-
-**Mailing list example**:
-- subject: [ANNOUNCE] Apache Teaclave (incubating) 0.3.0 released
-- to: announce@apache.org, dev@teaclave.apache.org
-- link: <https://lists.apache.org/thread/frck6z5v135f8c7w64nkgqk86w1soqc7>
-
-**Blog example**:
-- title: Announcing Apache Teaclave (incubating) 0.3.0
-- link: <https://teaclave.apache.org/blog/2021-10-01-announcing-teaclave-0-3-0/>
diff --git a/examples/c/builtin_echo.c b/examples/c/builtin_echo.c
index 3276be3..9a83835 100644
--- a/examples/c/builtin_echo.c
+++ b/examples/c/builtin_echo.c
@@ -34,7 +34,7 @@ const char *register_function_request_serialized = QUOTE({
"executor_type" : "builtin",
"public" : true,
"payload" : [],
- "arguments" : ["message"],
+ "arguments" : [{"key": "message", "default_value": "", "allow_overwrite": true}],
"inputs" : [],
"outputs" : [],
"user_allowlist": []
diff --git a/examples/c/builtin_ordered_set_intersect.c b/examples/c/builtin_ordered_set_intersect.c
index 1ce5e57..21d9c43 100644
--- a/examples/c/builtin_ordered_set_intersect.c
+++ b/examples/c/builtin_ordered_set_intersect.c
@@ -60,7 +60,7 @@ const char *register_function_request_serialized = QUOTE(
"executor_type": "builtin",
"public": true,
"payload": [],
- "arguments": ["order"],
+ "arguments": [{"key": "order", "default_value": "", "allow_overwrite": true}],
"inputs": [
{"name": "input_data1", "description": "Client 0 data.", "optional": false},
{"name": "input_data2", "description": "Client 1 data.", "optional": false}
diff --git a/examples/python/builtin_cleanroom_algorithm2.py b/examples/python/builtin_cleanroom_algorithm2.py
new file mode 100644
index 0000000..76c8830
--- /dev/null
+++ b/examples/python/builtin_cleanroom_algorithm2.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python3
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import sys
+import time
+import json
+
+from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap, FunctionArgument
+from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
+
+# User 0: an algorithm provider.
+# User 1: a RNA provider.
+
+
+class UserData:
+
+ def __init__(self,
+ user_id,
+ password,
+ input_url="",
+ output_url="",
+ input_cmac=[],
+ key=[]):
+ self.user_id = user_id
+ self.password = password
+ self.input_url = input_url
+ self.output_url = output_url
+ self.input_cmac = input_cmac
+ self.key = key
+
+
+# If you're using `docker-compose` to start the Teaclave server containers,
+# please change `localhost` to `teaclave-file-service`
+INPUT_FILE_URL_PREFIX = "http://localhost:6789/fixtures/functions/cleanroom-algorithm2-hash/"
+OUTPUT_FILE_URL_PREFIX = "http://localhost:6789/fixtures/functions/cleanroom-algorithm2-hash/"
+
+# User0 updates the algorithm. User1 sends the RNA information and gets the results.
+USER_DATA_0 = UserData("Algorithm Owner", "password", None, None, None, None)
+
+USER_DATA_1 = UserData("Gene Owner", "password",
+ INPUT_FILE_URL_PREFIX + "stdout.enc",
+ OUTPUT_FILE_URL_PREFIX + "result.enc", [
+ 0xff, 0xed, 0x3a, 0xe7, 0xef, 0xc9, 0x1f, 0x2c,
+ 0xd1, 0x24, 0xbf, 0x0b, 0xed, 0xff, 0xb5, 0x1b
+ ], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
+
+
+class DataList:
+
+ def __init__(self, data_name, data_id):
+ self.data_name = data_name
+ self.data_id = data_id
+
+
+class Client:
+
+ def __init__(self, user_id, user_password):
+ self.user_id = user_id
+ self.user_password = user_password
+ with connect_authentication_service() as client:
+ print(f"[+] {self.user_id} login")
+ token = client.user_login(self.user_id, self.user_password)
+ self.client = connect_frontend_service()
+ metadata = {"id": self.user_id, "token": token}
+ self.client.metadata = metadata
+
+ def register_function(self):
+ client = self.client
+
+ print(f"[+] {self.user_id} registering the algorithm2 function")
+ function_id = client.register_function(
+ name="builtin-cleanroom-algorithm2-hash",
+ description="algorithm2",
+ executor_type="builtin",
+ arguments=[FunctionArgument("args"),
+ FunctionArgument("debug")],
+ inputs=[FunctionInput("input_file", "protain data.")],
+ outputs=[FunctionOutput("output_file", "Output data.")])
+ return function_id
+
+ def create_task(self, function_id):
+ print(f"[+] {self.user_id} creating the task")
+ client = self.client
+ args = ["algorithm2", "100", "200"]
+ task_id = client.create_task(
+ function_id=function_id,
+ function_arguments=({
+ "args": json.dumps(args),
+ "debug": "false",
+ }),
+ executor="builtin",
+ inputs_ownership=[OwnerList("input_file", [USER_DATA_1.user_id])],
+ outputs_ownership=[
+ OwnerList("output_file", [USER_DATA_1.user_id])
+ ])
+ return task_id
+
+ def run_task(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} invoking the task")
+ client.invoke_task(task_id)
+
+ def register_data(self, task_id, input_url, input_cmac, output_url,
+ file_key, input_label, output_label):
+ client = self.client
+ print(f"[+] {self.user_id} registering the input file")
+ cmac = input_cmac
+ schema = "teaclave-file-128"
+ key = file_key
+ iv = []
+ print(input_url)
+ input_id = client.register_input_file(input_url, schema, key, iv, cmac)
+ print(output_url)
+ output_id = client.register_output_file(output_url, schema, key, iv)
+ print(f"[+] {self.user_id} assigning data to task")
+ client.assign_data_to_task(task_id, [DataList(input_label, input_id)],
+ [DataList(output_label, output_id)])
+
+ def approve_task(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} approving task")
+ client.approve_task(task_id)
+
+ def get_task_result(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} getting task result")
+ return bytes(client.get_task_result(task_id))
+
+
+def main():
+ print(
+ "User 0 (Algorithm owner) registers the function and uploads the algorithm."
+ )
+ print(
+ "User 1 (Gene Owner) creates the task, uploads the secret data, and retrieves the result."
+ )
+ # Register user
+ platform_admin = PlatformAdmin("admin", "teaclave")
+ try:
+ platform_admin.register_user(USER_DATA_0.user_id, USER_DATA_0.password)
+ platform_admin.register_user(USER_DATA_1.user_id, USER_DATA_1.password)
+ except Exception:
+ pass
+ user0 = Client(USER_DATA_0.user_id, USER_DATA_0.password)
+ function_id = user0.register_function()
+
+ start = time.time()
+
+ user1 = Client(USER_DATA_1.user_id, USER_DATA_1.password)
+
+ task_id = user1.create_task(function_id)
+ user1.register_data(task_id, USER_DATA_1.input_url, USER_DATA_1.input_cmac,
+ USER_DATA_1.output_url, USER_DATA_1.key, "input_file",
+ "output_file")
+
+ # user1.approve_task(task_id)
+ user1.approve_task(task_id)
+
+ ## USER 1 start the computation
+ user1.run_task(task_id)
+
+ ## USER 1 get the result
+ result_user1 = user1.get_task_result(task_id)
+
+ end = time.time()
+
+ print("[+] Gene Owner result: " + result_user1.decode("utf-8"))
+ print("[+] Time: " + str(end - start))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/examples/python/builtin_echo.py b/examples/python/builtin_echo.py
index 8c6f154..fdfed5e 100644
--- a/examples/python/builtin_echo.py
+++ b/examples/python/builtin_echo.py
@@ -20,6 +20,7 @@
import sys
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service
+from teaclave import FunctionArgument
class BuiltinEchoExample:
@@ -42,7 +43,7 @@ class BuiltinEchoExample:
name="builtin-echo",
description="Native Echo Function",
executor_type="builtin",
- arguments=["message"])
+ arguments=[FunctionArgument("message")])
print("[+] creating task")
task_id = client.create_task(
diff --git a/examples/python/builtin_face_detection.py b/examples/python/builtin_face_detection.py
index 416e99c..a074373 100644
--- a/examples/python/builtin_face_detection.py
+++ b/examples/python/builtin_face_detection.py
@@ -25,6 +25,7 @@ from PIL import Image, ImageDraw
import requests
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service
+from teaclave import FunctionArgument
class BuiltinFaceDetectionExample:
@@ -49,9 +50,12 @@ class BuiltinFaceDetectionExample:
executor_type="builtin",
inputs=[],
arguments=[
- "image", "min_face_size", "score_thresh",
- "pyramid_scale_factor", "slide_window_step_x",
- "slide_window_step_y"
+ FunctionArgument("image"),
+ FunctionArgument("min_face_size"),
+ FunctionArgument("score_thresh"),
+ FunctionArgument("pyramid_scale_factor"),
+ FunctionArgument("slide_window_step_x"),
+ FunctionArgument("slide_window_step_y")
])
print("[+] creating task")
diff --git a/examples/python/builtin_gbdt_train.py b/examples/python/builtin_gbdt_train.py
index 43f0898..b5392ab 100644
--- a/examples/python/builtin_gbdt_train.py
+++ b/examples/python/builtin_gbdt_train.py
@@ -19,7 +19,7 @@
import sys
-from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap
+from teaclave import FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service
@@ -44,9 +44,15 @@ class BuiltinGbdtExample:
description="Native Gbdt Training Function",
executor_type="builtin",
arguments=[
- "feature_size", "max_depth", "iterations", "shrinkage",
- "feature_sample_ratio", "data_sample_ratio", "min_leaf_size",
- "loss", "training_optimization_level"
+ FunctionArgument("feature_size"),
+ FunctionArgument("max_depth"),
+ FunctionArgument("iterations"),
+ FunctionArgument("shrinkage"),
+ FunctionArgument("feature_sample_ratio"),
+ FunctionArgument("data_sample_ratio"),
+ FunctionArgument("min_leaf_size"),
+ FunctionArgument("loss"),
+ FunctionArgument("training_optimization_level")
],
inputs=[
FunctionInput("training_data", "Input traning data file.")
diff --git a/examples/python/builtin_online_decrypt.py b/examples/python/builtin_online_decrypt.py
index aee9c80..9a30b3b 100644
--- a/examples/python/builtin_online_decrypt.py
+++ b/examples/python/builtin_online_decrypt.py
@@ -21,6 +21,7 @@ import sys
import base64
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service
+from teaclave import FunctionArgument
class BuiltinOnlineDecryptExample:
@@ -43,7 +44,12 @@ class BuiltinOnlineDecryptExample:
name="builtin_online_decrypt",
description="Native Online Decrypt",
executor_type="builtin",
- arguments=["key", "nonce", "encrypted_data", "algorithm"])
+ arguments=[
+ FunctionArgument("key"),
+ FunctionArgument("nonce"),
+ FunctionArgument("encrypted_data"),
+ FunctionArgument("algorithm")
+ ])
print("[+] creating task")
task_id = client.create_task(
diff --git a/examples/python/builtin_ordered_set_intersect.py b/examples/python/builtin_ordered_set_intersect.py
index a9eaa65..6cb8981 100644
--- a/examples/python/builtin_ordered_set_intersect.py
+++ b/examples/python/builtin_ordered_set_intersect.py
@@ -19,7 +19,7 @@
import sys
-from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap
+from teaclave import FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
# In the example, user 0 creates the task and user 0, 1, upload their private data.
@@ -91,7 +91,7 @@ class Client:
name="builtin-ordered-set-intersect",
description="Native Private Set Intersection",
executor_type="builtin",
- arguments=["order"],
+ arguments=[FunctionArgument("order")],
inputs=[
FunctionInput("input_data1", "Client 0 data."),
FunctionInput("input_data2", "Client 1 data.")
diff --git a/examples/python/builtin_private_join_and_compute.py b/examples/python/builtin_private_join_and_compute.py
index 461463e..aab8ca7 100644
--- a/examples/python/builtin_private_join_and_compute.py
+++ b/examples/python/builtin_private_join_and_compute.py
@@ -19,7 +19,7 @@
import sys
-from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap
+from teaclave import FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
# In the example, user 3 creates the task and user 0, 1, 2 upload their private data.
@@ -98,7 +98,7 @@ class ConfigClient:
name="builtin-private-join-and-compute",
description="Native Private Join And Compute",
executor_type="builtin",
- arguments=["num_user"],
+ arguments=[FunctionArgument("num_user")],
inputs=[
FunctionInput("input_data0", "Bank A data file."),
FunctionInput("input_data1", "Bank B data file."),
diff --git a/examples/python/builtin_rsa_sign.py b/examples/python/builtin_rsa_sign.py
index 0724756..b21e91c 100644
--- a/examples/python/builtin_rsa_sign.py
+++ b/examples/python/builtin_rsa_sign.py
@@ -19,7 +19,7 @@
import sys
-from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap
+from teaclave import FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
@@ -61,7 +61,7 @@ def register_func(client):
name="builtin-rsa-sign",
description="Native Rsa Signing Function",
executor_type="builtin",
- arguments=["data"],
+ arguments=[FunctionArgument("data")],
inputs=[FunctionInput("rsa_key", "Input key file.")])
return function_id
diff --git a/examples/python/cleanroom_algorithm1.py b/examples/python/cleanroom_algorithm1.py
new file mode 100644
index 0000000..e417039
--- /dev/null
+++ b/examples/python/cleanroom_algorithm1.py
@@ -0,0 +1,196 @@
+#!/usr/bin/env python3
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import sys
+import time
+import json
+
+from teaclave import FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap
+from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
+
+# User 0: an algorithm provider.
+# User 1: a RNA provider.
+
+
+class UserData:
+
+ def __init__(self,
+ user_id,
+ password,
+ input_url="",
+ output_url="",
+ input_cmac=[],
+ key=[]):
+ self.user_id = user_id
+ self.password = password
+ self.input_url = input_url
+ self.output_url = output_url
+ self.input_cmac = input_cmac
+ self.key = key
+
+
+# If you're using `docker-compose` to start the Teaclave server containers,
+# please change `localhost` to `teaclave-file-service`
+INPUT_FILE_URL_PREFIX = "http://localhost:6789/fixtures/functions/cleanroom-algorithm1/"
+OUTPUT_FILE_URL_PREFIX = "http://localhost:6789/fixtures/functions/cleanroom-algorithm1/"
+
+# User0 updates the algorithm. User1 sends the RNA information and gets the results.
+USER_DATA_0 = UserData("Algorithm Owner", "password", None, None, None, None)
+
+USER_DATA_1 = UserData("Gene Owner", "password",
+ INPUT_FILE_URL_PREFIX + "testseq.enc",
+ OUTPUT_FILE_URL_PREFIX + "stdout.enc", [
+ 0x99, 0x88, 0x31, 0x62, 0x30, 0xe6, 0x40, 0x67,
+ 0xde, 0xe1, 0x20, 0xf2, 0xaf, 0x7b, 0xe6, 0xcf
+ ], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
+
+PAYLOAD_FILE = "../../tests/fixtures/functions/cleanroom-algorithm1/cleanroom-app.cpk"
+
+
+class DataList:
+
+ def __init__(self, data_name, data_id):
+ self.data_name = data_name
+ self.data_id = data_id
+
+
+class Client:
+
+ def __init__(self, user_id, user_password):
+ self.user_id = user_id
+ self.user_password = user_password
+ with connect_authentication_service() as client:
+ print(f"[+] {self.user_id} login")
+ token = client.user_login(self.user_id, self.user_password)
+ self.client = connect_frontend_service()
+ metadata = {"id": self.user_id, "token": token}
+ self.client.metadata = metadata
+
+ def register_function(self):
+ client = self.client
+
+ print(f"[+] {self.user_id} registering the algorithm1 function")
+ with open(PAYLOAD_FILE, "rb") as f:
+ payload = f.read()
+ function_id = client.register_function(
+ name="cleanroom",
+ description="algorithm1",
+ payload=list(payload),
+ executor_type="cleanroom",
+ arguments=[FunctionArgument("args"),
+ FunctionArgument("debug")],
+ inputs=[FunctionInput("input_file", "RNA data.")],
+ outputs=[FunctionOutput("output_file", "Output data.")])
+ return function_id
+
+ def create_task(self, function_id):
+ print(f"[+] {self.user_id} creating the task")
+ client = self.client
+ args = [
+ "algorithm1_v", "100", "0", "0", "0", "0", "0", "5.0",
+ "example.shape"
+ ]
+ task_id = client.create_task(
+ function_id=function_id,
+ function_arguments=({
+ "args": json.dumps(args),
+ "debug": "true",
+ }),
+ executor="cleanroom",
+ inputs_ownership=[OwnerList("input_file", [USER_DATA_1.user_id])],
+ outputs_ownership=[
+ OwnerList("output_file", [USER_DATA_1.user_id])
+ ])
+ return task_id
+
+ def run_task(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} invoking the task")
+ client.invoke_task(task_id)
+
+ def register_data(self, task_id, input_url, input_cmac, output_url,
+ file_key, input_label, output_label):
+ client = self.client
+
+ print(f"[+] {self.user_id} registering the input file")
+ cmac = input_cmac
+ schema = "teaclave-file-128"
+ key = file_key
+ iv = []
+ print(input_url)
+ input_id = client.register_input_file(input_url, schema, key, iv, cmac)
+ print(output_url)
+ output_id = client.register_output_file(output_url, schema, key, iv)
+ print(f"[+] {self.user_id} assigning data to task")
+ client.assign_data_to_task(task_id, [DataList(input_label, input_id)],
+ [DataList(output_label, output_id)])
+
+ def approve_task(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} approving task")
+ client.approve_task(task_id)
+
+ def get_task_result(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} getting task result")
+ return bytes(client.get_task_result(task_id))
+
+
+def main():
+ print(
+ "User 0 (Algorithm owner) registers the function and uploads the algorithm."
+ )
+ print(
+ "User 1 (Gene Owner) creates the task, uploads the secret data, and retrieves the result."
+ )
+ # Register user
+ platform_admin = PlatformAdmin("admin", "teaclave")
+ try:
+ platform_admin.register_user(USER_DATA_0.user_id, USER_DATA_0.password)
+ platform_admin.register_user(USER_DATA_1.user_id, USER_DATA_1.password)
+ except Exception:
+ pass
+ user0 = Client(USER_DATA_0.user_id, USER_DATA_0.password)
+ function_id = user0.register_function()
+
+ start = time.time()
+
+ user1 = Client(USER_DATA_1.user_id, USER_DATA_1.password)
+ task_id = user1.create_task(function_id)
+ user1.register_data(task_id, USER_DATA_1.input_url, USER_DATA_1.input_cmac,
+ USER_DATA_1.output_url, USER_DATA_1.key, "input_file",
+ "output_file")
+
+ # user1.approve_task(task_id)
+ user1.approve_task(task_id)
+
+ ## USER 1 start the computation
+ user1.run_task(task_id)
+
+ ## USER 1 get the result
+ result_user1 = user1.get_task_result(task_id)
+
+ end = time.time()
+
+ print("[+] User 1 result: " + result_user1.decode("utf-8"))
+ print("[+] Time: " + str(end - start))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/examples/python/cleanroom_algorithm1_repeat.py b/examples/python/cleanroom_algorithm1_repeat.py
new file mode 100644
index 0000000..2ccaa99
--- /dev/null
+++ b/examples/python/cleanroom_algorithm1_repeat.py
@@ -0,0 +1,222 @@
+#!/usr/bin/env python3
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import sys
+import time
+import traceback
+
+from teaclave import (AuthenticationService, FrontendService,
+ AuthenticationClient, FrontendClient, FunctionInput,
+ FunctionOutput, FunctionArgument, OwnerList, DataMap)
+from utils import (AUTHENTICATION_SERVICE_ADDRESS, FRONTEND_SERVICE_ADDRESS,
+ AS_ROOT_CA_CERT_PATH, ENCLAVE_INFO_PATH, USER_ID,
+ USER_PASSWORD, PlatformAdmin)
+
+# User 0: an algorithm provider.
+# User 1: a RNA provider.
+
+
+class UserData:
+
+ def __init__(self,
+ user_id,
+ password,
+ input_url="",
+ output_url="",
+ input_cmac=[],
+ key=[]):
+ self.user_id = user_id
+ self.password = password
+ self.input_url = input_url
+ self.output_url = output_url
+ self.input_cmac = input_cmac
+ self.key = key
+
+
+# If you're using `docker-compose` to start the Teaclave server containers,
+# please change `localhost` to `teaclave-file-service`
+INPUT_FILE_URL_PREFIX = "http://localhost:6789/fixtures/functions/cleanroom-algorithm1/"
+OUTPUT_FILE_URL_PREFIX = "http://localhost:6789/fixtures/functions/cleanroom-algorithm1/"
+
+# User0 updates the algorithm. User1 sends the RNA information and gets the results.
+USER_DATA_0 = UserData("Algorithm Owner", "password", None, None, None, None)
+
+USER_DATA_1 = UserData("Gene Owner", "password",
+ INPUT_FILE_URL_PREFIX + "testseq.enc",
+ OUTPUT_FILE_URL_PREFIX + "stdout.enc", [
+ 0x99, 0x88, 0x31, 0x62, 0x30, 0xe6, 0x40, 0x67,
+ 0xde, 0xe1, 0x20, 0xf2, 0xaf, 0x7b, 0xe6, 0xcf
+ ], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
+
+PAYLOAD_FILE = "../../tests/fixtures/functions/cleanroom-algorithm1/cleanroom-app.cpk"
+
+
+class DataList:
+
+ def __init__(self, data_name, data_id):
+ self.data_name = data_name
+ self.data_id = data_id
+
+
+class Client:
+
+ def __init__(self, user_id, user_password):
+ self.user_id = user_id
+ self.user_password = user_password
+ self.client = AuthenticationService(
+ AUTHENTICATION_SERVICE_ADDRESS, AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH).connect().get_client()
+ print(f"[+] {self.user_id} login")
+ token = self.client.user_login(self.user_id, self.user_password)
+ self.client = FrontendService(
+ FRONTEND_SERVICE_ADDRESS, AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH).connect().get_client()
+ metadata = {"id": self.user_id, "token": token}
+ self.client.metadata = metadata
+
+ def register_function(self):
+ client = self.client
+
+ print(f"[+] {self.user_id} registering the algorithm1 function")
+ with open(PAYLOAD_FILE, "rb") as f:
+ payload = f.read()
+ function_id = client.register_function(
+ name="diagnosis",
+ description="algorithm1",
+ payload=list(payload),
+ executor_type="cleanroom",
+ arguments=[FunctionArgument("args"),
+ FunctionArgument("debug")],
+ inputs=[FunctionInput("input_file", "RNA data.")],
+ outputs=[
+ FunctionOutput("output_file", "Output data."),
+ FunctionOutput("log_file", "Log.")
+ ])
+ return function_id
+
+ def create_task(self, function_id):
+ print(f"[+] {self.user_id} creating the task")
+ client = self.client
+ task_id = client.create_task(
+ function_id=function_id,
+ function_arguments=({
+ "args": "algorithm1_v 100 0 0 0 0 0 5.0 example.shape",
+ "debug": "true",
+ }),
+ executor="cleanroom",
+ inputs_ownership=[OwnerList("input_file", [USER_DATA_1.user_id])],
+ outputs_ownership=[
+ OwnerList("output_file", [USER_DATA_1.user_id]),
+ OwnerList("log_file", [USER_DATA_1.user_id])
+ ])
+ return task_id
+
+ def run_task(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} invoking the task")
+ client.invoke_task(task_id)
+
+ def register_data(self, task_id, input_url, input_cmac, output_url,
+ file_key, input_label, output_label):
+ client = self.client
+
+ print(f"[+] {self.user_id} registering the input file")
+ url = input_url
+ cmac = input_cmac
+ schema = "teaclave-file-128"
+ key = file_key
+ iv = []
+ input_id = client.register_input_file(url, schema, key, iv, cmac)
+ print(f"[+] {self.user_id} registering the output file")
+ url = output_url
+ schema = "teaclave-file-128"
+ key = file_key
+ iv = []
+ output_id = client.register_output_file(url, schema, key, iv)
+ log_id = client.register_output_file(
+ OUTPUT_FILE_URL_PREFIX + "stderr.enc", schema, key, iv)
+ print(f"[+] {self.user_id} assigning data to task")
+ client.assign_data_to_task(
+ task_id, [DataList(input_label, input_id)],
+ [DataList(output_label, output_id),
+ DataList("log_file", log_id)])
+
+ def approve_task(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} approving task")
+ client.approve_task(task_id)
+
+ def get_task_result(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} getting task result")
+ return bytes(client.get_task_result(task_id))
+
+
+def client_run_once(function_id):
+ user1 = Client(USER_DATA_1.user_id, USER_DATA_1.password)
+ task_id = user1.create_task(function_id)
+ user1.register_data(task_id, USER_DATA_1.input_url, USER_DATA_1.input_cmac,
+ USER_DATA_1.output_url, USER_DATA_1.key, "input_file",
+ "output_file")
+
+ # user1.approve_task(task_id)
+ user1.approve_task(task_id)
+
+ # USER 1 start the computation
+ user1.run_task(task_id)
+
+ # USER 1 get the result
+ result_user1 = user1.get_task_result(task_id)
+
+
+def main():
+ # Register user
+ platform_admin = PlatformAdmin("admin", "teaclave")
+ platform_admin.register_user(USER_DATA_0.user_id, USER_DATA_0.password)
+ platform_admin.register_user(USER_DATA_1.user_id, USER_DATA_1.password)
+ while True:
+ try:
+ user0 = Client(USER_DATA_0.user_id, USER_DATA_0.password)
+ function_id = user0.register_function()
+ break
+ except Exception as e:
+ print(f"Python Client: Admin register function got execption: {e}",
+ flush=True)
+ traceback.print_tb(e.__traceback__)
+
+ i = 1
+ while True:
+ try:
+ print(f"Python Client {i}th invocation started...", flush=True)
+ start = time.time()
+ client_run_once(function_id)
+ end = time.time()
+ elapsed = end - start
+ print(
+ f"Python Client {i}th invocation finishied: elapsed {elapsed} seconds...",
+ flush=True)
+ i = i + 1
+ except Exception as e:
+ print(f"Python Client {i}th invocation got execption: {e}",
+ flush=True)
+ traceback.print_tb(e.__traceback__)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/examples/python/cleanroom_stderr.py b/examples/python/cleanroom_stderr.py
new file mode 100644
index 0000000..6c55689
--- /dev/null
+++ b/examples/python/cleanroom_stderr.py
@@ -0,0 +1,200 @@
+#!/usr/bin/env python3
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import sys
+import json
+
+from teaclave import FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap
+from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
+
+# User 0: an algorithm provider.
+# User 1: a RNA provider.
+
+
+class UserData:
+
+ def __init__(self,
+ user_id,
+ password,
+ input_url="",
+ output_url="",
+ input_cmac=[],
+ key=[]):
+ self.user_id = user_id
+ self.password = password
+ self.input_url = input_url
+ self.output_url = output_url
+ self.input_cmac = input_cmac
+ self.key = key
+
+
+# If you're using `docker-compose` to start the Teaclave server containers,
+# please change `localhost` to `teaclave-file-service`
+INPUT_FILE_URL_PREFIX = "http://localhost:6789/fixtures/functions/cleanroom-stderr/"
+OUTPUT_FILE_URL_PREFIX = "http://localhost:6789/fixtures/functions/cleanroom-stderr/"
+
+# User0 updates the algorithm. User1 sends the RNA information and gets the results.
+USER_DATA_0 = UserData("Algorithm Owner 2", "password", None, None, None, None)
+
+USER_DATA_1 = UserData("Data Owner 2", "password",
+ INPUT_FILE_URL_PREFIX + "testseq.enc",
+ OUTPUT_FILE_URL_PREFIX + "stdout.enc", [
+ 0x99, 0x88, 0x31, 0x62, 0x30, 0xe6, 0x40, 0x67,
+ 0xde, 0xe1, 0x20, 0xf2, 0xaf, 0x7b, 0xe6, 0xcf
+ ], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
+
+PAYLOAD_FILE = "../../tests/fixtures/functions/cleanroom-stderr/app.cpk"
+
+
+class DataList:
+
+ def __init__(self, data_name, data_id):
+ self.data_name = data_name
+ self.data_id = data_id
+
+
+class Client:
+
+ def __init__(self, user_id, user_password):
+ self.user_id = user_id
+ self.user_password = user_password
+ with connect_authentication_service() as client:
+ print(f"[+] {self.user_id} login")
+ token = client.user_login(self.user_id, self.user_password)
+ self.client = connect_frontend_service()
+ metadata = {"id": self.user_id, "token": token}
+ self.client.metadata = metadata
+
+ def register_function_debug(self):
+ client = self.client
+
+ print(f"[+] {self.user_id} registering the algorithm1 function")
+ with open(PAYLOAD_FILE, "rb") as f:
+ payload = f.read()
+ function_id = client.register_function(
+ name="diagnosis",
+ #name="cleanroom",
+ description="algorithm1",
+ payload=list(payload),
+ executor_type="cleanroom",
+ arguments=[FunctionArgument("args"),
+ FunctionArgument("debug")],
+ inputs=[FunctionInput("input_file", "RNA data.")],
+ outputs=[
+ FunctionOutput("output_file", "Output data."),
+ FunctionOutput("log_file", "Log.")
+ ])
+ return function_id
+
+ def create_task_debug(self, function_id):
+ print(f"[+] {self.user_id} creating the task")
+ client = self.client
+ args = ["algorithm1_v", "100", "0", "0"]
+ task_id = client.create_task(
+ function_id=function_id,
+ function_arguments=({
+ "args": json.dumps(args),
+ "debug": "true",
+ }),
+ executor="cleanroom",
+ inputs_ownership=[OwnerList("input_file", [USER_DATA_1.user_id])],
+ outputs_ownership=[
+ OwnerList("output_file", [USER_DATA_1.user_id]),
+ OwnerList("log_file", [USER_DATA_1.user_id])
+ ])
+ return task_id
+
+ def run_task(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} invoking the task")
+ client.invoke_task(task_id)
+
+ def register_data_debug(self, task_id, input_url, input_cmac, output_url,
+ file_key, input_label, output_label):
+ client = self.client
+ print(f"[+] {self.user_id} registering the input file")
+ url = input_url
+ cmac = input_cmac
+ schema = "teaclave-file-128"
+ key = file_key
+ iv = []
+ input_id = client.register_input_file(url, schema, key, iv, cmac)
+ print(f"[+] {self.user_id} registering the output file")
+ url = output_url
+ schema = "teaclave-file-128"
+ key = file_key
+ iv = []
+ output_id = client.register_output_file(url, schema, key, iv)
+ log_id = client.register_output_file(
+ OUTPUT_FILE_URL_PREFIX + "stderr.enc", schema, key, iv)
+ print(f"[+] {self.user_id} assigning data to task")
+ client.assign_data_to_task(
+ task_id, [DataList(input_label, input_id)],
+ [DataList(output_label, output_id),
+ DataList("log_file", log_id)])
+
+ def approve_task(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} approving task")
+ client.approve_task(task_id)
+
+ def get_task_result(self, task_id):
+ client = self.client
+ print(f"[+] {self.user_id} getting task result")
+ return bytes(client.get_task_result(task_id))
+
+
+def main():
+ print(
+ "User 0 (Algorithm owner) registers the function and uploads the algorithm."
+ )
+ print(
+ "User 1 (DATA Owner) creates the task, uploads the secret data, and retrieves the result."
+ )
+ # Register user
+ platform_admin = PlatformAdmin("admin", "teaclave")
+ try:
+ platform_admin.register_user(USER_DATA_0.user_id, USER_DATA_0.password)
+ platform_admin.register_user(USER_DATA_1.user_id, USER_DATA_1.password)
+ except Exception:
+ pass
+ user0 = Client(USER_DATA_0.user_id, USER_DATA_0.password)
+ function_id = user0.register_function_debug()
+
+ user1 = Client(USER_DATA_1.user_id, USER_DATA_1.password)
+
+ task_id = user1.create_task_debug(function_id)
+ user1.register_data_debug(task_id, USER_DATA_1.input_url,
+ USER_DATA_1.input_cmac, USER_DATA_1.output_url,
+ USER_DATA_1.key, "input_file", "output_file")
+
+ # user1.approve_task(task_id)
+ user1.approve_task(task_id)
+
+ ## USER 1 start the computation
+ user1.run_task(task_id)
+
+ ## USER 1 get the result
+ result_user1 = user1.get_task_result(task_id)
+
+ print("[+] User 1 result: " + result_user1.decode("utf-8"))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/examples/python/mesapy_deadloop_cancel.py b/examples/python/mesapy_deadloop_cancel.py
index a4b0eaa..2bd7206 100644
--- a/examples/python/mesapy_deadloop_cancel.py
+++ b/examples/python/mesapy_deadloop_cancel.py
@@ -75,22 +75,22 @@ class MesaPyEchoExample:
result = client.get_task(task_id)
if result["status"] != TaskStatus.Canceled:
print("[+] Task is not canceled, cancel again")
- try:
- client.cancel_task(task_id)
- except Exception as e:
- # this happens when the task has already been canceled
- print(f"[-] cancel task failed, reason: {str(e)}")
+ client.cancel_task(task_id)
try:
result = client.get_task_result(task_id)
except Exception as e:
- # this is expected, since the task is cancelled
- print(f"[-] getting result failed, reason: {str(e)}")
+ print(f"[+] result: {str(e)}")
+ result = str(e)
+
+ return result
def main():
example = MesaPyEchoExample(USER_ID, USER_PASSWORD)
- example.deadloop()
+ rv = example.deadloop()
+
+ print("[+] function return: ", rv)
if __name__ == '__main__':
diff --git a/examples/python/mesapy_echo.py b/examples/python/mesapy_echo.py
index d24c2ae..b60df00 100644
--- a/examples/python/mesapy_echo.py
+++ b/examples/python/mesapy_echo.py
@@ -19,7 +19,7 @@
import sys
-from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap
+from teaclave import FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
@@ -49,7 +49,7 @@ class MesaPyEchoExample:
description="An echo function implemented in Python",
executor_type="python",
payload=list(payload),
- arguments=["message"])
+ arguments=[FunctionArgument("message")])
print("[+] creating task")
task_id = client.create_task(function_id=function_id,
diff --git a/examples/python/mesapy_logistic_reg.py b/examples/python/mesapy_logistic_reg.py
index 1838c16..6d00ce5 100644
--- a/examples/python/mesapy_logistic_reg.py
+++ b/examples/python/mesapy_logistic_reg.py
@@ -23,7 +23,7 @@ An example about Logistic Regression in MesaPy.
import sys
import binascii
from typing import List
-from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap
+from teaclave import FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
from enum import Enum
@@ -117,7 +117,7 @@ class ConfigClient:
name=functionname,
description="worker: %s" % functionname,
executor_type=ex.name,
- arguments=list(args.keys()),
+ arguments=[FunctionArgument(arg) for arg in args],
payload=list(p_str),
inputs=[
FunctionInput(label, "user input data file: %s" % label)
diff --git a/examples/python/test_default_arguments.py b/examples/python/test_default_arguments.py
new file mode 100644
index 0000000..aca7d5d
--- /dev/null
+++ b/examples/python/test_default_arguments.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import sys
+
+from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service
+from teaclave import FunctionArgument
+
+
+class BuiltinEchoExample:
+
+ def __init__(self, user_id, user_password):
+ self.user_id = user_id
+ self.user_password = user_password
+
+ def echo(self, message="Hello, Teaclave!"):
+ with connect_authentication_service() as client:
+ print("[+] login")
+ token = client.user_login(self.user_id, self.user_password)
+
+ with connect_frontend_service() as client:
+ metadata = {"id": self.user_id, "token": token}
+ client.metadata = metadata
+
+ print("[+] registering function")
+ function_id = client.register_function(
+ name="builtin-echo",
+ description="Native Echo Function",
+ executor_type="builtin",
+ arguments=[
+ FunctionArgument("message", "Hello, Cleanroom", False)
+ ])
+
+ print("[+] creating task")
+ task_id = client.create_task(function_id=function_id,
+ function_arguments={},
+ executor="builtin")
+
+ print("[+] invoking task")
+ client.invoke_task(task_id)
+
+ print("[+] getting result")
+ result = client.get_task_result(task_id)
+ print("[+] done")
+
+ return bytes(result)
+
+
+def main():
+ example = BuiltinEchoExample(USER_ID, USER_PASSWORD)
+ if len(sys.argv) > 1:
+ message = sys.argv[1]
+ rt = example.echo(message)
+ else:
+ rt = example.echo()
+
+ print("[+] function return: ", rt)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/examples/python/test_disable_function.py b/examples/python/test_disable_function.py
index 5c51e6d..dbea609 100644
--- a/examples/python/test_disable_function.py
+++ b/examples/python/test_disable_function.py
@@ -19,7 +19,7 @@
import sys
-from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap
+from teaclave import FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
@@ -50,12 +50,13 @@ class ConfigClient:
print(f"[+] {self.user_id} registering function")
- function_id = client.register_function(name=func_name,
- description=func_name,
- executor_type="builtin",
- arguments=["num_user"],
- inputs=[],
- outputs=[])
+ function_id = client.register_function(
+ name=func_name,
+ description=func_name,
+ executor_type="builtin",
+ arguments=[FunctionArgument("num_user")],
+ inputs=[],
+ outputs=[])
return function_id
diff --git a/examples/python/wasm_c_simple_add.py b/examples/python/wasm_c_simple_add.py
index c45175a..b53c5a4 100644
--- a/examples/python/wasm_c_simple_add.py
+++ b/examples/python/wasm_c_simple_add.py
@@ -19,7 +19,7 @@
import sys
-from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap
+from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap, FunctionArgument
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
@@ -45,11 +45,13 @@ class WASMAddExample:
with open(payload_file, "rb") as f:
payload = f.read()
- function_id = client.register_function(name="entrypoint",
- description="test of wasm",
- executor_type="wamr",
- payload=list(payload),
- arguments=["adder1", "adder2"])
+ function_id = client.register_function(
+ name="entrypoint",
+ description="test of wasm",
+ executor_type="wamr",
+ payload=list(payload),
+ arguments=[FunctionArgument("adder1"),
+ FunctionArgument("adder2")])
print("[+] creating task")
task_id = client.create_task(function_id=function_id,
diff --git a/examples/python/wasm_rust_psi.py b/examples/python/wasm_rust_psi.py
index 2713802..53ab0e2 100644
--- a/examples/python/wasm_rust_psi.py
+++ b/examples/python/wasm_rust_psi.py
@@ -19,7 +19,7 @@
import sys
-from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap
+from teaclave import FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
@@ -102,7 +102,10 @@ class Client:
payload=list(payload),
executor_type="wamr",
arguments=[
- "input1_fid", "input2_fid", "output1_fid", "output2_fid"
+ FunctionArgument("input1_fid"),
+ FunctionArgument("input2_fid"),
+ FunctionArgument("output1_fid"),
+ FunctionArgument("output2_fid")
],
inputs=[
FunctionInput(USER_DATA_0.input_fid, "Client 0 data."),
diff --git a/examples/python/wasm_rust_psi_payload/Cargo.lock b/examples/python/wasm_rust_psi_payload/Cargo.lock
index 2819d2d..d367651 100644
--- a/examples/python/wasm_rust_psi_payload/Cargo.lock
+++ b/examples/python/wasm_rust_psi_payload/Cargo.lock
@@ -2,7 +2,7 @@
# It is not intended for manual editing.
[[package]]
name = "teaclave_context"
-version = "0.4.0"
+version = "0.2.0"
[[package]]
name = "wasm_rust_psi_payload"
diff --git a/examples/python/wasm_tvm_mnist.py b/examples/python/wasm_tvm_mnist.py
index 90d1d09..6f33807 100644
--- a/examples/python/wasm_tvm_mnist.py
+++ b/examples/python/wasm_tvm_mnist.py
@@ -19,7 +19,7 @@
import sys
-from teaclave import FunctionInput, FunctionOutput, OwnerList, DataMap
+from teaclave import FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap
from utils import USER_ID, USER_PASSWORD, connect_authentication_service, connect_frontend_service, PlatformAdmin
# If you're using `docker-compose` to start the Teaclave server containers,
@@ -61,7 +61,7 @@ def main():
description="WAMR TVM MNIST Prediction",
payload=list(payload),
executor_type="wamr",
- arguments=["input_img"],
+ arguments=[FunctionArgument("input_img")],
inputs=[
FunctionInput("input_img",
"Input image for handwriting number perdiction")
diff --git a/examples/python/wasm_tvm_mnist_payload/Cargo.lock b/examples/python/wasm_tvm_mnist_payload/Cargo.lock
index 8af6ccb..5d2ad33 100644
--- a/examples/python/wasm_tvm_mnist_payload/Cargo.lock
+++ b/examples/python/wasm_tvm_mnist_payload/Cargo.lock
@@ -1632,7 +1632,7 @@ dependencies = [
[[package]]
name = "teaclave_context"
-version = "0.4.0"
+version = "0.2.0"
[[package]]
name = "tempfile"
diff --git a/examples/rust/builtin_echo/Cargo.lock b/examples/rust/builtin_echo/Cargo.lock
index 34be5b6..c3634a3 100644
--- a/examples/rust/builtin_echo/Cargo.lock
+++ b/examples/rust/builtin_echo/Cargo.lock
@@ -50,7 +50,7 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]]
name = "builtin_echo"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"pem",
@@ -359,7 +359,7 @@ dependencies = [
[[package]]
name = "protected_fs_rs"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"cfg-if 0.1.10",
"libc",
@@ -553,7 +553,7 @@ dependencies = [
[[package]]
name = "teaclave_attestation"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"base64 0.13.0",
@@ -581,7 +581,7 @@ dependencies = [
[[package]]
name = "teaclave_client_sdk"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"libc",
@@ -597,7 +597,7 @@ dependencies = [
[[package]]
name = "teaclave_config"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"log",
@@ -608,7 +608,7 @@ dependencies = [
[[package]]
name = "teaclave_crypto"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"hex",
@@ -621,7 +621,7 @@ dependencies = [
[[package]]
name = "teaclave_proto"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"base64 0.13.0",
@@ -640,7 +640,7 @@ dependencies = [
[[package]]
name = "teaclave_rpc"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"cfg-if 0.1.10",
@@ -659,7 +659,7 @@ dependencies = [
[[package]]
name = "teaclave_rpc_proc_macro"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"proc-macro2",
"quote",
@@ -668,7 +668,7 @@ dependencies = [
[[package]]
name = "teaclave_types"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"hex",
diff --git a/examples/rust/builtin_echo/Cargo.toml b/examples/rust/builtin_echo/Cargo.toml
index 3f46b0e..95203f0 100644
--- a/examples/rust/builtin_echo/Cargo.toml
+++ b/examples/rust/builtin_echo/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "builtin_echo"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "builtin_echo function example using Teaclave client SDK."
license = "Apache-2.0"
diff --git a/examples/rust/builtin_ordered_set_intersect/Cargo.lock b/examples/rust/builtin_ordered_set_intersect/Cargo.lock
index 972321b..4e3bf21 100644
--- a/examples/rust/builtin_ordered_set_intersect/Cargo.lock
+++ b/examples/rust/builtin_ordered_set_intersect/Cargo.lock
@@ -50,7 +50,7 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]]
name = "builtin_ordered_set_intersect"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"pem",
@@ -359,7 +359,7 @@ dependencies = [
[[package]]
name = "protected_fs_rs"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"cfg-if 0.1.10",
"libc",
@@ -553,7 +553,7 @@ dependencies = [
[[package]]
name = "teaclave_attestation"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"base64 0.13.0",
@@ -581,7 +581,7 @@ dependencies = [
[[package]]
name = "teaclave_client_sdk"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"libc",
@@ -597,7 +597,7 @@ dependencies = [
[[package]]
name = "teaclave_config"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"log",
@@ -608,7 +608,7 @@ dependencies = [
[[package]]
name = "teaclave_crypto"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"hex",
@@ -621,7 +621,7 @@ dependencies = [
[[package]]
name = "teaclave_proto"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"base64 0.13.0",
@@ -640,7 +640,7 @@ dependencies = [
[[package]]
name = "teaclave_rpc"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"cfg-if 0.1.10",
@@ -659,7 +659,7 @@ dependencies = [
[[package]]
name = "teaclave_rpc_proc_macro"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"proc-macro2",
"quote",
@@ -668,7 +668,7 @@ dependencies = [
[[package]]
name = "teaclave_types"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"hex",
diff --git a/examples/rust/builtin_ordered_set_intersect/Cargo.toml b/examples/rust/builtin_ordered_set_intersect/Cargo.toml
index f297aa7..b4ca1e7 100644
--- a/examples/rust/builtin_ordered_set_intersect/Cargo.toml
+++ b/examples/rust/builtin_ordered_set_intersect/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "builtin_ordered_set_intersect"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "builtin_ordered_set_intersect function example using Teaclave client SDK."
license = "Apache-2.0"
diff --git a/executor/Cargo.toml b/executor/Cargo.toml
index 6f3832b..e32219e 100644
--- a/executor/Cargo.toml
+++ b/executor/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_executor"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave executor"
license = "Apache-2.0"
@@ -58,6 +58,9 @@ full_builtin_function = [
"builtin_principal_components_analysis",
"builtin_private_join_and_compute",
"builtin_rsa_sign",
+ "builtin_cleanroom_algorithm2_hash",
+ "builtin_cleanroom_algorithm2_hash_trial",
+ "builtin_cleanroom_algorithm2_hash_trial_tier2",
]
builtin_echo = []
@@ -72,9 +75,13 @@ builtin_ordered_set_intersect = []
builtin_principal_components_analysis = []
builtin_private_join_and_compute = []
builtin_rsa_sign = []
+builtin_cleanroom_algorithm2_hash = []
+builtin_cleanroom_algorithm2_hash_trial = []
+builtin_cleanroom_algorithm2_hash_trial_tier2 = []
+
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
anyhow = { version = "1.0.26" }
serde_json = { version = "1.0.39" }
serde = { version = "1.0.92", features = ["derive"] }
diff --git a/executor/context/Cargo.toml b/executor/context/Cargo.toml
index 662fa40..05760d1 100644
--- a/executor/context/Cargo.toml
+++ b/executor/context/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_executor_context"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave executor"
license = "Apache-2.0"
diff --git a/executor/src/builtin.rs b/executor/src/builtin.rs
index a327432..17ce3dc 100644
--- a/executor/src/builtin.rs
+++ b/executor/src/builtin.rs
@@ -19,9 +19,10 @@
use std::prelude::v1::*;
use teaclave_function::{
- Echo, FaceDetection, GbdtPredict, GbdtTrain, LogisticRegressionPredict,
- LogisticRegressionTrain, OnlineDecrypt, OrderedSetIntersect, PasswordCheck,
- PrincipalComponentsAnalysis, PrivateJoinAndCompute, RsaSign,
+ Echo, FaceDetection, GbdtPredict, GbdtTrain, Algorithm2Hash, Algorithm2HashTrial,
+ Algorithm2HashTrialTier2, LogisticRegressionPredict, LogisticRegressionTrain, OnlineDecrypt,
+ OrderedSetIntersect, PasswordCheck, PrincipalComponentsAnalysis, PrivateJoinAndCompute,
+ RsaSign,
};
use teaclave_types::{FunctionArguments, FunctionRuntime, TeaclaveExecutor};
@@ -65,6 +66,14 @@ impl TeaclaveExecutor for BuiltinFunctionExecutor {
}
#[cfg(feature = "builtin_face_detection")]
FaceDetection::NAME => FaceDetection::new().run(arguments, runtime),
+ #[cfg(feature = "builtin_cleanroom_algorithm2_hash")]
+ Algorithm2Hash::NAME => Algorithm2Hash::new().run(arguments, runtime),
+ #[cfg(feature = "builtin_cleanroom_algorithm2_hash_trial")]
+ Algorithm2HashTrial::NAME => Algorithm2HashTrial::new().run(arguments, runtime),
+ #[cfg(feature = "builtin_cleanroom_algorithm2_hash_trial_tier2")]
+ Algorithm2HashTrialTier2::NAME => {
+ Algorithm2HashTrialTier2::new().run(arguments, runtime)
+ }
#[cfg(feature = "builtin_password_check")]
PasswordCheck::NAME => PasswordCheck::new().run(arguments, runtime),
_ => bail!("Function not found."),
diff --git a/executor/src/cleanroom.rs b/executor/src/cleanroom.rs
new file mode 100644
index 0000000..bf1e811
--- /dev/null
+++ b/executor/src/cleanroom.rs
@@ -0,0 +1,547 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::prelude::v1::*;
+
+use teaclave_executor_context::context::reset_thread_context;
+use teaclave_executor_context::context::set_thread_context;
+use teaclave_executor_context::context::Context;
+
+use anyhow::anyhow;
+use serde::{Deserialize, Serialize};
+use std::ffi::{c_void, CStr, CString};
+use std::os::raw::c_char;
+use std::ptr;
+use std::time::SystemTime;
+#[cfg(feature = "mesalock_sgx")]
+use std::untrusted::time::SystemTimeEx;
+
+use teaclave_types::{FunctionArguments, FunctionRuntime, TeaclaveExecutor};
+
+const DEFAULT_HEAP_SIZE: u32 = 0;
+const DEFAULT_STACK_SIZE: u32 = 463840;
+const DEFAULT_ERROR_BUF_SIZE: usize = 128;
+
+#[allow(unused)]
+#[no_mangle]
+pub static mut DEBUG_FLAG: i32 = 0;
+
+#[repr(C)]
+#[derive(Debug)]
+struct NativeSymbol {
+ symbol: *const c_char,
+ func_ptr: *const c_void,
+ signature: *const c_char,
+ attachment: *const c_void,
+}
+
+#[allow(unused)]
+#[no_mangle]
+pub extern "C" fn rust_printf(c_buf: *const c_char) {
+ let c_str = unsafe { CStr::from_ptr(c_buf) };
+ let str_slice = c_str.to_string_lossy();
+ log::debug!("Cleanroom: {:?}", str_slice);
+}
+
+#[allow(unused)]
+#[no_mangle]
+pub extern "C" fn teaclave_sgx_log(c_buf: *const c_char) {
+ let c_str = unsafe { CStr::from_ptr(c_buf) };
+ let str_slice = c_str.to_string_lossy();
+ log::warn!(
+ "Cleanroom: The ocall function {:?} should not be reachable.",
+ str_slice
+ );
+}
+
+#[derive(Serialize, Deserialize)]
+struct Summary {
+ status: bool,
+ reason: String,
+ execution_time: f32,
+}
+
+extern "C" {
+
+ fn wasm_runtime_init() -> bool;
+
+ fn wasm_runtime_load(
+ buf: *const u8,
+ size: u32,
+ error_buf: *mut u8,
+ error_buf_size: u32,
+ ) -> *const c_void;
+
+ fn wasm_runtime_set_wasi_args(
+ module: *const c_void,
+ dir_list: *const u8,
+ dir_count: u32,
+ map_dir_list: *const c_void,
+ map_dit_list_count: u32,
+ env_list: *const c_void,
+ env_count: u32,
+ argv: *const u8,
+ argc: u32,
+ );
+
+ fn wasm_application_execute_main(
+ module_inst: *const c_void,
+ argc: u32,
+ argv: *const u8,
+ ) -> bool;
+
+ fn wasm_runtime_instantiate(
+ module: *const c_void,
+ stack_size: u32,
+ heap_size: u32,
+ error_buf: *mut u8,
+ error_buf_size: u32,
+ ) -> *const c_void;
+
+ fn wasm_runtime_get_exception(module_inst: *const c_void) -> *const c_char;
+
+ fn wasm_runtime_deinstantiate(module_inst: *const c_void);
+
+ fn wasm_runtime_unload(module: *const c_void);
+
+ fn wasm_runtime_destroy();
+
+}
+
+fn get_key(arguments: &FunctionArguments, key: &str) -> String {
+ let args = arguments.clone().into_vec();
+ let len = args.len();
+ for (i, arg) in args.iter().enumerate() {
+ if (arg.eq(key)) && i < (len - 1) {
+ return args[i + 1].clone();
+ }
+ }
+ String::from("")
+}
+
+#[derive(Default)]
+pub struct CleanroomRuntime;
+
+impl TeaclaveExecutor for CleanroomRuntime {
+ fn execute(
+ &self,
+ _name: String,
+ arguments: FunctionArguments,
+ payload: Vec<u8>,
+ runtime: FunctionRuntime,
+ ) -> anyhow::Result<String> {
+ let debug_flag = get_key(&arguments, "debug");
+ let argv_string = get_key(&arguments, "args");
+ let dir_argv_string = get_key(&arguments, "wdir");
+ let current_time = SystemTime::now();
+
+ if debug_flag.eq("true") {
+ unsafe { DEBUG_FLAG = 1 };
+ } else {
+ unsafe { DEBUG_FLAG = 0 };
+ }
+ let mut argvs: Vec<String>;
+ if argv_string.trim().is_empty() {
+ argvs = Vec::new();
+ } else {
+ argvs = serde_json::from_str(&argv_string)
+ .map_err(|_| anyhow!("Cleanroom: invalid input arguments"))?;
+ argvs.retain(|x| (!x.is_empty()));
+ }
+ log::warn!("argvs: {:?}", &argvs);
+ let argv_cstr: Vec<_> = argvs
+ .iter()
+ .map(|arg| CString::new(arg.as_str()))
+ .collect::<Result<_, _>>()?;
+
+ let argv: Vec<_> = argv_cstr
+ .iter()
+ .map(|arg| arg.as_bytes_with_nul().as_ptr())
+ .collect();
+ let argc = argv.len();
+ let dir_argvs: Vec<String> = dir_argv_string.split(' ').map(|s| s.to_string()).collect();
+ log::debug!("working directory: {:?}", &dir_argvs);
+ let dir_argv_cstr: Vec<_> = dir_argvs
+ .iter()
+ .map(|arg| CString::new(arg.as_str()))
+ .collect::<Result<_, _>>()?;
+
+ let dir_argv: Vec<_> = dir_argv_cstr
+ .iter()
+ .map(|arg| arg.as_bytes_with_nul().as_ptr())
+ .collect();
+ let dir_argc = dir_argv.len();
+
+ let mut error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
+
+ set_thread_context(Context::new(runtime))?;
+ let mut result;
+ let ret = unsafe { wasm_runtime_init() };
+ if !ret {
+ reset_thread_context()?;
+ let time_duration = current_time.elapsed()?;
+ let time_secs = time_duration.as_secs_f32();
+ let summary = Summary {
+ status: false,
+ reason: "wasm runtime init failed".to_string(),
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ return Ok(summary_result);
+ }
+
+ let module = unsafe {
+ wasm_runtime_load(
+ payload.as_ptr(),
+ payload.len() as u32,
+ error_buf.as_mut_ptr(),
+ error_buf.len() as u32,
+ )
+ };
+
+ rust_printf(error_buf.as_mut_ptr() as *const i8);
+ if (module as usize) == 0 {
+ unsafe { wasm_runtime_destroy() };
+ reset_thread_context()?;
+ let time_duration = current_time.elapsed()?;
+ let time_secs = time_duration.as_secs_f32();
+
+ let summary = Summary {
+ status: false,
+ reason: "wasm runtime load failed".to_string(),
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ return Ok(summary_result);
+ }
+
+ unsafe {
+ wasm_runtime_set_wasi_args(
+ module,
+ dir_argv.as_ptr() as *const u8,
+ dir_argc as u32,
+ ptr::null_mut(),
+ 0,
+ ptr::null_mut(),
+ 0,
+ argv.as_ptr() as *const u8,
+ argc as u32,
+ )
+ };
+ error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
+ let module_instance = unsafe {
+ wasm_runtime_instantiate(
+ module,
+ DEFAULT_STACK_SIZE,
+ DEFAULT_HEAP_SIZE,
+ error_buf.as_mut_ptr(),
+ error_buf.len() as u32,
+ )
+ };
+
+ if (module_instance as usize) == 0 {
+ unsafe { wasm_runtime_unload(module) };
+ unsafe { wasm_runtime_destroy() };
+ reset_thread_context()?;
+ let time_duration = current_time.elapsed()?;
+ let time_secs = time_duration.as_secs_f32();
+ let summary = Summary {
+ status: false,
+ reason: "wasm runtime instantiate failed".to_string(),
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ return Ok(summary_result);
+ }
+
+ result = unsafe { wasm_application_execute_main(module_instance, 0, ptr::null_mut()) };
+
+ let exception = unsafe { wasm_runtime_get_exception(module_instance) };
+ unsafe {
+ if !exception.is_null() {
+ log::debug!(
+ "Exception: {:?}",
+ CStr::from_ptr(exception).to_string_lossy(),
+ );
+ result = false;
+ }
+ }
+
+ unsafe { wasm_runtime_deinstantiate(module_instance) };
+ unsafe { wasm_runtime_unload(module) };
+ unsafe { wasm_runtime_destroy() };
+ reset_thread_context()?;
+ let time_duration = current_time.elapsed()?;
+ let time_secs = time_duration.as_secs_f32();
+
+ let summary = Summary {
+ status: result,
+ reason: "Succeed".to_string(),
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ Ok(summary_result)
+ }
+}
+
+#[cfg(feature = "enclave_unit_test")]
+pub mod tests {
+ use super::*;
+ #[cfg(feature = "mesalock_sgx")]
+ use std::collections::HashMap;
+ use std::untrusted::fs;
+ use teaclave_crypto::*;
+ use teaclave_runtime::*;
+ use teaclave_test_utils::*;
+ use teaclave_types::*;
+
+ const IN_STDIN_FILE: &str = "input_file";
+ const OUT_STDOUT_FILE: &str = "output_file";
+
+ pub fn run_tests() -> bool {
+ run_tests!(
+ test_readfile,
+ test_args,
+ test_stdout,
+ test_stdin,
+ test_algorithm1,
+ test_stderr,
+ )
+ }
+
+ fn test_readfile() {
+ let mut args = HashMap::new();
+ args.insert("args".to_string(), "".to_string());
+ args.insert("wdir".to_string(), "data".to_string());
+ let args = FunctionArguments::from(args);
+ let wa_payload =
+ include_bytes!("../../tests/fixtures/functions/cleanroom-readfile/readfile.wasm");
+
+ let wa_payload = wa_payload.to_vec();
+ let stdin = "fixtures/functions/cleanroom-readfile/stdin";
+ let input_info =
+ StagedFileInfo::new(stdin, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let stdout = "fixtures/functions/cleanroom-readfile/stdout";
+ let output_info =
+ StagedFileInfo::new(stdout, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let config_file = "fixtures/functions/cleanroom-readfile/data/a.txt";
+ let config_file_info = StagedFileInfo::new(
+ config_file,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let input_files = StagedFiles::new(hashmap!(IN_STDIN_FILE => input_info,
+ "data/a.txt" => config_file_info));
+ let output_files = StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info));
+
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+
+ let function = CleanroomRuntime::default();
+ let _summary = function
+ .execute("".to_string(), args, wa_payload, runtime)
+ .unwrap();
+
+ let stdout_result = fs::read_to_string(&stdout).unwrap();
+ log::debug!("{:?}", stdout_result);
+ }
+
+ fn test_stdout() {
+ let args = HashMap::new();
+
+ let args = FunctionArguments::from(args);
+
+ let wa_payload = include_bytes!("../../tests/fixtures/functions/cleanroom-stdout/test.aot");
+
+ let wa_payload = wa_payload.to_vec();
+ let input_seq = "fixtures/functions/cleanroom-stdout/stdin";
+ let input_info =
+ StagedFileInfo::new(input_seq, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let output_seq = "fixtures/functions/cleanroom-stdout/stdout";
+ let output_info = StagedFileInfo::new(
+ output_seq,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let input_files = StagedFiles::new(hashmap!(IN_STDIN_FILE => input_info));
+ let output_files = StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info));
+
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+
+ let function = CleanroomRuntime::default();
+ let _summary = function
+ .execute("".to_string(), args, wa_payload, runtime)
+ .unwrap();
+
+ let output_data = fs::read_to_string(&output_seq).unwrap();
+ log::debug!("Hello world: {:?}", output_data);
+ }
+
+ fn test_stdin() {
+ let args = HashMap::new();
+
+ let args = FunctionArguments::from(args);
+
+ let wa_payload =
+ include_bytes!("../../tests/fixtures/functions/cleanroom-stdin/getline.wasm");
+
+ let wa_payload = wa_payload.to_vec();
+ let input_seq = "fixtures/functions/cleanroom-stdin/stdin";
+ let input_info =
+ StagedFileInfo::new(input_seq, TeaclaveFile128Key::random(), FileAuthTag::mock());
+ let output_seq = "fixtures/functions/cleanroom-stdin/stdout";
+ let output_info = StagedFileInfo::new(
+ output_seq,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let input_files = StagedFiles::new(hashmap!(IN_STDIN_FILE => input_info));
+ let output_files = StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info));
+
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+
+ let function = CleanroomRuntime::default();
+ let _summary = function
+ .execute("".to_string(), args, wa_payload, runtime)
+ .unwrap();
+
+ let output_data = fs::read_to_string(&output_seq).unwrap();
+ log::debug!("{:?}", output_data);
+ }
+
+ fn test_args() {
+ let mut args = HashMap::new();
+ args.insert(
+ "args".to_string(),
+ r#"["1", "2", "3", "4", "5", "6", "7"]"#.to_string(),
+ );
+ let args = FunctionArguments::from(args);
+ let wa_payload = include_bytes!("../../tests/fixtures/functions/cleanroom-args/args.wasm");
+
+ let wa_payload = wa_payload.to_vec();
+ let stdin = "fixtures/functions/cleanroom-args/stdin";
+ let input_info =
+ StagedFileInfo::new(stdin, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let stdout = "fixtures/functions/cleanroom-args/stdout";
+ let output_info =
+ StagedFileInfo::new(stdout, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let input_files = StagedFiles::new(hashmap!(IN_STDIN_FILE => input_info));
+ let output_files = StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info));
+
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+
+ let function = CleanroomRuntime::default();
+ let _summary = function
+ .execute("".to_string(), args, wa_payload, runtime)
+ .unwrap();
+
+ let stdout_result = fs::read_to_string(&stdout).unwrap();
+ log::debug!("{:?}", stdout_result);
+ }
+
+ fn test_algorithm1() {
+ let mut args = HashMap::new();
+ args.insert(
+ "args".to_string(),
+ r#"["algorithm1_v", "100", "0", "0", "0", "0", "0", "5.0", "example.shape"]"#
+ .to_string(),
+ );
+ args.insert("wdir".to_string(), ".".to_string());
+ let args = FunctionArguments::from(args);
+
+ let wa_payload =
+ include_bytes!("../../tests/fixtures/functions/cleanroom-algorithm1/algorithm1.aot");
+
+ let wa_payload = wa_payload.to_vec();
+ let stdin = "fixtures/functions/cleanroom-algorithm1/testseq";
+ let input_info =
+ StagedFileInfo::new(stdin, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let stdout = "fixtures/functions/cleanroom-algorithm1/stdout";
+ let output_info =
+ StagedFileInfo::new(stdout, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let config_file = "fixtures/functions/cleanroom-algorithm1/example.shape";
+ let config_file_info = StagedFileInfo::new(
+ config_file,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let input_files = StagedFiles::new(
+ hashmap!(IN_STDIN_FILE => input_info, "example.shape" => config_file_info),
+ );
+ let output_files = StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info));
+
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+
+ let function = CleanroomRuntime::default();
+ let _summary = function
+ .execute("".to_string(), args, wa_payload, runtime)
+ .unwrap();
+
+ let stdout_result = fs::read_to_string(&stdout).unwrap();
+ log::debug!("{:?}", stdout_result);
+ }
+
+ fn test_stderr() {
+ let mut args = HashMap::new();
+ args.insert("args".to_string(), r#"["1", "12"]"#.to_string());
+ args.insert("debug".to_string(), "true".to_string());
+
+ let args = FunctionArguments::from(args);
+
+ let wa_payload = include_bytes!("../../tests/fixtures/functions/cleanroom-stderr/app.wasm");
+
+ let wa_payload = wa_payload.to_vec();
+ let input_seq = "fixtures/functions/cleanroom-stderr/stdin";
+ let input_info =
+ StagedFileInfo::new(input_seq, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let output_seq = "fixtures/functions/cleanroom-stderr/stdout";
+ let output_info = StagedFileInfo::new(
+ output_seq,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let log_seq = "fixtures/functions/cleanroom-stderr/stderr";
+ let log_info =
+ StagedFileInfo::new(log_seq, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let input_files = StagedFiles::new(hashmap!(IN_STDIN_FILE => input_info));
+ let output_files =
+ StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info,"log_file" => log_info));
+
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+
+ let function = CleanroomRuntime::default();
+ let _summary = function
+ .execute("cleanroom".to_string(), args, wa_payload, runtime)
+ .unwrap();
+
+ let output_data = fs::read_to_string(&output_seq).unwrap();
+ log::debug!("Hello world: {:?}", output_data);
+ }
+}
diff --git a/executor/src/lib.rs b/executor/src/lib.rs
index 86a4c2e..691629b 100644
--- a/executor/src/lib.rs
+++ b/executor/src/lib.rs
@@ -26,6 +26,7 @@ extern crate log;
#[cfg(executor_builtin)]
mod builtin;
+mod cleanroom;
#[cfg(executor_mesapy)]
mod mesapy;
#[cfg(executor_wamr)]
@@ -33,6 +34,7 @@ mod wamr;
#[cfg(executor_builtin)]
pub use builtin::BuiltinFunctionExecutor;
+pub use cleanroom::CleanroomRuntime;
#[cfg(executor_mesapy)]
pub use mesapy::MesaPy;
#[cfg(executor_wamr)]
@@ -48,8 +50,9 @@ pub mod tests {
v.push(mesapy::tests::run_tests());
#[cfg(executor_builtin)]
v.push(builtin::tests::run_tests());
- #[cfg(executor_wamr)]
- v.push(wamr::tests::run_tests());
+ //#[cfg(executor_wamr)]
+ //v.push(wamr::tests::run_tests());
+ v.push(cleanroom::tests::run_tests());
v.iter().all(|&x| x)
}
}
diff --git a/executor/src/wamr.rs b/executor/src/wamr.rs
index 21c9cb8..4840200 100644
--- a/executor/src/wamr.rs
+++ b/executor/src/wamr.rs
@@ -266,6 +266,7 @@ pub mod tests {
use teaclave_test_utils::*;
use teaclave_types::*;
+ #[allow(unused)]
pub fn run_tests() -> bool {
run_tests!(test_wamr_tvm_mnist, test_wamr_millionaire,)
}
diff --git a/file_agent/Cargo.lock b/file_agent/Cargo.lock
index 2d01445..fdfbc6c 100644
--- a/file_agent/Cargo.lock
+++ b/file_agent/Cargo.lock
@@ -715,7 +715,7 @@ dependencies = [
[[package]]
name = "protected_fs_rs"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"cfg-if 0.1.10",
"libc",
@@ -1026,7 +1026,7 @@ dependencies = [
[[package]]
name = "teaclave_crypto"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"hex",
@@ -1039,7 +1039,7 @@ dependencies = [
[[package]]
name = "teaclave_file_agent"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"base64",
@@ -1061,7 +1061,7 @@ dependencies = [
[[package]]
name = "teaclave_test_utils"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"inventory",
"teaclave_test_utils_proc_macro",
@@ -1078,7 +1078,7 @@ dependencies = [
[[package]]
name = "teaclave_types"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"hex",
diff --git a/file_agent/Cargo.toml b/file_agent/Cargo.toml
index 6878669..d656ee7 100644
--- a/file_agent/Cargo.toml
+++ b/file_agent/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_file_agent"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave file agent for worker"
license = "Apache-2.0"
@@ -31,7 +31,7 @@ crate-type = ["staticlib", "rlib"]
default = []
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
anyhow = { version = "1.0.26" }
base64 = { version = "0.13.0" }
serde_json = { version = "1.0.39" }
diff --git a/function/Cargo.toml b/function/Cargo.toml
index 2c94ca4..a8e084e 100644
--- a/function/Cargo.toml
+++ b/function/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_function"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave built-in functions."
license = "Apache-2.0"
@@ -43,7 +43,7 @@ enclave_unit_test = [
]
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
anyhow = { version = "1.0.26" }
serde_json = { version = "1.0.39" }
serde = { version = "1.0.92", features = ["derive"] }
@@ -63,6 +63,7 @@ teaclave_runtime = { path = "../runtime", optional = true }
teaclave_test_utils = { path = "../tests/utils", optional = true }
teaclave_executor_context = { path = "../executor/context" }
+
sgx_cov = { version = "1.1.3", optional = true }
sgx_tstd = { version = "1.1.3", features = ["net", "thread", "backtrace"], optional = true }
sgx_types = { version = "1.1.3" }
diff --git a/function/src/cleanroom_algorithm2.rs b/function/src/cleanroom_algorithm2.rs
new file mode 100644
index 0000000..2f07a24
--- /dev/null
+++ b/function/src/cleanroom_algorithm2.rs
@@ -0,0 +1,325 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::prelude::v1::*;
+
+use teaclave_executor_context::context::reset_thread_context;
+use teaclave_executor_context::context::set_thread_context;
+use teaclave_executor_context::context::Context;
+
+use crate::cleanroom_algorithm2_hash::CLEANROOM_NATIVE_DEBUG_FLAG;
+use anyhow::anyhow;
+use serde::{Deserialize, Serialize};
+use std::ffi::{CStr, CString};
+use std::format;
+use std::time::SystemTime;
+use teaclave_types::{FunctionArguments, FunctionRuntime};
+
+#[cfg(feature = "mesalock_sgx")]
+use std::untrusted::time::SystemTimeEx;
+
+#[derive(Default)]
+pub struct Algorithm2;
+
+const DEFAULT_ERROR_BUF_SIZE: usize = 128;
+
+#[derive(Serialize, Deserialize)]
+struct Summary {
+ status: bool,
+ reason: String,
+ execution_time: f32,
+}
+
+extern "C" {
+ fn call_algorithm2_classic(
+ argc: u32,
+ argv: *const u8,
+ error_buf: *mut u8,
+ error_buf_size: u32,
+ error_code: *mut u32,
+ ) -> u32;
+}
+
+fn get_key(arguments: &FunctionArguments, key: &str) -> String {
+ let args = arguments.clone().into_vec();
+ let len = args.len();
+ for (i, arg) in args.iter().enumerate() {
+ if (arg.eq(key)) && i < (len - 1) {
+ return args[i + 1].clone();
+ }
+ }
+ String::from("")
+}
+
+impl Algorithm2 {
+ pub const NAME: &'static str = "builtin-cleanroom-algorithm2";
+
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ pub fn run(
+ &self,
+ arguments: FunctionArguments,
+ runtime: FunctionRuntime,
+ ) -> anyhow::Result<String> {
+ let debug_flag = get_key(&arguments, "debug");
+ let argv_string = get_key(&arguments, "args");
+ let current_time = SystemTime::now();
+ log::info!("Hello cleanroom algorithm2: {:?}", arguments.into_vec());
+
+ if debug_flag.eq("true") {
+ unsafe { CLEANROOM_NATIVE_DEBUG_FLAG = 1 };
+ } else {
+ unsafe { CLEANROOM_NATIVE_DEBUG_FLAG = 0 };
+ }
+
+ let mut argvs: Vec<String>;
+ if argv_string.trim().is_empty() {
+ argvs = Vec::new();
+ } else {
+ argvs = serde_json::from_str(&argv_string)
+ .map_err(|_| anyhow!("Cleanroom: invalid input arguments"))?;
+ argvs.retain(|x| (!x.is_empty()));
+ }
+ log::warn!("argvs: {:?}", &argvs);
+ let argv_cstr: Vec<_> = argvs
+ .iter()
+ .map(|arg| CString::new(arg.as_str()))
+ .collect::<Result<_, _>>()?;
+ let argv: Vec<_> = argv_cstr
+ .iter()
+ .map(|arg| arg.as_bytes_with_nul().as_ptr())
+ .collect();
+ let argc = argv.len();
+ let mut error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
+ let mut error_code = 0;
+ set_thread_context(Context::new(runtime))?;
+ let ret = unsafe {
+ call_algorithm2_classic(
+ argc as u32,
+ argv.as_ptr() as *const u8,
+ error_buf.as_mut_ptr(),
+ error_buf.len() as u32,
+ &mut error_code,
+ )
+ };
+ log::warn!("Return code {:?}", ret);
+ reset_thread_context()?;
+ let time_duration = current_time.elapsed()?;
+ let time_secs = time_duration.as_secs_f32();
+ if error_code != 0 {
+ let buf_str = unsafe { CStr::from_ptr(error_buf.as_mut_ptr() as *const i8) };
+ let buf_str_slice = buf_str.to_string_lossy();
+ let result_exception = format!(
+ "Function got exceptions ({}). Reason: {}",
+ error_code, buf_str_slice,
+ );
+ let summary = Summary {
+ status: false,
+ reason: result_exception,
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ return Ok(summary_result);
+ }
+ if ret != 0 {
+ let result_error_code = format!(
+ "Function returned with error code: {}. Please enable the diagnosis mode.",
+ ret
+ );
+ let summary = Summary {
+ status: false,
+ reason: result_error_code,
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ return Ok(summary_result);
+ }
+ let summary = Summary {
+ status: true,
+ reason: "Succeeded".to_string(),
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ Ok(summary_result)
+ }
+}
+
+#[cfg(feature = "enclave_unit_test")]
+pub mod tests {
+ use super::*;
+ #[cfg(feature = "mesalock_sgx")]
+ use std::collections::HashMap;
+ use std::untrusted::fs;
+ use teaclave_crypto::*;
+ use teaclave_runtime::*;
+ use teaclave_test_utils::*;
+ use teaclave_types::*;
+
+ const IN_STDIN_FILE: &str = "input_file";
+ const OUT_STDOUT_FILE: &str = "output_file";
+
+ pub fn run_tests() -> bool {
+ run_tests!(
+ test_cleanroom_native,
+ test_algorithm2_stderr_native,
+ test_algorithm2_exception_native
+ )
+ }
+
+ fn test_cleanroom_native() {
+ let mut args = HashMap::new();
+ args.insert(
+ "args".to_string(),
+ r#"["algorithm2", "100", "200"]"#.to_string(),
+ );
+ let args = FunctionArguments::from(args);
+
+ let stdin = "fixtures/functions/cleanroom-algorithm2-hash/stdin";
+ let input_info =
+ StagedFileInfo::new(stdin, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let stdout = "fixtures/functions/cleanroom-algorithm2-hash/stdout";
+ let output_info =
+ StagedFileInfo::new(stdout, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let config_file1 = "fixtures/functions/cleanroom-algorithm2-hash/coding_wheel.txt";
+ let config_file_info1 = StagedFileInfo::new(
+ config_file1,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let config_file2 =
+ "fixtures/functions/cleanroom-algorithm2-hash/codon_usage_freq_table_human.csv";
+ let config_file_info2 = StagedFileInfo::new(
+ config_file2,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let input_files = StagedFiles::new(
+ hashmap!(IN_STDIN_FILE => input_info, "./coding_wheel.txt" => config_file_info1, "./codon_usage_freq_table_human.csv" => config_file_info2),
+ );
+
+ let output_files = StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info));
+
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+ let function = Algorithm2;
+
+ let summary = function.run(args, runtime).unwrap();
+ log::warn!("{:?}", summary);
+ }
+
+ fn test_algorithm2_stderr_native() {
+ let mut args = HashMap::new();
+ args.insert("args".to_string(), r#"["algorithm2"]"#.to_string());
+ args.insert("debug".to_string(), "true".to_string());
+ let args = FunctionArguments::from(args);
+
+ let stdin = "fixtures/functions/cleanroom-algorithm2-hash/stdin";
+ let input_info =
+ StagedFileInfo::new(stdin, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let stdout = "fixtures/functions/cleanroom-algorithm2-hash/stdout1";
+ let output_info =
+ StagedFileInfo::new(stdout, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let log_seq = "fixtures/functions/cleanroom-algorithm2-hash/stderr1";
+ let log_info =
+ StagedFileInfo::new(log_seq, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let config_file1 = "fixtures/functions/cleanroom-algorithm2-hash/coding_wheel.txt";
+ let config_file_info1 = StagedFileInfo::new(
+ config_file1,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let config_file2 =
+ "fixtures/functions/cleanroom-algorithm2-hash/codon_usage_freq_table_human.csv";
+ let config_file_info2 = StagedFileInfo::new(
+ config_file2,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let input_files = StagedFiles::new(
+ hashmap!(IN_STDIN_FILE => input_info, "./coding_wheel.txt" => config_file_info1, "./codon_usage_freq_table_human.csv" => config_file_info2),
+ );
+
+ let output_files =
+ StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info, "log_file" => log_info));
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+ let function = Algorithm2;
+
+ let summary = function.run(args, runtime).unwrap();
+ log::warn!("{:?}", summary);
+ let log_info = fs::read_to_string(&log_seq).unwrap();
+ log::warn!("Stderr result: {:?}", log_info);
+ }
+
+ fn test_algorithm2_exception_native() {
+ let mut args = HashMap::new();
+ args.insert(
+ "args".to_string(),
+ r#"["algorithm2", "100", "200"]"#.to_string(),
+ );
+ args.insert("debug".to_string(), "true".to_string());
+ let args = FunctionArguments::from(args);
+
+ let stdin = "fixtures/functions/cleanroom-algorithm2-hash/stdin2";
+ let input_info =
+ StagedFileInfo::new(stdin, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let stdout = "fixtures/functions/cleanroom-algorithm2-hash/stdout2";
+ let output_info =
+ StagedFileInfo::new(stdout, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let log_seq = "fixtures/functions/cleanroom-algorithm2-hash/stderr2";
+ let log_info =
+ StagedFileInfo::new(log_seq, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let config_file1 = "fixtures/functions/cleanroom-algorithm2-hash/coding_wheel.txt";
+ let config_file_info1 = StagedFileInfo::new(
+ config_file1,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let config_file2 =
+ "fixtures/functions/cleanroom-algorithm2-hash/codon_usage_freq_table_human.csv";
+ let config_file_info2 = StagedFileInfo::new(
+ config_file2,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let input_files = StagedFiles::new(
+ hashmap!(IN_STDIN_FILE => input_info, "./coding_wheel.txt" => config_file_info1, "./codon_usage_freq_table_human.csv" => config_file_info2),
+ );
+
+ let output_files =
+ StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info, "log_file" => log_info));
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+ let function = Algorithm2;
+
+ let summary = function.run(args, runtime).unwrap();
+ log::warn!("{:?}", summary);
+ }
+}
diff --git a/function/src/cleanroom_algorithm2_hash.rs b/function/src/cleanroom_algorithm2_hash.rs
new file mode 100644
index 0000000..f98041a
--- /dev/null
+++ b/function/src/cleanroom_algorithm2_hash.rs
@@ -0,0 +1,338 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::prelude::v1::*;
+
+use teaclave_executor_context::context::reset_thread_context;
+use teaclave_executor_context::context::set_thread_context;
+use teaclave_executor_context::context::Context;
+
+use anyhow::anyhow;
+use serde::{Deserialize, Serialize};
+use std::ffi::{CStr, CString};
+use std::format;
+use std::os::raw::c_char;
+use std::time::SystemTime;
+use teaclave_types::{FunctionArguments, FunctionRuntime};
+
+#[cfg(feature = "mesalock_sgx")]
+use std::untrusted::time::SystemTimeEx;
+
+#[derive(Default)]
+pub struct Algorithm2Hash;
+
+const DEFAULT_ERROR_BUF_SIZE: usize = 128;
+
+#[allow(unused)]
+#[no_mangle]
+pub static mut CLEANROOM_NATIVE_DEBUG_FLAG: i32 = 0;
+
+#[allow(unused)]
+#[no_mangle]
+pub extern "C" fn cleanroom_native_printf(c_buf: *const c_char) {
+ let c_str = unsafe { CStr::from_ptr(c_buf) };
+ let str_slice = c_str.to_string_lossy();
+ log::debug!("Cleanroom Algorithm2 hash: {:?}", str_slice);
+}
+
+#[derive(Serialize, Deserialize)]
+struct Summary {
+ status: bool,
+ reason: String,
+ execution_time: f32,
+}
+
+extern "C" {
+ fn call_algorithm2(
+ argc: u32,
+ argv: *const u8,
+ error_buf: *mut u8,
+ error_buf_size: u32,
+ error_code: *mut u32,
+ ) -> u32;
+}
+
+fn get_key(arguments: &FunctionArguments, key: &str) -> String {
+ let args = arguments.clone().into_vec();
+ let len = args.len();
+ for (i, arg) in args.iter().enumerate() {
+ if (arg.eq(key)) && i < (len - 1) {
+ return args[i + 1].clone();
+ }
+ }
+ String::from("")
+}
+
+impl Algorithm2Hash {
+ pub const NAME: &'static str = "builtin-cleanroom-algorithm2-hash";
+
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ pub fn run(
+ &self,
+ arguments: FunctionArguments,
+ runtime: FunctionRuntime,
+ ) -> anyhow::Result<String> {
+ let debug_flag = get_key(&arguments, "debug");
+ let argv_string = get_key(&arguments, "args");
+ let current_time = SystemTime::now();
+ log::info!("Cleanroom algorithm2 hash: {:?}", arguments.into_vec());
+
+ if debug_flag.eq("true") {
+ unsafe { CLEANROOM_NATIVE_DEBUG_FLAG = 1 };
+ } else {
+ unsafe { CLEANROOM_NATIVE_DEBUG_FLAG = 0 };
+ }
+
+ let mut argvs: Vec<String>;
+ if argv_string.trim().is_empty() {
+ argvs = Vec::new();
+ } else {
+ argvs = serde_json::from_str(&argv_string)
+ .map_err(|_| anyhow!("Cleanroom: invalid input arguments"))?;
+ argvs.retain(|x| (!x.is_empty()));
+ argvs.retain(|x| (!x.starts_with("--")));
+ }
+ log::warn!("argvs: {:?}", &argvs);
+ let argv_cstr: Vec<_> = argvs
+ .iter()
+ .map(|arg| CString::new(arg.as_str()))
+ .collect::<Result<_, _>>()?;
+ let argv: Vec<_> = argv_cstr
+ .iter()
+ .map(|arg| arg.as_bytes_with_nul().as_ptr())
+ .collect();
+ let argc = argv.len();
+ let mut error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
+ let mut error_code = 0;
+ set_thread_context(Context::new(runtime))?;
+ let ret = unsafe {
+ call_algorithm2(
+ argc as u32,
+ argv.as_ptr() as *const u8,
+ error_buf.as_mut_ptr(),
+ error_buf.len() as u32,
+ &mut error_code,
+ )
+ };
+ log::warn!("Return code {:?}", ret);
+ reset_thread_context()?;
+ let time_duration = current_time.elapsed()?;
+ let time_secs = time_duration.as_secs_f32();
+ if error_code != 0 {
+ let buf_str = unsafe { CStr::from_ptr(error_buf.as_mut_ptr() as *const i8) };
+ let buf_str_slice = buf_str.to_string_lossy();
+ let result_exception = format!(
+ "Function got exceptions ({}). Reason: {}",
+ error_code, buf_str_slice,
+ );
+ let summary = Summary {
+ status: false,
+ reason: result_exception,
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ return Ok(summary_result);
+ }
+ if ret != 0 {
+ let result_error_code = format!(
+ "Function returned with error code: {}. Please enable the diagnosis mode.",
+ ret
+ );
+ let summary = Summary {
+ status: false,
+ reason: result_error_code,
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ return Ok(summary_result);
+ }
+ let summary = Summary {
+ status: true,
+ reason: "Succeeded".to_string(),
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ Ok(summary_result)
+ }
+}
+
+#[cfg(feature = "enclave_unit_test")]
+pub mod tests {
+ use super::*;
+ #[cfg(feature = "mesalock_sgx")]
+ use std::collections::HashMap;
+ use std::untrusted::fs;
+ use teaclave_crypto::*;
+ use teaclave_runtime::*;
+ use teaclave_test_utils::*;
+ use teaclave_types::*;
+
+ const IN_STDIN_FILE: &str = "input_file";
+ const OUT_STDOUT_FILE: &str = "output_file";
+
+ pub fn run_tests() -> bool {
+ run_tests!(
+ test_cleanroom_native,
+ test_algorithm2_stderr_native,
+ test_algorithm2_exception_native
+ )
+ }
+
+ fn test_cleanroom_native() {
+ let mut args = HashMap::new();
+ args.insert(
+ "args".to_string(),
+ r#"["algorithm2", "100", "200"]"#.to_string(),
+ );
+ let args = FunctionArguments::from(args);
+
+ let stdin = "fixtures/functions/cleanroom-algorithm2-hash/stdin";
+ let input_info =
+ StagedFileInfo::new(stdin, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let stdout = "fixtures/functions/cleanroom-algorithm2-hash/stdout";
+ let output_info =
+ StagedFileInfo::new(stdout, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let config_file1 = "fixtures/functions/cleanroom-algorithm2-hash/coding_wheel.txt";
+ let config_file_info1 = StagedFileInfo::new(
+ config_file1,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let config_file2 =
+ "fixtures/functions/cleanroom-algorithm2-hash/codon_usage_freq_table_human.csv";
+ let config_file_info2 = StagedFileInfo::new(
+ config_file2,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let input_files = StagedFiles::new(
+ hashmap!(IN_STDIN_FILE => input_info, "./coding_wheel.txt" => config_file_info1, "./codon_usage_freq_table_human.csv" => config_file_info2),
+ );
+
+ let output_files = StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info));
+
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+ let function = Algorithm2Hash;
+
+ let summary = function.run(args, runtime).unwrap();
+ log::warn!("{:?}", summary);
+ }
+
+ fn test_algorithm2_stderr_native() {
+ let mut args = HashMap::new();
+ args.insert("args".to_string(), r#"["algorithm2"]"#.to_string());
+ args.insert("debug".to_string(), "true".to_string());
+ let args = FunctionArguments::from(args);
+
+ let stdin = "fixtures/functions/cleanroom-algorithm2-hash/stdin";
+ let input_info =
+ StagedFileInfo::new(stdin, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let stdout = "fixtures/functions/cleanroom-algorithm2-hash/stdout1";
+ let output_info =
+ StagedFileInfo::new(stdout, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let log_seq = "fixtures/functions/cleanroom-algorithm2-hash/stderr1";
+ let log_info =
+ StagedFileInfo::new(log_seq, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let config_file1 = "fixtures/functions/cleanroom-algorithm2-hash/coding_wheel.txt";
+ let config_file_info1 = StagedFileInfo::new(
+ config_file1,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let config_file2 =
+ "fixtures/functions/cleanroom-algorithm2-hash/codon_usage_freq_table_human.csv";
+ let config_file_info2 = StagedFileInfo::new(
+ config_file2,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let input_files = StagedFiles::new(
+ hashmap!(IN_STDIN_FILE => input_info, "./coding_wheel.txt" => config_file_info1, "./codon_usage_freq_table_human.csv" => config_file_info2),
+ );
+
+ let output_files =
+ StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info, "log_file" => log_info));
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+ let function = Algorithm2Hash;
+
+ let summary = function.run(args, runtime).unwrap();
+ log::warn!("{:?}", summary);
+ let log_info = fs::read_to_string(&log_seq).unwrap();
+ log::warn!("Stderr result: {:?}", log_info);
+ }
+
+ fn test_algorithm2_exception_native() {
+ let mut args = HashMap::new();
+ args.insert(
+ "args".to_string(),
+ r#"["algorithm2", "100", "200"]"#.to_string(),
+ );
+ args.insert("debug".to_string(), "true".to_string());
+ let args = FunctionArguments::from(args);
+
+ let stdin = "fixtures/functions/cleanroom-algorithm2-hash/stdin2";
+ let input_info =
+ StagedFileInfo::new(stdin, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let stdout = "fixtures/functions/cleanroom-algorithm2-hash/stdout2";
+ let output_info =
+ StagedFileInfo::new(stdout, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let log_seq = "fixtures/functions/cleanroom-algorithm2-hash/stderr2";
+ let log_info =
+ StagedFileInfo::new(log_seq, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let config_file1 = "fixtures/functions/cleanroom-algorithm2-hash/coding_wheel.txt";
+ let config_file_info1 = StagedFileInfo::new(
+ config_file1,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let config_file2 =
+ "fixtures/functions/cleanroom-algorithm2-hash/codon_usage_freq_table_human.csv";
+ let config_file_info2 = StagedFileInfo::new(
+ config_file2,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let input_files = StagedFiles::new(
+ hashmap!(IN_STDIN_FILE => input_info, "./coding_wheel.txt" => config_file_info1, "./codon_usage_freq_table_human.csv" => config_file_info2),
+ );
+
+ let output_files =
+ StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info, "log_file" => log_info));
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+ let function = Algorithm2Hash;
+
+ let summary = function.run(args, runtime).unwrap();
+ log::warn!("{:?}", summary);
+ }
+}
diff --git a/function/src/cleanroom_algorithm2_hash_trial.rs b/function/src/cleanroom_algorithm2_hash_trial.rs
new file mode 100644
index 0000000..1dc38ed
--- /dev/null
+++ b/function/src/cleanroom_algorithm2_hash_trial.rs
@@ -0,0 +1,163 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::prelude::v1::*;
+
+use crate::cleanroom_algorithm2_hash::CLEANROOM_NATIVE_DEBUG_FLAG;
+use anyhow::anyhow;
+use serde::{Deserialize, Serialize};
+use std::ffi::{CStr, CString};
+use std::format;
+use std::time::SystemTime;
+use teaclave_executor_context::context::reset_thread_context;
+use teaclave_executor_context::context::set_thread_context;
+use teaclave_executor_context::context::Context;
+use teaclave_types::{FunctionArguments, FunctionRuntime};
+
+#[cfg(feature = "mesalock_sgx")]
+use std::untrusted::time::SystemTimeEx;
+
+#[derive(Default)]
+pub struct Algorithm2HashTrial;
+
+const DEFAULT_ERROR_BUF_SIZE: usize = 128;
+
+#[derive(Serialize, Deserialize)]
+struct Summary {
+ status: bool,
+ reason: String,
+ execution_time: f32,
+}
+
+extern "C" {
+ fn call_algorithm2_trial(
+ argc: u32,
+ argv: *const u8,
+ error_buf: *mut u8,
+ error_buf_size: u32,
+ error_code: *mut u32,
+ ) -> u32;
+}
+
+fn get_key(arguments: &FunctionArguments, key: &str) -> String {
+ let args = arguments.clone().into_vec();
+ let len = args.len();
+ for (i, arg) in args.iter().enumerate() {
+ if (arg.eq(key)) && i < (len - 1) {
+ return args[i + 1].clone();
+ }
+ }
+ String::from("")
+}
+
+impl Algorithm2HashTrial {
+ pub const NAME: &'static str = "builtin-cleanroom-algorithm2-hash-trial";
+
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ pub fn run(
+ &self,
+ arguments: FunctionArguments,
+ runtime: FunctionRuntime,
+ ) -> anyhow::Result<String> {
+ let debug_flag = get_key(&arguments, "debug");
+ let argv_string = get_key(&arguments, "args");
+ let current_time = SystemTime::now();
+ log::info!(
+ "Cleanroom algorithm2 hash trial: {:?}",
+ arguments.into_vec()
+ );
+
+ if debug_flag.eq("true") {
+ unsafe { CLEANROOM_NATIVE_DEBUG_FLAG = 1 };
+ } else {
+ unsafe { CLEANROOM_NATIVE_DEBUG_FLAG = 0 };
+ }
+
+ let mut argvs: Vec<String>;
+ if argv_string.trim().is_empty() {
+ argvs = Vec::new();
+ } else {
+ argvs = serde_json::from_str(&argv_string)
+ .map_err(|_| anyhow!("Cleanroom: invalid input arguments"))?;
+ argvs.retain(|x| (!x.is_empty()));
+ }
+ log::warn!("argvs: {:?}", &argvs);
+ let argv_cstr: Vec<_> = argvs
+ .iter()
+ .map(|arg| CString::new(arg.as_str()))
+ .collect::<Result<_, _>>()?;
+ let argv: Vec<_> = argv_cstr
+ .iter()
+ .map(|arg| arg.as_bytes_with_nul().as_ptr())
+ .collect();
+ let argc = argv.len();
+ let mut error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
+ let mut error_code = 0;
+ set_thread_context(Context::new(runtime))?;
+ let ret = unsafe {
+ call_algorithm2_trial(
+ argc as u32,
+ argv.as_ptr() as *const u8,
+ error_buf.as_mut_ptr(),
+ error_buf.len() as u32,
+ &mut error_code,
+ )
+ };
+ log::warn!("Return code {:?}", ret);
+ reset_thread_context()?;
+ let time_duration = current_time.elapsed()?;
+ let time_secs = time_duration.as_secs_f32();
+ if error_code != 0 {
+ let buf_str = unsafe { CStr::from_ptr(error_buf.as_mut_ptr() as *const i8) };
+ let buf_str_slice = buf_str.to_string_lossy();
+ let result_exception = format!(
+ "Function got exceptions ({}). Reason: {}",
+ error_code, buf_str_slice,
+ );
+ let summary = Summary {
+ status: false,
+ reason: result_exception,
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ return Ok(summary_result);
+ }
+ if ret != 0 {
+ let result_error_code = format!(
+ "Function returned with error code: {}. Please enable the diagnosis mode.",
+ ret
+ );
+ let summary = Summary {
+ status: false,
+ reason: result_error_code,
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ return Ok(summary_result);
+ }
+ let summary = Summary {
+ status: true,
+ reason: "Succeeded".to_string(),
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ Ok(summary_result)
+ }
+}
diff --git a/function/src/cleanroom_algorithm2_hash_trial_tier2.rs b/function/src/cleanroom_algorithm2_hash_trial_tier2.rs
new file mode 100644
index 0000000..44740b4
--- /dev/null
+++ b/function/src/cleanroom_algorithm2_hash_trial_tier2.rs
@@ -0,0 +1,207 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::prelude::v1::*;
+
+use crate::cleanroom_algorithm2_hash::CLEANROOM_NATIVE_DEBUG_FLAG;
+use anyhow::anyhow;
+use serde::{Deserialize, Serialize};
+use std::ffi::{CStr, CString};
+use std::format;
+use std::time::SystemTime;
+use teaclave_executor_context::context::reset_thread_context;
+use teaclave_executor_context::context::set_thread_context;
+use teaclave_executor_context::context::Context;
+use teaclave_types::{FunctionArguments, FunctionRuntime};
+
+#[cfg(feature = "mesalock_sgx")]
+use std::untrusted::time::SystemTimeEx;
+
+#[derive(Default)]
+pub struct Algorithm2HashTrialTier2;
+
+const DEFAULT_ERROR_BUF_SIZE: usize = 128;
+
+#[derive(Serialize, Deserialize)]
+struct Summary {
+ status: bool,
+ reason: String,
+ execution_time: f32,
+}
+
+/**
+ * Call algorithm2 trial tier2 function wrapper.
+ *
+ * [IN] @param argc the number of arguments. The wrapper only proceeds when the argc is 5.
+ * [IN] @param argv the arguments array. argv[1] = default_beamsize argv[2] = default_lambda argv[3] = candidate_beamsize argv[4] = candidate_lambda. Each array is serialized as a string. Items in the array are splited with ';'. e.g., [1,2,3] is serialized as "1;2;3;"
+ * [OUT] @param error_buf
+ * [OUT] @param error_buf_size
+ * [OUT] @param error_code
+ *
+ * @return 0 if the algorithm2 always returns 0. Callers can check the error code and the
+ * error_buf to know the reason.
+ */
+extern "C" {
+ fn call_algorithm2_trial2(
+ argc: u32,
+ argv: *const u8,
+ error_buf: *mut u8,
+ error_buf_size: u32,
+ error_code: *mut u32,
+ ) -> u32;
+}
+
+fn get_key(arguments: &FunctionArguments, key: &str) -> String {
+ let args = arguments.clone().into_vec();
+ let len = args.len();
+ for (i, arg) in args.iter().enumerate() {
+ if (arg.eq(key)) && i < (len - 1) {
+ return args[i + 1].clone();
+ }
+ }
+ String::from("")
+}
+
+impl Algorithm2HashTrialTier2 {
+ pub const NAME: &'static str = "builtin-cleanroom-algorithm2-hash-trial-tier2";
+
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ pub fn run(
+ &self,
+ arguments: FunctionArguments,
+ runtime: FunctionRuntime,
+ ) -> anyhow::Result<String> {
+ let debug_flag = get_key(&arguments, "debug");
+ let argv_string = get_key(&arguments, "args");
+ let current_time = SystemTime::now();
+ let beamsize_default: [i32; 4] = [10, 100, 500, 1000];
+ let lambda_default: [f32; 9] = [0.2, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 7.0, 10.0];
+ let beamsize_candidate: [i32; 4] = [5, 6, 8, 50];
+ let lambda_candidate: [f32; 2] = [0.02, 0.3];
+ log::info!(
+ "Cleanroom algorithm2 hash trial tier2: {:?}",
+ arguments.into_vec()
+ );
+
+ if debug_flag.eq("true") {
+ unsafe { CLEANROOM_NATIVE_DEBUG_FLAG = 1 };
+ } else {
+ unsafe { CLEANROOM_NATIVE_DEBUG_FLAG = 0 };
+ }
+
+ let mut argvs: Vec<String>;
+ if argv_string.trim().is_empty() {
+ argvs = Vec::new();
+ } else {
+ argvs = serde_json::from_str(&argv_string)
+ .map_err(|_| anyhow!("Cleanroom: invalid input arguments"))?;
+ argvs.retain(|x| (!x.is_empty()));
+ }
+ if argvs.len() != 5 {
+ log::info!("Use default arguments");
+ argvs.clear();
+ let argv = "cleanroom".to_string();
+ argvs.push(argv);
+ let argv = beamsize_default
+ .iter()
+ .map(|i| format!("{};", i))
+ .collect::<String>();
+ argvs.push(argv);
+ let argv = lambda_default
+ .iter()
+ .map(|i| format!("{};", i))
+ .collect::<String>();
+ argvs.push(argv);
+ let argv = beamsize_candidate
+ .iter()
+ .map(|i| format!("{};", i))
+ .collect::<String>();
+ argvs.push(argv);
+ let argv = lambda_candidate
+ .iter()
+ .map(|i| format!("{};", i))
+ .collect::<String>();
+ argvs.push(argv);
+ } else {
+ log::info!("Use user's arguments");
+ }
+ log::warn!("argvs: {:?}", &argvs);
+ let argv_cstr: Vec<_> = argvs
+ .iter()
+ .map(|arg| CString::new(arg.as_str()))
+ .collect::<Result<_, _>>()?;
+ let argv: Vec<_> = argv_cstr
+ .iter()
+ .map(|arg| arg.as_bytes_with_nul().as_ptr())
+ .collect();
+ let argc = argv.len();
+ let mut error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
+ let mut error_code = 0;
+ set_thread_context(Context::new(runtime))?;
+ let ret = unsafe {
+ call_algorithm2_trial2(
+ argc as u32,
+ argv.as_ptr() as *const u8,
+ error_buf.as_mut_ptr(),
+ error_buf.len() as u32,
+ &mut error_code,
+ )
+ };
+ log::warn!("Return code {:?}", ret);
+ reset_thread_context()?;
+ let time_duration = current_time.elapsed()?;
+ let time_secs = time_duration.as_secs_f32();
+ if error_code != 0 {
+ let buf_str = unsafe { CStr::from_ptr(error_buf.as_mut_ptr() as *const i8) };
+ let buf_str_slice = buf_str.to_string_lossy();
+ let result_exception = format!(
+ "Function got exceptions ({}). Reason: {}",
+ error_code, buf_str_slice,
+ );
+ let summary = Summary {
+ status: false,
+ reason: result_exception,
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ return Ok(summary_result);
+ }
+ if ret != 0 {
+ let result_error_code = format!(
+ "Function returned with error code: {}. Please enable the diagnosis mode.",
+ ret
+ );
+ let summary = Summary {
+ status: false,
+ reason: result_error_code,
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ return Ok(summary_result);
+ }
+ let summary = Summary {
+ status: true,
+ reason: "Succeeded".to_string(),
+ execution_time: time_secs,
+ };
+ let summary_result = serde_json::to_string(&summary)?;
+ Ok(summary_result)
+ }
+}
diff --git a/function/src/lib.rs b/function/src/lib.rs
index 641512c..ce99049 100644
--- a/function/src/lib.rs
+++ b/function/src/lib.rs
@@ -22,6 +22,10 @@ extern crate sgx_tstd as std;
#[cfg(feature = "mesalock_sgx")]
use std::prelude::v1::*;
+mod cleanroom_algorithm2;
+mod cleanroom_algorithm2_hash;
+mod cleanroom_algorithm2_hash_trial;
+mod cleanroom_algorithm2_hash_trial_tier2;
mod echo;
mod face_detection;
mod gbdt_predict;
@@ -35,6 +39,10 @@ mod principal_components_analysis;
mod private_join_and_compute;
mod rsa_sign;
+pub use cleanroom_algorithm2::Algorithm2;
+pub use cleanroom_algorithm2_hash::Algorithm2Hash;
+pub use cleanroom_algorithm2_hash_trial::Algorithm2HashTrial;
+pub use cleanroom_algorithm2_hash_trial_tier2::Algorithm2HashTrialTier2;
pub use echo::Echo;
pub use face_detection::FaceDetection;
pub use gbdt_predict::GbdtPredict;
@@ -55,6 +63,8 @@ pub mod tests {
pub fn run_tests() -> bool {
check_all_passed!(
+ cleanroom_algorithm2_hash::tests::run_tests(),
+ cleanroom_algorithm2::tests::run_tests(),
echo::tests::run_tests(),
face_detection::tests::run_tests(),
gbdt_predict::tests::run_tests(),
diff --git a/monitoring/prometheus.py b/monitoring/prometheus.py
new file mode 100755
index 0000000..a7d7e79
--- /dev/null
+++ b/monitoring/prometheus.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python3
+from prometheus_client import start_http_server, Counter
+import random
+import time
+import sys
+import re
+
+c = Counter('cleanroom_cpk_usage', 'Description of counter',
+ ['user_id', 'function_id', 'result'])
+f_c = Counter('cleanroom_cpk_usage_function_id', 'Description of counter',
+ ['function_id'])
+u_c = Counter('cleanroom_cpk_usage_user_id', 'Description of counter',
+ ['user_id'])
+
+frontend_service_c = Counter('cleanroom_frontend_service_total',
+ "Statistics of frontend service",
+ ['user_id', 'cli_version', 'request'])
+authentication_service_c = Counter('cleanroom_authentication_service_total',
+ "Statistics of authentiction service",
+ ['user_id', 'cli_version', 'request'])
+
+storage_service_c = Counter('cleanroom_storage_service_total',
+ "Statistics of storage service", ['request'])
+scheduler_service_c = Counter('cleanroom_scheduler_service_total',
+ "Statistics of scheduler service", ['request'])
+management_service_c = Counter('cleanroom_management_service_total',
+ "Statistics of management service", ['request'])
+
+
+def escape_ansi(line: str):
+ ansi_escape = re.compile(r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]')
+ return ansi_escape.sub('', line)
+
+
+def parse_log(service: str, log: str):
+ log = escape_ansi(log)
+ if "teaclave-execution-service" in service:
+ splits = log.strip().split("[MONITOR] InvokeTask: ")[1].split(",")
+ print(splits)
+ user_id = splits[0].strip('"')
+ function_id = splits[1].strip()
+ result = splits[2].strip()
+
+ c.labels(user_id, function_id, result).inc()
+ f_c.labels(function_id).inc()
+ u_c.labels(user_id).inc()
+ elif "teaclave-frontend-service" in service:
+ splits = log.strip().split("[MONITOR]")[1].split(",")
+ print(splits)
+ user_id = splits[0].strip().strip('"')
+ cli_version = splits[1].strip()
+ request = splits[2].strip()
+ frontend_service_c.labels(user_id, cli_version, request).inc()
+ elif "teaclave-authentication-service" in service:
+ splits = log.strip().split("[MONITOR]")[1].split(",")
+ print(splits)
+ user_id = splits[0].strip().strip('"')
+ cli_version = splits[1].strip()
+ request = splits[2].strip()
+ authentication_service_c.labels(user_id, cli_version, request).inc()
+ elif "teaclave-scheduler-service" in service:
+ splits = log.strip().split("[MONITOR]")[1].split(",")
+ request = splits[2].strip()
+ scheduler_service_c.labels(request).inc()
+ elif "teaclave-storage-service" in service:
+ splits = log.strip().split("[MONITOR]")[1].split(",")
+ request = splits[2].strip()
+ storage_service_c.labels(request).inc()
+ elif "teaclave-management-service" in service:
+ splits = log.strip().split("[MONITOR]")[1].split(",")
+ request = splits[2].strip()
+ management_service_c.labels(request).inc()
+
+
+def main():
+ start_http_server(9000)
+ for l in sys.stdin:
+ try:
+ service, log = (e.strip() for e in l.split("|"))
+ if "[MONITOR]" not in log: continue
+ parse_log(service, log)
+ except Exception as e:
+ print(e)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/cleanroom-cli/Makefile b/cleanroom-cli/Makefile
new file mode 100644
index 0000000..64b1cc7
--- /dev/null
+++ b/cleanroom-cli/Makefile
@@ -0,0 +1,29 @@
+PREFIX := install
+OS := $(shell uname -s)
+ARCH := $(shell uname -m)
+
+all: local
+
+local: install
+ cp -r conf $(PREFIX)/conf
+ cp ${CURDIR}/../release/services/enclave_info.toml ${CURDIR}/$(PREFIX)/conf/
+ tar -C $(PREFIX) -cvf ${CURDIR}/cleanroom-cli-${OS}-${ARCH}.tgz bin conf
+
+azure: install
+ cp -r ${CURDIR}/resource/azure/* ${CURDIR}/$(PREFIX)/
+ tar -C ${CURDIR}/$(PREFIX) -cvf ${CURDIR}/cleanroom-cli-${OS}-${ARCH}.tgz bin conf env
+
+install: pyoxidizer
+ mkdir -p ${CURDIR}/$(PREFIX)
+ cp -rf ${CURDIR}/build/*/release/install ${CURDIR}/$(PREFIX)/bin
+
+
+pyoxidizer:
+ pyoxidizer build --release --path ${CURDIR}
+
+clean:
+ @rm -rf ${CURDIR}/$(PREFIX)
+ @rm -rf ${CURDIR}/build ${CURDIR}/web_cli ${CURDIR}/package
+ @rm -f ${CURDIR}/*.tgz
+
+.PHONY: clean install deploy
diff --git a/cleanroom-cli/conf/dcap_root_cert.pem b/cleanroom-cli/conf/dcap_root_cert.pem
new file mode 100644
index 0000000..4746925
--- /dev/null
+++ b/cleanroom-cli/conf/dcap_root_cert.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFdzCCA1+gAwIBAgIUYGJXlZ8CxlRx7P6C+oiRsZAf47UwDQYJKoZIhvcNAQEL
+BQAwSzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRQwEgYDVQQKDAtUZWFjbGF2
+ZSBDQTEZMBcGA1UEAwwQVGVhY2xhdmUgUm9vdCBDQTAeFw0yMDAyMDUxOTA5MjFa
+Fw0zMDAyMDIxOTA5MjFaMEsxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIG
+A1UECgwLVGVhY2xhdmUgQ0ExGTAXBgNVBAMMEFRlYWNsYXZlIFJvb3QgQ0EwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpwW+USb44VPeN1zW0DuVv/k7j
+FWbzxx60E3laiPk9K/EQp8L/Ma0mdPWb6O5MkY/DgeLp7UFmgTnBsTNERqAwqZrQ
+drcyyBb3akLEDuiCQWF6B+jZ8PEoSUvLPW+5QeKHvB0KHVon2Z4qNgVnVWTUk26Z
+BUvQjuJHK8GSZx9sS7Aip4s8jkqwWtio7UmRAeOOR5DFj3xZ87BzpWXi/5jD9RLx
+ScnjfR7oM3bnwpQBWyaaBiFUuxB0hZX2HoD1cvjiNshka+XtASquf9WQVj1KgBX/
+J3gUz2UYgYKO5Tr5fdtpuOs/Kbk4FBV10uCzqbSm4tR8aehpIlcADguPPgOIMkrb
+yWEtidEP5CdVETda6HnUnylOtp0Qb+EgPqzJtGlvjOmTvfAKVDTTO9w0K/NVXEMl
+xbaWm0XJgwBM5t4lh8OXw7WmPvCyKYpGfa6lw0CX4S6haMmL2OWYBwcfLSTUntii
+ENRuiBwgTPOvq+9WYMLO+NZ+ILg/j6cvbDB+7mYdsYTmF49KxvpianBRZCk5D/8Y
+/7Ty/NKJKHG0qNfwcPJcsqndiy8nzlFT31hqdDewBqgpgqqXjTJ/Zgv7iTUJ0ZN4
+T+3bo2hkoXw/nsQp+vu5wk1ErQI0G9DlolJGHNpsgYg6dkNpVgO7FEW9cNp4dZoc
+03JgOTfh6fkMD/DMbQIDAQABo1MwUTAdBgNVHQ4EFgQU761M4yztQfbaV8FFK7re
+wSRuJOAwHwYDVR0jBBgwFoAU761M4yztQfbaV8FFK7rewSRuJOAwDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAmsqK6jP3ETdkLFuVlE7HNFhQP3Sj
+LcRnrwcIX4X8Wa1Bfi81Cb6AEbE2LqX1tBd0wIeLv9AgEJr3zJLssCB/yxYhyD3i
+La6AP4lxGgckI7XWgwK7BHrDNsWzb5fdp+mn5GAJPzmIWpqIA8Us3UfC08cKhTgL
+lRp5h+u2JHjjLN83BY7poKD1hCf5lKd+a5nNHLTLkMrZOBWz3i7nho4M+9YTeIzm
+7mI/4UqJtUS/yEYw6SZlj3fVHqGHesGTW0ivPb7YLKslflRMnGlaYFK2w+beb3se
+x2L148z2aYBL846feFJ1d+Gvi3FY9W4MzLki+B/9X+aVcIv1OUhQ0v8ARw1gwAOP
+6ogYWzs1/fc3sYY/t4awZHcFDcv07UKDoCmzZ+7DHVwF76zgeYjrRq+YUO6fRpUL
+xRuFXYNylzUqyDCF4rUAB5GrtUvr+8qpHg20Eh5r/R77atOzlLFAlvMhT7TUw27C
+KzHS+OAtUSaRhZfFpDcyCBxTIcWc38K/7ZUKu6O82pudiHnJ2A5UXVqxSAzstJM4
+NEdrMdbIaMx9jiQ+/6JIyrAe1ve/BcFqpOLqEuF6vhBg9du5BdW0JaZDB0jeSFqQ
+Lok/lT48ASwddkUHrFjTst3wXRM1KbxbzSSOrvOPPg4eRhjJUqZgL0akxYZEgEg8
+7Y71NCmZxQdvPmI=
+-----END CERTIFICATE-----
diff --git a/cleanroom-cli/conf/login.conf b/cleanroom-cli/conf/login.conf
new file mode 100644
index 0000000..8a1dfc9
--- /dev/null
+++ b/cleanroom-cli/conf/login.conf
@@ -0,0 +1,4 @@
+[login]
+username =
+token =
+
diff --git a/cleanroom-cli/conf/cleanroom.conf b/cleanroom-cli/conf/cleanroom.conf
new file mode 100644
index 0000000..7661780
--- /dev/null
+++ b/cleanroom-cli/conf/cleanroom.conf
@@ -0,0 +1,10 @@
+[address]
+authentication_service = localhost:7776
+frontend_service = localhost:7777
+file_service = http://localhost:6789
+cli_service = http://localhost:7801
+
+[attestation]
+as_root_ca_cert_path = dcap_root_cert.pem
+enclave_info_path = enclave_info.toml
+
diff --git a/cleanroom-cli/install.sh b/cleanroom-cli/install.sh
new file mode 100755
index 0000000..ab91b03
--- /dev/null
+++ b/cleanroom-cli/install.sh
@@ -0,0 +1,193 @@
+#!/bin/sh
+
+set -e
+
+if [ -t 1 ]; then
+ is_tty() {
+ true
+ }
+else
+ is_tty() {
+ false
+ }
+fi
+
+cleanroomcli_dir="$HOME/.cleanroom"
+web_url="https://cli.cleanroom.com/"
+enclave_info_url="https://cli.cleanroom.com/enclave_info.toml"
+
+command_exists() {
+ command -v "$@" >/dev/null 2>&1
+}
+
+
+# Adapted from code and information by Anton Kochkov (@XVilka)
+# Source: https://gist.github.com/XVilka/8346728
+supports_truecolor() {
+ case "$COLORTERM" in
+ truecolor|24bit) return 0 ;;
+ esac
+
+ case "$TERM" in
+ iterm |\
+ tmux-truecolor |\
+ linux-truecolor |\
+ xterm-truecolor |\
+ screen-truecolor) return 0 ;;
+ esac
+
+ return 1
+}
+
+
+setup_color() {
+ # Only use colors if connected to a terminal
+ if ! is_tty; then
+ FMT_RAINBOW=""
+ FMT_RED=""
+ FMT_GREEN=""
+ FMT_YELLOW=""
+ FMT_BLUE=""
+ FMT_BOLD=""
+ FMT_RESET=""
+ return
+ fi
+
+ if supports_truecolor; then
+ FMT_RAINBOW="
+ $(printf '\033[38;2;255;0;0m')
+ $(printf '\033[38;2;255;97;0m')
+ $(printf '\033[38;2;247;255;0m')
+ $(printf '\033[38;2;0;255;30m')
+ $(printf '\033[38;2;77;0;255m')
+ $(printf '\033[38;2;168;0;255m')
+ $(printf '\033[38;2;245;0;172m')
+ "
+ else
+ FMT_RAINBOW="
+ $(printf '\033[38;5;196m')
+ $(printf '\033[38;5;202m')
+ $(printf '\033[38;5;226m')
+ $(printf '\033[38;5;082m')
+ $(printf '\033[38;5;021m')
+ $(printf '\033[38;5;093m')
+ $(printf '\033[38;5;163m')
+ "
+ fi
+
+ FMT_RED=$(printf '\033[31m')
+ FMT_GREEN=$(printf '\033[92m')
+ FMT_YELLOW=$(printf '\033[33m')
+ FMT_BLUE=$(printf '\033[34m')
+ FMT_BOLD=$(printf '\033[1m')
+ FMT_RESET=$(printf '\033[0m')
+}
+
+curl_wrapper(){
+ source="$1"
+ option="$2"
+ destination="$3"
+ rm -f "$destination"
+ curl "$source" "$option" > "$destination"
+}
+
+download_cleanroomcli() {
+ echo "${FMT_GREEN}Downloading Cleanroom CLI...${FMT_RESET}"
+ mkdir -p "$cleanroomcli_dir"
+ current_dir="$PWD"
+ arch="$(uname -m)"
+ cd "$cleanroomcli_dir"
+ OS="$(uname -s)"
+ case "${OS}" in
+ Linux*)
+ if [ "$arch" = "x86_64" ]; then
+ cli_package_name="cleanroom-cli-${OS}-${arch}.tgz"
+ else
+ echo "Not supported architecture: ${OS}-${arch}"
+ exit 1
+ fi;
+ ;;
+ Darwin*)
+ if [ "$arch" = "x86_64" ]; then
+ cli_package_name="cleanroom-cli-${OS}-${arch}.tgz"
+ elif [ "$arch" = "arm64" ]; then
+ cli_package_name="cleanroom-cli-${OS}-${arch}.tgz"
+ else
+ echo "Not supported architecture: ${OS}-${arch}"
+ exit 1
+ fi;
+ ;;
+ *)
+ echo "${FMT_YELLOW}${OS}-${arch} is not supported.${FMT_RESET}"
+ exit 1
+ esac
+ echo "$cli_package_name"
+ release_url="${web_url}${cli_package_name}"
+ curl_wrapper $release_url "--progress-bar" $cli_package_name
+ tar xf $cli_package_name
+ curl_wrapper $enclave_info_url "-s" "conf/enclave_info.toml"
+ rm -f $cli_package_name
+ cd "$current_dir"
+}
+
+matches() {
+ input="$1"
+ pattern="$2"
+ echo "$input" | grep -q "$pattern"
+}
+
+ensure_command_exists() {
+ cmd="$1"
+ if ! command_exists "${cmd}"; then
+ echo "${FMT_YELLOW}${cmd} is not installed.${FMT_RESET} Please install ${cmd} first."
+ exit 1
+ fi
+}
+
+setup_cleanroomcli() {
+ echo "${FMT_GREEN}Setting up Cleanroom CLI environments...${FMT_RESET}"
+ output=$(ps u -p $PPID)
+ parent_shell=${output##* }
+ if matches "${parent_shell}" "bash"; then
+ if ! grep -q ". $cleanroomcli_dir/env" "${HOME}"/.bashrc; then
+ echo ". $cleanroomcli_dir/env" >> "${HOME}"/.bashrc
+ fi
+ elif matches "${parent_shell}" "zsh"; then
+ if ! grep -q ". $cleanroomcli_dir/env" "${HOME}"/.zshrc; then
+ echo ". $cleanroomcli_dir/env" >> "${HOME}"/.zshrc
+ fi
+ else
+ echo "${FMT_YELLOW}${parent_shell} is not supported at the present. Please use bash or zsh.${FMT_RESET}"
+ fi
+}
+
+print_success() {
+ echo "${FMT_GREEN}Setup Cleanroom CLI successfully...${FMT_RESET}"
+ echo "To get started you may need to restart your current shell or run 'source $HOME/.cleanroom/env'"
+}
+
+check_env() {
+ if [ -z "${HOME}" ] ; then
+ echo "HOME environment var is not defined. Please set HOME var by running 'export HOME=<Cleanroom CLI install path>'"
+ exit 1
+ fi
+}
+
+main() {
+ setup_color
+
+ ensure_command_exists "tar"
+ ensure_command_exists "grep"
+ ensure_command_exists "ps"
+
+ check_env
+ download_cleanroomcli
+ if ! command_exists "cleanroom-cli"; then
+ setup_cleanroomcli
+ fi
+ print_success
+
+}
+
+
+main "$@"
diff --git a/cleanroom-cli/cleanroom-cli.py b/cleanroom-cli/cleanroom-cli.py
new file mode 100755
index 0000000..acba81b
--- /dev/null
+++ b/cleanroom-cli/cleanroom-cli.py
@@ -0,0 +1,1366 @@
+#!/usr/bin/env python3
+# PYTHON_ARGCOMPLETE_OK
+
+import argparse
+import getpass
+import sys
+import configparser
+import urllib.parse
+import uuid
+import requests
+import tempfile
+import os
+from os import path
+from urllib.parse import urljoin
+from tabulate import tabulate
+import string
+import random
+import json
+import signal
+import time
+import argcomplete
+import pathlib
+import jwt
+import inspect
+import shutil
+from datetime import timezone
+from datetime import datetime
+from packaging.version import parse as parse_version
+from typing import Tuple, Dict, List, Any
+from urllib.request import Request, urlopen
+from typing import Tuple, Dict, List, Any
+
+__version__ = "0.1.6"
+
+CURRENT_PATH = path.dirname(path.realpath(__file__))
+CURRENT_DIR = os.path.dirname(path.realpath(__file__))
+sys.path.append(path.join(CURRENT_PATH, "../sdk/python"))
+from teaclave import AuthenticationService, FrontendService, FunctionInput, FunctionOutput, FunctionArgument, OwnerList, DataMap, TeaclaveException, FunctionExpirationDate
+
+CWD = os.getcwd()
+
+if path.isdir(path.join(CWD, "conf")):
+ CONFIG_DIR = path.join(CWD, "conf")
+elif path.isdir(path.join(pathlib.Path.home(), ".cleanroom/conf")):
+ CONFIG_DIR = path.join(pathlib.Path.home(), ".cleanroom/conf")
+else:
+ print("Can not find conf files")
+ exit(1)
+
+CONFIG_FILE = path.join(CONFIG_DIR, "cleanroom.conf")
+LOGIN_CONFIG_FILE = path.join(CONFIG_DIR, "login.conf")
+TMP_OUTPUT = path.join(CWD, ".cleanroom_output.txt")
+DUMP_REPORT = False
+
+try:
+ CONFIG = configparser.ConfigParser()
+ CONFIG.read(CONFIG_FILE)
+ LOGIN_CONFIG = configparser.ConfigParser()
+ LOGIN_CONFIG.read(LOGIN_CONFIG_FILE)
+ if not CONFIG["address"]["authentication_service"]:
+ raise Exception("authentication_service address is empty")
+
+ if not CONFIG["address"]["frontend_service"]:
+ raise Exception("authentication_service address is empty")
+
+ if not CONFIG["address"]["file_service"]:
+ raise Exception("file_service address is empty")
+
+ if not CONFIG["address"]["cli_service"]:
+ raise Exception("cli_service address is empty")
+
+ if not CONFIG["attestation"]["as_root_ca_cert_path"]:
+ raise Exception("as_root_ca_cert_path is empty")
+
+ if not CONFIG["attestation"]["enclave_info_path"]:
+ raise Exception("enclave_info_path is empty")
+
+ AS_ROOT_CA_CERT_PATH = path.join(
+ CONFIG_DIR, CONFIG["attestation"]["as_root_ca_cert_path"])
+ ENCLAVE_INFO_PATH = path.join(CONFIG_DIR,
+ CONFIG["attestation"]["enclave_info_path"])
+
+except Exception as e:
+ TeaclaveException(f"Failed to read the config file {CONFIG_FILE}: {e}")
+
+FILE_SERVICE_AUTH_HEADERS = {
+ "Authorization":
+ "Basic 001dda666e88921cfa9cecd5935d387b17b16c70022fe119ce69dee0ec84e3d9"
+}
+
+
+def cleanroom_info(info, end='\n'):
+ print('\033[92m' + info + '\033[0m', end=end, flush=True)
+
+
+def cleanroom_warn(warn, end='\n'):
+ print('\033[91m' + warn + '\033[0m', end=end, flush=True)
+
+
+class CleanroomException(TeaclaveException):
+ _cleanroom_error = dict()
+ _cleanroom_error[0] = ('Invalid funtion ID',
+ 'Please run list-functions again')
+ _cleanroom_error[1] = ('Cannot access file services',
+ 'Please check your Internet Connection')
+ _cleanroom_error[2] = ('File not found',
+ 'Please check the location of your input data')
+ _cleanroom_error[3] = ('Service is under maintanance',
+ 'Please wait and try later')
+ _cleanroom_error[4] = ('Invalid input', 'Please enter a valid input')
+ _cleanroom_error[5] = (
+ 'Invalid date format',
+ 'Please enter a valid date. Format: month/day/year. e.g., 03/01/2021')
+
+ def __init__(self, error_code: int, msg=''):
+ frame, filename, line_number, function_name, lines, index = inspect.stack(
+ )[1]
+ self.function_name = function_name
+ self.error_code = error_code
+ self.message = msg
+
+ def __str__(self):
+ CRED = '\033[91m'
+ CEND = '\033[0m'
+ if (self.error_code) in CleanroomException._cleanroom_error:
+ error = CleanroomException._cleanroom_error[self.error_code][0]
+ action = CleanroomException._cleanroom_error[self.error_code][1]
+ return '\n' + CRED + ('Error: {}. Action: {}. {}'.format(
+ error, action, self.message)) + CEND
+ return str(self.message)
+
+
+def get_role(config):
+ if config['login']['token'] == "":
+ return "NotLogin"
+ try:
+ claims = jwt.decode(config['login']['token'],
+ options={"verify_signature": False})
+ role = claims['role'].split("-")[0]
+ return role
+ except Exception as e:
+ return "Unknown"
+
+
+def parse_hostport(hp):
+ result = urllib.parse.urlsplit('//' + hp)
+ return result.hostname, result.port
+
+
+def shorten_uuid(fun_uuids):
+ default_length = 8
+ fun_ids = [uuid[-default_length:] for uuid in fun_uuids]
+ fun_ids_set = set(fun_ids)
+ if len(fun_ids_set) != len(fun_uuids):
+ default_length = default_length + 1
+ fun_ids = [uuid[-default_length:] for uuid in fun_uuids]
+ fun_ids_set = set(fun_ids)
+ return fun_ids
+
+
+def uid_to_id(fun_uid):
+ username = LOGIN_CONFIG['login']['username']
+ with connect_frontend_service() as client:
+ functions = client.list_functions(username)
+ fun_uuids = functions['registered_functions'] + functions[
+ 'allowed_functions']
+ fun_ids = shorten_uuid(fun_uuids)
+ for i, uuid in enumerate(fun_uuids):
+ if uuid == fun_uid:
+ return fun_ids[i]
+ raise CleanroomException(0)
+
+
+def id_to_uuid(fun_id):
+ username = LOGIN_CONFIG['login']['username']
+ with connect_frontend_service() as client:
+ functions = client.list_functions(username)
+ fun_uuids = functions['registered_functions'] + functions[
+ 'allowed_functions']
+ fun_ids = shorten_uuid(fun_uuids)
+ for i, v_id in enumerate(fun_ids):
+ if v_id == fun_id:
+ return fun_uuids[i]
+ raise CleanroomException(0)
+
+
+def yes_or_no(question):
+ cleanroom_info(f'{question} ? (y/n): ')
+ ans = input().strip().lower()
+ if ans not in ['y', 'n']:
+ print(f'{ans} is invalid, please try again...')
+ return yes_or_no(question)
+ if ans == 'y':
+ return True
+ return False
+
+
+def get_algorithm2_hash_time(beamsize, sequence_length) -> float:
+ a = 0.266
+ b = 0.193
+ if sequence_length < beamsize:
+ beamsize = sequence_length
+ return a * beamsize + b * sequence_length
+
+
+def connect_authentication_service():
+ address = parse_hostport(CONFIG["address"]["authentication_service"])
+ if DUMP_REPORT:
+ dump_report = path.join(CWD, "report")
+ if not path.isdir(dump_report):
+ os.mkdir(dump_report)
+ else:
+ dump_report = None
+ client = AuthenticationService(
+ address,
+ AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH,
+ dump_report,
+ ).connect()
+ client.metadata = {"cli-version": __version__}
+
+ return client
+
+
+def connect_frontend_service():
+ address = parse_hostport(CONFIG["address"]["frontend_service"])
+ if DUMP_REPORT:
+ dump_report = path.join(CWD, "report")
+ if not path.isdir(dump_report):
+ os.mkdir(dump_report)
+ else:
+ dump_report = None
+ client = FrontendService(
+ address,
+ AS_ROOT_CA_CERT_PATH,
+ ENCLAVE_INFO_PATH,
+ dump_report,
+ ).connect()
+ client.metadata = {
+ "id": LOGIN_CONFIG['login']['username'],
+ "token": LOGIN_CONFIG['login']['token'],
+ "cli-version": __version__
+ }
+ return client
+
+
+def login(args):
+ if not args.username:
+ args.username = input("Username: ")
+ if not args.password:
+ args.password = getpass.getpass()
+ with connect_authentication_service() as client:
+ token = client.user_login(args.username, args.password)
+ LOGIN_CONFIG['login']['username'] = args.username
+ LOGIN_CONFIG['login']['token'] = token
+ with open(LOGIN_CONFIG_FILE, 'w') as f:
+ LOGIN_CONFIG.write(f)
+ cleanroom_info(f"Login successfully")
+
+
+def change_password(args):
+ with connect_authentication_service() as client:
+ client.metadata.update({
+ "id": LOGIN_CONFIG['login']['username'],
+ "token": LOGIN_CONFIG['login']['token']
+ })
+ client.user_change_password(args.password)
+ logout(None)
+ cleanroom_info(f"Password change successfully, login you new password.")
+
+
+def logout(args):
+ LOGIN_CONFIG['login']['username'] = ""
+ LOGIN_CONFIG['login']['token'] = ""
+ with open(LOGIN_CONFIG_FILE, 'w') as f:
+ LOGIN_CONFIG.write(f)
+ cleanroom_info(f"Logout successfully")
+
+
+def update_shell_profile(shell_path):
+ shell_content = []
+ if path.isfile(shell_path):
+ with open(shell_path) as f:
+ shell_content = f.readlines()
+ origin_lines = len(shell_content)
+ shell_content = [
+ line for line in shell_content if ".cleanroom/env" not in line
+ ]
+ current_lines = len(shell_content)
+ if origin_lines != current_lines:
+ try:
+ temp_file = tempfile.NamedTemporaryFile(
+ delete=False,
+ dir=path.join(pathlib.Path.home(), ".cleanroom"))
+ with open(temp_file.name, 'w') as f:
+ for line in shell_content:
+ f.write(line)
+ f.flush()
+ os.replace(temp_file.name, shell_path)
+ except Exception as e:
+ if os.path.exists(temp_file.name):
+ try:
+ os.unlink(temp_file.name)
+ except:
+ pass
+
+
+def uninstall(args):
+ bashrc_path = path.join(pathlib.Path.home(), ".bashrc")
+ zshrc_path = path.join(pathlib.Path.home(), ".zshrc")
+ update_shell_profile(bashrc_path)
+ update_shell_profile(zshrc_path)
+ cleanroomcli_path = path.join(pathlib.Path.home(), ".cleanroom")
+ if path.isdir(cleanroomcli_path):
+ shutil.rmtree(cleanroomcli_path, ignore_errors=True)
+ else:
+ cleanroom_info(f"Cannot find the install directory")
+ exit(1)
+ cleanroom_info(f"Uninstall successfully, please restart your shell.")
+
+
+def register_user(args):
+ with connect_authentication_service() as client:
+ client.metadata.update({
+ "id": LOGIN_CONFIG['login']['username'],
+ "token": LOGIN_CONFIG['login']['token']
+ })
+ if args.role:
+ role = args.role
+ else:
+ role = "DataOwner"
+ if args.attribute:
+ attribute = args.attribute
+ else:
+ if args.role == "DataOwnerManager":
+ attribute = args.username
+ else:
+ attribute = LOGIN_CONFIG['login']['username']
+ client.user_register(args.username, args.password, role, attribute)
+ cleanroom_info(f"Register user successfully: {args.username}")
+
+
+def list_users(_args):
+ user_list = []
+ with connect_authentication_service() as client:
+ client.metadata.update({
+ "id": LOGIN_CONFIG['login']['username'],
+ "token": LOGIN_CONFIG['login']['token']
+ })
+ user_list = client.list_users(LOGIN_CONFIG['login']['username'])
+
+ cleanroom_info("List users successfully, managed users: " +
+ ", ".join(user_list))
+
+
+def register_cpk(args):
+ with connect_frontend_service() as client:
+ with open(args.cpk, "rb") as f:
+ payload = f.read()
+ if args.diagnosis:
+ outputs = [
+ FunctionOutput("output_file", "Output data"),
+ FunctionOutput("log_file", "Log")
+ ]
+ else:
+ outputs = [
+ FunctionOutput("output_file", "Output data"),
+ ]
+ if args.q:
+ usage_quota = args.q
+ else:
+ usage_quota = -1
+ if args.a:
+ function_arg = FunctionArgument("args", args.a, False)
+ else:
+ function_arg = FunctionArgument("args")
+ function_debug = FunctionArgument("debug")
+ function_id = client.register_function(
+ name=args.name,
+ description=args.description,
+ payload=list(payload),
+ executor_type="cleanroom",
+ arguments=[function_arg, function_debug],
+ inputs=[FunctionInput("input_file", "Input data")],
+ outputs=outputs,
+ user_allowlist=args.user_allowlist,
+ usage_quota=usage_quota)
+ cleanroom_info(f"Register CPK successfully: {function_id}")
+
+
+def register_native(args):
+ with connect_frontend_service() as client:
+ payload = b"not empty"
+ if args.diagnosis:
+ outputs = [
+ FunctionOutput("output_file", "Output data"),
+ FunctionOutput("log_file", "Log")
+ ]
+ else:
+ outputs = [
+ FunctionOutput("output_file", "Output data"),
+ ]
+
+ if args.q:
+ usage_quota = args.q
+ else:
+ usage_quota = -1
+ if args.a:
+ function_arg = FunctionArgument("args", args.a, False)
+ else:
+ function_arg = FunctionArgument("args")
+ function_debug = FunctionArgument("debug")
+ if args.expired:
+ try:
+ date = datetime.strptime(args.expired, "%m/%d/%Y")
+ utc_time = date.replace(tzinfo=timezone.utc)
+ utc_timestamp = utc_time.timestamp()
+ except Exception as e:
+ raise CleanroomException(5)
+ expired_date = FunctionExpirationDate(expired=True,
+ seconds=int(utc_timestamp),
+ nanos=0)
+ else:
+ expired_date = FunctionExpirationDate()
+ function_id = client.register_function(
+ name=args.name,
+ description=args.description,
+ payload=list(payload),
+ executor_type="builtin",
+ arguments=[function_arg, function_debug],
+ inputs=[
+ FunctionInput("input_file", "Input data"),
+ FunctionInput("./coding_wheel.txt", "Coding wheel"),
+ FunctionInput("./codon_usage_freq_table_human.csv",
+ "Codon usage freq table human"),
+ ],
+ outputs=outputs,
+ user_allowlist=args.user_allowlist,
+ usage_quota=usage_quota,
+ expiration_date=expired_date)
+ cleanroom_info(f"Register native function successfully: {function_id}")
+
+
+class CryptoInfo:
+
+ def __init__(self):
+ self.key = os.urandom(16)
+ self.iv = os.urandom(12)
+ self.cmac = None
+
+
+class CryptoInfo:
+
+ def __init__(self):
+ self.key = os.urandom(16)
+ self.iv = os.urandom(12)
+ self.cmac = None
+
+
+def gen_key():
+ return CryptoInfo()
+
+
+def gen_password():
+ all = string.ascii_letters + string.digits
+ return "".join(random.sample(all, 8))
+
+
+CURRENT_RUNNING_TASK_ID = None
+
+
+def signal_handler(sig, frame):
+ with connect_frontend_service() as client:
+ if not CURRENT_RUNNING_TASK_ID:
+ cleanroom_info(f"Ctrl+C pressed. Canceled.")
+ sys.exit(1)
+ else:
+ cleanroom_info(
+ f"Ctrl+C pressed. Canceling task {CURRENT_RUNNING_TASK_ID}")
+
+ try:
+ client.cancel_task(CURRENT_RUNNING_TASK_ID)
+ time.sleep(3)
+ # cancel twice to make sure the task is canceled
+ client.cancel_task(CURRENT_RUNNING_TASK_ID)
+ except:
+ pass
+ sys.exit(0)
+
+
+def get_task_time(task_id, input_length, args):
+ with connect_frontend_service() as client:
+ task_info = client.get_task(task_id)
+ function_id = task_info['function_id']
+ function_info = client.get_function(function_id)
+ total_time = 0
+ if function_info[
+ 'name'] == 'builtin-cleanroom-algorithm2-hash-trial-tier2':
+ default_beam_size = [10, 100, 500, 1000]
+ default_lambda = [0.2, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 7.0, 10.0]
+ ratio = len(default_lambda)
+ for beam in default_beam_size:
+ task_time = get_algorithm2_hash_time(beam, input_length)
+ total_time = total_time + ratio * task_time
+ if total_time > 3600.0:
+ hours = total_time / 3600.0
+ if not args.silent:
+ cleanroom_info(
+ f'Estimating the execution time: {round(hours, 1)} hours...')
+ cleanroom_info(
+ 'Please keep the process running and networking available during the execution.'
+ )
+ if yes_or_no('Continue submitting the task') == False:
+ exit(1)
+ elif total_time > 60:
+ minutes = total_time / 60.0
+ if not args.silent:
+ cleanroom_info(
+ f'Estimating the execution time: {round(minutes, 1)} minutes...'
+ )
+ cleanroom_info(
+ 'Please keep the process running and networking available during the execution.'
+ )
+ if yes_or_no('Continue submitting the task') == False:
+ exit(1)
+ else:
+ return
+
+
+def run(args):
+ start = time.time()
+ signal.signal(signal.SIGINT, signal_handler)
+ native = False
+ function_uuid = id_to_uuid(args.function_id)
+ with connect_frontend_service() as client:
+ f = client.get_function(function_uuid)
+ if "builtin" in f["executor_type"]: native = True
+ get_function_usage_stats(args)
+ if native:
+ result = run_native(args)
+ else:
+ result = run_cpk(args)
+ end = time.time()
+ elapsed = end - start
+ result = json.loads(result)
+ execution = result["execution_time"]
+ queueing = elapsed - execution
+ cleanroom_info(
+ f"Total Time: {elapsed:.2f}s ({queueing:.2f}s queueing, {execution:.2f}s running)"
+ )
+
+ if result["status"] == True:
+ cleanroom_info("Task succeeded!")
+ else:
+ cleanroom_info(f"Task failed. {result['reason']}")
+ if args.output_file != None:
+ cleanroom_info(f"Output file: {args.output_file}")
+ else:
+ with open(TMP_OUTPUT) as f:
+ print(f.read(), end='')
+ os.unlink(TMP_OUTPUT)
+
+
+def upload_register_input_file(client, file_path):
+ input_crypto = gen_key()
+ if not file_path:
+ input_data_id = client.register_input_file("placeholder://",
+ "aes-gcm-128",
+ list(input_crypto.key),
+ list(input_crypto.iv),
+ [0] * 16)
+ return input_data_id
+
+ if not path.exists(file_path):
+ raise CleanroomException(2, f"File not found: {file_path}")
+
+ internal_file_service_url = "http://teaclave-file-service:6789/"
+ file_service_url = CONFIG['address']['file_service']
+ with tempfile.TemporaryDirectory() as dirpath:
+ encrypted_input_file = str(uuid.uuid1())
+ input_file_path = path.join(dirpath, encrypted_input_file)
+ input_crypto = encrypt(file_path, input_file_path, input_crypto)
+ url = urljoin(file_service_url, encrypted_input_file)
+ try:
+ x = requests.put(url,
+ data=open(input_file_path, 'rb'),
+ headers=FILE_SERVICE_AUTH_HEADERS)
+ if x.status_code != 200:
+ raise CleanroomException(1, "Cannot access file service")
+ except:
+ raise CleanroomException(1, "Cannot access file service")
+
+ schema = "aes-gcm-128"
+ url = urljoin(internal_file_service_url, encrypted_input_file)
+ input_data_id = client.register_input_file(url, schema,
+ list(input_crypto.key),
+ list(input_crypto.iv),
+ list(input_crypto.cmac))
+ return input_data_id
+
+
+def run_native(args):
+ if not args.arguments:
+ arguments = []
+ elif len(args.arguments) > 1 and args.arguments[0] == "--":
+ arguments = args.arguments[1:]
+ else:
+ raise Exception("Cannot parse arguments")
+
+ output_crypto = gen_key()
+ diagnosis_crypto = gen_key()
+ file_service_url = CONFIG['address']['file_service']
+ internal_file_service_url = "http://teaclave-file-service:6789/"
+
+ username = [LOGIN_CONFIG['login']['username']]
+ with connect_frontend_service() as client:
+ if args.diagnosis:
+ outputs_ownership = [
+ OwnerList("output_file", username),
+ OwnerList("log_file", username)
+ ]
+ debug = "true"
+ else:
+ outputs_ownership = [
+ OwnerList("output_file", username),
+ ]
+ debug = "false"
+ argument_list = ["cleanroom"]
+ argument_list.extend(arguments)
+ arguments = json.dumps(argument_list)
+ function_uuid = id_to_uuid(args.function_id)
+ task_id = client.create_task(
+ function_id=function_uuid,
+ function_arguments=({
+ "args": arguments,
+ "debug": debug
+ }),
+ executor="builtin",
+ inputs_ownership=[
+ OwnerList("input_file", username),
+ OwnerList("./coding_wheel.txt", username),
+ OwnerList("./codon_usage_freq_table_human.csv", username),
+ ],
+ outputs_ownership=outputs_ownership)
+
+ if args.input_file != None:
+ input_data_id = upload_register_input_file(client, args.input_file)
+ with open(args.input_file) as f:
+ data = f.readlines()
+ if len(data) > 0:
+ input_length = len(data[0])
+ else:
+ input_length = 0
+ else:
+ cleanroom_info(
+ 'If the input sequence is longer than 1024, please use the option -i=<input file path>'
+ )
+ cleanroom_info('Please enter a valid input: ', end='')
+ sequence = input()
+ if sequence.strip() == '':
+ raise CleanroomException(4)
+ input_length = len(sequence)
+ plain_input_file = str(uuid.uuid1())
+ with tempfile.TemporaryDirectory() as dirpath:
+ plain_input_file = str(uuid.uuid1())
+ input_data_file = path.join(dirpath, plain_input_file)
+ with open(input_data_file, "w") as f:
+ f.write(sequence)
+ input_data_id = upload_register_input_file(
+ client, input_data_file)
+
+ coding_whell_data_id = upload_register_input_file(
+ client, args.coding_wheel)
+ codon_data_id = upload_register_input_file(client,
+ args.codon_usage_freq_table)
+ cleanroom_info(f"Creating task with input... done")
+ encrypted_output_file = str(uuid.uuid1())
+
+ schema = "aes-gcm-128"
+ url = urljoin(internal_file_service_url, encrypted_output_file)
+ output_data_id = client.register_output_file(url, schema,
+ list(output_crypto.key),
+ list(output_crypto.iv))
+
+ if args.diagnosis:
+ encrypted_diagnosis_file = str(uuid.uuid1())
+ url = urljoin(internal_file_service_url, encrypted_diagnosis_file)
+ diagnosis_data_id = client.register_output_file(
+ url, schema, list(diagnosis_crypto.key),
+ list(diagnosis_crypto.iv))
+ client.assign_data_to_task(task_id, [
+ DataMap("input_file", input_data_id),
+ DataMap("./coding_wheel.txt", coding_whell_data_id),
+ DataMap("./codon_usage_freq_table_human.csv", codon_data_id),
+ ], [
+ DataMap("output_file", output_data_id),
+ DataMap("log_file", diagnosis_data_id)
+ ])
+ else:
+ client.assign_data_to_task(task_id, [
+ DataMap("input_file", input_data_id),
+ DataMap("./coding_wheel.txt", coding_whell_data_id),
+ DataMap("./codon_usage_freq_table_human.csv", codon_data_id),
+ ], [DataMap("output_file", output_data_id)])
+
+ global CURRENT_RUNNING_TASK_ID
+ CURRENT_RUNNING_TASK_ID = task_id
+ get_task_time(task_id, input_length, args)
+ cleanroom_info("Invoking task...", end=" ")
+ client.invoke_task(task_id)
+ cleanroom_info(f"done")
+ cleanroom_info("Getting result...", end=" ")
+ attempt = 0
+ while True:
+ try:
+ result = client.get_task_result(task_id)
+ break
+ except socket.error:
+ attempt = attempt + 1
+ if attempt < 3:
+ cleanroom_warn('Networking failure. Reconnecting...')
+ continue
+ else:
+ raise TeaclaveException(0)
+ cleanroom_info(f"done")
+ result = ''.join([chr(c) for c in result])
+
+ with tempfile.TemporaryDirectory() as dirpath:
+ output_file_path = path.join(dirpath, encrypted_output_file)
+ url = urljoin(file_service_url, encrypted_output_file)
+ x = requests.get(url, headers=FILE_SERVICE_AUTH_HEADERS)
+ if x.status_code != 200:
+ raise CleanroomException(1, "Cannot access file service")
+ with open(output_file_path, "wb") as f:
+ f.write(x.content)
+ if args.output_file != None:
+ decrypt(output_file_path, args.output_file, output_crypto)
+ else:
+ decrypt(output_file_path, TMP_OUTPUT, output_crypto)
+
+ if args.diagnosis:
+ with tempfile.TemporaryDirectory() as dirpath:
+ output_file_path = path.join(dirpath, encrypted_diagnosis_file)
+ url = urljoin(file_service_url, encrypted_diagnosis_file)
+ x = requests.get(url, headers=FILE_SERVICE_AUTH_HEADERS)
+ if x.status_code != 200:
+ raise CleanroomException(1, "Cannot access file service")
+ with open(output_file_path, "wb") as f:
+ f.write(x.content)
+ diagnosis_file_path = "diagnosis.txt"
+ decrypt(output_file_path, "diagnosis.txt", diagnosis_crypto)
+ cleanroom_info(f"Diagnosis file: {diagnosis_file_path}")
+
+ return result
+
+
+def run_cpk(args):
+ if not args.arguments:
+ arguments = []
+ elif args.arguments[0] == "--":
+ arguments = args.arguments[1:]
+ else:
+ raise Exception("Cannot parse arguments")
+
+ input_crypto = gen_key()
+ output_crypto = gen_key()
+ diagnosis_crypto = gen_key()
+ file_service_url = CONFIG['address']['file_service']
+ internal_file_service_url = "http://teaclave-file-service:6789/"
+
+ username = [LOGIN_CONFIG['login']['username']]
+ with connect_frontend_service() as client:
+ if args.diagnosis:
+ outputs_ownership = [
+ OwnerList("output_file", username),
+ OwnerList("log_file", username)
+ ]
+ debug = "true"
+ else:
+ outputs_ownership = [
+ OwnerList("output_file", username),
+ ]
+ debug = "false"
+ argument_list = ["cleanroom"]
+ argument_list.extend(arguments)
+ arguments = json.dumps(argument_list)
+
+ function_uuid = id_to_uuid(args.function_id)
+ task_id = client.create_task(
+ function_id=function_uuid,
+ function_arguments=({
+ "args": arguments,
+ "debug": debug
+ }),
+ executor="cleanroom",
+ inputs_ownership=[OwnerList("input_file", username)],
+ outputs_ownership=outputs_ownership)
+ with tempfile.TemporaryDirectory() as dirpath:
+ encrypted_input_file = str(uuid.uuid1())
+ input_file_path = path.join(dirpath, encrypted_input_file)
+ input_data_file = ""
+ if args.input_file != None:
+ input_data_file = args.input_file
+ else:
+ cleanroom_info('Please enter a valid input: ', end='')
+ sequence = input()
+ if sequence.strip() == '':
+ raise CleanroomException(4)
+ plain_input_file = str(uuid.uuid1())
+ input_data_file = path.join(dirpath, plain_input_file)
+ with open(input_data_file, "w") as f:
+ f.write(sequence)
+ input_crypto = encrypt(input_data_file, input_file_path,
+ input_crypto)
+ url = urljoin(file_service_url, encrypted_input_file)
+ try:
+ x = requests.put(url,
+ data=open(input_file_path, 'rb'),
+ headers=FILE_SERVICE_AUTH_HEADERS)
+ if x.status_code != 200:
+ raise CleanroomException(1, "Cannot access file service")
+ except:
+ raise CleanroomException(1, "Cannot access file service")
+
+ schema = "aes-gcm-128"
+ url = urljoin(internal_file_service_url, encrypted_input_file)
+ input_data_id = client.register_input_file(url, schema,
+ list(input_crypto.key),
+ list(input_crypto.iv),
+ list(input_crypto.cmac))
+
+ encrypted_output_file = str(uuid.uuid1())
+
+ schema = "aes-gcm-128"
+ url = urljoin(internal_file_service_url, encrypted_output_file)
+ output_data_id = client.register_output_file(url, schema,
+ list(output_crypto.key),
+ list(output_crypto.iv))
+
+ if args.diagnosis:
+ encrypted_diagnosis_file = str(uuid.uuid1())
+ url = urljoin(internal_file_service_url, encrypted_diagnosis_file)
+ diagnosis_data_id = client.register_output_file(
+ url, schema, list(diagnosis_crypto.key),
+ list(diagnosis_crypto.iv))
+ client.assign_data_to_task(
+ task_id, [DataMap("input_file", input_data_id)], [
+ DataMap("output_file", output_data_id),
+ DataMap("log_file", diagnosis_data_id)
+ ])
+ else:
+ client.assign_data_to_task(
+ task_id, [DataMap("input_file", input_data_id)],
+ [DataMap("output_file", output_data_id)])
+ global CURRENT_RUNNING_TASK_ID
+ CURRENT_RUNNING_TASK_ID = task_id
+ cleanroom_info("Invoking task...", end=" ")
+ client.invoke_task(task_id)
+ cleanroom_info(f"done")
+ cleanroom_info("Getting result...", end=" ")
+ result = client.get_task_result(task_id)
+ cleanroom_info(f"done")
+ result = ''.join([chr(c) for c in result])
+
+ with tempfile.TemporaryDirectory() as dirpath:
+ output_file_path = path.join(dirpath, encrypted_output_file)
+ url = urljoin(file_service_url, encrypted_output_file)
+ x = requests.get(url, headers=FILE_SERVICE_AUTH_HEADERS)
+ if x.status_code != 200:
+ raise CleanroomException(1, "Cannot access file service")
+ with open(output_file_path, "wb") as f:
+ f.write(x.content)
+ if args.output_file != None:
+ decrypt(output_file_path, args.output_file, output_crypto)
+ else:
+ decrypt(output_file_path, TMP_OUTPUT, output_crypto)
+
+ if args.diagnosis:
+ with tempfile.TemporaryDirectory() as dirpath:
+ output_file_path = path.join(dirpath, encrypted_diagnosis_file)
+ url = urljoin(file_service_url, encrypted_diagnosis_file)
+ x = requests.get(url, headers=FILE_SERVICE_AUTH_HEADERS)
+ if x.status_code != 200:
+ raise CleanroomException(1, "Cannot access file service")
+ with open(output_file_path, "wb") as f:
+ f.write(x.content)
+ diagnosis_file_path = "diagnosis.txt"
+ decrypt(output_file_path, "diagnosis.txt", diagnosis_crypto)
+ cleanroom_info(f"Diagnosis file: {diagnosis_file_path}")
+
+ return result
+
+
+def list_functions(args):
+
+ def print_function_table(functions, title, extra=False):
+ if not functions: return
+ table = []
+ fun_ids = shorten_uuid(functions)
+ for i, function_id in enumerate(functions):
+ f = client.get_function(function_id)
+ description = f['description'][:75] + (f['description'][75:]
+ and '..')
+ if extra:
+ headers = [
+ "Function ID", "Owner", "Allowed User Groups",
+ "Description"
+ ]
+ entry = [
+ fun_ids[i], f['owner'], ",".join(f['user_allowlist']),
+ f['description'].replace(';', '\n')
+ ]
+ else:
+ headers = ["Function ID", "Description"]
+ entry = [fun_ids[i], f['description'].replace(';', '\n')]
+ table.append(entry)
+
+ print()
+ cleanroom_info("=== " + title + " ===")
+ print()
+ cleanroom_info(tabulate(table, headers=headers, showindex="always"))
+
+ username = LOGIN_CONFIG['login']['username']
+ with connect_frontend_service() as client:
+ functions = client.list_functions(username)
+ print_function_table(functions['registered_functions'],
+ "Registered Functions",
+ extra=True)
+ print_function_table(functions['allowed_functions'],
+ "Allowed Functions")
+
+
+def get_function_usage_stats(args):
+ username = LOGIN_CONFIG['login']['username']
+ function_uuid = id_to_uuid(args.function_id)
+ with connect_frontend_service() as client:
+ function_usage = client.get_function_usage_stats(
+ username, function_uuid)
+ function_quota = function_usage['function_quota']
+ current_usage = function_usage['current_usage']
+ if (function_quota > 0):
+ cleanroom_info(
+ 'Max invocation times: {function_quota}. Current invocation times: {current_usage}.'
+ .format(function_quota=function_quota,
+ current_usage=current_usage))
+ else:
+ cleanroom_info(
+ f'Max invocation times: inf. Current invocation times: {current_usage}.'
+ )
+
+
+def reset_user_password(args):
+ with connect_authentication_service() as client:
+ client.metadata.update({
+ "id": LOGIN_CONFIG['login']['username'],
+ "token": LOGIN_CONFIG['login']['token']
+ })
+ password = client.reset_user_password(args.username)
+ cleanroom_info(
+ f"Password reset successfully. New password: {password}")
+
+
+def delete_user(args):
+ with connect_authentication_service() as client:
+ client.metadata.update({
+ "id": LOGIN_CONFIG['login']['username'],
+ "token": LOGIN_CONFIG['login']['token']
+ })
+ client.delete_user(args.username)
+ cleanroom_info(f"User delete successfully.")
+
+
+def delete_function(args):
+ with connect_frontend_service() as client:
+ function_uuid = id_to_uuid(args.function)
+ client.disable_function(function_uuid)
+ print(f"Function delete successfully.")
+
+
+def upgrade_cli(args):
+ req = Request(urljoin(CONFIG["address"]["cli_service"], "version"),
+ headers={'User-Agent': 'Mozilla/5.0'})
+ install_scripts_url = urljoin(CONFIG["address"]["cli_service"],
+ "install.sh")
+ cmd = 'sh -c "$(curl -kfsSL {url})"'.format(url=install_scripts_url)
+ try:
+ version = urlopen(req).read().decode('utf-8')
+ except:
+ raise CleanroomException(3)
+ if parse_version(version) > parse_version(__version__):
+ cleanroom_info(
+ "Current version: {v}.".format(v=parse_version(__version__)))
+ cleanroom_info("Latest version: {v}.".format(v=parse_version(version)))
+ cleanroom_info("Upgrading...")
+ os.system(cmd)
+ else:
+ cleanroom_info("Current version: {v} is the latest.".format(
+ v=parse_version(__version__)))
+
+
+def update_enclave_info(args):
+ req = Request(urljoin(CONFIG["address"]["cli_service"],
+ "enclave_info.toml"),
+ headers={'User-Agent': 'Mozilla/5.0'})
+ try:
+ enclave_info = urlopen(req).read()
+ except:
+ raise CleanroomException(3)
+ cleanroom_info("Updating ceritficates from: " + req.full_url)
+ with open(ENCLAVE_INFO_PATH, "wb") as f:
+ f.write(enclave_info)
+
+
+def parse_register_cpk(parser):
+ parser_register_cpk = parser.add_parser('register-cpk',
+ help='register CPK')
+ parser_register_cpk.add_argument('-c',
+ '--cpk',
+ type=str,
+ required=True,
+ help='CPK file path')
+ parser_register_cpk.add_argument('-n',
+ '--name',
+ default="function name",
+ type=str,
+ help='function name')
+ parser_register_cpk.add_argument('-d',
+ '--description',
+ default="fucntion description",
+ type=str,
+ help='function description')
+ parser_register_cpk.add_argument('-a',
+ required=False,
+ type=str,
+ help='function arguments')
+ parser_register_cpk.add_argument('-q',
+ required=False,
+ default=-1,
+ type=int,
+ help='function available quota')
+ parser_register_cpk.add_argument(
+ '-u',
+ '--user-allowlist',
+ nargs='+',
+ required=True,
+ default="A list of data owner managers can use this function",
+ type=str,
+ help='CPK file path')
+ parser_register_cpk.add_argument('--diagnosis',
+ action='store_true',
+ help='enable diagnosis mode')
+ parser_register_cpk.set_defaults(func=register_cpk)
+
+
+def parse_register_native(parser):
+ parser_register_native = parser.add_parser('register-native',
+ help='register native function')
+ parser_register_native.add_argument('-n',
+ '--name',
+ default="function name",
+ type=str,
+ help='function name')
+ parser_register_native.add_argument('-d',
+ '--description',
+ default="fucntion description",
+ type=str,
+ help='function description')
+ parser_register_native.add_argument('-a',
+ required=False,
+ type=str,
+ help='function argument')
+ parser_register_native.add_argument('-q',
+ default=-1,
+ required=False,
+ type=int,
+ help='function available quota')
+ parser_register_native.add_argument(
+ '-e',
+ '--expired',
+ required=False,
+ type=str,
+ help='function expired-date. format: month/day/year')
+ parser_register_native.add_argument(
+ '-u',
+ '--user-allowlist',
+ nargs='+',
+ required=True,
+ default="A list of data owner managers can use this function",
+ type=str,
+ help='CPK file path')
+ parser_register_native.add_argument('--diagnosis',
+ action='store_true',
+ help='enable diagnosis mode')
+ parser_register_native.set_defaults(func=register_native)
+
+
+def parse_run(parser):
+ parser_run = parser.add_parser('run', help='run cleanroom function')
+ parser_run.add_argument('-f',
+ '--function-id',
+ required=True,
+ type=str,
+ help='function ID')
+ parser_run.add_argument('-i',
+ '--input-file',
+ type=str,
+ help='input file path')
+ parser_run.add_argument('-o',
+ '--output-file',
+ type=str,
+ help='output file path')
+ parser_run.add_argument('--coding-wheel',
+ type=str,
+ help='coding wheel file path')
+ parser_run.add_argument('--codon-usage-freq-table',
+ type=str,
+ help='codon usage freq table')
+ parser_run.add_argument('--diagnosis',
+ action='store_true',
+ help='enable diagnosis mode')
+ parser_run.add_argument('--silent',
+ action='store_true',
+ help='silence mode')
+ parser_run.add_argument('arguments',
+ nargs=argparse.REMAINDER,
+ help='arguments of the function')
+ parser_run.set_defaults(func=run)
+
+
+def parse_register_user(parser):
+ parser_register_user = parser.add_parser('register-user',
+ help='register a new user')
+ parser_register_user.add_argument('-u',
+ '--username',
+ type=str,
+ required=True,
+ help='username')
+ parser_register_user.add_argument('-p',
+ '--password',
+ required=True,
+ type=str,
+ help='password')
+ parser_register_user.add_argument('-r', '--role', type=str, help='Role')
+ parser_register_user.add_argument('-a',
+ '--attribute',
+ type=str,
+ help='Attribute')
+ parser_register_user.set_defaults(func=register_user)
+
+
+def parse_login(parser):
+ parser_login = parser.add_parser('login', help='login')
+ parser_login.add_argument(
+ '-u',
+ '--username',
+ type=str,
+ required=False,
+ help='username, request interactively if not set')
+ parser_login.add_argument(
+ '-p',
+ '--password',
+ required=False,
+ type=str,
+ help='password, request interactively if not set')
+ parser_login.set_defaults(func=login)
+
+
+def parse_change_password(parser):
+ parser_change_password = parser.add_parser('change-password',
+ help='change current password')
+ parser_change_password.add_argument('-p',
+ '--password',
+ type=str,
+ required=True,
+ help='password')
+ parser_change_password.set_defaults(func=change_password)
+
+
+def parse_delete_user(parser):
+ parser_delete_user = parser.add_parser('delete-user', help='delete user')
+ parser_delete_user.add_argument('-u',
+ '--username',
+ type=str,
+ required=True,
+ help='username')
+ parser_delete_user.set_defaults(func=delete_user)
+
+
+def parse_delete_function(parser):
+ parser_delete_function = parser.add_parser('delete-function',
+ help='delete function')
+ parser_delete_function.add_argument('-f',
+ '--function',
+ type=str,
+ required=True,
+ help='function ID')
+ parser_delete_function.set_defaults(func=delete_function)
+
+
+def parse_check_function_usage(parser):
+ parser_check_function_usage = parser.add_parser(
+ 'check-usage', help='check function usage')
+ parser_check_function_usage.add_argument('-f',
+ '--function-id',
+ type=str,
+ required=True,
+ help='function ID')
+ parser_check_function_usage.set_defaults(func=get_function_usage_stats)
+
+
+def parse_list_users(parser):
+ parser_login = parser.add_parser('list-users',
+ help='list all managed users')
+ parser_login.set_defaults(func=list_users)
+
+
+def parse_logout(parser):
+ parser_logout = parser.add_parser('logout', help='logout')
+ parser_logout.set_defaults(func=logout)
+
+
+def parse_uninstall(parser):
+ parser_uninstall = parser.add_parser('uninstall',
+ help='uninstall Cleanroom CLI')
+ parser_uninstall.set_defaults(func=uninstall)
+
+
+def parse_list_functions(parser):
+ parser_run = parser.add_parser('list-functions',
+ help='list all cleanroom functions')
+ parser_run.set_defaults(func=list_functions)
+
+
+def parse_reset_user_password(parser):
+ parser_reset_user = parser.add_parser('reset-user-password',
+ help='reset user password')
+ parser_reset_user.add_argument('-u',
+ '--username',
+ type=str,
+ required=True,
+ help='username')
+ parser_reset_user.set_defaults(func=reset_user_password)
+
+
+def parse_upgrade(parser):
+ parser_upgrade = parser.add_parser('upgrade',
+ help='upgrade cleanroom-cli')
+ parser_upgrade.set_defaults(func=upgrade_cli)
+
+
+def parse_update_enclave_info(parser):
+ parser_update_enclave_info = parser.add_parser('update-enclave-info',
+ help='update enclave info')
+ parser_update_enclave_info.set_defaults(func=update_enclave_info)
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(
+ prog='cleanroom-cli',
+ description='Cleanroom Command Line Interface')
+ parser.add_argument('--version',
+ action='version',
+ version='%(prog)s ' + __version__)
+ parser.add_argument('--dump-report',
+ action='store_true',
+ help='dump attestation report')
+ parser.set_defaults(dump_report=False)
+ subparsers = parser.add_subparsers()
+
+ parse_login(subparsers)
+ parse_change_password(subparsers)
+ parse_logout(subparsers)
+ parse_upgrade(subparsers)
+ parse_update_enclave_info(subparsers)
+ parse_uninstall(subparsers)
+
+ role = get_role(LOGIN_CONFIG)
+ if role == "DataOwner":
+ parse_run(subparsers)
+ parse_check_function_usage(subparsers)
+ parse_list_functions(subparsers)
+ elif role == "DataOwnerManager":
+ parse_run(subparsers)
+ parse_list_functions(subparsers)
+ parse_check_function_usage(subparsers)
+ parse_register_user(subparsers)
+ parse_reset_user_password(subparsers)
+ parse_delete_user(subparsers)
+ parse_list_users(subparsers)
+ elif role == "FunctionOwner":
+ parse_register_cpk(subparsers)
+ parse_run(subparsers)
+ parse_check_function_usage(subparsers)
+ parse_list_functions(subparsers)
+ parse_register_native(subparsers)
+ parse_delete_function(subparsers)
+ elif role == "NotLogin":
+ pass
+ else:
+ parse_check_function_usage(subparsers)
+ parse_register_user(subparsers)
+ parse_reset_user_password(subparsers)
+ parse_delete_user(subparsers)
+ parse_list_users(subparsers)
+ parse_register_cpk(subparsers)
+ parse_register_native(subparsers)
+ parse_run(subparsers)
+ parse_list_functions(subparsers)
+ parse_delete_function(subparsers)
+
+ try:
+ argcomplete.autocomplete(parser)
+ argcomplete.autocomplete(subparsers)
+ args = parser.parse_args()
+ except:
+ return 1
+
+ if args.dump_report:
+ global DUMP_REPORT
+ DUMP_REPORT = True
+
+ try:
+ args.func(args)
+ except AttributeError:
+ parser.print_help()
+ return 0
+ except CleanroomException as e:
+ if os.path.exists(TMP_OUTPUT):
+ os.unlink(TMP_OUTPUT)
+ print(e, file=sys.stderr)
+ return 0
+ except TeaclaveException as e:
+ if path.exists(TMP_OUTPUT):
+ os.unlink(TMP_OUTPUT)
+ print(e, file=sys.stderr)
+ if e.error_code == 3:
+ cleanroom_info("Updating encalve info...")
+ update_enclave_info(args=None)
+ cleanroom_info("Please run previous command again...")
+ return 0
+ except Exception as e:
+ if path.exists(TMP_OUTPUT):
+ os.unlink(TMP_OUTPUT)
+ print(e, file=sys.stderr)
+ return 1
+
+ return 0
+
+
+from teaclave import aes_gcm_file_encrypt, aes_gcm_file_decrypt
+
+
+def encrypt(input_file: str, output_file: str,
+ crypto_info: CryptoInfo) -> CryptoInfo:
+ crypto_info.cmac = aes_gcm_file_encrypt(crypto_info.key, crypto_info.iv,
+ input_file, output_file)
+ return crypto_info
+
+
+def decrypt(input_file: str, output_file: str, crypto_info):
+ return aes_gcm_file_decrypt(crypto_info.key, crypto_info.iv, input_file,
+ output_file)
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/cleanroom-cli/pyoxidizer.bzl b/cleanroom-cli/pyoxidizer.bzl
new file mode 100644
index 0000000..9008874
--- /dev/null
+++ b/cleanroom-cli/pyoxidizer.bzl
@@ -0,0 +1,33 @@
+def make_exe():
+ dist = default_python_distribution()
+ policy = dist.make_python_packaging_policy()
+ policy.allow_files = True
+ policy.file_scanner_emit_files = True
+ policy.resources_location = "filesystem-relative:lib"
+ python_config = dist.make_python_interpreter_config()
+ python_config.module_search_paths = ["$ORIGIN/lib"]
+ python_config.run_module = "cleanroom-cli"
+ exe = dist.to_python_executable(
+ name="cleanroom-cli",
+ packaging_policy=policy,
+ config=python_config,
+ )
+ exe.add_python_resources(exe.read_package_root(CWD, ["cleanroom-cli"]))
+ exe.add_python_resources(exe.read_package_root("../sdk/python", ["teaclave"]))
+ for resource in exe.pip_install(["-r", "requirements.txt"]):
+ if type(resource) == "File" and ".so." in resource.path:
+ print("Adding " + resource.path + " to bundle")
+ resource.add_include = True
+ exe.add_python_resource(resource)
+ return exe
+
+def make_install(exe):
+ files = FileManifest()
+ files.add_python_resource(".", exe)
+
+ return files
+
+register_target("exe", make_exe)
+register_target("install", make_install, depends=["exe"], default=True)
+
+resolve_targets()
diff --git a/cleanroom-cli/readme-0.0.5.md b/cleanroom-cli/readme-0.0.5.md
new file mode 100644
index 0000000..4a93b1e
--- /dev/null
+++ b/cleanroom-cli/readme-0.0.5.md
@@ -0,0 +1,109 @@
+# Cleanroom CLI v0.0.5
+In this document, we will walk you with the steps to invoke a function as
+data owners.
+There are two roles in the release: `Data owner manager` and `Data owner`.
+The `Data owner manager` registers users for the `Data owner`.
+
+In the current version, we have registered two demo functions in the Teaclave
+Cleanroom service. In the future, we will also support the role `function owner`,
+who can develop a Cleanroom App with the Cleanroom Development Kit and register
+the functions on their owns.
+
+## Start the Docker
+We have prepared a docker image on the DockerHub. Users can get the docker with
+the following command.
+```
+docker run --rm \
+ --net="host" \
+ -w /cleanroom_sdk_cli \
+ -it organization/cleanroom-cli:0.0.5 \
+ bash
+```
+In addition, you can use `-v $(pwd):/workspace` to mount a host folder
+into the docker container.
+
+## Data Owner Manager registers users for Data Owner
+```
+cd data-owner-manageer
+./user-manager.py login -u data_owner_manager -p teaclave
+./user-manager.py register-user -u user_A -p teaclave
+./user-manager.py register-user -u user_B -p teaclave
+./user-manager.py logout
+```
+
+## Data Owner lists and invokes current available functions
+```
+cd data-owner
+./cleanroom.py login -u user_A -p teaclave
+./cleanroom.py list-functions
+```
+We have deployed two functions for the `Data Owner Manager`.
+As a data owner, you are expected to see two avaialble functions. Note that the function ids
+might be different as shown below.
+
+```
+=== Allowed Functions ===
+
+ Function ID Owner Allowed User Groups Description
+-- --------------------------------------------- ------- --------------------- -------------
+ 0 function-73bf9a9b-6631-4500-8f61-08a518219e4c admin data_owner_manager algorithm1
+ 1 function-98ee3801-6940-4b1a-b78a-a24946b736ef admin data_owner_manager algorithm2
+```
+
+After getting the function id, the data owner (login as user_A), can invoke the function and get the result.
+
+```
+export ALGORITHM1=function-73bf9a9b-6631-4500-8f61-08a518219e4c
+export ALGORITHM2=function-98ee3801-6940-4b1a-b78a-a24946b736ef
+./cleanroom.py run -f $ALGORITHM1 -i sample_inputs/rna1.txt -o result1.txt
+cat result1.txt
+GCCUGGUGACCAUAGCGAGUCGGUACCACCCCUUCCCAUCCCGAACAGGACCGUGAAACGACUCCGCGCCGAUGAUAGUGCGGAUUCCCGUGUGAAAGUAGGUCAUCGCCAGGC
+(((((((((.....((((((((....(((.(((((.......))..)))...)))...)))))).))(((.........((((....)))).........)))..))))))))) (-35.50)
+```
+```
+./cleanroom.py run -f $ALGORITHM2 -i sample_inputs/protein1.txt -o result2.txt
+cat result2.txt
+using codon table ./codon_usage_freq_table_human.csv
+viterbi score 6460-64
+CAI score 0 -nan
+runtime no backtrace: 20 s
+has bp sequence GGGACCAUCACUGUCGAGGAGCUUAAGAAGCUCCUCGAGCAGUGGAACCUGGUCAUCGGGUUCCUGUUCCUUACGUGGAUCUGCUUGCUGCAGUUCGCGUAUGCGAACAGGAAC
+has bp structure ..((((((((((((((((((((((...))))))))))).))))))....))))).....(((((((((((.((((((((.((((.....)))))))))))).).))))))))))
+protein length: 38
+RNA length: 114
+sequence: GGGACCAUCACUGUCGAGGAGCUUAAGAAGCUCCUCGAGCAGUGGAACCUGGUCAUCGGGUUCCUGUUCCUUACGUGGAUCUGCUUGCUGCAGUUCGCGUAUGCGAACAGGAAC
+structure: ..((((((((((((((((((((((...))))))))))).))))))....))))).....(((((((((((.((((((((.((((.....)))))))))))).).))))))))))
+free energy: -64.6
+ln CAI: 0 -nan
+CAI: 0.743604
+tuples: []
+runtime: 11 s
+beam size: -1
+lambda: 0
+s1 size 10000000
+s2 size 10000000
+./cleanroom.py logout
+```
+```
+./cleanroom.py run -f $ALGORITHM2 -i sample_inputs/protein1.txt -o result2_args.txt -- -b -1 -l 10.0 -c codon_usage_freq_table_human.csv -s1 30 -s2 19
+cat result2_args.txt
+using codon table codon_usage_freq_table_human.csv
+viterbi score 5870-58
+CAI score -94.4436 0.779942
+runtime no backtrace: 20 s
+has bp sequence GGGACCAUCACUGUCGAGGAGCUUAAGAAGCUCCUCGAGCAGUGGAACCUGGUCAUAGGCUUCCUGUUUCUGACAUGGAUCUGCCUGUUGCAGUUCGCUUAUGCGAACCGCAAC
+has bp structure ..((((((((((((((((((((((...))))))))))).))))))....)))))..((((.(((((((...)))).)))...))))(((((.((((((....)))))).)))))
+protein length: 38
+RNA length: 114
+sequence: GGGACCAUCACUGUCGAGGAGCUUAAGAAGCUCCUCGAGCAGUGGAACCUGGUCAUAGGCUUCCUGUUUCUGACAUGGAUCUGCCUGUUGCAGUUCGCUUAUGCGAACCGCAAC
+structure: ..((((((((((((((((((((((...))))))))))).))))))....)))))..((((.(((((((...)))).)))...))))(((((.((((((....)))))).)))))
+free energy: -58.7
+ln CAI: -94.4436 0.779942
+CAI: 0.779942
+tuples: []
+runtime: 11 s
+beam size: -1
+lambda: 10
+s1 size 30
+s2 size 19
+```
diff --git a/cleanroom-cli/readme.md b/cleanroom-cli/readme.md
new file mode 100644
index 0000000..9a80d09
--- /dev/null
+++ b/cleanroom-cli/readme.md
@@ -0,0 +1,79 @@
+# Cleanroom CLI v0.0.6
+
+This document will walk you through using the Cleanroom CLI to invoke functions and manage users.
+
+## User: Start the Docker
+
+Users can obtain the Cleanroom CLI from Docker Hub with the following command.
+```
+$ docker run --rm \
+ -w /cleanroom_sdk_cli \
+ -it organization/cleanroom-cli:0.0.6 \
+ bash
+```
+Users can use `-v $(pwd):/workspace` to mount a host folder into the docker container.
+
+## User: login and invoke functions
+
+Users are required to log in and obtain a valid function ID before invoking a Cleanroom function.
+Here is an example.
+
+```bash
+$ cd data-owner
+$ ./cleanroom.py login -u <USERNAME> -p <PASSWORD>
+$ ./cleanroom.py list-functions
+
+=== Allowed Functions ===
+
+ Function ID Description
+-- --------------------------------------------- -----------------------------
+ 0 function-e6657fe7-5e48-466a-8c86-181d4082eb95 algorithm1
+ 1 function-106503b3-0e78-4a01-b9f3-2ac8ca5b60f1 algorithm2-hash -- <beam> <lambda>
+ 2 function-6aeae4b3-83b1-4334-8b01-4c561665c0ad algorithm2-hash --diagnosis -- <beam> <lambda>
+```
+
+In this example, three functions are listed by the currently logged-in user. Each function is shown with `FunctionID`, `Owner`, `AllowedUserGroup`, and `Description`.
+
+User can select the `FunctionID` based on its `Description` and invoke the function with `./cleanroom.py run -f <FunctionID> -i <InputPath> -o <OutputPath> -- <Args>`.
+
+Here is an example for invoking the function with the description `algorithm2-hash`.
+
+***Note that `<Args>` of the `algorithm2-hash` function must follow this covension `-- <beam_size> <lambda>`.*** Otherwise, users would get a `Function returned with error code: 1.` error message.
+
+```bash
+$ export ALGORITHM2=function-106503b3-0e78-4a01-b9f3-2ac8ca5b60f1
+$ ./cleanroom.py run -f $ALGORITHM2 -i sample_inputs/protein1.txt -o result2.txt -- 100 200
+Creating task with input sample_inputs/protein1.txt...done
+Invoking task... done, task_id: task-69e5b639-3041-4057-b0c8-e7b03a9068f4
+Getting result... finished
+Task succeeded!
+Output file: result2.txt
+$ cat result2.txt
+input protein: GTITVEELKKLLEQWNLVIGFLFLTWICLLQFAYANRN
+sequence: GGCACCAUCACCGUGGAGGAGCUGAAGAAGCUGCUGGAGCAGUGGAACCUGGUGAUCGGCUUCCUGUUCCUGACCUGGAUCUGCCUGCUGCAGUUCGCCUACGCCAACCGGAAC
+structure: ..........(((.(..((...((.((..((.((((.(((((((((.((.(((.(..(((.....)))..).))).)).)))).))))).))))..)))).))))..))))...
+mRNA folding free energy: -31.20 kcal/mol; mRNA CAI: 1.0000
+```
+
+## About User management
+
+Cleanroom assigns privileged users called `Data Owner Manager`. `Data Owner Manager` can manage users with the `./user-manager.py` interface.
+
+Here is an example.
+
+```bash
+$ cd data-owner-manageer
+$ ./user-manager.py login -u <MANAGER> -p <MANAGER_PASSWORD>
+$ ./user-manager.py register-user -u <USERA> -p <USERA_PASSWORD>
+$ ./user-manager.py register-user -u <USERB> -p <USERB_PASSWORD>
+```
+
+Compared with the previous version (0.0.5), `Data Owner Manager` can list current
+data owners.
+
+```bash
+$ ./user-manager.py list-users
+List users successful, managed users: <USERA>, <USERB>
+```
+
+
diff --git a/cleanroom-cli/requirements.txt b/cleanroom-cli/requirements.txt
new file mode 100644
index 0000000..db81650
--- /dev/null
+++ b/cleanroom-cli/requirements.txt
@@ -0,0 +1,8 @@
+toml==0.10.2
+pyOpenSSL==21.0.0
+tabulate==0.8.9
+requests==2.22.0
+argcomplete==2.0.0
+packaging==21.3
+PyJWT==2.3.0
+cryptography==36.0.1
diff --git a/cleanroom-cli/resource/azure/conf/dcap_root_cert.pem b/cleanroom-cli/resource/azure/conf/dcap_root_cert.pem
new file mode 100644
index 0000000..c2b2907
--- /dev/null
+++ b/cleanroom-cli/resource/azure/conf/dcap_root_cert.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
diff --git a/cleanroom-cli/resource/azure/conf/login.conf b/cleanroom-cli/resource/azure/conf/login.conf
new file mode 100644
index 0000000..8a1dfc9
--- /dev/null
+++ b/cleanroom-cli/resource/azure/conf/login.conf
@@ -0,0 +1,4 @@
+[login]
+username =
+token =
+
diff --git a/cleanroom-cli/resource/azure/conf/cleanroom.conf b/cleanroom-cli/resource/azure/conf/cleanroom.conf
new file mode 100644
index 0000000..511c259
--- /dev/null
+++ b/cleanroom-cli/resource/azure/conf/cleanroom.conf
@@ -0,0 +1,10 @@
+[address]
+authentication_service = api.authentication.dev.cleanroom.com:7776
+frontend_service = api.frontend.dev.cleanroom.com:7777
+file_service = http://api.file.dev.cleanroom.com:7789
+cli_service = http://cli.cleanroom.com
+
+[attestation]
+as_root_ca_cert_path = dcap_root_cert.pem
+enclave_info_path = enclave_info.toml
+
diff --git a/cleanroom-cli/resource/azure/env b/cleanroom-cli/resource/azure/env
new file mode 100644
index 0000000..d45707a
--- /dev/null
+++ b/cleanroom-cli/resource/azure/env
@@ -0,0 +1,11 @@
+#!/bin/sh
+# cleanroom shell setup
+# affix colons on either side of $PATH to simplify matching
+case ":${PATH}:" in
+ *:"$HOME/.cleanroom/bin":*)
+ ;;
+ *)
+ # Prepending path in case a system-installed version needs to be overridden
+ export PATH="$HOME/.cleanroom/bin:$PATH"
+ ;;
+esac
diff --git a/cleanroom-cli/run_test.sh b/cleanroom-cli/run_test.sh
new file mode 100755
index 0000000..ac23583
--- /dev/null
+++ b/cleanroom-cli/run_test.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+set -e
+
+
+
+echo "test attestation"
+./test/test_attestation.sh
+
+echo "test user management"
+./test/test_user_manage.sh
+
+echo "test register functions"
+./test/test_register_function.sh
+
+echo "test invoke functions"
+./test/test_invoke.sh
+
+echo "test check function usage"
+./test/test_check_usage.sh
+
+echo "test update enclave info"
+./test/test_update.sh
+
diff --git a/cleanroom-cli/test/install.sh b/cleanroom-cli/test/install.sh
new file mode 100755
index 0000000..cc87992
--- /dev/null
+++ b/cleanroom-cli/test/install.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+set -e
+
+
+setup_color() {
+ # Only use colors if connected to a terminal
+
+ FMT_RED=$(printf '\033[31m')
+ FMT_GREEN=$(printf '\033[92m')
+ FMT_YELLOW=$(printf '\033[33m')
+ FMT_BLUE=$(printf '\033[34m')
+ FMT_BOLD=$(printf '\033[1m')
+ FMT_RESET=$(printf '\033[0m')
+}
+
+
+
+print_success() {
+ echo "${FMT_GREEN}Setup Cleanroom CLI successfully...${FMT_RESET}"
+ echo "To get started you may need to restart your current shell."
+}
+
+main() {
+ setup_color
+ print_success
+}
+
+
+main "$@"
diff --git a/cleanroom-cli/test/test_attestation.sh b/cleanroom-cli/test/test_attestation.sh
new file mode 100755
index 0000000..d99c711
--- /dev/null
+++ b/cleanroom-cli/test/test_attestation.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+pushd install
+
+cli="bin/cleanroom-cli"
+$cli
+$cli login -u admin -p teaclave
+
+popd
\ No newline at end of file
diff --git a/cleanroom-cli/test/test_check_usage.sh b/cleanroom-cli/test/test_check_usage.sh
new file mode 100755
index 0000000..5b10e6b
--- /dev/null
+++ b/cleanroom-cli/test/test_check_usage.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+set -e
+pushd install
+cli="bin/cleanroom-cli"
+$cli login -u user-trial -p teaclave
+$cli list-functions
+FUNCID=($($cli list-functions | grep -E "^* +algorithm2-trial"))
+ALGORITHM2_TRIAL=${FUNCID[1]}
+$cli check-usage -f "$ALGORITHM2_TRIAL"
+
+
+FUNCID=($($cli list-functions | grep -E "^* +algorithm2-trial-tier2"))
+ALGORITHM2_TRIAL_TIER2=${FUNCID[1]}
+$cli check-usage -f "$ALGORITHM2_TRIAL_TIER2"
+popd
\ No newline at end of file
diff --git a/cleanroom-cli/test/test_invoke.sh b/cleanroom-cli/test/test_invoke.sh
new file mode 100755
index 0000000..f2e36c2
--- /dev/null
+++ b/cleanroom-cli/test/test_invoke.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+set -e
+
+pushd install
+cli="bin/cleanroom-cli"
+rna1="GCCUGGUGACCAUAGCGAGUCGGUACCACCCCUUCCCAUCCCGAACAGGACCGUGAAACGACUCCGCGCCGAUGAUAGUGCGGAUUCCCGUGUGAAAGUAGGUCAUCGCCAGGC"
+protein1="GTITVEELKKLLEQWNLVIGFLFLTWICLLQFAYANRN"
+
+$cli login -u admin -p teaclave
+$cli login -u user1 -p teaclave
+$cli list-functions
+FUNCID=($($cli list-functions | grep -E "^* +algorithm1"))
+ALGORITHM1=${FUNCID[1]}
+
+FUNCID=($($cli list-functions | grep -E "^* +algorithm2"))
+ALGORITHM2=${FUNCID[1]}
+
+FUNCID=($($cli list-functions | grep -E "^* +algorithm2 --diagnosis"))
+ALGORITHM2_DIS=${FUNCID[1]}
+
+echo $rna1 > rna1.txt
+echo $protein1 > protein1.txt
+
+echo "running algorithm1 ${ALGORITHM1}"
+$cli run -f "$ALGORITHM1" -i rna1.txt -o result1.txt
+cat result1.txt
+
+echo "running algorithm2 ${ALGORITHM2}"
+$cli run -f "$ALGORITHM2" -i protein1.txt -o result2.txt -- 100 2
+cat result2.txt
+
+echo "running algorithm2 with the diagnosis mode ${ALGORITHM2_DIS}"
+$cli run -f "$ALGORITHM2_DIS" -i protein1.txt -o result3.txt --diagnosis -- 100 2
+cat result3.txt
+
+$cli login -u user-trial -p teaclave
+$cli list-functions
+FUNCID=($($cli list-functions | grep -E "^* +algorithm2-trial"))
+ALGORITHM2_TRIAL=${FUNCID[1]}
+echo MGDTAKPYFVKRTKDRGTMDDDDFRRGHPQQDYLIIDDHAKGHGSKMEKGLQKKKITPGNYGNTPRKGPCAVSSNPYAFKNPIYSQPAWMNDSHKDQSKRWLSDEHTGNSDNWREFKPGPRIPVINRQRKDSFQENEDGYRWQDTRGCRTVRRLFHKDLTSLETTSEMEAGSPENKKQRSRPRKPRKTRNEENEQDGDLEGPVIDESVLSTKELLGLQQAEERLKRDCIDRLKRRPRNYPTAKYTCRLCDVLIESIAFAHKHIKEKRHKKNIKEKQEEELLTTLPPPTPSQINAVGIAIDKVVQEFGLHNENLEQRLEIKRIMENVFQHKLPDCSLRLYGSSCSRLGFKNSDVNIDIQFPAIMSQPDVLLLVQECLKNSDSFIDVDADFHARVPVVVCREKQSGLLCKVSAGNENACLTTKHLTALGKLEPKLVPLVIAFRYWAKLCSIDRPEEGGLPPYVFALMAIFFLQQRKEPLLPVYLGSWIEGFSLSKLGNFNLQDIEKDVVIWEHTDSAAGDTGITKEEAPRETPIKRGQVSLILDVKHQPSVPVGQLWVELLRFYALEFNLADLVISIRVKELVSRELKDWPKKRIAIEDPYSVKRNVARTLNSQPVFEYILHCLRTTYKYFALPHKITKSSLLKPLNAITCISEHSKEVINHHPDVQTKDDKLKNSVLAQGPGATSSAANTCKVQPLTLKETAESFGSPPKEEMGNEHISVHPENSDCIQADVNSDDYKGDKVYHPETGRKNEKEKVGRKGKHLLTVDQKRGEHVVCGSTRNNESESTLDLEGFQNPTAKECEGLATLDNKADLDGESTEGTEELEDSLNHFTHSVQGQTSEMIPSDEEEEDDEEEEEEEEPRLTINQREDEDGMANEDELDNTYTGSGDEDALSEEDDELGEAAKYEDVKECGKHVERALLVELNKISLKEENVCEEKNSPVDQSDFFYEFSKLIFTKGKSPTVVCSLCKREGHLKKDCPEDFKRIQLEPLPPLTPKFLNILDQVCIQCYKDFSPTIIEDQAREHIRQNLESFIRQDFPGTKLSLFGSSKNGFGFKQSDLDVCMTINGLETAEGLDCVRTIEELARVLRKHSGLRNILPITTAKVPIVKFFHLRSGLEVDISLYNTLALHNTRLLSAYSAIDPRVKYLCYTMKVFTKMCDIGDASRGSLSSYAYTLMVLYFLQQRNPPVIPVLQEIYKGEKKPEIFVDGWNIYFFDQIDELPTYWSECGKNTESVGQLWLGLLRFYTEEFDFKEHVISIRRKSLLTTFKKQWTSKYIVIEDPFDLNHNLGAGLSRKMTNFIMKAFINGRRVFGIPVKGFPKDYPSKMEYFFDPDVLTEGELAPNDRCCRICGKIGHFMKDCPMRRKVRRRRDQEDALNQRYPENKEKRSKEDKEIHNKYTEREVSTKEDKPIQCTPQKAKPMRAAADLGREKILRPPVEKWKRQDDKDLREKRCFICGREGHIKKECPQFKGSSGSLSSKYMTQGKASAKRTQQES | $cli run -f "$ALGORITHM2_TRIAL" --silent
+
+echo MGDTAKPYFVKRTKDRGTMDDDDFRRGHPQQDYLIIDD | $cli run -f "$ALGORITHM2_TRIAL"
+
+set +e
+$cli list-functions
+FUNCID=($($cli list-functions | grep -E "^* +algorithm2-limited-times"))
+ALGORITHM2_TRIAL_LIMITED_TIMES=${FUNCID[1]}
+echo MGDTAKPYFVKRTKDRGTMDDDDFRRGHPQQDYLIIDD | $cli run -f "$ALGORITHM2_TRIAL_LIMITED_TIMES" --silent
+echo MGDTAKPYFVKRTKDRGTMDDDDFRRGHPQQDYLIIDD | $cli run -f "$ALGORITHM2_TRIAL_LIMITED_TIMES" --silent
+echo MGDTAKPYFVKRTKDRGTMDDDDFRRGHPQQDYLIIDD | $cli run -f "$ALGORITHM2_TRIAL_LIMITED_TIMES" --silent
+echo MGDTAKPYFVKRTKDRGTMDDDDFRRGHPQQDYLIIDD | $cli run -f "$ALGORITHM2_TRIAL_LIMITED_TIMES" --silent
+
+FUNCID=($($cli list-functions | grep -E "^* +algorithm2-trial-tier2"))
+ALGORITHM2_TRIAL_TIER2=${FUNCID[1]}
+echo MAVLSKEYGFVLLTGAASFIMVAHLAINVSKARKKYKVEYPIMYSTDPENGHIFNCIQRAHQNTLEVYPPFLFFLAVGGVYHPRIASGLGLAWIVGRVLYAYGYYTGEPSKRSRGALGSIALLGLVGTT| $cli run -f "$ALGORITHM2_TRIAL_TIER2" --silent
+echo MGDTAKPYFVKRTKDRGTMDDDDFRRGHPQQDYLIIDD | $cli run -f "$ALGORITHM2_TRIAL_TIER2" --silent
+
+$cli login -u user-trial1 -p teaclave
+FUNCID=($($cli list-functions | grep -E "^* +algorithm2-trial-expired"))
+ALGORITHM2_TRIAL_EXPIRED=${FUNCID[1]}
+echo MGDTAKPYFVKRTKDRGTMDDDDFRRGHPQQDYLIIDD | $cli run -f "$ALGORITHM2_TRIAL_EXPIRED"
+
+FUNCID=($($cli list-functions | grep -E "^* +algorithm2-limited-times"))
+ALGORITHM2_TRIAL_LIMITED_TIMES=${FUNCID[1]}
+echo MGDTAKPYFVKRTKDRGTMDDDDFRRGHPQQDYLIIDD | $cli run -f "$ALGORITHM2_TRIAL_LIMITED_TIMES"
+
+popd
diff --git a/cleanroom-cli/test/test_register_function.sh b/cleanroom-cli/test/test_register_function.sh
new file mode 100755
index 0000000..89a39d0
--- /dev/null
+++ b/cleanroom-cli/test/test_register_function.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+set -e
+
+
+pushd install
+
+cli="bin/cleanroom-cli"
+
+$cli login -u admin -p teaclave
+
+function1_description="algorithm1;option: [Empty];registration_time: 2022-02-08 22:51:33;version: 1.0;"
+$cli register-cpk -c ../cpk/algorithm1.cpk -n algorithm1 -d "$function1_description" -u organization
+
+function2_description="algorithm2;option: --beam <int> --lambda <float>;version: 1.0"
+$cli register-native -n builtin-cleanroom-algorithm2-hash -d "$function2_description" -u organization
+
+function3_description="algorithm2 --diagnosis;version: 1.0 ;option: --beam <int> --lambda <float>"
+$cli register-native -n builtin-cleanroom-algorithm2-hash -d "$function3_description" -u organization --diagnosis
+
+function4_description="algorithm2-trial;option: [Empty];version: 1.0"
+$cli register-native -n builtin-cleanroom-algorithm2-hash-trial -d "$function4_description" -u organization-trial
+
+function5_description="algorithm2-limited-times;option: [Empty];version: 1.0"
+$cli register-native -n builtin-cleanroom-algorithm2-hash-trial -d "$function5_description" -q 3 -u organization-trial
+
+function6_description="algorithm2-trial-tier2;option: [Empty];version: 1.0;usage limits: 10;expired date: 06/01/2022"
+$cli register-native -n builtin-cleanroom-algorithm2-hash-trial-tier2 -d "$function6_description" -q 10 -e 06/01/2022 -u organization-trial
+
+function7_description="algorithm2-trial-expired;option: [Empty];version: 1.0;usage limits: 10;expired date: 01/02/2011"
+$cli register-native -n builtin-cleanroom-algorithm2-hash-trial-tier2 -d "$function7_description" -q 10 -e 01/02/2011 -u organization-trial
+
+popd
\ No newline at end of file
diff --git a/cleanroom-cli/test/test_update.sh b/cleanroom-cli/test/test_update.sh
new file mode 100755
index 0000000..af69745
--- /dev/null
+++ b/cleanroom-cli/test/test_update.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+set -e
+
+
+cleanup() {
+ # gracefully terminate all background services with SIGTERM
+ [[ -z "$(jobs -p -r)" ]] || kill -s SIGTERM $(jobs -p -r)
+ wait # wait for resource release
+ echo "All jobs terminated."
+}
+
+trap cleanup INT TERM ERR
+
+OS=$(uname -s)
+ARCH=$(uname -m)
+cp ../release/services/enclave_info.toml test
+cp cleanroom-cli-"${OS}"-"${ARCH}".tgz test
+python3 -m http.server 7801 -d test &
+
+pushd install
+
+# Test updating enclave_info.toml
+cli="bin/cleanroom-cli"
+$cli login -u admin -p teaclave
+rm -f conf/enclave_info.toml
+{
+ set +e
+ $cli login -u admin -p teaclave
+}
+
+# Test Upgrading CLI
+$cli upgrade
+cleanup
+popd
\ No newline at end of file
diff --git a/cleanroom-cli/test/test_user_manage.sh b/cleanroom-cli/test/test_user_manage.sh
new file mode 100755
index 0000000..3997f4b
--- /dev/null
+++ b/cleanroom-cli/test/test_user_manage.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+set -e
+
+pushd install
+
+cli="bin/cleanroom-cli"
+$cli login -u admin -p teaclave
+$cli register-user -u organization -p teaclave -r DataOwnerManager
+$cli register-user -u organization-trial -p teaclave -r DataOwnerManager
+$cli login -u organization -p teaclave
+$cli register-user -u user1 -p teaclave
+$cli register-user -u user2 -p teaclave
+$cli register-user -u user3 -p teaclave
+$cli register-user -u user4 -p teaclave
+$cli reset-user-password -u user4
+$cli change-password -p new_teaclave
+$cli logout
+$cli login -u organization -p new_teaclave
+$cli delete-user -u user3
+$cli logout
+
+
+$cli login -u organization-trial -p teaclave
+$cli register-user -u user-trial -p teaclave
+$cli register-user -u user-trial1 -p teaclave
+
+
+
+$cli login -u user2 -p teaclave
+$cli change-password -p new_teaclave
+$cli logout
+$cli login -u user2 -p new_teaclave
+
+echo "User3 loses the access"
+$cli logout
+{
+ set +e
+ $cli login -u user3 -p teaclave
+}
+
+popd
\ No newline at end of file
diff --git a/cleanroom-cli/test/version b/cleanroom-cli/test/version
new file mode 100644
index 0000000..3eefcb9
--- /dev/null
+++ b/cleanroom-cli/test/version
@@ -0,0 +1 @@
+1.0.0
diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml
index f35f2fd..b095ebf 100644
--- a/rpc/Cargo.toml
+++ b/rpc/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_rpc"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave RPC"
license = "Apache-2.0"
@@ -37,7 +37,7 @@ mesalock_sgx = [
anyhow = { version = "1.0.26" }
cfg-if = { version = "0.1.9" }
http = { version = "0.2" }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
rustls = { version = "0.16.0", features = ["dangerous_configuration"] }
serde = { version = "1.0.92", features = ["derive"] }
serde_json = { version = "1.0.39" }
diff --git a/rpc/proc_macro/Cargo.toml b/rpc/proc_macro/Cargo.toml
index 08bf734..55764d7 100644
--- a/rpc/proc_macro/Cargo.toml
+++ b/rpc/proc_macro/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_rpc_proc_macro"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
license = "Apache-2.0"
edition = "2018"
diff --git a/rpc/src/protocol.rs b/rpc/src/protocol.rs
index d550850..3f67e53 100644
--- a/rpc/src/protocol.rs
+++ b/rpc/src/protocol.rs
@@ -18,11 +18,15 @@
#![allow(clippy::nonstandard_macro_braces)]
#![allow(clippy::unknown_clippy_lints)]
+use log::debug;
use log::trace;
use serde::{Deserialize, Serialize};
use std::io;
use std::prelude::v1::*;
+#[cfg(feature = "mesalock_sgx")]
+use std::untrusted::time::InstantEx;
use std::vec::Vec;
+use teaclave_types::profile_highlight;
use teaclave_types::TeaclaveServiceResponseError;
use thiserror::Error;
@@ -80,37 +84,54 @@ where
self.transport.read_exact(&mut header)?;
let buf_len = u64::from_be_bytes(header);
+ let name = std::any::type_name::<V>();
+ if name.contains("Request") {
+ debug!(
+ "[+] Start reading bytes from transport layer {}: {}",
+ name, buf_len
+ );
+ }
if buf_len > self.max_frame_len {
return Err(ProtocolError::Other(anyhow::anyhow!(
"Exceed max frame length"
)));
}
- let mut recv_buf: Vec<u8> = vec![0u8; buf_len as usize];
- self.transport.read_exact(&mut recv_buf)?;
-
- trace!("Recv: {}", std::string::String::from_utf8_lossy(&recv_buf));
- let r: V = serde_json::from_slice(&recv_buf)?;
-
- Ok(r)
+ let recv_buf = profile_highlight!(format!("[+] Read Bytes {}: {}", name, buf_len), {
+ let mut recv_buf: Vec<u8> = vec![0u8; buf_len as usize];
+ self.transport.read_exact(&mut recv_buf)?;
+ recv_buf
+ });
+
+ profile_highlight!(format!("Deserialize {}, {} :", name, recv_buf.len()), {
+ let r: V = serde_json::from_slice(&recv_buf)?;
+ debug!("[+] Deserialize success: {}, {}", name, recv_buf.len());
+ Ok(r)
+ })
}
pub fn write_message<U>(&mut self, message: U) -> std::result::Result<(), ProtocolError>
where
U: Serialize + std::fmt::Debug,
{
+ let name = std::any::type_name::<U>();
let send_buf = serde_json::to_vec(&message)?;
trace!("Send: {}", std::string::String::from_utf8_lossy(&send_buf));
let buf_len = send_buf.len() as u64;
- let header = buf_len.to_be_bytes();
+ profile_highlight!(
+ format!("Sent Resonse bytes {}, size {}: ", name, buf_len),
+ {
+ let header = buf_len.to_be_bytes();
- self.transport.write_all(&header)?;
- self.transport.write_all(&send_buf)?;
- self.transport.flush()?;
+ self.transport.write_all(&header)?;
+ self.transport.write_all(&send_buf)?;
+ self.transport.flush()?;
- Ok(())
+ Ok(())
+ }
+ )
}
}
diff --git a/rpc/src/transport.rs b/rpc/src/transport.rs
index c30bb68..ad82dff 100644
--- a/rpc/src/transport.rs
+++ b/rpc/src/transport.rs
@@ -19,6 +19,7 @@ use crate::protocol;
use crate::Request;
use crate::TeaclaveService;
use anyhow::Result;
+use log::debug;
use log::warn;
use serde::{Deserialize, Serialize};
use std::prelude::v1::*;
@@ -115,6 +116,12 @@ where
let response: JsonProtocolResult<U, TeaclaveServiceResponseError> =
service.handle_request(request).into();
protocol.write_message(response)?;
+ debug!(
+ "[+] {} End handling {} and writing back: {}. Ready for next request...",
+ std::any::type_name::<X>(),
+ std::any::type_name::<V>(),
+ std::any::type_name::<U>()
+ );
}
}
}
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index 30a1814..79ec89b 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_runtime"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave runtime"
license = "Apache-2.0"
@@ -37,7 +37,7 @@ cov = ["sgx_cov"]
enclave_unit_test = ["teaclave_test_utils/mesalock_sgx"]
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
anyhow = { version = "1.0.26" }
teaclave_types = { path = "../types" }
diff --git a/scripts/run_teaclave.sh b/scripts/run_teaclave.sh
new file mode 100755
index 0000000..98a930c
--- /dev/null
+++ b/scripts/run_teaclave.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+set -e
+
+TEACLAVE_PROJECT_ROOT="/teaclave"
+TEACLAVE_SERVICE_INSTALL_DIR="/teaclave/release/services"
+
+
+start_storage_server() {
+ python3 ${TEACLAVE_PROJECT_ROOT}/tests/scripts/simple_http_server.py 6789 &
+}
+
+wait_port() {
+ for port in "$@"
+ do
+ timeout 20 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' localhost "$port"
+ done
+}
+
+cleanup() {
+ # gracefully terminate all background services with SIGTERM
+ [[ -z "$(jobs -p -r)" ]] || kill -s SIGTERM $(jobs -p -r)
+ wait # wait for resource release
+ echo "All jobs terminated."
+}
+
+pushd ${TEACLAVE_SERVICE_INSTALL_DIR} || exit
+trap cleanup INT TERM ERR
+./teaclave_authentication_service &
+./teaclave_storage_service &
+wait_port 7776 17776 17778 # wait for authentication and storage service
+./teaclave_management_service &
+./teaclave_scheduler_service &
+wait_port 17777 17780 # wait for management service and scheduler_service
+./teaclave_access_control_service &
+./teaclave_frontend_service &
+wait_port 17779 7777 # wait for other services
+
+start_storage_server
+
+# Run of execution services separately
+./teaclave_execution_service & exe_pid1=$!
+sleep 25 # wait for execution services
+sleep 3600
+popd
+cleanup
\ No newline at end of file
diff --git a/sdk/payload/wasm/teaclave_context/Cargo.toml b/sdk/payload/wasm/teaclave_context/Cargo.toml
index 454e754..3b43659 100644
--- a/sdk/payload/wasm/teaclave_context/Cargo.toml
+++ b/sdk/payload/wasm/teaclave_context/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_context"
-version = "0.4.0"
+version = "0.2.0"
edition = "2018"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Contex File interfaces for WASM payloads"
diff --git a/sdk/python/teaclave.py b/sdk/python/teaclave.py
index e6e7aef..835e21a 100644
--- a/sdk/python/teaclave.py
+++ b/sdk/python/teaclave.py
@@ -31,9 +31,11 @@ import os
import time
import ssl
import socket
+import inspect
+import ctypes
from typing import Tuple, Dict, List, Any
-from enum import IntEnum
+from enum import IntEnum, auto
import cryptography
from cryptography import x509
@@ -45,7 +47,8 @@ from OpenSSL import crypto
__all__ = [
'FrontendService', 'AuthenticationService', 'FunctionInput',
- 'FunctionOutput', 'OwnerList', 'DataMap'
+ 'FunctionOutput', 'FunctionArgument', 'OwnerList', 'DataMap',
+ 'FunctionExpirationDate'
]
Metadata = Dict[str, str]
@@ -67,7 +70,59 @@ class Request:
class TeaclaveException(Exception):
- pass
+ _teaclave_error = dict()
+ _teaclave_error[0] = ('Networking error',
+ 'Please check your Internet connection')
+ _teaclave_error[1] = ('Remote attestation error',
+ 'Please check your root certificate')
+ _teaclave_error[2] = ('Remote attestation error',
+ 'Please check your root certificate`')
+ _teaclave_error[3] = ('Remote attestation error',
+ 'Please check the `enclave_info.toml` file')
+ _teaclave_error[4] = ('Login error',
+ 'Please check your username and token')
+ _teaclave_error[5] = (
+ 'Login error',
+ 'Please ask your administrator to register a user for you')
+ _teaclave_error[6] = ('Username already exists',
+ 'Please use a different username')
+ _teaclave_error[7] = ('Permission Deny',
+ 'You are not authorized to run the command')
+ _teaclave_error[8] = ('Authentication error',
+ 'Please login your account first')
+ _teaclave_error[9] = (
+ 'Invalid Task',
+ 'Function is registered with the diagnosis mode. Please run with the --diagnosis option'
+ )
+ _teaclave_error[10] = ('Fail to disable function',
+ 'Only the function owner can delete a function')
+ _teaclave_error[11] = ('Fail to delete user',
+ 'Only the user-manager can delete a user')
+ _teaclave_error[12] = ('Invalid password',
+ "Please use a different password")
+ _teaclave_error[13] = ('Authentication error',
+ "Please login in your account")
+ _teaclave_error[14] = ('Quota has been used up',
+ 'This trial account has reached its usage limits')
+ _teaclave_error[15] = ('The function is expired',
+ 'Please contact the function owner')
+
+ def __init__(self, error_code: int, msg=''):
+ frame, filename, line_number, function_name, lines, index = inspect.stack(
+ )[1]
+ self.function_name = function_name
+ self.error_code = error_code
+ self.message = msg
+
+ def __str__(self):
+ CRED = '\033[91m'
+ CEND = '\033[0m'
+ if (self.error_code) in TeaclaveException._teaclave_error:
+ error = TeaclaveException._teaclave_error[self.error_code][0]
+ action = TeaclaveException._teaclave_error[self.error_code][1]
+ return CRED + ('Error: {}. Action: {}.'.format(error,
+ action)) + CEND
+ return str(self.message)
class TeaclaveService:
@@ -79,7 +134,7 @@ class TeaclaveService:
address: Tuple[str, int],
as_root_ca_cert_path: str,
enclave_info_path: str,
- dump_report=False):
+ dump_report=None):
self._context = ssl._create_unverified_context()
self._name = name
self._address = address
@@ -108,17 +163,21 @@ class TeaclaveService:
def connect(self):
"""Establish trusted connection and verify remote attestation report.
"""
- sock = socket.create_connection(self._address)
+ try:
+ sock = socket.create_connection(self._address)
+ except Exception as e:
+ raise TeaclaveException(0)
channel = self._context.wrap_socket(sock,
server_hostname=self._address[0])
cert = channel.getpeercert(binary_form=True)
- if not cert: raise TeaclaveException("Peer cert is None")
+ if not cert: raise TeaclaveException(2)
try:
self._verify_report(self._as_root_ca_cert_path,
self._enclave_info_path, cert, self._name)
+ except TeaclaveException as e:
+ raise e
except Exception as e:
- raise TeaclaveException(
- f"Failed to verify attestation report: {e}")
+ raise TeaclaveException(1)
self.channel = channel
return self
@@ -143,7 +202,10 @@ class TeaclaveService:
if self._dump_report:
try:
- with open(self._name + "_attestation_report.pem", "wb") as f:
+ with open(
+ os.path.join(self._dump_report,
+ self._name + "_attestation_report.pem"),
+ "wb") as f:
f.write(
cert.public_bytes(cryptography.hazmat.primitives.
serialization.Encoding.PEM))
@@ -163,7 +225,7 @@ class TeaclaveService:
]
except:
raise TeaclaveException(
- "Failed to load singing certificate of the report")
+ msg="Failed to load singing certificate of the report")
# verify signing cert with AS root cert
try:
@@ -171,13 +233,13 @@ class TeaclaveService:
as_root_ca_cert = f.read()
except:
raise TeaclaveException(
- "Failed to open attestation service root certificate")
+ msg="Failed to open attestation service root certificate")
try:
as_root_ca_cert = load_certificate(FILETYPE_PEM, as_root_ca_cert)
except:
raise TeaclaveException(
- "Failed to load attestation service root certificate")
+ msg="Failed to load attestation service root certificate")
store = X509Store()
store.add_cert(as_root_ca_cert)
@@ -193,7 +255,7 @@ class TeaclaveService:
# verify report's signature
crypto.verify(certs[0], signature, bytes(ext["report"]), 'sha256')
except:
- raise TeaclaveException("Failed to verify report signature")
+ raise TeaclaveException(3)
report = json.loads(report)
quote = report['isvEnclaveQuoteBody']
@@ -207,15 +269,15 @@ class TeaclaveService:
try:
enclave_info = toml.load(enclave_info_path)
except:
- raise TeaclaveException("Failed to load enclave info")
+ raise TeaclaveException(3)
# verify mr_enclave and mr_signer
enclave_name = "teaclave_" + endpoint_name + "_service"
if mr_enclave != enclave_info[enclave_name]["mr_enclave"]:
- raise Exception("Failed to verify mr_enclave")
+ raise TeaclaveException(3)
if mr_signer != enclave_info[enclave_name]["mr_signer"]:
- raise Exception("Failed to verify mr_signer")
+ raise TeaclaveException(3)
class FunctionInput:
@@ -248,6 +310,41 @@ class FunctionOutput:
self.optional = optional
+class FunctionArgument:
+ """Function argument for registring.
+
+ Args:
+ key: Name of the argument.
+ default_value: A default value of the argument. The default value is "".
+ allow_overwrite: If allow_overwrite flag is set to be true. The service
+ will allow the task creator to overwrite the arguement
+ value when creating tasks.
+ """
+
+ def __init__(self,
+ key: str,
+ default_value: str = "",
+ allow_overwrite=True):
+ self.key = key
+ self.default_value = default_value
+ self.allow_overwrite = allow_overwrite
+
+
+class FunctionExpirationDate:
+ """Function expiration date.
+
+ Args:
+ expired:
+ seconds:
+ nanos:
+ """
+
+ def __init__(self, expired=False, seconds: int = 0, nanos: int = 0):
+ self.expired = expired
+ self.seconds = seconds
+ self.nanos = nanos
+
+
class OwnerList:
"""Defines data ownership.
@@ -315,8 +412,9 @@ class UserUpdateRequest(Request):
class UserLoginRequest(Request):
- def __init__(self, user_id: str, user_password: str):
+ def __init__(self, metadata: Metadata, user_id: str, user_password: str):
self.request = "user_login"
+ self.metadata = metadata
self.id = user_id
self.password = user_password
@@ -370,7 +468,7 @@ class AuthenticationService(TeaclaveService):
address: Tuple[str, int],
as_root_ca_cert_path: str,
enclave_info_path: str,
- dump_report=False):
+ dump_report=None):
super().__init__("authentication", address, as_root_ca_cert_path,
enclave_info_path, dump_report)
@@ -396,7 +494,10 @@ class AuthenticationService(TeaclaveService):
reason = "unknown"
if "request_error" in response:
reason = response["request_error"]
- raise TeaclaveException(f"Failed to register user ({reason})")
+ if reason == 'permission denied':
+ raise TeaclaveException(7)
+ else:
+ raise TeaclaveException(6)
def user_update(self, user_id: str, user_password: str, role: str,
attribute: str):
@@ -433,7 +534,8 @@ class AuthenticationService(TeaclaveService):
str: User login token.
"""
self.check_channel()
- request = UserLoginRequest(user_id, user_password)
+ metadata = {"id": user_id}
+ request = UserLoginRequest(metadata, user_id, user_password)
_write_message(self.channel, request)
response = _read_message(self.channel)
if response["result"] == "ok":
@@ -442,7 +544,10 @@ class AuthenticationService(TeaclaveService):
reason = "unknown"
if "request_error" in response:
reason = response["request_error"]
- raise TeaclaveException(f"Failed to login user ({reason})")
+ if reason == 'user id not found':
+ raise TeaclaveException(5)
+ else:
+ raise TeaclaveException(4)
def user_change_password(self, user_password: str):
"""Change password.
@@ -461,7 +566,12 @@ class AuthenticationService(TeaclaveService):
reason = "unknown"
if "request_error" in response:
reason = response["request_error"]
- raise TeaclaveException(f"Failed to change password ({reason})")
+ if reason == "permission denied":
+ raise TeaclaveException(7)
+ elif reason == "authentication failed":
+ raise TeaclaveException(13)
+ else:
+ raise TeaclaveException(12)
def reset_user_password(self, user_id: str) -> str:
"""Reset password of a managed user.
@@ -483,7 +593,10 @@ class AuthenticationService(TeaclaveService):
reason = "unknown"
if "request_error" in response:
reason = response["request_error"]
- raise TeaclaveException(f"Failed to reset password ({reason})")
+ if reason == "permission denied":
+ raise TeaclaveException(7)
+ else:
+ raise TeaclaveException(13)
def delete_user(self, user_id: str) -> str:
"""Delete a user.
@@ -502,7 +615,10 @@ class AuthenticationService(TeaclaveService):
reason = "unknown"
if "request_error" in response:
reason = response["request_error"]
- raise TeaclaveException(f"Failed to delete user ({reason})")
+ if reason == "permission denied":
+ raise TeaclaveException(7)
+ else:
+ raise TeaclaveException(13)
def list_users(self, user_id: str) -> str:
"""List managed users
@@ -523,15 +639,28 @@ class AuthenticationService(TeaclaveService):
reason = "unknown"
if "request_error" in response:
reason = response["request_error"]
- raise TeaclaveException(f"Failed to list user ({reason})")
+ if reason == "permission denied":
+ raise TeaclaveException(7)
+ else:
+ raise TeaclaveException(13)
class RegisterFunctionRequest(Request):
- def __init__(self, metadata: Metadata, name: str, description: str,
- executor_type: str, public: bool, payload: List[int],
- arguments: List[str], inputs: List[FunctionInput],
- outputs: List[FunctionOutput], user_allowlist: List[str]):
+ def __init__(
+ self,
+ metadata: Metadata,
+ name: str,
+ description: str,
+ executor_type: str,
+ public: bool,
+ payload: List[int],
+ arguments: List[FunctionArgument],
+ inputs: List[FunctionInput],
+ outputs: List[FunctionOutput],
+ user_allowlist: List[str],
+ usage_quota: int,
+ expiration_date: FunctionExpirationDate = FunctionExpirationDate()):
self.request = "register_function"
self.metadata = metadata
self.name = name
@@ -543,15 +672,26 @@ class RegisterFunctionRequest(Request):
self.inputs = inputs
self.outputs = outputs
self.user_allowlist = user_allowlist
+ self.usage_quota = usage_quota
+ self.expiration_date = expiration_date
class UpdateFunctionRequest(Request):
- def __init__(self, metadata: Metadata, function_id: str, name: str,
- description: str, executor_type: str, public: bool,
- payload: List[int], arguments: List[str],
- inputs: List[FunctionInput], outputs: List[FunctionOutput],
- user_allowlist: List[str]):
+ def __init__(
+ self,
+ metadata: Metadata,
+ function_id: str,
+ name: str,
+ description: str,
+ executor_type: str,
+ public: bool,
+ payload: List[int],
+ arguments: List[str],
+ inputs: List[FunctionInput],
+ outputs: List[FunctionOutput],
+ user_allowlist: List[str],
+ expiration_date: FunctionExpirationDate = FunctionExpirationDate()):
self.request = "update_function"
self.metadata = metadata
self.function_id = function_id
@@ -564,6 +704,7 @@ class UpdateFunctionRequest(Request):
self.inputs = inputs
self.outputs = outputs
self.user_allowlist = user_allowlist
+ self.expiration_date = expiration_date
class ListFunctionsRequest(Request):
@@ -598,6 +739,15 @@ class GetFunctionRequest(Request):
self.function_id = function_id
+class GetFunctionUsageStatsRequest(Request):
+
+ def __init__(self, metadata: Metadata, user_id: str, function_id: str):
+ self.request = "get_function_usage_stats"
+ self.metadata = metadata
+ self.user_id = user_id
+ self.function_id = function_id
+
+
class RegisterInputFileRequest(Request):
def __init__(self, metadata: Metadata, url: str, cmac: List[int],
@@ -710,7 +860,7 @@ class FrontendService(TeaclaveService):
address: Tuple[str, int],
as_root_ca_cert_path: str,
enclave_info_path: str,
- dump_report=False):
+ dump_report=None):
super().__init__("frontend", address, as_root_ca_cert_path,
enclave_info_path, dump_report)
@@ -721,17 +871,19 @@ class FrontendService(TeaclaveService):
executor_type: str,
public: bool = True,
payload: List[int] = [],
- arguments: List[str] = [],
+ arguments: List[FunctionArgument] = [],
inputs: List[FunctionInput] = [],
outputs: List[FunctionOutput] = [],
user_allowlist: List[str] = [],
- ):
+ usage_quota: int = -1,
+ expiration_date: FunctionExpirationDate = FunctionExpirationDate()):
self.check_metadata()
self.check_channel()
request = RegisterFunctionRequest(self.metadata, name, description,
executor_type, public, payload,
arguments, inputs, outputs,
- user_allowlist)
+ user_allowlist, usage_quota,
+ expiration_date)
_write_message(self.channel, request)
response = _read_message(self.channel)
if response["result"] == "ok":
@@ -740,7 +892,10 @@ class FrontendService(TeaclaveService):
reason = "unknown"
if "request_error" in response:
reason = response["request_error"]
- raise TeaclaveException(f"Failed to register function ({reason})")
+ if reason == "permission denied":
+ raise TeaclaveException(7)
+ else:
+ raise TeaclaveException(13)
def update_function(
self,
@@ -750,7 +905,7 @@ class FrontendService(TeaclaveService):
executor_type: str,
public: bool = True,
payload: List[int] = [],
- arguments: List[str] = [],
+ arguments: List[FunctionArgument] = [],
inputs: List[FunctionInput] = [],
outputs: List[FunctionOutput] = [],
user_allowlist: List[str] = [],
@@ -780,7 +935,13 @@ class FrontendService(TeaclaveService):
if response["result"] == "ok":
return response["content"]
else:
- raise TeaclaveException("Failed to list functions")
+ reason = "unknown"
+ if "request_error" in response:
+ reason = response["request_error"]
+ if reason == "permission denied":
+ raise TeaclaveException(7)
+ else:
+ raise TeaclaveException(13)
def get_function(self, function_id: str):
self.check_metadata()
@@ -794,7 +955,28 @@ class FrontendService(TeaclaveService):
reason = "unknown"
if "request_error" in response:
reason = response["request_error"]
- raise TeaclaveException(f"Failed to get function ({reason})")
+ if reason == "permission denied":
+ raise TeaclaveException(7)
+ else:
+ raise TeaclaveException(13)
+
+ def get_function_usage_stats(self, user_id: str, function_id: str):
+ self.check_metadata()
+ self.check_channel()
+ request = GetFunctionUsageStatsRequest(self.metadata, user_id,
+ function_id)
+ _write_message(self.channel, request)
+ response = _read_message(self.channel)
+ if response["result"] == "ok":
+ return response["content"]
+ else:
+ reason = "unknown"
+ if "request_error" in response:
+ reason = response["request_error"]
+ if reason == "permission denied":
+ raise TeaclaveException(7)
+ else:
+ raise TeaclaveException(13)
def delete_function(self, function_id: str):
self.check_metadata()
@@ -816,7 +998,13 @@ class FrontendService(TeaclaveService):
if response["result"] == "ok":
return response["content"]
else:
- raise TeaclaveException("Failed to disable function")
+ reason = "unknown"
+ if "request_error" in response:
+ reason = response["request_error"]
+ if reason == "permission denied":
+ raise TeaclaveException(7)
+ else:
+ raise TeaclaveException(13)
def register_input_file(self, url: str, schema: str, key: List[int],
iv: List[int], cmac: List[int]):
@@ -872,7 +1060,12 @@ class FrontendService(TeaclaveService):
reason = "unknown"
if "request_error" in response:
reason = response["request_error"]
- raise TeaclaveException(f"Failed to create task ({reason})")
+ if reason == "function expired":
+ raise TeaclaveException(15)
+ if reason == "quota has been used up":
+ raise TeaclaveException(14)
+ else:
+ raise TeaclaveException(9)
def assign_data_to_task(self, task_id: str, inputs: List[DataMap],
outputs: List[DataMap]):
@@ -916,7 +1109,10 @@ class FrontendService(TeaclaveService):
reason = "unknown"
if "request_error" in response:
reason = response["request_error"]
- raise TeaclaveException(f"Failed to invoke task ({reason})")
+ if reason == "quota has been used up":
+ raise TeaclaveException(14)
+ else:
+ raise TeaclaveException(f"Failed to invoke task ({reason})")
def cancel_task(self, task_id: str):
self.check_metadata()
@@ -936,22 +1132,22 @@ class FrontendService(TeaclaveService):
self.check_metadata()
self.check_channel()
request = GetTaskRequest(self.metadata, task_id)
-
_write_message(self.channel, request)
response = _read_message(self.channel)
if response["result"] != "ok":
reason = "unknown"
if "request_error" in response:
reason = response["request_error"]
- raise TeaclaveException(f"Failed to get task result ({reason})")
+ raise TeaclaveException(f"Failed to get task ({reason})")
return response["content"]
def get_task_result(self, task_id: str):
- self.check_metadata()
- self.check_channel()
request = GetTaskRequest(self.metadata, task_id)
-
+ i = 0
while True:
+ self.check_metadata()
+ self.check_channel()
+ i = i + 1
_write_message(self.channel, request)
response = _read_message(self.channel)
if response["result"] != "ok":
@@ -960,7 +1156,10 @@ class FrontendService(TeaclaveService):
reason = response["request_error"]
raise TeaclaveException(
f"Failed to get task result ({reason})")
- time.sleep(1)
+ if i < 20:
+ time.sleep(i)
+ else:
+ time.sleep(20)
if response["content"]["status"] == TaskStatus.Finished:
break
elif response["content"]["status"] == TaskStatus.Canceled:
@@ -1028,3 +1227,39 @@ def _read_message(sock: ssl.SSLSocket):
raw += data
response = json.loads(raw)
return response
+
+
+from cryptography.hazmat.primitives.ciphers.aead import AESGCM
+
+AAD = bytes([0 for i in range(0, 8)])
+
+
+def aes_gcm_encrypt(key, iv, plaintext):
+ cipher = AESGCM(key)
+ ciphertext_with_tag = cipher.encrypt(iv, plaintext, AAD)
+ return ciphertext_with_tag
+
+
+def aes_gcm_file_encrypt(key, iv, infile, outfile):
+ with open(infile, mode='rb') as file:
+ plaintext = file.read()
+
+ ciphertext_with_tag = aes_gcm_encrypt(key, iv, plaintext)
+
+ with open(outfile, mode='wb') as file:
+ file.write(ciphertext_with_tag)
+ return ciphertext_with_tag[-16:]
+
+
+def aes_gcm_decrypt(key, iv, ciphertext_with_tag):
+ cipher = AESGCM(key)
+ return cipher.decrypt(iv, ciphertext_with_tag, AAD)
+
+
+def aes_gcm_file_decrypt(key, iv, infile, outfile):
+ with open(infile, mode='rb') as file:
+ ciphertext_with_tag = file.read()
+ plaintext = aes_gcm_decrypt(key, iv, ciphertext_with_tag)
+ with open(outfile, mode='wb') as file:
+ file.write(plaintext)
+ return
diff --git a/sdk/rust/Cargo.lock b/sdk/rust/Cargo.lock
index 6078717..13d41db 100644
--- a/sdk/rust/Cargo.lock
+++ b/sdk/rust/Cargo.lock
@@ -350,7 +350,7 @@ dependencies = [
[[package]]
name = "protected_fs_rs"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"cfg-if 0.1.10",
"libc",
@@ -544,7 +544,7 @@ dependencies = [
[[package]]
name = "teaclave_attestation"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"base64 0.13.0",
@@ -572,7 +572,7 @@ dependencies = [
[[package]]
name = "teaclave_client_sdk"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"libc",
@@ -588,7 +588,7 @@ dependencies = [
[[package]]
name = "teaclave_config"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"log",
@@ -599,7 +599,7 @@ dependencies = [
[[package]]
name = "teaclave_crypto"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"hex",
@@ -612,11 +612,12 @@ dependencies = [
[[package]]
name = "teaclave_proto"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"base64 0.13.0",
"cfg-if 0.1.10",
+ "log",
"prost",
"rand",
"serde",
@@ -631,7 +632,7 @@ dependencies = [
[[package]]
name = "teaclave_rpc"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"cfg-if 0.1.10",
@@ -650,7 +651,7 @@ dependencies = [
[[package]]
name = "teaclave_rpc_proc_macro"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"proc-macro2",
"quote",
@@ -659,7 +660,7 @@ dependencies = [
[[package]]
name = "teaclave_types"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"anyhow",
"hex",
diff --git a/sdk/rust/Cargo.toml b/sdk/rust/Cargo.toml
index 1f97f89..92799a6 100644
--- a/sdk/rust/Cargo.toml
+++ b/sdk/rust/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_client_sdk"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Rust Client SDK"
license = "Apache-2.0"
diff --git a/sdk/rust/src/lib.rs b/sdk/rust/src/lib.rs
index 69c9f3a..6f9510d 100644
--- a/sdk/rust/src/lib.rs
+++ b/sdk/rust/src/lib.rs
@@ -41,7 +41,7 @@ pub use teaclave_proto::teaclave_frontend_service::{
RegisterOutputFileRequest, RegisterOutputFileResponse,
};
pub use teaclave_types::{
- EnclaveInfo, Executor, FileCrypto, FunctionInput, FunctionOutput, TaskResult,
+ EnclaveInfo, Executor, FileCrypto, FunctionArgument, FunctionInput, FunctionOutput, TaskResult,
};
pub mod bindings;
@@ -211,7 +211,7 @@ impl FrontendClient {
description: &str,
executor_type: &str,
payload: Option<&[u8]>,
- arguments: Option<&[&str]>,
+ arguments: Option<Vec<FunctionArgument>>,
inputs: Option<Vec<FunctionInput>>,
outputs: Option<Vec<FunctionOutput>>,
) -> Result<String> {
@@ -592,7 +592,7 @@ mod tests {
"An native echo function.",
"builtin",
None,
- Some(&["message"]),
+ Some(vec![FunctionArgument::new("message", "", true)]),
None,
None,
)
diff --git a/sdk/swift/TeaclaveClientSDK/TeaclaveClientSDK.podspec b/sdk/swift/TeaclaveClientSDK/TeaclaveClientSDK.podspec
index e6c5194..b4f7740 100644
--- a/sdk/swift/TeaclaveClientSDK/TeaclaveClientSDK.podspec
+++ b/sdk/swift/TeaclaveClientSDK/TeaclaveClientSDK.podspec
@@ -17,13 +17,13 @@
Pod::Spec.new do |s|
s.name = "TeaclaveClientSDK"
- s.version = "0.4.0"
+ s.version = "0.2.0"
s.summary = "Teaclave Client SDK."
s.homepage = "https://teaclave.apache.org"
s.license = "Apache-2.0"
s.author = { "Teaclave Contributors" => "dev@teaclave.apache.org" }
s.ios.deployment_target = '13.0'
- s.source = { :git => "https://github.com/apache/incubator-teaclave.git", :tag => "v0.4.0" }
+ s.source = { :git => "https://github.com/apache/incubator-teaclave.git", :tag => "v0.2.0" }
s.source_files = "TeaclaveClietnSDK", "TeaclaveClientSDK/**/*.{h,swift}", "External"
s.module_map = 'TeaclaveClientSDK/TeaclaveClientSDK.modulemap'
s.vendored_libraries= 'External/libteaclave_client_sdk.a'
diff --git a/sdk/swift/TeaclaveClientSDK/TeaclaveClientSDK.xcodeproj/project.pbxproj b/sdk/swift/TeaclaveClientSDK/TeaclaveClientSDK.xcodeproj/project.pbxproj
index b61144c..cedafe4 100644
--- a/sdk/swift/TeaclaveClientSDK/TeaclaveClientSDK.xcodeproj/project.pbxproj
+++ b/sdk/swift/TeaclaveClientSDK/TeaclaveClientSDK.xcodeproj/project.pbxproj
@@ -394,7 +394,7 @@
"$(PROJECT_DIR)",
"$(PROJECT_DIR)/../../rust/target/universal/debug",
);
- MARKETING_VERSION = 0.4.0;
+ MARKETING_VERSION = 0.2.0;
MODULEMAP_FILE = "$(SRCROOT)/TeaclaveClientSDK/TeaclaveClientSDK.modulemap";
PRODUCT_BUNDLE_IDENTIFIER = org.apache.teaclave.TeaclaveClientSDK;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
@@ -433,7 +433,7 @@
"$(PROJECT_DIR)",
"$(PROJECT_DIR)/../../rust/target/universal/debug",
);
- MARKETING_VERSION = 0.4.0;
+ MARKETING_VERSION = 0.2.0;
MODULEMAP_FILE = "$(SRCROOT)/TeaclaveClientSDK/TeaclaveClientSDK.modulemap";
PRODUCT_BUNDLE_IDENTIFIER = org.apache.teaclave.TeaclaveClientSDK;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
diff --git a/services/access_control/app/Cargo.toml b/services/access_control/app/Cargo.toml
index 63c4c7e..9d44118 100644
--- a/services/access_control/app/Cargo.toml
+++ b/services/access_control/app/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_access_control_service"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Access Control Service"
license = "Apache-2.0"
diff --git a/services/access_control/enclave/Cargo.toml b/services/access_control/enclave/Cargo.toml
index fc8d5dd..d5ee467 100644
--- a/services/access_control/enclave/Cargo.toml
+++ b/services/access_control/enclave/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_access_control_service_enclave"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Access Control Service enclave"
license = "Apache-2.0"
@@ -46,7 +46,7 @@ enclave_unit_test = ["teaclave_binder/enclave_unit_test", "teaclave_test_utils/m
[dependencies]
anyhow = { version = "1.0.26" }
cfg-if = { version = "0.1.9" }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
serde = { version = "1.0.92" }
serde_json = { version = "1.0.39" }
thiserror = { version = "1.0.9" }
diff --git a/services/authentication/app/Cargo.toml b/services/authentication/app/Cargo.toml
index 01f42d2..9a41ab0 100644
--- a/services/authentication/app/Cargo.toml
+++ b/services/authentication/app/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_authentication_service"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Authentication Service"
license = "Apache-2.0"
diff --git a/services/authentication/enclave/Cargo.toml b/services/authentication/enclave/Cargo.toml
index 5708e4e..696e9d9 100644
--- a/services/authentication/enclave/Cargo.toml
+++ b/services/authentication/enclave/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_authentication_service_enclave"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Authentication Service enclave"
license = "Apache-2.0"
@@ -46,7 +46,7 @@ enclave_unit_test = ["teaclave_binder/enclave_unit_test", "teaclave_test_utils/m
[dependencies]
anyhow = { version = "1.0.26" }
cfg-if = { version = "0.1.9" }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
serde = { version = "1.0.92" }
serde_json = { version = "1.0.39" }
diff --git a/services/execution/app/Cargo.toml b/services/execution/app/Cargo.toml
index 360d6dc..22e001d 100644
--- a/services/execution/app/Cargo.toml
+++ b/services/execution/app/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_execution_service"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave worker."
license = "Apache-2.0"
diff --git a/services/execution/enclave/Cargo.toml b/services/execution/enclave/Cargo.toml
index b763666..2bf7877 100644
--- a/services/execution/enclave/Cargo.toml
+++ b/services/execution/enclave/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_execution_service_enclave"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Execution Service"
license = "Apache-2.0"
@@ -46,11 +46,12 @@ cov = ["teaclave_service_enclave_utils/cov"]
enclave_unit_test = ["teaclave_binder/enclave_unit_test", "teaclave_test_utils/mesalock_sgx"]
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
anyhow = { version = "1.0.26" }
serde_json = { version = "1.0.39" }
serde = { version = "1.0.92", features = ["derive"] }
thiserror = { version = "1.0.9" }
+bincode = {version = "1.3.1" }
gbdt = { version = "0.1.0", features = ["input", "enable_training"] }
uuid = { version = "0.8.1", features = ["v4"] }
url = { version = "2.1.1", features = ["serde"]}
diff --git a/services/execution/enclave/Enclave.config.xml b/services/execution/enclave/Enclave.config.xml
index b09351d..b77e739 100644
--- a/services/execution/enclave/Enclave.config.xml
+++ b/services/execution/enclave/Enclave.config.xml
@@ -22,10 +22,15 @@
<ProdID>0</ProdID>
<ISVSVN>0</ISVSVN>
<StackMaxSize>0x200000</StackMaxSize> <!-- 2M -->
- <HeapMaxSize>0x30000000</HeapMaxSize> <!-- 768M -->
+ <HeapMaxSize>0x380000000</HeapMaxSize> <!-- 14G -->
<TCSNum>22</TCSNum>
<TCSPolicy>0</TCSPolicy>
<DisableDebug>0</DisableDebug>
<MiscSelect>0</MiscSelect>
<MiscMask>0xFFFFFFFF</MiscMask>
+ <ReservedMemMinSize> 0x2000000</ReservedMemMinSize>
+ <ReservedMemInitSize>0x2000000</ReservedMemInitSize>
+ <ReservedMemMaxSize> 0x8000000</ReservedMemMaxSize>
+ <!-- On SGX1 platform, ReservedMemExecutable==1 means set reserved memory as read, write and execute (RWX) -->
+ <ReservedMemExecutable>1</ReservedMemExecutable>
</EnclaveConfiguration>
diff --git a/services/execution/enclave/src/coding_wheel.txt b/services/execution/enclave/src/coding_wheel.txt
new file mode 100644
index 0000000..909610a
--- /dev/null
+++ b/services/execution/enclave/src/coding_wheel.txt
@@ -0,0 +1,21 @@
+Phe U U CU
+Leu C U GCUA U U GA
+Ser U C GCUA A G CU
+Tyr U A CU
+STOP U A GA U G A
+Cys U G CU
+Trp U G G
+Pro C C GCUA
+His C A CU
+Gln C A GA
+Arg C G GCUA A G GA
+Ile A U CUA
+Met A U G
+Thr A C GCUA
+Asn A A CU
+Lys A A GA
+Val G U GCUA
+Asp G A CU
+Glu G A GA
+Gly G G GCUA
+Ala G C GCUA
\ No newline at end of file
diff --git a/services/execution/enclave/src/codon_usage_freq_table_human.csv b/services/execution/enclave/src/codon_usage_freq_table_human.csv
new file mode 100644
index 0000000..4e49f4f
--- /dev/null
+++ b/services/execution/enclave/src/codon_usage_freq_table_human.csv
@@ -0,0 +1,65 @@
+#,,
+UAA,*,0.28
+UAG,*,0.2
+UGA,*,0.52
+GCU,A,0.26
+GCC,A,0.4
+GCA,A,0.23
+GCG,A,0.11
+UGU,C,0.45
+UGC,C,0.55
+GAU,D,0.46
+GAC,D,0.54
+GAA,E,0.42
+GAG,E,0.58
+UUU,F,0.45
+UUC,F,0.55
+GGU,G,0.16
+GGC,G,0.34
+GGA,G,0.25
+GGG,G,0.25
+CAU,H,0.41
+CAC,H,0.59
+AUU,I,0.36
+AUC,I,0.48
+AUA,I,0.16
+AAA,K,0.42
+AAG,K,0.58
+UUA,L,0.07
+UUG,L,0.13
+CUU,L,0.13
+CUC,L,0.2
+CUA,L,0.07
+CUG,L,0.41
+AUG,M,1
+AAU,N,0.46
+AAC,N,0.54
+CCU,P,0.28
+CCC,P,0.33
+CCA,P,0.27
+CCG,P,0.11
+CAA,Q,0.25
+CAG,Q,0.75
+CGU,R,0.08
+CGC,R,0.19
+CGA,R,0.11
+CGG,R,0.21
+AGA,R,0.2
+AGG,R,0.2
+UCU,S,0.18
+UCC,S,0.22
+UCA,S,0.15
+UCG,S,0.06
+AGU,S,0.15
+AGC,S,0.24
+ACU,T,0.24
+ACC,T,0.36
+ACA,T,0.28
+ACG,T,0.12
+GUU,V,0.18
+GUC,V,0.24
+GUA,V,0.11
+GUG,V,0.47
+UGG,W,1
+UAU,Y,0.43
+UAC,Y,0.57
\ No newline at end of file
diff --git a/services/execution/enclave/src/lib.rs b/services/execution/enclave/src/lib.rs
index c422765..f012786 100644
--- a/services/execution/enclave/src/lib.rs
+++ b/services/execution/enclave/src/lib.rs
@@ -129,6 +129,7 @@ pub mod tests {
service::tests::test_invoke_echo,
service::tests::test_invoke_gbdt_train,
task_file_manager::tests::test_input,
+ task_file_manager::tests::test_placeholder,
)
}
}
diff --git a/services/execution/enclave/src/service.rs b/services/execution/enclave/src/service.rs
index 0aa7515..af13087 100644
--- a/services/execution/enclave/src/service.rs
+++ b/services/execution/enclave/src/service.rs
@@ -1,4 +1,5 @@
// Licensed to the Apache Software Foundation (ASF) under one
+// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
@@ -15,25 +16,60 @@
// specific language governing permissions and limitations
// under the License.
+use crate::task_file_manager::TaskFileManager;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::prelude::v1::*;
use std::sync::mpsc;
use std::sync::{Arc, SgxMutex as Mutex};
use std::thread;
-
-use crate::task_file_manager::TaskFileManager;
use teaclave_proto::teaclave_common::{ExecutorCommand, ExecutorStatus};
use teaclave_proto::teaclave_scheduler_service::*;
use teaclave_rpc::endpoint::Endpoint;
use teaclave_types::*;
use teaclave_worker::Worker;
-use anyhow::Result;
+use anyhow::{anyhow, Result};
+use serde::{Deserialize, Serialize};
+use std::ffi::OsStr;
+use std::os::unix::ffi::OsStrExt;
use uuid::Uuid;
static WORKER_BASE_DIR: &str = "/tmp/teaclave_agent/";
+#[derive(Debug, Serialize, Deserialize, Clone)]
+struct Resource {
+ name: String,
+ path: String,
+ content: Vec<u8>,
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+struct Cpk {
+ app_name: String,
+ work_dir: String,
+ wasm_payload: Vec<u8>,
+ resource: Vec<Resource>,
+}
+
+impl Cpk {
+ fn new_from_bytes(data: impl AsRef<[u8]>) -> anyhow::Result<Cpk> {
+ bincode::deserialize(data.as_ref()).map_err(|_| anyhow!("Invalid cpk format!"))
+ }
+
+ fn has_resource(&self) -> bool {
+ !self.resource.is_empty()
+ }
+
+ fn get_payload(&self) -> Vec<u8> {
+ self.wasm_payload.clone()
+ }
+
+ fn get_resource(&self) -> Vec<Resource> {
+ self.resource.clone()
+ }
+}
+
#[derive(Clone)]
pub(crate) struct TeaclaveExecutionService {
worker: Arc<Worker>,
@@ -77,7 +113,7 @@ impl TeaclaveExecutionService {
let mut task_handle: Option<thread::JoinHandle<()>> = None;
loop {
- std::thread::sleep(std::time::Duration::from_secs(3));
+ std::thread::sleep(std::time::Duration::from_secs(1));
match self.heartbeat() {
Ok(ExecutorCommand::Stop) => {
@@ -119,18 +155,18 @@ impl TeaclaveExecutionService {
Ok(result) => {
let task_unwrapped = current_task.as_ref().as_ref().unwrap();
match result {
- Ok(_) => log::debug!(
- "InvokeTask: {:?}, {:?}, success",
- task_unwrapped.task_id,
+ Ok(_) => log::info!(
+ "[MONITOR] InvokeTask: {:?}, {:?}, success",
+ task_unwrapped.user_id,
task_unwrapped.function_id
),
- Err(_) => log::debug!(
- "InvokeTask: {:?}, {:?}, failure",
- task_unwrapped.task_id,
+ Err(_) => log::info!(
+ "[MONITOR] InvokeTask: {:?}, {:?}, failure",
+ task_unwrapped.user_id,
task_unwrapped.function_id
),
}
- log::debug!("InvokeTask result: {:?}", result);
+ log::info!("InvokeTask result: {:?}", result);
let task_copy = current_task.clone();
match self
.update_task_result(&task_copy.as_ref().as_ref().unwrap().task_id, result)
@@ -169,7 +205,7 @@ impl TeaclaveExecutionService {
.map_err(|_| anyhow::anyhow!("Cannot lock scheduler client"))?
.pull_task(request)?;
- log::debug!("pull_stask response: {:?}", response);
+ log::info!("pull_stask response: {:?}", response);
Ok(response.staged_task)
}
@@ -229,7 +265,7 @@ fn invoke_task(task: &StagedTask, fusion_base: &PathBuf) -> Result<TaskOutputs>
)?;
let invocation = prepare_task(&task, &file_mgr)?;
- log::debug!("Invoke function: {:?}", invocation);
+ log::info!("Invoke function: {:?}", invocation);
let worker = Worker::default();
let summary = worker.invoke_function(invocation)?;
@@ -239,15 +275,84 @@ fn invoke_task(task: &StagedTask, fusion_base: &PathBuf) -> Result<TaskOutputs>
}
fn prepare_task(task: &StagedTask, file_mgr: &TaskFileManager) -> Result<StagedFunction> {
- let input_files = file_mgr.prepare_staged_inputs()?;
+ let mut input_files = file_mgr.prepare_staged_inputs()?;
let output_files = file_mgr.prepare_staged_outputs()?;
+ log::info!("before loading: staged_task:{:?}", task);
+
+ // offload
+ let function_payload = if !task.function_payload.is_empty() {
+ let offload_info = OsStr::from_bytes(task.function_payload.as_slice());
+ let offload_path = PathBuf::from(offload_info);
+ log::info!("offload_path: {:?}", offload_path);
+ let function_payload = std::untrusted::fs::read(&offload_path)?;
+ log::info!(
+ "reload function_payload, size =: {:?}",
+ function_payload.len()
+ );
+ function_payload
+ } else {
+ task.function_payload.clone()
+ };
+
+ if task.executor_type == ExecutorType::CleanroomRuntime {
+ let new_cpk = &Cpk::new_from_bytes(&function_payload)?;
+ let wasm_payload = new_cpk.get_payload();
+ let mut arguments = task.function_arguments.clone();
+ if new_cpk.has_resource() {
+ let work_dir = new_cpk.work_dir.to_owned();
+ let resource = new_cpk.get_resource();
+ for r in resource {
+ let full_path = &r.path.to_owned();
+ let content = r.content;
+ let fileinfo: StagedFileInfo =
+ StagedFileInfo::create_with_bytes(full_path, &content)?;
+ input_files.insert(full_path, fileinfo);
+ }
+ // Adding working directory
+ let args_vec = arguments.into_vec();
+ let mut args = HashMap::new();
+ args.insert(args_vec[0].to_owned(), args_vec[1].to_owned());
+ args.insert("wdir".to_string(), work_dir);
+ arguments = FunctionArguments::from(args);
+ }
+ let staged_function = StagedFunctionBuilder::new()
+ .executor_type(task.executor_type)
+ .executor(task.executor)
+ .name(&task.function_name)
+ .arguments(arguments)
+ .payload(wasm_payload)
+ .input_files(input_files)
+ .output_files(output_files)
+ .runtime_name("default")
+ .build();
+ return Ok(staged_function);
+ }
+
+ if task.executor_type == ExecutorType::Builtin
+ && task
+ .function_name
+ .contains("builtin-cleanroom-algorithm2-hash")
+ {
+ let csv_data = include_bytes!("./codon_usage_freq_table_human.csv");
+ let coding_wheel_data = include_bytes!("./coding_wheel.txt");
+ if !input_files.contain("coding_wheel.txt") {
+ let fileinfo: StagedFileInfo =
+ StagedFileInfo::create_with_bytes("coding_wheel.txt", coding_wheel_data)?;
+ input_files.insert("coding_wheel.txt", fileinfo);
+ }
+ if !input_files.contain("codon_usage_freq_table_human.csv") {
+ let fileinfo: StagedFileInfo =
+ StagedFileInfo::create_with_bytes("codon_usage_freq_table_human.csv", csv_data)?;
+ input_files.insert("codon_usage_freq_table_human.csv", fileinfo);
+ }
+ }
let staged_function = StagedFunctionBuilder::new()
.executor_type(task.executor_type)
.executor(task.executor)
.name(&task.function_name)
.arguments(task.function_arguments.clone())
- .payload(task.function_payload.clone())
+ .payload(function_payload)
.input_files(input_files)
.output_files(output_files)
.runtime_name("default")
diff --git a/services/execution/enclave/src/task_file_manager.rs b/services/execution/enclave/src/task_file_manager.rs
index ea71c2b..17235a3 100644
--- a/services/execution/enclave/src/task_file_manager.rs
+++ b/services/execution/enclave/src/task_file_manager.rs
@@ -66,8 +66,9 @@ impl TaskFileManager {
let cwd = Path::new(inter_base.as_ref()).join(task_id.to_string());
let inputs_base = cwd.join("inputs");
let outputs_base = cwd.join("outputs");
-
- let inter_inputs = InterInputs::new(&inputs_base, inputs.clone())?;
+ let mut inputs_tmp = inputs.clone();
+ inputs_tmp.placeholder_filter();
+ let inter_inputs = InterInputs::new(&inputs_base, inputs_tmp)?;
let inter_outputs = InterOutputs::new(&outputs_base, outputs.clone())?;
let tfmgr = TaskFileManager {
@@ -94,6 +95,16 @@ impl TaskFileManager {
self.inter_outputs.upload(&self.fusion_base)?;
Ok(auth_tags)
}
+
+ #[allow(dead_code)]
+ pub(crate) fn inputs_num(&self) -> usize {
+ self.inter_inputs.len()
+ }
+
+ #[allow(dead_code)]
+ pub(crate) fn outputs_num(&self) -> usize {
+ self.inter_outputs.len()
+ }
}
impl InterInput {
@@ -195,6 +206,11 @@ impl InterInputs {
.map(|inter_file| inter_file.to_staged_file_entry())
.collect()
}
+
+ #[allow(dead_code)]
+ pub(crate) fn len(&self) -> usize {
+ self.inner.len()
+ }
}
impl std::iter::FromIterator<InterOutput> for InterOutputs {
@@ -277,6 +293,11 @@ impl InterOutputs {
handle_file_request(request)?;
Ok(())
}
+
+ #[allow(dead_code)]
+ pub(crate) fn len(&self) -> usize {
+ self.inner.len()
+ }
}
// Staged file is put in $base_dir/${funiq_key}-staged/$original_name
@@ -356,4 +377,41 @@ pub mod tests {
.unwrap();
file_mgr.upload_outputs().unwrap();
}
+
+ pub fn test_placeholder() {
+ let key = [0; 16];
+ let iv = [1; 12];
+ let crypto = AesGcm128Key::new(&key, &iv).unwrap();
+ let input_url =
+ Url::parse("http://localhost:6789/fixtures/functions/gbdt_training/train.aes_gcm_128")
+ .unwrap();
+ let tag = FileAuthTag::from_hex("592f1e607649d89ff2aa8a2841a57cad").unwrap();
+ let input_file = FunctionInputFile::new(input_url, tag, crypto);
+
+ let placeholder_url = Url::parse(
+ "placeholder://localhost:6789/fixtures/functions/gbdt_training/train.aes_gcm_128",
+ )
+ .unwrap();
+ let tag = FileAuthTag::from_hex("592f1e607649d89ff2aa8a2841a57cad").unwrap();
+ let placeholder_file = FunctionInputFile::new(placeholder_url, tag, crypto);
+ let inputs = hashmap!("training_data" => input_file, "placeholder" => placeholder_file);
+ let outputs = hashmap!();
+ let task_id = Uuid::new_v4();
+
+ let file_mgr = TaskFileManager::new(
+ "/tmp",
+ "/tmp/fusion_base",
+ &task_id,
+ &inputs.into(),
+ &outputs.into(),
+ )
+ .unwrap();
+ file_mgr.prepare_staged_inputs().unwrap();
+ file_mgr.prepare_staged_outputs().unwrap();
+
+ let inputs_num = file_mgr.inputs_num();
+ let outputs_num = file_mgr.outputs_num();
+ assert!(inputs_num == 1);
+ assert!(outputs_num == 0);
+ }
}
diff --git a/services/frontend/app/Cargo.toml b/services/frontend/app/Cargo.toml
index 3b84e6b..517bca0 100644
--- a/services/frontend/app/Cargo.toml
+++ b/services/frontend/app/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_frontend_service"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Frontend Service"
license = "Apache-2.0"
diff --git a/services/frontend/enclave/Cargo.toml b/services/frontend/enclave/Cargo.toml
index 116852a..f342803 100644
--- a/services/frontend/enclave/Cargo.toml
+++ b/services/frontend/enclave/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_frontend_service_enclave"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Frontend Service enclave"
license = "Apache-2.0"
@@ -46,7 +46,7 @@ enclave_unit_test = ["teaclave_binder/enclave_unit_test", "teaclave_test_utils/m
[dependencies]
anyhow = { version = "1.0.26" }
cfg-if = { version = "0.1.9" }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
serde = { version = "1.0.92" }
serde_json = { version = "1.0.39" }
thiserror = { version = "1.0.9" }
diff --git a/services/frontend/enclave/src/service.rs b/services/frontend/enclave/src/service.rs
index 9f7a34c..83176ba 100644
--- a/services/frontend/enclave/src/service.rs
+++ b/services/frontend/enclave/src/service.rs
@@ -32,15 +32,15 @@ use teaclave_proto::teaclave_frontend_service::{
ApproveTaskRequest, ApproveTaskResponse, AssignDataRequest, AssignDataResponse,
CancelTaskRequest, CancelTaskResponse, CreateTaskRequest, CreateTaskResponse,
DeleteFunctionRequest, DeleteFunctionResponse, DisableFunctionRequest, DisableFunctionResponse,
- GetFunctionRequest, GetFunctionResponse, GetInputFileRequest, GetInputFileResponse,
- GetOutputFileRequest, GetOutputFileResponse, GetTaskRequest, GetTaskResponse,
- InvokeTaskRequest, InvokeTaskResponse, ListFunctionsRequest, ListFunctionsResponse,
- RegisterFunctionRequest, RegisterFunctionResponse, RegisterFusionOutputRequest,
- RegisterFusionOutputResponse, RegisterInputFileRequest, RegisterInputFileResponse,
- RegisterInputFromOutputRequest, RegisterInputFromOutputResponse, RegisterOutputFileRequest,
- RegisterOutputFileResponse, TeaclaveFrontend, UpdateFunctionRequest, UpdateFunctionResponse,
- UpdateInputFileRequest, UpdateInputFileResponse, UpdateOutputFileRequest,
- UpdateOutputFileResponse,
+ GetFunctionRequest, GetFunctionResponse, GetFunctionUsageStatsRequest,
+ GetFunctionUsageStatsResponse, GetInputFileRequest, GetInputFileResponse, GetOutputFileRequest,
+ GetOutputFileResponse, GetTaskRequest, GetTaskResponse, InvokeTaskRequest, InvokeTaskResponse,
+ ListFunctionsRequest, ListFunctionsResponse, RegisterFunctionRequest, RegisterFunctionResponse,
+ RegisterFusionOutputRequest, RegisterFusionOutputResponse, RegisterInputFileRequest,
+ RegisterInputFileResponse, RegisterInputFromOutputRequest, RegisterInputFromOutputResponse,
+ RegisterOutputFileRequest, RegisterOutputFileResponse, TeaclaveFrontend, UpdateFunctionRequest,
+ UpdateFunctionResponse, UpdateInputFileRequest, UpdateInputFileResponse,
+ UpdateOutputFileRequest, UpdateOutputFileResponse,
};
use teaclave_proto::teaclave_management_service::TeaclaveManagementClient;
use teaclave_rpc::endpoint::Endpoint;
@@ -109,6 +109,7 @@ enum Endpoints {
GetInputFile,
RegisterFunction,
GetFunction,
+ GetFunctionUsageStats,
UpdateFunction,
ListFunctions,
DeleteFunction,
@@ -150,7 +151,7 @@ fn authorize(claims: &UserAuthClaims, request: Endpoints) -> bool {
| Endpoints::ApproveTask
| Endpoints::InvokeTask
| Endpoints::CancelTask => role.is_data_owner(),
- Endpoints::GetFunction | Endpoints::ListFunctions => {
+ Endpoints::GetFunctionUsageStats | Endpoints::GetFunction | Endpoints::ListFunctions => {
role.is_function_owner() || role.is_data_owner()
}
}
@@ -332,6 +333,18 @@ impl TeaclaveFrontend for TeaclaveFrontendService {
)
}
+ fn get_function_usage_stats(
+ &self,
+ request: Request<GetFunctionUsageStatsRequest>,
+ ) -> TeaclaveServiceResponseResult<GetFunctionUsageStatsResponse> {
+ authentication_and_forward_to_management!(
+ self,
+ request,
+ get_function_usage_stats,
+ Endpoints::GetFunctionUsageStats
+ )
+ }
+
fn delete_function(
&self,
request: Request<DeleteFunctionRequest>,
diff --git a/services/management/app/Cargo.toml b/services/management/app/Cargo.toml
index 6484f79..15524cc 100644
--- a/services/management/app/Cargo.toml
+++ b/services/management/app/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_management_service"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Management Service"
license = "Apache-2.0"
diff --git a/services/management/enclave/Cargo.toml b/services/management/enclave/Cargo.toml
index a4bb4ea..cabec59 100644
--- a/services/management/enclave/Cargo.toml
+++ b/services/management/enclave/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_management_service_enclave"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Management Service enclave"
license = "Apache-2.0"
@@ -46,7 +46,7 @@ enclave_unit_test = ["teaclave_binder/enclave_unit_test", "teaclave_test_utils/m
[dependencies]
anyhow = { version = "1.0.26" }
cfg-if = { version = "0.1.9" }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
serde = { version = "1.0.92" }
serde_json = { version = "1.0.39" }
thiserror = { version = "1.0.9" }
@@ -54,6 +54,7 @@ ring = { version = "0.16.5" }
rand = { version = "0.7.0" }
uuid = { version = "0.8.1", features = ["v4"] }
url = { version = "2.1.1", features = ["serde"]}
+chrono = { version = "0.4.6" }
teaclave_attestation = { path = "../../../attestation" }
teaclave_config = { path = "../../../config" }
diff --git a/services/management/enclave/src/error.rs b/services/management/enclave/src/error.rs
index 952fa30..c7cea37 100644
--- a/services/management/enclave/src/error.rs
+++ b/services/management/enclave/src/error.rs
@@ -39,14 +39,14 @@ pub(crate) enum ManagementServiceError {
InvalidTaskId,
#[error("invalid task")]
InvalidTask,
- #[error("failed to assign data to task")]
- TaskAssignDataError,
- #[error("failed to approve task")]
- TaskApproveError,
- #[error("failed to invoke task")]
- TaskInvokeError,
- #[error("failed to cancel task, reason: {0}")]
- TaskCancelError(String),
+ #[error("failed to change task state")]
+ TaskStateError,
+ #[error("failed to offload the payload")]
+ OffloadError,
+ #[error("Fusion base directory is not mounted or Offload base directory is not mounted")]
+ ConfigError,
+ #[error("quota has been used up")]
+ QuotaError,
}
impl From<ManagementServiceError> for TeaclaveServiceResponseError {
diff --git a/services/management/enclave/src/lib.rs b/services/management/enclave/src/lib.rs
index 45ee3ba..b94aa88 100644
--- a/services/management/enclave/src/lib.rs
+++ b/services/management/enclave/src/lib.rs
@@ -22,10 +22,12 @@ extern crate sgx_tstd as std;
#[macro_use]
extern crate log;
-use anyhow::{anyhow, Result};
+use anyhow::{anyhow, bail, Result};
use std::prelude::v1::*;
+use std::untrusted::path::PathEx;
+use crate::error::ManagementServiceError;
use teaclave_attestation::{verifier, AttestationConfig, RemoteAttestation};
use teaclave_binder::proto::{
ECallCommand, FinalizeEnclaveInput, FinalizeEnclaveOutput, InitEnclaveInput, InitEnclaveOutput,
@@ -94,7 +96,33 @@ fn start_service(config: &RuntimeConfig) -> Result<()> {
info!(" Starting Management: setup storage endpoint finished ...");
- let service = service::TeaclaveManagementService::new(storage_service_endpoint)?;
+ let fusion_base = config.mount.fusion_base_dir.as_path();
+
+ // We only create this base directory in test_mode
+ // This directory should be mounted in release mode
+ #[cfg(test_mode)]
+ std::untrusted::fs::create_dir_all(&fusion_base)?;
+
+ if !fusion_base.exists() {
+ log::error!(
+ " Starting Management: Fusion base directory is not mounted: {}",
+ fusion_base.display()
+ );
+ bail!(ManagementServiceError::ConfigError);
+ }
+
+ let offload_base = fusion_base.join("functions");
+ std::untrusted::fs::create_dir_all(&offload_base)?;
+
+ if !offload_base.exists() {
+ log::error!(
+ " Starting Management: Offload base directory is not mounted: {}",
+ offload_base.display()
+ );
+ bail!(ManagementServiceError::ConfigError);
+ }
+
+ let service = service::TeaclaveManagementService::new(storage_service_endpoint, offload_base)?;
info!(" Starting Management: start listening ...");
match server.start(service) {
diff --git a/services/management/enclave/src/service.rs b/services/management/enclave/src/service.rs
index a69124b..790067a 100644
--- a/services/management/enclave/src/service.rs
+++ b/services/management/enclave/src/service.rs
@@ -17,22 +17,28 @@
use crate::error::ManagementServiceError;
use anyhow::anyhow;
+use chrono::{DateTime, NaiveDateTime};
use std::convert::TryInto;
+use std::os::unix::ffi::OsStrExt;
+use std::path::{Path, PathBuf};
use std::prelude::v1::*;
use std::sync::{Arc, SgxMutex as Mutex};
+use std::time::SystemTime;
+#[cfg(feature = "mesalock_sgx")]
+use std::untrusted::time::SystemTimeEx;
use teaclave_proto::teaclave_frontend_service::{
ApproveTaskRequest, ApproveTaskResponse, AssignDataRequest, AssignDataResponse,
CancelTaskRequest, CancelTaskResponse, CreateTaskRequest, CreateTaskResponse,
DeleteFunctionRequest, DeleteFunctionResponse, DisableFunctionRequest, DisableFunctionResponse,
- GetFunctionRequest, GetFunctionResponse, GetInputFileRequest, GetInputFileResponse,
- GetOutputFileRequest, GetOutputFileResponse, GetTaskRequest, GetTaskResponse,
- InvokeTaskRequest, InvokeTaskResponse, ListFunctionsRequest, ListFunctionsResponse,
- RegisterFunctionRequest, RegisterFunctionResponse, RegisterFusionOutputRequest,
- RegisterFusionOutputResponse, RegisterInputFileRequest, RegisterInputFileResponse,
- RegisterInputFromOutputRequest, RegisterInputFromOutputResponse, RegisterOutputFileRequest,
- RegisterOutputFileResponse, UpdateFunctionRequest, UpdateFunctionResponse,
- UpdateInputFileRequest, UpdateInputFileResponse, UpdateOutputFileRequest,
- UpdateOutputFileResponse,
+ GetFunctionRequest, GetFunctionResponse, GetFunctionUsageStatsRequest,
+ GetFunctionUsageStatsResponse, GetInputFileRequest, GetInputFileResponse, GetOutputFileRequest,
+ GetOutputFileResponse, GetTaskRequest, GetTaskResponse, InvokeTaskRequest, InvokeTaskResponse,
+ ListFunctionsRequest, ListFunctionsResponse, RegisterFunctionRequest, RegisterFunctionResponse,
+ RegisterFusionOutputRequest, RegisterFusionOutputResponse, RegisterInputFileRequest,
+ RegisterInputFileResponse, RegisterInputFromOutputRequest, RegisterInputFromOutputResponse,
+ RegisterOutputFileRequest, RegisterOutputFileResponse, UpdateFunctionRequest,
+ UpdateFunctionResponse, UpdateInputFileRequest, UpdateInputFileResponse,
+ UpdateOutputFileRequest, UpdateOutputFileResponse,
};
use teaclave_proto::teaclave_management_service::TeaclaveManagement;
use teaclave_proto::teaclave_storage_service::{
@@ -54,6 +60,7 @@ use uuid::Uuid;
#[derive(Clone)]
pub(crate) struct TeaclaveManagementService {
storage_client: Arc<Mutex<TeaclaveStorageClient>>,
+ offload_base: PathBuf,
}
impl TeaclaveManagement for TeaclaveManagementService {
@@ -250,11 +257,41 @@ impl TeaclaveManagement for TeaclaveManagementService {
) -> TeaclaveServiceResponseResult<RegisterFunctionResponse> {
let user_id = get_request_user_id(&request)?;
- let function = FunctionBuilder::from(request.message)
+ let mut function = FunctionBuilder::from(request.message)
.id(Uuid::new_v4())
.owner(user_id.clone())
.build();
+ let offload_name = format!("{}.func", function.uuid().to_string());
+ let offload_path = self.offload_base.join(&offload_name);
+ log::info!("offload_path: {:?}", offload_path);
+
+ //let offload_url = format!("fusion:///TEACLAVE_FUSION_BASE/functions/{}", &offload_name);
+ //log::info!("offload_url: {:?}", offload_url);
+
+ // Ensure the function expiration date is valid
+ if function.expiration_date.expired {
+ let _expired_date = NaiveDateTime::from_timestamp_opt(
+ function.expiration_date.seconds,
+ function.expiration_date.nanos as u32,
+ )
+ .ok_or_else(|| anyhow!("Invalid date"))?;
+ }
+
+ log::info!(
+ "[MONITOR] Register Function: {:?}, Expired: {:?}, Seconds: {:?}, Nanos: {:?}",
+ &function.id,
+ function.expiration_date.expired,
+ function.expiration_date.seconds,
+ function.expiration_date.nanos,
+ );
+
+ std::untrusted::fs::write(&offload_path, function.payload)
+ .map_err(|_| ManagementServiceError::OffloadError)?;
+
+ function.payload = offload_path.as_os_str().as_bytes().to_vec();
+ log::info!("function payload offloaded: {:?}", function);
+ log::info!("function key: {:?}", &function.key());
self.write_to_db(&function)?;
let mut u = User::default();
@@ -486,25 +523,86 @@ impl TeaclaveManagement for TeaclaveManagementService {
}
}
+ fn get_function_usage_stats(
+ &self,
+ request: Request<GetFunctionUsageStatsRequest>,
+ ) -> TeaclaveServiceResponseResult<GetFunctionUsageStatsResponse> {
+ let user_id = get_request_user_id(&request)?;
+ let role = get_request_role(&request)?;
+ let request = request.message;
+ let function: Function = self
+ .read_from_db(&request.function_id)
+ .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
+ let mut request_group_id = user_id.to_string();
+ if let UserRole::DataOwner(s) = &role {
+ request_group_id = s.into();
+ }
+ match role {
+ UserRole::DataOwner(a) | UserRole::DataOwnerManager(a) => {
+ ensure!(
+ (function.public || function.user_allowlist.contains(&a)),
+ ManagementServiceError::PermissionDenied
+ );
+ }
+ UserRole::PlatformAdmin => (),
+ _ => {
+ return Err(ManagementServiceError::PermissionDenied.into());
+ }
+ }
+ let mut u = FunctionUsage::default();
+ u.function_id = function.id;
+ u.group_name = request_group_id;
+ u.use_numbers = 0;
+ let external_id = u.external_id();
+ let function_usage = self.read_from_db::<FunctionUsage>(&external_id);
+ let function_current_use_numbers;
+ match function_usage {
+ Ok(usage) => {
+ function_current_use_numbers = usage.use_numbers;
+ }
+ Err(_) => {
+ function_current_use_numbers = 0;
+ }
+ }
+ let function_quota = function.usage_quota;
+ let response = GetFunctionUsageStatsResponse {
+ function_quota,
+ current_usage: function_current_use_numbers,
+ };
+ Ok(response)
+ }
+
// access control: none
// when a task is created, following rules will be verified:
// 1) arugments match function definition
// 2) input files match function definition
// 3) output files match function definition
// 4) requested user_id in the user_allowlist
+ // 5) if the function
fn create_task(
&self,
request: Request<CreateTaskRequest>,
) -> TeaclaveServiceResponseResult<CreateTaskResponse> {
let user_id = get_request_user_id(&request)?;
let role = get_request_role(&request)?;
-
let request = request.message;
let function: Function = self
.read_from_db(&request.function_id)
.map_err(|_| ManagementServiceError::InvalidFunctionId)?;
+ if function.expiration_date.expired {
+ let now = DateTime::<chrono::offset::Utc>::from(SystemTime::now())
+ .naive_local()
+ .date();
+ let expired_date = NaiveDateTime::from_timestamp_opt(
+ function.expiration_date.seconds,
+ function.expiration_date.nanos as u32,
+ )
+ .ok_or_else(|| anyhow!("Invalid date"))?;
+ ensure!((now <= expired_date.date()), anyhow!("function expired"));
+ }
+
match role {
UserRole::DataOwner(a) | UserRole::DataOwnerManager(a) => {
ensure!(
@@ -526,11 +624,9 @@ impl TeaclaveManagement for TeaclaveManagementService {
function,
)
.map_err(|_| ManagementServiceError::InvalidTask)?;
-
- log::debug!("CreateTask: {:?}", task);
+ log::info!("CreateTask: {:?}", task);
let ts: TaskState = task.into();
self.write_to_db(&ts)?;
-
let response = CreateTaskResponse::new(ts.external_id());
Ok(response)
}
@@ -600,7 +696,7 @@ impl TeaclaveManagement for TeaclaveManagementService {
let mut task: Task<Assign> = ts.try_into().map_err(|e| {
log::warn!("Assign state error: {:?}", e);
- ManagementServiceError::TaskAssignDataError
+ ManagementServiceError::TaskStateError
})?;
for (data_name, data_id) in request.inputs.iter() {
@@ -643,13 +739,13 @@ impl TeaclaveManagement for TeaclaveManagementService {
let mut task: Task<Approve> = ts.try_into().map_err(|e| {
log::warn!("Approve state error: {:?}", e);
- ManagementServiceError::TaskApproveError
+ ManagementServiceError::TaskStateError
})?;
task.approve(&user_id)
.map_err(|_| ManagementServiceError::PermissionDenied)?;
- log::debug!("ApproveTask: approve:{:?}", task);
+ log::info!("ApproveTask: approve:{:?}", task);
let ts: TaskState = task.into();
self.write_to_db(&ts)?;
@@ -665,7 +761,12 @@ impl TeaclaveManagement for TeaclaveManagementService {
request: Request<InvokeTaskRequest>,
) -> TeaclaveServiceResponseResult<InvokeTaskResponse> {
let user_id = get_request_user_id(&request)?;
+ let role = get_request_role(&request)?;
let request = request.message;
+ let mut request_group_id = user_id.to_string();
+ if let UserRole::DataOwner(s) = &role {
+ request_group_id = s.into();
+ }
let ts: TaskState = self
.read_from_db(&request.task_id)
@@ -683,9 +784,46 @@ impl TeaclaveManagement for TeaclaveManagementService {
log::debug!("InvokeTask: get function: {:?}", function);
+ let mut u = FunctionUsage::default();
+ u.function_id = function.id;
+ u.group_name = request_group_id;
+ u.use_numbers = 0;
+ let external_id = u.external_id();
+ let function_usage = self.read_from_db::<FunctionUsage>(&external_id);
+ let function_current_use_numbers;
+ match function_usage {
+ Ok(usage) => {
+ function_current_use_numbers = usage.use_numbers;
+ }
+ Err(_) => {
+ function_current_use_numbers = 0;
+ }
+ }
+ match role {
+ UserRole::DataOwner(a) | UserRole::DataOwnerManager(a) => {
+ log::info!(
+ "[MONITOR] Invoke Task: Function: {:?}, User ID: {:?}, User group: {:?}, Total quota: {:?}, Used quota: {:?}",
+ &function.id,
+ &user_id,
+ &a,
+ function.usage_quota,
+ function_current_use_numbers,
+ );
+ if (function.usage_quota <= function_current_use_numbers)
+ && (function.usage_quota > 0)
+ {
+ return Err(ManagementServiceError::QuotaError.into());
+ }
+ }
+ UserRole::PlatformAdmin => (),
+ _ => {
+ return Err(ManagementServiceError::PermissionDenied.into());
+ }
+ }
+
let mut task: Task<Stage> = ts.try_into().map_err(|e| {
log::warn!("Stage state error: {:?}", e);
- ManagementServiceError::TaskInvokeError
+ ManagementServiceError::TaskStateError
})?;
log::debug!("InvokeTask: get task: {:?}", task);
@@ -697,7 +835,8 @@ impl TeaclaveManagement for TeaclaveManagementService {
let ts: TaskState = task.into();
self.write_to_db(&ts)?;
-
+ u.use_numbers = function_current_use_numbers + 1;
+ self.write_to_db(&u)?;
Ok(InvokeTaskResponse)
}
@@ -736,9 +875,7 @@ impl TeaclaveManagement for TeaclaveManagementService {
// race will not affect correctness/privacy
let mut task: Task<Cancel> = ts.try_into().map_err(|e| {
log::warn!("Cancel state error: {:?}", e);
- ManagementServiceError::TaskCancelError(
- "task has already been canceled".to_string(),
- )
+ ManagementServiceError::TaskStateError
})?;
log::debug!("Canceled Task: {:?}", task);
@@ -746,9 +883,7 @@ impl TeaclaveManagement for TeaclaveManagementService {
task.update_result(TaskResult::Err(TaskFailure {
reason: "Task canceled".to_string(),
}))
- .map_err(|_| {
- ManagementServiceError::TaskCancelError("cannot update result".to_string())
- })?;
+ .map_err(|_| ManagementServiceError::TaskStateError)?;
let ts: TaskState = task.into();
self.write_to_db(&ts)?;
@@ -761,7 +896,10 @@ impl TeaclaveManagement for TeaclaveManagementService {
}
impl TeaclaveManagementService {
- pub(crate) fn new(storage_service_endpoint: Endpoint) -> anyhow::Result<Self> {
+ pub(crate) fn new(
+ storage_service_endpoint: Endpoint,
+ offload_base: impl AsRef<Path>,
+ ) -> anyhow::Result<Self> {
let mut i = 0;
let channel = loop {
match storage_service_endpoint.connect() {
@@ -775,7 +913,10 @@ impl TeaclaveManagementService {
std::thread::sleep(std::time::Duration::from_secs(3));
};
let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new(channel)?));
- let service = Self { storage_client };
+ let service = Self {
+ storage_client,
+ offload_base: offload_base.as_ref().to_owned(),
+ };
#[cfg(test_mode)]
service.add_mock_data()?;
@@ -882,6 +1023,8 @@ impl TeaclaveManagementService {
let function_output = FunctionOutput::new("output", "output_desc", false);
let function_input2 = FunctionInput::new("input2", "input_desc", false);
let function_output2 = FunctionOutput::new("output2", "output_desc", false);
+ let function_arg1 = FunctionArgument::new("arg1", "", true);
+ let function_arg2 = FunctionArgument::new("arg2", "", true);
let function = FunctionBuilder::new()
.id(Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap())
@@ -889,13 +1032,15 @@ impl TeaclaveManagementService {
.description("mock-desc")
.payload(b"mock-payload".to_vec())
.public(true)
- .arguments(vec!["arg1".to_string(), "arg2".to_string()])
+ .arguments(vec![function_arg1, function_arg2])
.inputs(vec![function_input, function_input2])
.outputs(vec![function_output, function_output2])
.owner("teaclave".to_string())
+ .usage_quota(-1)
.build();
self.write_to_db(&function)?;
+ let function_arg1 = FunctionArgument::new("arg1", "", true);
let function_output = FunctionOutput::new("output", "output_desc", false);
let function = FunctionBuilder::new()
@@ -904,12 +1049,14 @@ impl TeaclaveManagementService {
.description("mock-desc")
.payload(b"mock-payload".to_vec())
.public(true)
- .arguments(vec!["arg1".to_string()])
+ .arguments(vec![function_arg1])
.outputs(vec![function_output])
.owner("teaclave".to_string())
+ .usage_quota(-1)
.build();
self.write_to_db(&function)?;
+ let function_arg1 = FunctionArgument::new("arg1", "", true);
let function = FunctionBuilder::new()
.id(Uuid::parse_str("00000000-0000-0000-0000-000000000003").unwrap())
@@ -917,9 +1064,10 @@ impl TeaclaveManagementService {
.description("Private mock function")
.payload(b"mock-payload".to_vec())
.public(false)
- .arguments(vec!["arg1".to_string()])
+ .arguments(vec![function_arg1])
.owner("mock_user".to_string())
.user_allowlist(vec!["mock_user".to_string(), "mock_user1".to_string()])
+ .usage_quota(-1)
.build();
self.write_to_db(&function)?;
@@ -986,16 +1134,18 @@ pub mod tests {
pub fn handle_function() {
let function_input = FunctionInput::new("input", "input_desc", false);
let function_output = FunctionOutput::new("output", "output_desc", false);
+ let function_arg = FunctionArgument::new("arg", "", true);
let function = FunctionBuilder::new()
.id(Uuid::new_v4())
.name("mock_function")
.description("mock function")
.payload(b"python script".to_vec())
- .arguments(vec!["arg".to_string()])
+ .arguments(vec![function_arg])
.inputs(vec![function_input])
.outputs(vec![function_output])
.public(true)
.owner("mock_user")
+ .usage_quota(-1)
.build();
assert!(Function::match_prefix(&function.key_string()));
let value = function.to_vec().unwrap();
@@ -1004,14 +1154,16 @@ pub mod tests {
}
pub fn handle_task() {
+ let function_arg = FunctionArgument::new("arg", "", true);
let function = FunctionBuilder::new()
.id(Uuid::new_v4())
.name("mock_function")
.description("mock function")
.payload(b"python script".to_vec())
- .arguments(vec!["arg".to_string()])
+ .arguments(vec![function_arg])
.public(true)
.owner("mock_user")
+ .usage_quota(-1)
.build();
let function_arguments = FunctionArguments::from_json(json!({"arg": "data"})).unwrap();
@@ -1039,6 +1191,7 @@ pub mod tests {
.payload(b"python script".to_vec())
.public(true)
.owner("mock_user")
+ .usage_quota(-1)
.build();
let url = Url::parse("s3://bucket_id/path?token=mock_token").unwrap();
diff --git a/services/proto/Cargo.toml b/services/proto/Cargo.toml
index 525f0f1..252274a 100644
--- a/services/proto/Cargo.toml
+++ b/services/proto/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_proto"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "RPC protocol of Teaclave services."
license = "Apache-2.0"
@@ -42,7 +42,8 @@ rand = { version = "0.7.0" }
serde = { version = "1.0.39", features = ["derive"] }
serde_json = { version = "1.0.39" }
url = { version = "2.1.1" }
-uuid = { version = "0.8.1", features = ["v4"] }
+uuid = { version = "0.8.1", features = ["v4"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
sgx_cov = { version = "1.1.3", optional = true }
sgx_tstd = { version = "1.1.3", features = ["net", "backtrace"], optional = true }
diff --git a/services/proto/proto_gen/Cargo.lock b/services/proto/proto_gen/Cargo.lock
index 42835a9..c84bfe1 100644
--- a/services/proto/proto_gen/Cargo.lock
+++ b/services/proto/proto_gen/Cargo.lock
@@ -489,7 +489,7 @@ dependencies = [
[[package]]
name = "teaclave_proto_gen"
-version = "0.4.0"
+version = "0.2.0"
dependencies = [
"askama",
"prost",
diff --git a/services/proto/proto_gen/Cargo.toml b/services/proto/proto_gen/Cargo.toml
index 026ae8e..0772215 100644
--- a/services/proto/proto_gen/Cargo.toml
+++ b/services/proto/proto_gen/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_proto_gen"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Generating Rust protocols from protobuf."
license = "Apache-2.0"
diff --git a/services/proto/proto_gen/templates/proto.j2 b/services/proto/proto_gen/templates/proto.j2
index 84ffdaa..a9a6c70 100644
--- a/services/proto/proto_gen/templates/proto.j2
+++ b/services/proto/proto_gen/templates/proto.j2
@@ -48,9 +48,15 @@ pub trait {{ service.proto_name }} {
) -> teaclave_types::TeaclaveServiceResponseResult<{{ service.proto_name }}Response> {
use core::convert::TryFrom;
use std::string::ToString;
+ #[cfg(feature = "mesalock_sgx")]
+ use std::untrusted::time::InstantEx;
match request.message {
{%- for m in service.methods %}
{{ service.proto_name }}Request::{{ m.proto_name }}(r) => {
+ profile_highlight!("{{ service.proto_name }}Request::{{ m.proto_name }}", {
+ log::info!("[MONITOR] {}, {}, {{ service.proto_name }}Request::{{ m.proto_name }}",
+ request.metadata.get("id").unwrap_or(&"None".to_string()),
+ request.metadata.get("cli-version").unwrap_or(&"None".to_string()));
let r = {{ m.impl_input_type }}::try_from(r)
.map_err(|_| teaclave_types::TeaclaveServiceResponseError::InternalError("internal".to_string()))?;
let r = teaclave_rpc::Request {
@@ -60,6 +66,7 @@ pub trait {{ service.proto_name }} {
let response = self.{{ m.name }}(r)?;
let response = {{ m.output_type }}::from(response);
Ok(response).map({{ service.proto_name }}Response::{{ m.proto_name }})
+ })
},
{%- endfor %}
}
diff --git a/services/proto/src/lib.rs b/services/proto/src/lib.rs
index 18c285f..b546096 100644
--- a/services/proto/src/lib.rs
+++ b/services/proto/src/lib.rs
@@ -27,6 +27,21 @@ pub mod teaclave_management_service;
pub mod teaclave_scheduler_service;
pub mod teaclave_storage_service;
+#[macro_export]
+macro_rules! profile_highlight {
+ ($desc:literal, $blk:block) => {{
+ let before = std::time::Instant::now();
+ let result = $blk;
+ let elapsed = before.elapsed().as_secs_f64();
+ if elapsed < 0.5 {
+ log::debug!(" {}: Elapsed time: {:?}", $desc, elapsed);
+ } else {
+ log::info!(" {}: Elapsed time: \x1B[1;31m{:?}\x1B[0m", $desc, elapsed);
+ }
+ result
+ }};
+}
+
macro_rules! include_proto {
($package: tt) => {
include!(concat!(env!("OUT_DIR"), concat!("/", $package, ".rs")));
diff --git a/services/proto/src/proto/teaclave_frontend_service.proto b/services/proto/src/proto/teaclave_frontend_service.proto
index 31d8fd0..6e77344 100644
--- a/services/proto/src/proto/teaclave_frontend_service.proto
+++ b/services/proto/src/proto/teaclave_frontend_service.proto
@@ -107,21 +107,35 @@ message FunctionOutput {
bool optional = 3;
}
+message FunctionArgument {
+ string key = 1;
+ string default_value = 2;
+ bool allow_overwrite = 3;
+}
+
message OwnerList {
string data_name = 1;
repeated string uids = 2;
}
+message FunctionExpirationDate {
+ bool expired = 1;
+ int64 seconds = 2;
+ int32 nanos = 3;
+}
+
message RegisterFunctionRequest {
string name = 1;
string description = 2;
string executor_type = 3;
bool public = 4;
bytes payload = 5;
- repeated string arguments = 6;
+ repeated FunctionArgument arguments = 6;
repeated FunctionInput inputs = 10;
repeated FunctionOutput outputs = 11;
repeated string user_allowlist = 12;
+ int32 usage_quota = 13;
+ FunctionExpirationDate expiration_date = 14;
}
message RegisterFunctionResponse {
@@ -135,10 +149,12 @@ message UpdateFunctionRequest {
string executor_type = 4;
bool public = 5;
bytes payload = 6;
- repeated string arguments = 7;
+ repeated FunctionArgument arguments = 7;
repeated FunctionInput inputs = 10;
repeated FunctionOutput outputs = 11;
repeated string user_allowlist = 12;
+ int32 usage_quota = 13;
+ FunctionExpirationDate expiration_date = 14;
}
message UpdateFunctionResponse {
@@ -156,7 +172,7 @@ message GetFunctionResponse {
string owner = 4;
bytes payload = 5;
bool public = 6;
- repeated string arguments = 7;
+ repeated FunctionArgument arguments = 7;
repeated FunctionInput inputs = 10;
repeated FunctionOutput outputs = 11;
repeated string user_allowlist = 12;
@@ -166,6 +182,16 @@ message DeleteFunctionRequest {
string function_id = 1;
}
+message GetFunctionUsageStatsRequest {
+ string user_id = 1;
+ string function_id = 2;
+}
+
+message GetFunctionUsageStatsResponse {
+ int32 function_quota = 1;
+ int32 current_usage = 2;
+}
+
message DeleteFunctionResponse { }
message DisableFunctionRequest {
@@ -258,6 +284,7 @@ service TeaclaveFrontend {
rpc GetInputFile (GetInputFileRequest) returns (GetInputFileResponse);
rpc RegisterFunction (RegisterFunctionRequest) returns (RegisterFunctionResponse);
rpc GetFunction (GetFunctionRequest) returns (GetFunctionResponse);
+ rpc GetFunctionUsageStats (GetFunctionUsageStatsRequest) returns (GetFunctionUsageStatsResponse);
rpc UpdateFunction (UpdateFunctionRequest) returns (UpdateFunctionResponse);
rpc ListFunctions (ListFunctionsRequest) returns (ListFunctionsResponse);
rpc DeleteFunction (DeleteFunctionRequest) returns (DeleteFunctionResponse);
diff --git a/services/proto/src/proto/teaclave_management_service.proto b/services/proto/src/proto/teaclave_management_service.proto
index d79bd42..7d9639a 100644
--- a/services/proto/src/proto/teaclave_management_service.proto
+++ b/services/proto/src/proto/teaclave_management_service.proto
@@ -36,6 +36,7 @@ service TeaclaveManagement {
rpc RegisterFunction (teaclave_frontend_service_proto.RegisterFunctionRequest) returns (teaclave_frontend_service_proto.RegisterFunctionResponse);
rpc UpdateFunction (teaclave_frontend_service_proto.UpdateFunctionRequest) returns (teaclave_frontend_service_proto.UpdateFunctionResponse);
rpc GetFunction (teaclave_frontend_service_proto.GetFunctionRequest) returns (teaclave_frontend_service_proto.GetFunctionResponse);
+ rpc GetFunctionUsageStats (teaclave_frontend_service_proto.GetFunctionUsageStatsRequest) returns (teaclave_frontend_service_proto.GetFunctionUsageStatsResponse);
rpc DeleteFunction (teaclave_frontend_service_proto.DeleteFunctionRequest) returns (teaclave_frontend_service_proto.DeleteFunctionResponse);
rpc DisableFunction (teaclave_frontend_service_proto.DisableFunctionRequest) returns (teaclave_frontend_service_proto.DisableFunctionResponse);
rpc ListFunctions (teaclave_frontend_service_proto.ListFunctionsRequest) returns (teaclave_frontend_service_proto.ListFunctionsResponse);
diff --git a/services/proto/src/teaclave_frontend_service.rs b/services/proto/src/teaclave_frontend_service.rs
index b353ad0..f64e3b5 100644
--- a/services/proto/src/teaclave_frontend_service.rs
+++ b/services/proto/src/teaclave_frontend_service.rs
@@ -26,9 +26,9 @@ use std::collections::HashMap;
use std::prelude::v1::*;
use teaclave_rpc::into_request;
use teaclave_types::{
- Executor, ExecutorType, ExternalID, FileAuthTag, FileCrypto, FunctionArguments,
- FunctionBuilder, FunctionInput, FunctionOutput, OwnerList, TaskFileOwners, TaskResult,
- TaskStatus, UserID, UserList,
+ Executor, ExecutorType, ExternalID, FileAuthTag, FileCrypto, FunctionArgument,
+ FunctionArguments, FunctionBuilder, FunctionExpirationDate, FunctionInput, FunctionOutput,
+ OwnerList, TaskFileOwners, TaskResult, TaskStatus, UserID, UserList,
};
use url::Url;
@@ -285,10 +285,12 @@ pub struct RegisterFunctionRequest {
pub executor_type: ExecutorType,
pub payload: Vec<u8>,
pub public: bool,
- pub arguments: Vec<String>,
+ pub arguments: Vec<FunctionArgument>,
pub inputs: Vec<FunctionInput>,
pub outputs: Vec<FunctionOutput>,
pub user_allowlist: Vec<String>,
+ pub usage_quota: i32,
+ pub expiration_date: FunctionExpirationDate,
}
#[derive(Default)]
@@ -301,6 +303,7 @@ impl RegisterFunctionRequestBuilder {
let request = RegisterFunctionRequest {
executor_type: ExecutorType::Builtin,
public: true,
+ usage_quota: -1,
..Default::default()
};
@@ -332,11 +335,13 @@ impl RegisterFunctionRequestBuilder {
self
}
- pub fn arguments<T: IntoIterator>(mut self, args: T) -> Self
- where
- <T as IntoIterator>::Item: ToString,
- {
- self.request.arguments = args.into_iter().map(|x| x.to_string()).collect();
+ pub fn usage_quota(mut self, usage_quota: i32) -> Self {
+ self.request.usage_quota = usage_quota;
+ self
+ }
+
+ pub fn arguments(mut self, args: Vec<FunctionArgument>) -> Self {
+ self.request.arguments = args;
self
}
@@ -355,6 +360,11 @@ impl RegisterFunctionRequestBuilder {
self
}
+ pub fn expiration_date(mut self, expiration_date: FunctionExpirationDate) -> Self {
+ self.request.expiration_date = expiration_date;
+ self
+ }
+
pub fn build(self) -> RegisterFunctionRequest {
self.request
}
@@ -373,6 +383,8 @@ impl From<RegisterFunctionRequest> for FunctionBuilder {
.inputs(request.inputs)
.outputs(request.outputs)
.user_allowlist(request.user_allowlist)
+ .usage_quota(request.usage_quota)
+ .expiration_date(request.expiration_date)
}
}
@@ -398,10 +410,12 @@ pub struct UpdateFunctionRequest {
pub executor_type: ExecutorType,
pub payload: Vec<u8>,
pub public: bool,
- pub arguments: Vec<String>,
+ pub arguments: Vec<FunctionArgument>,
pub inputs: Vec<FunctionInput>,
pub outputs: Vec<FunctionOutput>,
pub user_allowlist: Vec<String>,
+ pub usage_quota: i32,
+ pub expiration_date: FunctionExpirationDate,
}
#[derive(Default)]
@@ -450,11 +464,13 @@ impl UpdateFunctionRequestBuilder {
self
}
- pub fn arguments<T: IntoIterator>(mut self, args: T) -> Self
- where
- <T as IntoIterator>::Item: ToString,
- {
- self.request.arguments = args.into_iter().map(|x| x.to_string()).collect();
+ pub fn usage_quota(mut self, usage_quota: i32) -> Self {
+ self.request.usage_quota = usage_quota;
+ self
+ }
+
+ pub fn arguments(mut self, args: Vec<FunctionArgument>) -> Self {
+ self.request.arguments = args;
self
}
@@ -473,6 +489,11 @@ impl UpdateFunctionRequestBuilder {
self
}
+ pub fn expiration_date(mut self, expiration_date: FunctionExpirationDate) -> Self {
+ self.request.expiration_date = expiration_date;
+ self
+ }
+
pub fn build(self) -> UpdateFunctionRequest {
self.request
}
@@ -492,6 +513,8 @@ impl From<UpdateFunctionRequest> for FunctionBuilder {
.inputs(request.inputs)
.outputs(request.outputs)
.user_allowlist(request.user_allowlist)
+ .usage_quota(request.usage_quota)
+ .expiration_date(request.expiration_date)
}
}
@@ -529,12 +552,36 @@ pub struct GetFunctionResponse {
pub payload: Vec<u8>,
pub public: bool,
pub executor_type: ExecutorType,
- pub arguments: Vec<String>,
+ pub arguments: Vec<FunctionArgument>,
pub inputs: Vec<FunctionInput>,
pub outputs: Vec<FunctionOutput>,
pub user_allowlist: Vec<String>,
}
+#[into_request(TeaclaveManagementRequest::GetFunctionUsageStats)]
+#[into_request(TeaclaveFrontendRequest::GetFunctionUsageStats)]
+#[derive(Debug)]
+pub struct GetFunctionUsageStatsRequest {
+ pub user_id: UserID,
+ pub function_id: ExternalID,
+}
+
+impl GetFunctionUsageStatsRequest {
+ pub fn new(function_id: ExternalID, user_id: UserID) -> Self {
+ Self {
+ user_id,
+ function_id,
+ }
+ }
+}
+
+#[into_request(TeaclaveManagementResponse::GetFunctionUsageStats)]
+#[derive(Debug)]
+pub struct GetFunctionUsageStatsResponse {
+ pub function_quota: i32,
+ pub current_usage: i32,
+}
+
#[into_request(TeaclaveManagementRequest::DeleteFunction)]
#[into_request(TeaclaveFrontendRequest::DeleteFunction)]
#[derive(Debug)]
@@ -1109,6 +1156,53 @@ impl From<FunctionOutput> for proto::FunctionOutput {
}
}
+impl std::convert::TryFrom<proto::FunctionArgument> for FunctionArgument {
+ type Error = Error;
+
+ fn try_from(proto: proto::FunctionArgument) -> Result<Self> {
+ let ret = Self {
+ key: proto.key,
+ default_value: proto.default_value,
+ allow_overwrite: proto.allow_overwrite,
+ };
+
+ Ok(ret)
+ }
+}
+
+impl From<FunctionArgument> for proto::FunctionArgument {
+ fn from(arg: FunctionArgument) -> Self {
+ Self {
+ key: arg.key,
+ default_value: arg.default_value,
+ allow_overwrite: arg.allow_overwrite,
+ }
+ }
+}
+
+impl std::convert::TryFrom<proto::FunctionExpirationDate> for FunctionExpirationDate {
+ type Error = Error;
+
+ fn try_from(proto: proto::FunctionExpirationDate) -> Result<Self> {
+ let ret = Self {
+ expired: proto.expired,
+ seconds: proto.seconds,
+ nanos: proto.nanos,
+ };
+ Ok(ret)
+ }
+}
+
+impl From<FunctionExpirationDate> for proto::FunctionExpirationDate {
+ fn from(expiration_date: FunctionExpirationDate) -> Self {
+ Self {
+ expired: expiration_date.expired,
+ seconds: expiration_date.seconds,
+ nanos: expiration_date.nanos,
+ }
+ }
+}
+
impl std::convert::TryFrom<proto::RegisterFunctionRequest> for RegisterFunctionRequest {
type Error = Error;
@@ -1123,18 +1217,28 @@ impl std::convert::TryFrom<proto::RegisterFunctionRequest> for RegisterFunctionR
.into_iter()
.map(FunctionOutput::try_from)
.collect();
+ let args: Result<Vec<FunctionArgument>> = proto
+ .arguments
+ .into_iter()
+ .map(FunctionArgument::try_from)
+ .collect();
let executor_type = proto.executor_type.try_into()?;
-
+ let expiration_date: FunctionExpirationDate = proto
+ .expiration_date
+ .ok_or_else(|| anyhow!("missing expiration date"))?
+ .try_into()?;
let ret = Self {
name: proto.name,
description: proto.description,
executor_type,
payload: proto.payload,
public: proto.public,
- arguments: proto.arguments,
+ arguments: args?,
inputs: inputs?,
outputs: outputs?,
user_allowlist: proto.user_allowlist,
+ usage_quota: proto.usage_quota,
+ expiration_date,
};
Ok(ret)
}
@@ -1152,6 +1256,11 @@ impl From<RegisterFunctionRequest> for proto::RegisterFunctionRequest {
.into_iter()
.map(proto::FunctionOutput::from)
.collect();
+ let arguments: Vec<proto::FunctionArgument> = request
+ .arguments
+ .into_iter()
+ .map(proto::FunctionArgument::from)
+ .collect();
Self {
name: request.name,
@@ -1159,10 +1268,12 @@ impl From<RegisterFunctionRequest> for proto::RegisterFunctionRequest {
executor_type: request.executor_type.into(),
payload: request.payload,
public: request.public,
- arguments: request.arguments,
+ arguments,
inputs,
outputs,
user_allowlist: request.user_allowlist,
+ usage_quota: request.usage_quota,
+ expiration_date: Some(request.expiration_date.into()),
}
}
}
@@ -1201,8 +1312,18 @@ impl std::convert::TryFrom<proto::UpdateFunctionRequest> for UpdateFunctionReque
.into_iter()
.map(FunctionOutput::try_from)
.collect();
+ let args: Result<Vec<FunctionArgument>> = proto
+ .arguments
+ .into_iter()
+ .map(FunctionArgument::try_from)
+ .collect();
let executor_type = proto.executor_type.try_into()?;
+ let expiration_date: FunctionExpirationDate = proto
+ .expiration_date
+ .ok_or_else(|| anyhow!("missing expiration date"))?
+ .try_into()?;
+
let ret = Self {
function_id,
name: proto.name,
@@ -1210,10 +1331,12 @@ impl std::convert::TryFrom<proto::UpdateFunctionRequest> for UpdateFunctionReque
executor_type,
payload: proto.payload,
public: proto.public,
- arguments: proto.arguments,
+ arguments: args?,
inputs: inputs?,
outputs: outputs?,
user_allowlist: proto.user_allowlist,
+ usage_quota: proto.usage_quota,
+ expiration_date,
};
Ok(ret)
}
@@ -1231,6 +1354,11 @@ impl From<UpdateFunctionRequest> for proto::UpdateFunctionRequest {
.into_iter()
.map(proto::FunctionOutput::from)
.collect();
+ let arguments: Vec<proto::FunctionArgument> = request
+ .arguments
+ .into_iter()
+ .map(proto::FunctionArgument::from)
+ .collect();
Self {
function_id: request.function_id.to_string(),
@@ -1239,10 +1367,12 @@ impl From<UpdateFunctionRequest> for proto::UpdateFunctionRequest {
executor_type: request.executor_type.into(),
payload: request.payload,
public: request.public,
- arguments: request.arguments,
+ arguments,
inputs,
outputs,
user_allowlist: request.user_allowlist,
+ usage_quota: request.usage_quota,
+ expiration_date: Some(request.expiration_date.into()),
}
}
}
@@ -1293,6 +1423,52 @@ impl std::convert::TryFrom<proto::DeleteFunctionResponse> for DeleteFunctionResp
}
}
+impl From<GetFunctionUsageStatsRequest> for proto::GetFunctionUsageStatsRequest {
+ fn from(request: GetFunctionUsageStatsRequest) -> Self {
+ Self {
+ user_id: request.user_id.to_string(),
+ function_id: request.function_id.to_string(),
+ }
+ }
+}
+
+impl std::convert::TryFrom<proto::GetFunctionUsageStatsRequest> for GetFunctionUsageStatsRequest {
+ type Error = Error;
+
+ fn try_from(proto: proto::GetFunctionUsageStatsRequest) -> Result<Self> {
+ let user_id: UserID = proto.user_id.try_into()?;
+ let function_id: ExternalID = proto.function_id.try_into()?;
+ let ret = Self {
+ user_id,
+ function_id,
+ };
+
+ Ok(ret)
+ }
+}
+
+impl From<GetFunctionUsageStatsResponse> for proto::GetFunctionUsageStatsResponse {
+ fn from(request: GetFunctionUsageStatsResponse) -> Self {
+ Self {
+ function_quota: request.function_quota,
+ current_usage: request.current_usage,
+ }
+ }
+}
+
+impl std::convert::TryFrom<proto::GetFunctionUsageStatsResponse> for GetFunctionUsageStatsResponse {
+ type Error = Error;
+
+ fn try_from(proto: proto::GetFunctionUsageStatsResponse) -> Result<Self> {
+ let ret = Self {
+ function_quota: proto.function_quota,
+ current_usage: proto.current_usage,
+ };
+
+ Ok(ret)
+ }
+}
+
impl From<DeleteFunctionResponse> for proto::DeleteFunctionResponse {
fn from(_response: DeleteFunctionResponse) -> Self {
Self {}
@@ -1406,6 +1582,11 @@ impl std::convert::TryFrom<proto::GetFunctionResponse> for GetFunctionResponse {
.into_iter()
.map(FunctionOutput::try_from)
.collect();
+ let args: Result<Vec<FunctionArgument>> = proto
+ .arguments
+ .into_iter()
+ .map(FunctionArgument::try_from)
+ .collect();
let executor_type = proto.executor_type.try_into()?;
let ret = Self {
@@ -1415,7 +1596,7 @@ impl std::convert::TryFrom<proto::GetFunctionResponse> for GetFunctionResponse {
executor_type,
payload: proto.payload,
public: proto.public,
- arguments: proto.arguments,
+ arguments: args?,
inputs: inputs?,
outputs: outputs?,
user_allowlist: proto.user_allowlist,
@@ -1437,6 +1618,11 @@ impl From<GetFunctionResponse> for proto::GetFunctionResponse {
.into_iter()
.map(proto::FunctionOutput::from)
.collect();
+ let arguments: Vec<proto::FunctionArgument> = response
+ .arguments
+ .into_iter()
+ .map(proto::FunctionArgument::from)
+ .collect();
Self {
name: response.name,
@@ -1445,7 +1631,7 @@ impl From<GetFunctionResponse> for proto::GetFunctionResponse {
executor_type: response.executor_type.into(),
payload: response.payload,
public: response.public,
- arguments: response.arguments,
+ arguments,
inputs,
outputs,
user_allowlist: response.user_allowlist,
diff --git a/services/proto/src/teaclave_management_service.rs b/services/proto/src/teaclave_management_service.rs
index 6f8cbcb..deb7663 100644
--- a/services/proto/src/teaclave_management_service.rs
+++ b/services/proto/src/teaclave_management_service.rs
@@ -62,6 +62,10 @@ pub type CreateTaskRequest = crate::teaclave_frontend_service::CreateTaskRequest
pub type CreateTaskResponse = crate::teaclave_frontend_service::CreateTaskResponse;
pub type GetTaskRequest = crate::teaclave_frontend_service::GetTaskRequest;
pub type GetTaskResponse = crate::teaclave_frontend_service::GetTaskResponse;
+pub type GetFunctionUsageStatsRequest =
+ crate::teaclave_frontend_service::GetFunctionUsageStatsRequest;
+pub type GetFunctionUsageStatsResponse =
+ crate::teaclave_frontend_service::GetFunctionUsageStatsResponse;
pub type AssignDataRequest = crate::teaclave_frontend_service::AssignDataRequest;
pub type AssignDataResponse = crate::teaclave_frontend_service::AssignDataResponse;
pub type ApproveTaskRequest = crate::teaclave_frontend_service::ApproveTaskRequest;
diff --git a/services/scheduler/app/Cargo.toml b/services/scheduler/app/Cargo.toml
index 556aa25..a12d9b5 100644
--- a/services/scheduler/app/Cargo.toml
+++ b/services/scheduler/app/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_scheduler_service"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave worker."
license = "Apache-2.0"
diff --git a/services/scheduler/enclave/Cargo.toml b/services/scheduler/enclave/Cargo.toml
index e991a27..41cdeaf 100644
--- a/services/scheduler/enclave/Cargo.toml
+++ b/services/scheduler/enclave/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_scheduler_service_enclave"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Scheduler Service"
license = "Apache-2.0"
@@ -44,7 +44,7 @@ cov = ["teaclave_service_enclave_utils/cov"]
enclave_unit_test = ["teaclave_binder/enclave_unit_test", "teaclave_test_utils/mesalock_sgx"]
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
anyhow = { version = "1.0.26" }
serde_json = { version = "1.0.39" }
serde = { version = "1.0.92", features = ["derive"] }
diff --git a/services/scheduler/enclave/src/service.rs b/services/scheduler/enclave/src/service.rs
index 2a739ac..970f2f6 100644
--- a/services/scheduler/enclave/src/service.rs
+++ b/services/scheduler/enclave/src/service.rs
@@ -61,7 +61,7 @@ pub struct TeaclaveSchedulerDeamon {
impl TeaclaveSchedulerDeamon {
pub fn run(&self) -> Result<()> {
loop {
- std::thread::sleep(std::time::Duration::from_secs(2));
+ std::thread::sleep(std::time::Duration::from_secs(1));
let mut resources = self
.resources
diff --git a/services/storage/app/Cargo.toml b/services/storage/app/Cargo.toml
index 385a8f8..1cde92c 100644
--- a/services/storage/app/Cargo.toml
+++ b/services/storage/app/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_storage_service"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Storage Service"
license = "Apache-2.0"
diff --git a/services/storage/enclave/Cargo.toml b/services/storage/enclave/Cargo.toml
index 98c6c9d..054a197 100644
--- a/services/storage/enclave/Cargo.toml
+++ b/services/storage/enclave/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_storage_service_enclave"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave Storage Service enclave"
license = "Apache-2.0"
@@ -46,7 +46,7 @@ enclave_unit_test = ["teaclave_binder/enclave_unit_test", "teaclave_test_utils/m
[dependencies]
anyhow = { version = "1.0.26" }
cfg-if = { version = "0.1.9" }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
serde = { version = "1.0.92" }
thiserror = { version = "1.0.9" }
diff --git a/services/storage/enclave/Enclave.config.xml b/services/storage/enclave/Enclave.config.xml
index d95a7e5..acd589b 100644
--- a/services/storage/enclave/Enclave.config.xml
+++ b/services/storage/enclave/Enclave.config.xml
@@ -1,3 +1,4 @@
+
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
@@ -21,8 +22,8 @@
<EnclaveConfiguration>
<ProdID>0</ProdID>
<ISVSVN>0</ISVSVN>
- <StackMaxSize>0x400000</StackMaxSize> <!-- 2M -->
- <HeapMaxSize>0x30000000</HeapMaxSize> <!-- 768M -->
+ <StackMaxSize>0x800000</StackMaxSize> <!-- 2M -->
+ <HeapMaxSize>0x50000000</HeapMaxSize> <!-- 768M -->
<TCSNum>22</TCSNum>
<TCSPolicy>0</TCSPolicy>
<DisableDebug>0</DisableDebug>
diff --git a/services/storage/enclave/src/lib.rs b/services/storage/enclave/src/lib.rs
index 2e4b262..455240d 100644
--- a/services/storage/enclave/src/lib.rs
+++ b/services/storage/enclave/src/lib.rs
@@ -24,6 +24,7 @@ extern crate log;
use std::cell::RefCell;
use std::format;
+use std::path::Path;
use std::prelude::v1::*;
use std::sync::mpsc::channel;
use std::thread;
@@ -42,6 +43,7 @@ use teaclave_config::RuntimeConfig;
use teaclave_proto::teaclave_storage_service::{TeaclaveStorageRequest, TeaclaveStorageResponse};
use teaclave_rpc::config::SgxTrustedTlsServerConfig;
use teaclave_rpc::server::SgxTrustedTlsServer;
+use teaclave_service_enclave_utils::base_dir_for_db;
use teaclave_service_enclave_utils::ServiceEnclave;
use teaclave_types::{EnclaveInfo, TeeServiceError, TeeServiceResult};
@@ -80,13 +82,15 @@ fn start_service(config: &RuntimeConfig) -> Result<()> {
)?;
info!(" Starting Storage: Server config setup finished ...");
+ let db_base = base_dir_for_db(&config)?;
+
let (sender, receiver) = channel();
thread::spawn(move || {
info!(" Starting Storage: opening database ...");
#[cfg(test_mode)]
- let db = test_mode::create_mock_db();
+ let db = test_mode::create_mock_db(db_base);
#[cfg(not(test_mode))]
- let db = create_teaclave_db();
+ let db = create_teaclave_db(db_base);
let mut storage_service = service::TeaclaveStorageService::new(RefCell::new(db), receiver);
@@ -112,22 +116,30 @@ fn start_service(config: &RuntimeConfig) -> Result<()> {
}
#[cfg(not(test_mode))]
-pub(crate) fn create_teaclave_db() -> DB {
- let opt = rusty_leveldb::in_memory();
- let database = DB::open("teaclave_db", opt).expect("cannot open teaclave_db");
+pub(crate) fn create_teaclave_db(base_dir: impl AsRef<Path>) -> DB {
+ let key = [
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09,
+ 0x08,
+ ];
+ let db_path = base_dir.as_ref().join("teaclave_db");
+ let opt = rusty_leveldb::Options::new_disk_db_with(key);
+ let database = DB::open(&db_path, opt).expect("cannot open teaclave_db");
+ info!("teaclave_db created: {:?}", db_path);
database
}
#[cfg(test_mode)]
mod test_mode {
use super::*;
- pub(crate) fn create_mock_db() -> DB {
+ pub(crate) fn create_mock_db(base_dir: impl AsRef<Path>) -> DB {
let key = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
0x09, 0x08,
];
let opt = rusty_leveldb::Options::new_disk_db_with(key);
- let mut database = DB::open("mock_db", opt).unwrap();
+ let db_path = base_dir.as_ref().join("mock_db");
+ let mut database = DB::open(&db_path, opt).unwrap();
+ info!("mock_db created: {:?}", db_path);
database.put(b"test_get_key", b"test_get_value").unwrap();
database
.put(b"test_delete_key", b"test_delete_value")
diff --git a/services/storage/enclave/src/service.rs b/services/storage/enclave/src/service.rs
index 57188c9..9240c89 100644
--- a/services/storage/enclave/src/service.rs
+++ b/services/storage/enclave/src/service.rs
@@ -132,6 +132,11 @@ impl<'a> DBQueue<'a> {
))),
};
+ info!(
+ "DB.Queue[{}]: dequeue, result.len = {}",
+ std::str::from_utf8(self.key).unwrap(),
+ &result.len()
+ );
// update head
let head_index = head_index.wrapping_add(1);
self.database
@@ -187,6 +192,11 @@ impl TeaclaveStorage for TeaclaveStorageService {
fn put(&self, request: Request<PutRequest>) -> TeaclaveServiceResponseResult<PutResponse> {
let request = request.message;
+ info!(
+ "DB.Put: request.key = {}, request.value.len = {}",
+ std::str::from_utf8(&request.key).unwrap(),
+ &request.value.len()
+ );
self.database
.borrow_mut()
.put(&request.key, &request.value)
@@ -204,6 +214,10 @@ impl TeaclaveStorage for TeaclaveStorageService {
request: Request<DeleteRequest>,
) -> TeaclaveServiceResponseResult<DeleteResponse> {
let request = request.message;
+ info!(
+ "DB.Delete: request.key = {}",
+ std::str::from_utf8(&request.key).unwrap()
+ );
self.database
.borrow_mut()
.delete(&request.key)
diff --git a/services/utils/service_app_utils/Cargo.toml b/services/utils/service_app_utils/Cargo.toml
index 4f16c8e..f2d2672 100644
--- a/services/utils/service_app_utils/Cargo.toml
+++ b/services/utils/service_app_utils/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_service_app_utils"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave service app utils"
license = "Apache-2.0"
@@ -28,7 +28,7 @@ edition = "2018"
ctrlc = { version = "3.1.2" }
env_logger = { version = "0.7.1" }
anyhow = { version = "1.0.26" }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
libc = { version = "0.2.66" }
signal-hook = { version = "0.1.13" }
diff --git a/services/utils/service_enclave_utils/Cargo.toml b/services/utils/service_enclave_utils/Cargo.toml
index 4a3bb77..51833f9 100644
--- a/services/utils/service_enclave_utils/Cargo.toml
+++ b/services/utils/service_enclave_utils/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_service_enclave_utils"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave enclave utils"
license = "Apache-2.0"
@@ -36,7 +36,7 @@ cov = ["sgx_cov", "sgx_trts"]
[dependencies]
anyhow = { version = "1.0.26" }
env_logger = { version = "0.7.1" }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
teaclave_service_enclave_utils_proc_macro = { path = "./proc_macro" }
teaclave_types = { path = "../../../types" }
diff --git a/services/utils/service_enclave_utils/proc_macro/Cargo.toml b/services/utils/service_enclave_utils/proc_macro/Cargo.toml
index 9624fa9..57d4a51 100644
--- a/services/utils/service_enclave_utils/proc_macro/Cargo.toml
+++ b/services/utils/service_enclave_utils/proc_macro/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_service_enclave_utils_proc_macro"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Procedure macro for service enclave utilities"
license = "Apache-2.0"
diff --git a/services/utils/service_enclave_utils/src/lib.rs b/services/utils/service_enclave_utils/src/lib.rs
index 5fb255b..7afe1b3 100644
--- a/services/utils/service_enclave_utils/src/lib.rs
+++ b/services/utils/service_enclave_utils/src/lib.rs
@@ -22,6 +22,7 @@ extern crate sgx_tstd as std;
use log::debug;
use log::error;
+use log::info;
use std::backtrace;
use std::path::PathBuf;
use std::sync::{Arc, SgxRwLock as RwLock};
@@ -76,8 +77,8 @@ impl ServiceEnclave {
pub fn finalize() -> teaclave_types::TeeServiceResult<()> {
debug!("Enclave finalizing");
unsafe {
- debug!("g_peak_heap_used: {}", g_peak_heap_used);
- debug!("g_peak_rsrv_mem_committed: {}", g_peak_rsrv_mem_committed);
+ info!("g_peak_heap_used: {}", g_peak_heap_used);
+ info!("g_peak_rsrv_mem_committed: {}", g_peak_rsrv_mem_committed);
}
#[cfg(feature = "cov")]
diff --git a/tests/coding_wheel.txt b/tests/coding_wheel.txt
new file mode 100644
index 0000000..909610a
--- /dev/null
+++ b/tests/coding_wheel.txt
@@ -0,0 +1,21 @@
+Phe U U CU
+Leu C U GCUA U U GA
+Ser U C GCUA A G CU
+Tyr U A CU
+STOP U A GA U G A
+Cys U G CU
+Trp U G G
+Pro C C GCUA
+His C A CU
+Gln C A GA
+Arg C G GCUA A G GA
+Ile A U CUA
+Met A U G
+Thr A C GCUA
+Asn A A CU
+Lys A A GA
+Val G U GCUA
+Asp G A CU
+Glu G A GA
+Gly G G GCUA
+Ala G C GCUA
\ No newline at end of file
diff --git a/tests/codon_usage_freq_table_human.csv b/tests/codon_usage_freq_table_human.csv
new file mode 100644
index 0000000..4e49f4f
--- /dev/null
+++ b/tests/codon_usage_freq_table_human.csv
@@ -0,0 +1,65 @@
+#,,
+UAA,*,0.28
+UAG,*,0.2
+UGA,*,0.52
+GCU,A,0.26
+GCC,A,0.4
+GCA,A,0.23
+GCG,A,0.11
+UGU,C,0.45
+UGC,C,0.55
+GAU,D,0.46
+GAC,D,0.54
+GAA,E,0.42
+GAG,E,0.58
+UUU,F,0.45
+UUC,F,0.55
+GGU,G,0.16
+GGC,G,0.34
+GGA,G,0.25
+GGG,G,0.25
+CAU,H,0.41
+CAC,H,0.59
+AUU,I,0.36
+AUC,I,0.48
+AUA,I,0.16
+AAA,K,0.42
+AAG,K,0.58
+UUA,L,0.07
+UUG,L,0.13
+CUU,L,0.13
+CUC,L,0.2
+CUA,L,0.07
+CUG,L,0.41
+AUG,M,1
+AAU,N,0.46
+AAC,N,0.54
+CCU,P,0.28
+CCC,P,0.33
+CCA,P,0.27
+CCG,P,0.11
+CAA,Q,0.25
+CAG,Q,0.75
+CGU,R,0.08
+CGC,R,0.19
+CGA,R,0.11
+CGG,R,0.21
+AGA,R,0.2
+AGG,R,0.2
+UCU,S,0.18
+UCC,S,0.22
+UCA,S,0.15
+UCG,S,0.06
+AGU,S,0.15
+AGC,S,0.24
+ACU,T,0.24
+ACC,T,0.36
+ACA,T,0.28
+ACG,T,0.12
+GUU,V,0.18
+GUC,V,0.24
+GUA,V,0.11
+GUG,V,0.47
+UGG,W,1
+UAU,Y,0.43
+UAC,Y,0.57
\ No newline at end of file
diff --git a/tests/fixtures/functions/cleanroom-args/Makefile b/tests/fixtures/functions/cleanroom-args/Makefile
new file mode 100644
index 0000000..cfad87d
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-args/Makefile
@@ -0,0 +1,15 @@
+CC = $(CRW_SDK_PATH)/bin/clang
+CFLAGS += --sysroot=$(CRW_SDK_PATH)/share/wasi-sysroot -Wl,--export=malloc -Wl,--export=free
+CXX = $(CRW_SDK_PATH)/bin/clang++
+CXXFLAGS += --sysroot=$(CRW_SDK_PATH)/share/wasi-sysroot -fno-exceptions -Wl,--export=malloc -Wl,--export=free
+
+
+all: wasm
+
+
+wasm:
+ $(CXX) args.cpp $(CXXFLAGS) -o args.wasm
+
+clean:
+ rm -f args.wasm
+
diff --git a/tests/fixtures/functions/cleanroom-args/args.cpp b/tests/fixtures/functions/cleanroom-args/args.cpp
new file mode 100644
index 0000000..2b67643
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-args/args.cpp
@@ -0,0 +1,9 @@
+#include <iostream>
+
+int main(int argc, char** argv) {
+ std::cout << "Have " << argc << " arguments:" << std::endl;
+ for (int i = 0; i < argc; ++i) {
+ std::cout << argv[i] << std::endl;
+ }
+}
+
diff --git a/tests/fixtures/functions/cleanroom-args/args.wasm b/tests/fixtures/functions/cleanroom-args/args.wasm
new file mode 100755
index 0000000..47a3133
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-args/args.wasm differ
diff --git a/tests/fixtures/functions/cleanroom-args/stdin b/tests/fixtures/functions/cleanroom-args/stdin
new file mode 100644
index 0000000..e69de29
diff --git a/tests/fixtures/functions/cleanroom-algorithm2-hash/coding_wheel.txt b/tests/fixtures/functions/cleanroom-algorithm2-hash/coding_wheel.txt
new file mode 100644
index 0000000..909610a
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-algorithm2-hash/coding_wheel.txt
@@ -0,0 +1,21 @@
+Phe U U CU
+Leu C U GCUA U U GA
+Ser U C GCUA A G CU
+Tyr U A CU
+STOP U A GA U G A
+Cys U G CU
+Trp U G G
+Pro C C GCUA
+His C A CU
+Gln C A GA
+Arg C G GCUA A G GA
+Ile A U CUA
+Met A U G
+Thr A C GCUA
+Asn A A CU
+Lys A A GA
+Val G U GCUA
+Asp G A CU
+Glu G A GA
+Gly G G GCUA
+Ala G C GCUA
\ No newline at end of file
diff --git a/tests/fixtures/functions/cleanroom-algorithm2-hash/codon_usage_freq_table_human.csv b/tests/fixtures/functions/cleanroom-algorithm2-hash/codon_usage_freq_table_human.csv
new file mode 100644
index 0000000..4e49f4f
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-algorithm2-hash/codon_usage_freq_table_human.csv
@@ -0,0 +1,65 @@
+#,,
+UAA,*,0.28
+UAG,*,0.2
+UGA,*,0.52
+GCU,A,0.26
+GCC,A,0.4
+GCA,A,0.23
+GCG,A,0.11
+UGU,C,0.45
+UGC,C,0.55
+GAU,D,0.46
+GAC,D,0.54
+GAA,E,0.42
+GAG,E,0.58
+UUU,F,0.45
+UUC,F,0.55
+GGU,G,0.16
+GGC,G,0.34
+GGA,G,0.25
+GGG,G,0.25
+CAU,H,0.41
+CAC,H,0.59
+AUU,I,0.36
+AUC,I,0.48
+AUA,I,0.16
+AAA,K,0.42
+AAG,K,0.58
+UUA,L,0.07
+UUG,L,0.13
+CUU,L,0.13
+CUC,L,0.2
+CUA,L,0.07
+CUG,L,0.41
+AUG,M,1
+AAU,N,0.46
+AAC,N,0.54
+CCU,P,0.28
+CCC,P,0.33
+CCA,P,0.27
+CCG,P,0.11
+CAA,Q,0.25
+CAG,Q,0.75
+CGU,R,0.08
+CGC,R,0.19
+CGA,R,0.11
+CGG,R,0.21
+AGA,R,0.2
+AGG,R,0.2
+UCU,S,0.18
+UCC,S,0.22
+UCA,S,0.15
+UCG,S,0.06
+AGU,S,0.15
+AGC,S,0.24
+ACU,T,0.24
+ACC,T,0.36
+ACA,T,0.28
+ACG,T,0.12
+GUU,V,0.18
+GUC,V,0.24
+GUA,V,0.11
+GUG,V,0.47
+UGG,W,1
+UAU,Y,0.43
+UAC,Y,0.57
\ No newline at end of file
diff --git a/tests/fixtures/functions/cleanroom-algorithm2-hash/stdin b/tests/fixtures/functions/cleanroom-algorithm2-hash/stdin
new file mode 100644
index 0000000..fb9dfbf
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-algorithm2-hash/stdin
@@ -0,0 +1 @@
+GTITVEELKKLLEQWNLVIGFLFLTWICLLQFAYANRN
diff --git a/tests/fixtures/functions/cleanroom-algorithm2-hash/stdin2 b/tests/fixtures/functions/cleanroom-algorithm2-hash/stdin2
new file mode 100644
index 0000000..f2d207f
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-algorithm2-hash/stdin2
@@ -0,0 +1 @@
+RLSRLRRRSRSLRLLSLLRLLLRSRSLSSSRSSLRRSSRSSLRLLRLRRRLRLLSLLRSRSLRRRRLRLRLLRRRSRRSLLLLSSLSSSLLRRLRLLSSSLLLLLRLSRSLSLLLRSLRSSLSSLLRRLLSLLSSLRLRRLLRRSRLLLSLRSLSRLLSRLSSRRRRSRLRLRRLRSLLRRSRSRSSLLLRRRLRRRSRSRRRLLSSRSRSSRSLRSSSLSLLRRLRLRRSRLLSSLSRSRRLLSLSLSRSSSSSSSLSRLLSLRSRLSSSLSSLLLSSRSSLRSSRLSRRSRSLSLSRSRLLRSLLSLSRLSSLRLRRSSLRSSRLRLLLRLRSRLSLLLLRSSSRSLLLLLLRSSSRRRLRSSRSLRRSLSLRLLLLRSLLLLRSSSLSSLSRRRSSRSLRSRLRLLRLSRSLRRSSLSLSLRSLLLLLSRSRSRSSSRRSLLSRLLLSSRLLSRRRSSSLRSLRRSRSLRRLRLRRLLSRLLLLLRLRRSRSRLLRRLRRLLLLRRRRRRSRLSLLLLLLLLRLRLRLSSSRSLRSRRRSSSSLRLLLSSRRSSSLSLSLSSLRLSLSRLSRLRRSRSRLRLRSSLRRRSSLSRRSRRLLRSRLLRRRRSRSRSRLLSSLSSLRSLSRSRSSLSSSLSLRRLSLLRLLRSSLLRSLSLRRRRRSLSRRSLRRLLSSSSLRSSSLRLSRSLSSSRLSLSSSSSRSLRRLRLLSSLLRSSSLSRLRLLRLSRRSLRRSSSLRSLSLRRLLSSRLLRLRLRSRSLLLRLLRRRLLLSLLRRLLSLSLLRSLLSRSLRRRSSRLLLSSRSRLLRLLRSSSRSRLLSSLLRLSRRLSSSSSSRLLLSSSLLRLLLSSRSSSSRLRLRLSLSLLLRRLSLLLLRLSLLRLSLRRLSSRSLSLSRSSRLSLLRLRRRRRRRLLLSRLRRRLSRLLLLRSSSLRSRRSSLLRSSLSLLLSRRRRRLLLLSLSLLSLLLRSSSSRLRLLRLSSLLLSRSSLSRSLLRSSRRRSLRRRSLRSSLRSRSSSLSLSRSLRSSRLRLRLRRRRLRRSSRRLLRLSSRSSLSSRRSRLSSSRLRSLRLLRRRSRLSRSRRRSRRLSRLSLSLLSSSRSRRSRRLRRLRSLRLSRLRRRRLSSSLSRSSRLRSRRSLRLSLLLLRSRLLSRSLSRSSRLLLRRRRSLLRSSRSRLRLRSLSRSLLLLSRRRLLLLSRRSSSRRRSSLRRSSLSLLLRLRRLRRLSLLSLRRRRRLSSLSRSSSLLSRSLRLSLSLRLSRLLLRRSLLSLRLRRSLRLSRSLLSLSRSRRRSSSLSSSRRLLRSLRSRSSLLSRLSRRSRLSLSRSSRSRLLRRRRLSSLSLSLSLLRLSRSLRLSSSSRRLSRSSSRSSSRLLLSRRLSRSSRLRSSLSSSSLLSLSLRRLLRSLRSRLSLSSRSRRLSSRRRLSRLLSLSLSRSRRLRRRLRLLRLSSSRSSRRSSSRRLLRSSLSSRLLRLLRLSRRLLRRLLSSSLRSS
diff --git a/tests/fixtures/functions/cleanroom-algorithm2-hash/stdout.enc b/tests/fixtures/functions/cleanroom-algorithm2-hash/stdout.enc
new file mode 100644
index 0000000..cf42d1c
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-algorithm2-hash/stdout.enc differ
diff --git a/tests/fixtures/functions/cleanroom-algorithm2/stdin b/tests/fixtures/functions/cleanroom-algorithm2/stdin
new file mode 100644
index 0000000..850871e
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-algorithm2/stdin
@@ -0,0 +1 @@
+MADSNGTITVEELKKLLEQWNLVIGFLFLTWICLLQFAYANR
diff --git a/tests/fixtures/functions/cleanroom-algorithm2/testseq.enc b/tests/fixtures/functions/cleanroom-algorithm2/testseq.enc
new file mode 100644
index 0000000..c485ca1
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-algorithm2/testseq.enc differ
diff --git a/tests/fixtures/functions/cleanroom-algorithm1/app.cpk b/tests/fixtures/functions/cleanroom-algorithm1/app.cpk
new file mode 100644
index 0000000..b776cd9
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-algorithm1/app.cpk differ
diff --git a/tests/fixtures/functions/cleanroom-algorithm1/cleanroom-app-aot.cpk b/tests/fixtures/functions/cleanroom-algorithm1/cleanroom-app-aot.cpk
new file mode 100644
index 0000000..a67ab93
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-algorithm1/cleanroom-app-aot.cpk differ
diff --git a/tests/fixtures/functions/cleanroom-algorithm1/cleanroom-app.cpk b/tests/fixtures/functions/cleanroom-algorithm1/cleanroom-app.cpk
new file mode 100644
index 0000000..e4f1f34
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-algorithm1/cleanroom-app.cpk differ
diff --git a/tests/fixtures/functions/cleanroom-algorithm1/cleanroom-diagnostic.cpk b/tests/fixtures/functions/cleanroom-algorithm1/cleanroom-diagnostic.cpk
new file mode 100644
index 0000000..2de3035
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-algorithm1/cleanroom-diagnostic.cpk differ
diff --git a/tests/fixtures/functions/cleanroom-algorithm1/example.shape b/tests/fixtures/functions/cleanroom-algorithm1/example.shape
new file mode 100644
index 0000000..7ccc399
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-algorithm1/example.shape
@@ -0,0 +1,114 @@
+1 NA
+2 NA
+3 NA
+4 NA
+5 NA
+6 NA
+7 NA
+8 NA
+9 2.0303
+10 3.4545
+11 3.9093
+12 3.3998
+13 2.4215
+14 1.5185
+15 0.26599
+16 0.044856
+17 0
+18 0.24481
+19 0.26915
+20 0.39516
+21 0.42047
+22 0.29272
+23 0.1189
+24 0.10819
+25 0.06756
+26 0.1099
+27 1.1082
+28 0.51335
+29 0.8531
+30 1.2355
+31 1.5989
+32 1.234
+33 1.014
+34 1.1945
+35 0.098511
+36 0.11049
+37 0.061875
+38 0.10532
+39 0.096157
+40 0.10929
+41 0.042156
+42 0.16029
+43 0.32049
+44 1.1684
+45 1.4619
+46 0.040105
+47 0.0025812
+48 0.034826
+49 0.057291
+50 0.039333
+51 0
+52 0.028677
+53 0.21812
+54 0.022805
+55 0.00021709
+56 0.013873
+57 0.013754
+58 0
+59 0
+60 0
+61 0.25117
+62 0.43657
+63 0.43743
+64 0.50744
+65 0.085134
+66 0.019398
+67 0.023139
+68 0.00074496
+69 0
+70 0
+71 0.39526
+72 0.059399
+73 0.033083
+74 0.01536
+75 0.0031007
+76 0.013488
+77 0.010088
+78 0
+79 0
+80 0
+81 0
+82 0.0076068
+83 0.061887
+84 0.031508
+85 0
+86 0
+87 0.023431
+88 0.045501
+89 0.093281
+90 0.27861
+91 0.3089
+92 2.4142
+93 0.24535
+94 0.18949
+95 0.033237
+96 0
+97 0
+98 0.020459
+99 0.24343
+100 1.5
+101 0.14023
+102 0.40887
+103 0.022548
+104 0.018817
+105 0.013818
+106 0.0041629
+107 0.0095489
+108 0.013491
+109 0
+110 0
+111 0.018041
+112 0.013599
+113 0
+114 0.0035904
diff --git a/tests/fixtures/functions/cleanroom-algorithm1/algorithm1.aot b/tests/fixtures/functions/cleanroom-algorithm1/algorithm1.aot
new file mode 100644
index 0000000..ccb75a8
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-algorithm1/algorithm1.aot differ
diff --git a/tests/fixtures/functions/cleanroom-algorithm1/algorithm1_c b/tests/fixtures/functions/cleanroom-algorithm1/algorithm1_c
new file mode 100755
index 0000000..065aa0f
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-algorithm1/algorithm1_c differ
diff --git a/tests/fixtures/functions/cleanroom-algorithm1/algorithm1_v b/tests/fixtures/functions/cleanroom-algorithm1/algorithm1_v
new file mode 100755
index 0000000..f68344b
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-algorithm1/algorithm1_v differ
diff --git a/tests/fixtures/functions/cleanroom-algorithm1/stdin b/tests/fixtures/functions/cleanroom-algorithm1/stdin
new file mode 100644
index 0000000..6949dd6
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-algorithm1/stdin
@@ -0,0 +1 @@
+GCCUGGUGACCAUAGCGAGUCGGUACCACCCCUUCCCAUCCCGAACAGGACCGUGAAACGACUCCGCGCCGAUGAUAGUGCGGAUUCCCGUGUGAAAGUAGGUCAUCGCCAGGC
diff --git a/tests/fixtures/functions/cleanroom-algorithm1/testseq b/tests/fixtures/functions/cleanroom-algorithm1/testseq
new file mode 100644
index 0000000..6949dd6
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-algorithm1/testseq
@@ -0,0 +1 @@
+GCCUGGUGACCAUAGCGAGUCGGUACCACCCCUUCCCAUCCCGAACAGGACCGUGAAACGACUCCGCGCCGAUGAUAGUGCGGAUUCCCGUGUGAAAGUAGGUCAUCGCCAGGC
diff --git a/tests/fixtures/functions/cleanroom-algorithm1/testseq.enc b/tests/fixtures/functions/cleanroom-algorithm1/testseq.enc
new file mode 100644
index 0000000..e9e7cc4
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-algorithm1/testseq.enc differ
diff --git a/tests/fixtures/functions/cleanroom-readfile/Makefile b/tests/fixtures/functions/cleanroom-readfile/Makefile
new file mode 100644
index 0000000..7aadce1
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-readfile/Makefile
@@ -0,0 +1,15 @@
+# C program
+CC = $(CRW_SDK_PATH)/bin/clang
+CFLAGS += --sysroot=$(CRW_SDK_PATH)/share/wasi-sysroot -Wl,--export=malloc -Wl,--export=free
+
+# C++ Program
+CXX = $(CRW_SDK_PATH)/bin/clang++
+CXXFLAGS += --sysroot=$(CRW_SDK_PATH)/share/wasi-sysroot -fno-exceptions -Wl,--export=malloc -Wl,--export=free
+
+all: wasm
+
+wasm:
+ $(CXX) readfile.cpp $(CXXFLAGS) -o readfile.wasm
+
+clean:
+ rm -f *.elf *.wasm
diff --git a/tests/fixtures/functions/cleanroom-readfile/data/a.txt b/tests/fixtures/functions/cleanroom-readfile/data/a.txt
new file mode 100644
index 0000000..7113212
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-readfile/data/a.txt
@@ -0,0 +1,3 @@
+dsfsdafsdafsdafsdafsdafsdaklfjsdaklfjsaldfjsldafjdlsafjsdaklfjsadlfjsda
+hello
+cleanroom
diff --git a/tests/fixtures/functions/cleanroom-readfile/readfile.cpp b/tests/fixtures/functions/cleanroom-readfile/readfile.cpp
new file mode 100644
index 0000000..9ee97ba
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-readfile/readfile.cpp
@@ -0,0 +1,18 @@
+#include <iostream>
+#include <fstream>
+
+
+int main(){
+char line[200];
+std::ifstream rfile;
+rfile.open("data/a.txt");
+if (rfile.is_open()) {
+ while (rfile.getline(line, 200)) {
+ std::cout << line << std::endl;
+ }
+ rfile.close();
+}
+else {
+ std::cout << "can not open the file\n";
+}
+}
diff --git a/tests/fixtures/functions/cleanroom-readfile/readfile.wasm b/tests/fixtures/functions/cleanroom-readfile/readfile.wasm
new file mode 100755
index 0000000..9346ae2
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-readfile/readfile.wasm differ
diff --git a/tests/fixtures/functions/cleanroom-readfile/stdin b/tests/fixtures/functions/cleanroom-readfile/stdin
new file mode 100644
index 0000000..e69de29
diff --git a/tests/fixtures/functions/cleanroom-stderr/Makefile b/tests/fixtures/functions/cleanroom-stderr/Makefile
new file mode 100644
index 0000000..568eeb6
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-stderr/Makefile
@@ -0,0 +1,14 @@
+CXX=$(CRW_SDK_PATH)/bin/clang++
+CXXFLAGS += --sysroot=$(CRW_SDK_PATH)/share/wasi-sysroot -fno-exceptions -Wl,--export=malloc -Wl,--export=free
+
+
+all: wasm
+
+wasm:
+ $(CXX) app.cpp $(CXXFLAGS) -o app.wasm
+
+elf:
+ g++ app.cpp -o app.elf
+
+clean:
+ rm -f *.wasm *.elf
diff --git a/tests/fixtures/functions/cleanroom-stderr/app.cpk b/tests/fixtures/functions/cleanroom-stderr/app.cpk
new file mode 100644
index 0000000..f0357eb
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-stderr/app.cpk differ
diff --git a/tests/fixtures/functions/cleanroom-stderr/app.cpp b/tests/fixtures/functions/cleanroom-stderr/app.cpp
new file mode 100644
index 0000000..d377cae
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-stderr/app.cpp
@@ -0,0 +1,12 @@
+
+
+#include <iostream>
+
+int main(int argc, char** argv) {
+ if (argc != 5){
+ std::cerr << "The number of arguments is not 5";
+ }
+ for (int i = i; i < 5; ++i) {
+ std::cout << argv[i] << std::endl;
+ }
+}
diff --git a/tests/fixtures/functions/cleanroom-stderr/app.wasm b/tests/fixtures/functions/cleanroom-stderr/app.wasm
new file mode 100755
index 0000000..3cb3bbe
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-stderr/app.wasm differ
diff --git a/tests/fixtures/functions/cleanroom-stderr/stdin b/tests/fixtures/functions/cleanroom-stderr/stdin
new file mode 100644
index 0000000..e69de29
diff --git a/tests/fixtures/functions/cleanroom-stderr/testseq.enc b/tests/fixtures/functions/cleanroom-stderr/testseq.enc
new file mode 100644
index 0000000..e9e7cc4
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-stderr/testseq.enc differ
diff --git a/tests/fixtures/functions/cleanroom-stdin/Makefile b/tests/fixtures/functions/cleanroom-stdin/Makefile
new file mode 100644
index 0000000..4ade41c
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-stdin/Makefile
@@ -0,0 +1,14 @@
+CC = $(CRW_SDK_PATH)/bin/clang
+CFLAGS += --sysroot=$(CRW_SDK_PATH)/share/wasi-sysroot -Wl,--export=malloc -Wl,--export=free
+CXX = $(CRW_SDK_PATH)/bin/clang++
+CXXFLAGS += --sysroot=$(CRW_SDK_PATH)/share/wasi-sysroot -fno-exceptions -Wl,--export=malloc -Wl,--export=free
+
+
+all: wasm
+
+
+wasm:
+ $(CXX) getline.cpp $(CXXFLAGS) -o getline.wasm
+
+clean:
+ rm -f getline.wasm
diff --git a/tests/fixtures/functions/cleanroom-stdin/getline.cpp b/tests/fixtures/functions/cleanroom-stdin/getline.cpp
new file mode 100644
index 0000000..d9c02b2
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-stdin/getline.cpp
@@ -0,0 +1,16 @@
+#include <iostream>
+#include <string>
+
+int main ()
+{
+ std::string name;
+
+
+ std::getline (std::cin,name);
+ std::cout << name;
+
+
+ return 0;
+}
+
+
diff --git a/tests/fixtures/functions/cleanroom-stdin/getline.wasm b/tests/fixtures/functions/cleanroom-stdin/getline.wasm
new file mode 100755
index 0000000..b91d583
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-stdin/getline.wasm differ
diff --git a/tests/fixtures/functions/cleanroom-stdin/stdin b/tests/fixtures/functions/cleanroom-stdin/stdin
new file mode 100644
index 0000000..7a9a89b
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-stdin/stdin
@@ -0,0 +1 @@
+ASDSADSADSADSADSADSADSADAS
diff --git a/tests/fixtures/functions/cleanroom-stdout/Makefile b/tests/fixtures/functions/cleanroom-stdout/Makefile
new file mode 100644
index 0000000..4dacdf4
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-stdout/Makefile
@@ -0,0 +1,14 @@
+CC = $(CRW_SDK_PATH)/bin/clang
+CFLAGS += --sysroot=$(CRW_SDK_PATH)/share/wasi-sysroot -Wl,--export=malloc -Wl,--export=free
+CXX = $(CRW_SDK_PATH)/bin/clang++
+CXXFLAGS += --sysroot=$(CRW_SDK_PATH)/share/wasi-sysroot -fno-exceptions -Wl,--export=malloc -Wl,--export=free
+
+
+all: wasm
+
+
+wasm:
+ $(CC) helloworld.c $(CFLAGS) -o helloworld.wasm
+
+clean:
+ rm -f helloworld.wasm
diff --git a/tests/fixtures/functions/cleanroom-stdout/helloworld.c b/tests/fixtures/functions/cleanroom-stdout/helloworld.c
new file mode 100644
index 0000000..5293dc2
--- /dev/null
+++ b/tests/fixtures/functions/cleanroom-stdout/helloworld.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(){
+ printf("hello world cleanroom!");
+ return 0;
+}
diff --git a/tests/fixtures/functions/cleanroom-stdout/helloworld.wasm b/tests/fixtures/functions/cleanroom-stdout/helloworld.wasm
new file mode 100755
index 0000000..b322577
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-stdout/helloworld.wasm differ
diff --git a/tests/fixtures/functions/cleanroom-stdout/stdin b/tests/fixtures/functions/cleanroom-stdout/stdin
new file mode 100644
index 0000000..e69de29
diff --git a/tests/fixtures/functions/cleanroom-stdout/test.aot b/tests/fixtures/functions/cleanroom-stdout/test.aot
new file mode 100644
index 0000000..e07d8bb
Binary files /dev/null and b/tests/fixtures/functions/cleanroom-stdout/test.aot differ
diff --git a/tests/functional/app/Cargo.toml b/tests/functional/app/Cargo.toml
index 5184716..734a535 100644
--- a/tests/functional/app/Cargo.toml
+++ b/tests/functional/app/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_functional_tests"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Enclave test driver"
license = "Apache-2.0"
@@ -25,7 +25,7 @@ build = "build.rs"
edition = "2018"
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
env_logger = { version = "0.7.1" }
anyhow = { version = "1.0.26" }
structopt = { version = "0.3" }
diff --git a/tests/functional/enclave/Cargo.toml b/tests/functional/enclave/Cargo.toml
index e45af59..6d7d6e5 100644
--- a/tests/functional/enclave/Cargo.toml
+++ b/tests/functional/enclave/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_functional_tests_enclave"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Service Functional Test"
license = "Apache-2.0"
@@ -48,7 +48,7 @@ cov = ["teaclave_service_enclave_utils/cov"]
anyhow = { version = "1.0.26" }
inventory = { version = "0.1.6" }
lazy_static = { version = "1.4.0" }
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
serde = { version = "1.0.92" }
serde_json = { version = "1.0.39" }
thiserror = { version = "1.0.9" }
diff --git a/tests/functional/enclave/src/end_to_end/builtin_echo.rs b/tests/functional/enclave/src/end_to_end/builtin_echo.rs
index 15a1f68..75a33c4 100644
--- a/tests/functional/enclave/src/end_to_end/builtin_echo.rs
+++ b/tests/functional/enclave/src/end_to_end/builtin_echo.rs
@@ -27,11 +27,12 @@ pub fn test_echo_task_success() {
let mut client =
create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).unwrap();
+ let function_arg = FunctionArgument::new("message", "", true);
// Register Function
let request = RegisterFunctionRequestBuilder::new()
.name("builtin-echo")
.description("Native Echo Function")
- .arguments(vec!["message"])
+ .arguments(vec![function_arg])
.build();
let response = client.register_function(request).unwrap();
diff --git a/tests/functional/enclave/src/end_to_end/builtin_gbdt_train.rs b/tests/functional/enclave/src/end_to_end/builtin_gbdt_train.rs
index b323666..a47f87b 100644
--- a/tests/functional/enclave/src/end_to_end/builtin_gbdt_train.rs
+++ b/tests/functional/enclave/src/end_to_end/builtin_gbdt_train.rs
@@ -49,15 +49,15 @@ fn register_gbdt_function(client: &mut TeaclaveFrontendClient) -> ExternalID {
let fn_input = FunctionInput::new("training_data", "Input traning data file.", false);
let fn_output = FunctionOutput::new("trained_model", "Output trained model.", false);
let fn_args = vec![
- "feature_size",
- "max_depth",
- "iterations",
- "shrinkage",
- "feature_sample_ratio",
- "data_sample_ratio",
- "min_leaf_size",
- "loss",
- "training_optimization_level",
+ FunctionArgument::new("feature_size", "", true),
+ FunctionArgument::new("max_depth", "", true),
+ FunctionArgument::new("iterations", "", true),
+ FunctionArgument::new("shrinkage", "", true),
+ FunctionArgument::new("feature_sample_ratio", "", true),
+ FunctionArgument::new("data_sample_ratio", "", true),
+ FunctionArgument::new("min_leaf_size", "", true),
+ FunctionArgument::new("loss", "", true),
+ FunctionArgument::new("training_optimization_level", "", true),
];
// Register Function
diff --git a/tests/functional/enclave/src/end_to_end/mesapy_data_fusion.rs b/tests/functional/enclave/src/end_to_end/mesapy_data_fusion.rs
index 69047de..8668290 100644
--- a/tests/functional/enclave/src/end_to_end/mesapy_data_fusion.rs
+++ b/tests/functional/enclave/src/end_to_end/mesapy_data_fusion.rs
@@ -231,10 +231,11 @@ def entrypoint(argv):
"#;
let input_spec = FunctionInput::new("InputData", "Lines of Data", false);
+ let function_arg = FunctionArgument::new("query", "", true);
let request = RegisterFunctionRequestBuilder::new()
.name("wlc")
.description("Mesapy Word Line Count Function")
- .arguments(vec!["query"])
+ .arguments(vec![function_arg])
.payload(script.into())
.executor_type(ExecutorType::Python)
.public(true)
diff --git a/tests/functional/enclave/src/end_to_end/mesapy_echo.rs b/tests/functional/enclave/src/end_to_end/mesapy_echo.rs
index 42d1fb6..b577e59 100644
--- a/tests/functional/enclave/src/end_to_end/mesapy_echo.rs
+++ b/tests/functional/enclave/src/end_to_end/mesapy_echo.rs
@@ -33,6 +33,7 @@ def entrypoint(argv):
assert argv[1] is not None
return argv[1]
";
+ let function_arg = FunctionArgument::new("message", "", true);
// Register Function
let request = RegisterFunctionRequestBuilder::new()
.name("mesapy_echo_demo")
@@ -40,7 +41,7 @@ def entrypoint(argv):
.payload(script.into())
.executor_type(ExecutorType::Python)
.public(true)
- .arguments(vec!["message"])
+ .arguments(vec![function_arg])
.build();
let response = client.register_function(request).unwrap();
diff --git a/tests/functional/enclave/src/execution_service.rs b/tests/functional/enclave/src/execution_service.rs
index 67af16d..00fe7f5 100644
--- a/tests/functional/enclave/src/execution_service.rs
+++ b/tests/functional/enclave/src/execution_service.rs
@@ -53,7 +53,7 @@ fn test_execute_function() {
let put_request = PutRequest::new(ts.key().as_slice(), ts.to_vec().unwrap().as_slice());
let _put_response = storage_client.put(put_request).unwrap();
- std::thread::sleep(std::time::Duration::from_secs(15));
+ std::thread::sleep(std::time::Duration::from_secs(80));
let get_request = GetRequest::new(ts.key().as_slice());
let get_response = storage_client.get(get_request).unwrap();
diff --git a/tests/functional/enclave/src/management_service.rs b/tests/functional/enclave/src/management_service.rs
index 7a975b1..9390998 100644
--- a/tests/functional/enclave/src/management_service.rs
+++ b/tests/functional/enclave/src/management_service.rs
@@ -128,12 +128,13 @@ fn test_get_input_file() {
fn test_register_function() {
let function_input = FunctionInput::new("input", "input_desc", false);
let function_output = FunctionOutput::new("output", "output_desc", false);
+ let function_arg = FunctionArgument::new("arg", "", true);
let request = RegisterFunctionRequestBuilder::new()
.name("mock_function")
.executor_type(ExecutorType::Python)
.payload(b"def entrypoint:\n\treturn".to_vec())
.public(true)
- .arguments(vec!["arg"])
+ .arguments(vec![function_arg])
.inputs(vec![function_input])
.outputs(vec![function_output])
.build();
@@ -148,12 +149,13 @@ fn test_register_function() {
fn test_register_private_function() {
let function_input = FunctionInput::new("input", "input_desc", false);
let function_output = FunctionOutput::new("output", "output_desc", false);
+ let function_arg = FunctionArgument::new("arg", "", true);
let request = RegisterFunctionRequestBuilder::new()
.name("mock_function")
.executor_type(ExecutorType::Python)
.payload(b"def entrypoint:\n\treturn".to_vec())
.public(false)
- .arguments(vec!["arg"])
+ .arguments(vec![function_arg])
.inputs(vec![function_input])
.outputs(vec![function_output])
.user_allowlist(vec!["mock_user".to_string()])
@@ -169,12 +171,13 @@ fn test_register_private_function() {
fn test_delete_function() {
let function_input = FunctionInput::new("input", "input_desc", false);
let function_output = FunctionOutput::new("output", "output_desc", false);
+ let function_arg = FunctionArgument::new("arg", "", true);
let request = RegisterFunctionRequestBuilder::new()
.name("mock_function")
.executor_type(ExecutorType::Python)
.payload(b"def entrypoint:\n\treturn".to_vec())
.public(true)
- .arguments(vec!["arg"])
+ .arguments(vec![function_arg])
.inputs(vec![function_input])
.outputs(vec![function_output])
.build();
@@ -192,12 +195,13 @@ fn test_delete_function() {
fn test_disable_function() {
let function_input = FunctionInput::new("input", "input_desc", false);
let function_output = FunctionOutput::new("output", "output_desc", false);
+ let function_arg = FunctionArgument::new("arg", "", true);
let request = RegisterFunctionRequestBuilder::new()
.name("mock_function")
.executor_type(ExecutorType::Python)
.payload(b"def entrypoint:\n\treturn".to_vec())
.public(true)
- .arguments(vec!["arg"])
+ .arguments(vec![function_arg])
.inputs(vec![function_input])
.outputs(vec![function_output])
.build();
@@ -215,12 +219,13 @@ fn test_disable_function() {
fn test_update_function() {
let function_input = FunctionInput::new("input", "input_desc", false);
let function_output = FunctionOutput::new("output", "output_desc", false);
+ let function_arg = FunctionArgument::new("arg", "", true);
let request = RegisterFunctionRequestBuilder::new()
.name("mock_function")
.executor_type(ExecutorType::Python)
.payload(b"def entrypoint:\n\treturn".to_vec())
.public(true)
- .arguments(vec!["arg"])
+ .arguments(vec![function_arg])
.inputs(vec![function_input])
.outputs(vec![function_output])
.build();
@@ -231,13 +236,14 @@ fn test_update_function() {
let function_input = FunctionInput::new("input", "input_desc", false);
let function_output = FunctionOutput::new("output", "output_desc", false);
+ let function_arg = FunctionArgument::new("arg", "", true);
let request = UpdateFunctionRequestBuilder::new()
.function_id(original_id.clone())
.name("mock_function")
.executor_type(ExecutorType::Python)
.payload(b"def entrypoint:\n\treturn".to_vec())
.public(false)
- .arguments(vec!["arg"])
+ .arguments(vec![function_arg])
.inputs(vec![function_input])
.outputs(vec![function_output])
.user_allowlist(vec!["mock_user".to_string()])
@@ -266,12 +272,13 @@ fn test_list_functions() {
fn test_get_function() {
let function_input = FunctionInput::new("input", "input_desc", false);
let function_output = FunctionOutput::new("output", "output_desc", false);
+ let function_arg = FunctionArgument::new("arg", "", true);
let request = RegisterFunctionRequestBuilder::new()
.name("mock_function")
.executor_type(ExecutorType::Python)
.payload(b"def entrypoint:\n\treturn".to_vec())
.public(false)
- .arguments(vec!["arg"])
+ .arguments(vec![function_arg])
.inputs(vec![function_input])
.outputs(vec![function_output])
.build();
diff --git a/tests/integration/app/Cargo.toml b/tests/integration/app/Cargo.toml
index b7f858d..a1bf9c2 100644
--- a/tests/integration/app/Cargo.toml
+++ b/tests/integration/app/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_integration_tests"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Integration tests"
license = "Apache-2.0"
@@ -25,7 +25,7 @@ build = "build.rs"
edition = "2018"
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
env_logger = { version = "0.7.1" }
anyhow = { version = "1.0.26" }
diff --git a/tests/integration/enclave/Cargo.toml b/tests/integration/enclave/Cargo.toml
index 8218e51..a856fc5 100644
--- a/tests/integration/enclave/Cargo.toml
+++ b/tests/integration/enclave/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_integration_tests_enclave"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Integration Test"
license = "Apache-2.0"
@@ -47,7 +47,7 @@ mesalock_sgx = [
cov = ["teaclave_service_enclave_utils/cov"]
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
anyhow = { version = "1.0.26" }
serde = { version = "1.0.92" }
serde_json = { version = "1.0.39" }
diff --git a/tests/profiling/app/Cargo.toml b/tests/profiling/app/Cargo.toml
new file mode 100644
index 0000000..cd85320
--- /dev/null
+++ b/tests/profiling/app/Cargo.toml
@@ -0,0 +1,41 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+[package]
+name = "teaclave_profiling"
+version = "0.2.0"
+authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
+description = "Enclave test driver"
+license = "Apache-2.0"
+build = "build.rs"
+edition = "2018"
+
+[features]
+default = ["teaclave_binder/app_unit_test"]
+
+[dependencies]
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
+env_logger = { version = "0.7.1" }
+anyhow = { version = "1.0.26" }
+uuid = { version = "0.8.1", features = ["v4"] }
+
+teaclave_file_agent = { path = "../../../file_agent" }
+teaclave_binder = { path = "../../../binder", features = ["app"] }
+teaclave_types = { path = "../../../types" }
+teaclave_test_utils = { path = "../../../tests/utils" }
+
+sgx_types = { version = "1.1.3" }
diff --git a/tests/profiling/app/build.rs b/tests/profiling/app/build.rs
new file mode 100644
index 0000000..168e837
--- /dev/null
+++ b/tests/profiling/app/build.rs
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::env;
+use std::path::PathBuf;
+
+fn choose_sgx_dylib(is_sim: bool) {
+ if is_sim {
+ println!("cargo:rustc-link-lib=dylib=sgx_urts_sim");
+ println!("cargo:rustc-link-lib=dylib=sgx_uae_service_sim");
+ } else {
+ println!("cargo:rustc-link-lib=dylib=sgx_urts");
+ println!("cargo:rustc-link-lib=dylib=sgx_uae_service");
+ }
+}
+
+fn main() {
+ let sdk_dir = env::var("SGX_SDK").unwrap_or("/opt/intel/sgxsdk".into());
+ println!("cargo:rustc-link-search=native={}/lib64", sdk_dir);
+
+ let out_path = env::var_os("ENCLAVE_OUT_DIR").unwrap_or("out".into());
+ let out_dir = &PathBuf::from(out_path);
+
+ println!("cargo:rustc-link-search=native={}", out_dir.display());
+ if let Ok(edl_dir) = env::var("TEACLAVE_EDL_DIR") {
+ println!("cargo:rerun-if-changed={}/Enclave_fa.edl", edl_dir);
+ }
+ println!("cargo:rustc-link-lib=static=Enclave_fa_u");
+
+ let is_sim = match env::var("SGX_MODE") {
+ Ok(ref v) if v == "SW" => true,
+ Ok(ref v) if v == "HW" => false,
+ Err(env::VarError::NotPresent) => false,
+ _ => {
+ panic!("Stop build process, wrong SGX_MODE env provided.");
+ }
+ };
+
+ choose_sgx_dylib(is_sim);
+}
diff --git a/tests/profiling/app/src/main.rs b/tests/profiling/app/src/main.rs
new file mode 100644
index 0000000..e0ffae5
--- /dev/null
+++ b/tests/profiling/app/src/main.rs
@@ -0,0 +1,85 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use log::error;
+use std::env;
+use std::fs;
+use std::io;
+use std::io::Write;
+use std::time::Instant;
+use teaclave_binder::proto::{ECallCommand, RunTestInput, RunTestOutput};
+use teaclave_binder::TeeBinder;
+use teaclave_types::TeeServiceResult;
+use uuid::Uuid;
+
+pub use teaclave_file_agent::ocall_handle_file_request;
+
+fn main() -> anyhow::Result<()> {
+ env_logger::init_from_env(
+ env_logger::Env::new()
+ .filter_or("TEACLAVE_LOG", "RUST_LOG")
+ .write_style_or("TEACLAVE_LOG_STYLE", "RUST_LOG_STYLE"),
+ );
+ let mut args: Vec<String> = env::args().collect();
+ let uuid = Uuid::new_v4().to_string();
+ let test_dir = format!("{}{}", "profiling/", uuid);
+ let stdin_path = format!("{}/{}", test_dir, "stdin");
+ let mut seq_buffer = String::new();
+ let stdin = io::stdin();
+ stdin.read_line(&mut seq_buffer)?;
+ fs::create_dir_all(test_dir)?;
+ let mut output = fs::File::create(stdin_path)?;
+ write!(output, "{}", seq_buffer)?;
+ args.push(uuid.clone());
+ test_app_and_enclave(args);
+
+ let stdout_path = format!("{}/{}/{}", "profiling", uuid, "stdout");
+ let contents = fs::read_to_string(stdout_path).expect("Something went wrong reading the file");
+ print!("{}", contents);
+ Ok(())
+}
+
+fn test_app_and_enclave(args: Vec<String>) {
+ let tee = TeeBinder::new(env!("CARGO_PKG_NAME")).unwrap();
+ tee.run_app_tests();
+ run_enclave_tests(&tee, args).unwrap();
+ tee.finalize();
+}
+
+fn start_enclave_unit_test_driver(tee: &TeeBinder, args: Vec<String>) -> anyhow::Result<()> {
+ let cmd = ECallCommand::RunTest;
+ let input = RunTestInput::new(args);
+ let now = Instant::now();
+ match tee.invoke::<RunTestInput, TeeServiceResult<RunTestOutput>>(cmd, input) {
+ Err(e) => {
+ error!("{:?}", e);
+ std::process::exit(1);
+ }
+ Ok(Err(e)) => {
+ error!("{:?}", e);
+ std::process::exit(1);
+ }
+ _ => (),
+ }
+ println!("Execution time:{}", now.elapsed().as_secs_f32());
+ Ok(())
+}
+
+fn run_enclave_tests(tee: &TeeBinder, args: Vec<String>) -> anyhow::Result<()> {
+ start_enclave_unit_test_driver(tee, args)?;
+ Ok(())
+}
diff --git a/tests/profiling/enclave/Cargo.toml b/tests/profiling/enclave/Cargo.toml
new file mode 100644
index 0000000..8ebbde6
--- /dev/null
+++ b/tests/profiling/enclave/Cargo.toml
@@ -0,0 +1,87 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+[package]
+name = "teaclave_profiling_enclave"
+version = "0.2.0"
+authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
+description = "Enclave Unit Test"
+license = "Apache-2.0"
+edition = "2018"
+
+[lib]
+name = "teaclave_profiling_enclave"
+crate-type = ["staticlib"]
+
+[features]
+default = []
+mesalock_sgx = [
+ "sgx_tstd",
+ "teaclave_binder/mesalock_sgx",
+ "teaclave_rpc/mesalock_sgx",
+ "teaclave_service_enclave_utils/mesalock_sgx",
+ "teaclave_types/mesalock_sgx",
+ "teaclave_types/enclave_unit_test",
+ "teaclave_crypto/mesalock_sgx",
+ "teaclave_crypto/enclave_unit_test",
+ "teaclave_config/mesalock_sgx",
+ "teaclave_worker/mesalock_sgx",
+ "teaclave_worker/enclave_unit_test",
+ "teaclave_executor/mesalock_sgx",
+ "teaclave_executor/enclave_unit_test",
+ "teaclave_function/mesalock_sgx",
+ "teaclave_function/enclave_unit_test",
+ "teaclave_runtime/mesalock_sgx",
+ "teaclave_runtime/enclave_unit_test",
+ "teaclave_executor_context/mesalock_sgx",
+ "teaclave_executor_context/enclave_unit_test",
+ "rusty-leveldb/mesalock_sgx",
+ "rusty-leveldb/enclave_unit_test",
+]
+cov = ["teaclave_service_enclave_utils/cov"]
+
+
+full_builtin_function = [
+ "builtin_cleanroom_native",
+]
+
+builtin_cleanroom_native = []
+
+[dependencies]
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
+anyhow = { version = "1.0.26" }
+serde_json = { version = "1.0.39" }
+serde = { version = "1.0.92" }
+thiserror = { version = "1.0.9" }
+
+teaclave_worker = { path = "../../../worker" }
+teaclave_executor = { path = "../../../executor" }
+teaclave_executor_context = { path = "../../../executor/context" }
+teaclave_function = { path = "../../../function" }
+teaclave_runtime = { path = "../../../runtime" }
+rusty-leveldb = { path = "../../../common/rusty_leveldb_sgx", default-features = false, optional = true }
+
+teaclave_test_utils = { path = "../../utils" }
+teaclave_config = { path = "../../../config" }
+teaclave_binder = { path = "../../../binder" }
+teaclave_rpc = { path = "../../../rpc" }
+teaclave_service_enclave_utils = { path = "../../../services/utils/service_enclave_utils" }
+teaclave_types = { path = "../../../types" }
+teaclave_crypto = { path = "../../../crypto" }
+
+sgx_tstd = { version = "1.1.3", features = ["net", "thread", "backtrace"], optional = true }
+sgx_types = { version = "1.1.3" }
diff --git a/tests/profiling/enclave/Enclave.config.xml b/tests/profiling/enclave/Enclave.config.xml
new file mode 100644
index 0000000..2b2a339
--- /dev/null
+++ b/tests/profiling/enclave/Enclave.config.xml
@@ -0,0 +1,36 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~
+-->
+<!-- Please refer to User's Guide for the explanation of each field -->
+<EnclaveConfiguration>
+ <ProdID>0</ProdID>
+ <ISVSVN>0</ISVSVN>
+ <StackMaxSize>0x200000</StackMaxSize>
+ <HeapMaxSize>0x100000000</HeapMaxSize>
+ <TCSNum>22</TCSNum>
+ <TCSPolicy>0</TCSPolicy>
+ <DisableDebug>0</DisableDebug>
+ <MiscSelect>0</MiscSelect>
+ <MiscMask>0xFFFFFFFF</MiscMask>
+ <ReservedMemMinSize> 0x2000000</ReservedMemMinSize>
+ <ReservedMemInitSize>0x2000000</ReservedMemInitSize>
+ <ReservedMemMaxSize> 0x8000000</ReservedMemMaxSize>
+ <!-- On SGX1 platform, ReservedMemExecutable==1 means set reserved memory as read, write and execute (RWX) -->
+ <ReservedMemExecutable>1</ReservedMemExecutable>
+</EnclaveConfiguration>
diff --git a/tests/profiling/enclave/src/lib.rs b/tests/profiling/enclave/src/lib.rs
new file mode 100644
index 0000000..ad45143
--- /dev/null
+++ b/tests/profiling/enclave/src/lib.rs
@@ -0,0 +1,108 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#![cfg_attr(feature = "mesalock_sgx", no_std)]
+#[cfg(feature = "mesalock_sgx")]
+extern crate sgx_tstd as std;
+
+#[cfg(feature = "mesalock_sgx")]
+use std::collections::HashMap;
+use std::format;
+use std::prelude::v1::*;
+use teaclave_crypto::*;
+use teaclave_runtime::*;
+use teaclave_types::*;
+
+const IN_STDIN_FILE: &str = "input_file";
+const OUT_STDOUT_FILE: &str = "output_file";
+
+use teaclave_binder::proto::{
+ ECallCommand, FinalizeEnclaveInput, FinalizeEnclaveOutput, InitEnclaveInput, InitEnclaveOutput,
+ RunTestInput, RunTestOutput,
+};
+use teaclave_binder::{handle_ecall, register_ecall_handler};
+use teaclave_function::Algorithm2HashTrialTier2;
+use teaclave_service_enclave_utils::ServiceEnclave;
+use teaclave_types::FunctionArguments;
+use teaclave_types::{self, TeeServiceResult};
+
+#[handle_ecall]
+fn handle_run_test(args: &RunTestInput) -> TeeServiceResult<RunTestOutput> {
+ let mut args_vec = args.test_names.clone();
+ let args_len = args_vec.len();
+ let uuid_vec = args_vec.split_off(args_len - 1);
+ let uuid = uuid_vec[0].clone();
+
+ let args_json = serde_json::to_string(&args_vec).unwrap();
+ let mut args = HashMap::new();
+ args.insert("args".to_string(), args_json);
+ let args = FunctionArguments::from(args);
+
+ let stdin = format!("{}/{}/{}", "profiling", uuid, "stdin");
+ let input_info = StagedFileInfo::new(stdin, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let stdout = format!("{}/{}/{}", "profiling", uuid, "stdout");
+ let output_info =
+ StagedFileInfo::new(stdout, TeaclaveFile128Key::random(), FileAuthTag::mock());
+
+ let config_file1 = "./coding_wheel.txt";
+ let config_file_info1 = StagedFileInfo::new(
+ config_file1,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let config_file2 = "./codon_usage_freq_table_human.csv";
+ let config_file_info2 = StagedFileInfo::new(
+ config_file2,
+ TeaclaveFile128Key::random(),
+ FileAuthTag::mock(),
+ );
+
+ let input_files = StagedFiles::new(
+ hashmap!(IN_STDIN_FILE => input_info, "./coding_wheel.txt" => config_file_info1, "./codon_usage_freq_table_human.csv" => config_file_info2),
+ );
+
+ let output_files = StagedFiles::new(hashmap!(OUT_STDOUT_FILE => output_info));
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+ let function = Algorithm2HashTrialTier2;
+
+ let summary = function.run(args, runtime).unwrap();
+ if summary.contains("Succeeded") {
+ return Ok(RunTestOutput);
+ }
+ Err(TeeServiceError::ServiceError)
+}
+
+#[handle_ecall]
+fn handle_init_enclave(_: &InitEnclaveInput) -> TeeServiceResult<InitEnclaveOutput> {
+ ServiceEnclave::init(env!("CARGO_PKG_NAME"))?;
+ Ok(InitEnclaveOutput)
+}
+
+#[handle_ecall]
+fn handle_finalize_enclave(_: &FinalizeEnclaveInput) -> TeeServiceResult<FinalizeEnclaveOutput> {
+ ServiceEnclave::finalize()?;
+ Ok(FinalizeEnclaveOutput)
+}
+
+register_ecall_handler!(
+ type ECallCommand,
+ (ECallCommand::RunTest, RunTestInput, RunTestOutput),
+ (ECallCommand::InitEnclave, InitEnclaveInput, InitEnclaveOutput),
+ (ECallCommand::FinalizeEnclave, FinalizeEnclaveInput, FinalizeEnclaveOutput),
+);
diff --git a/tests/scripts/auth_http_server.py b/tests/scripts/auth_http_server.py
new file mode 100755
index 0000000..3ae5275
--- /dev/null
+++ b/tests/scripts/auth_http_server.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python3
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from http.server import SimpleHTTPRequestHandler, HTTPServer
+from socketserver import ThreadingMixIn
+import threading
+import socketserver
+import sys
+
+key = ""
+
+
+class HTTPRequestHandler(SimpleHTTPRequestHandler):
+
+ def do_HEAD(self):
+ self.send_response(200)
+ self.send_header('Content-type', 'text/html')
+ self.end_headers()
+
+ def do_AUTHHEAD(self):
+ self.send_response(401)
+ self.send_header('WWW-Authenticate', 'Basic realm=\"Test\"')
+ self.send_header('Content-type', 'text/html')
+ self.end_headers()
+
+ def do_GET(self):
+ global key
+ ''' Present frontpage with user authentication. '''
+ if self.headers.get('Authorization') == None:
+ self.do_AUTHHEAD()
+ pass
+ elif self.headers.get('Authorization') == 'Basic ' + key:
+ SimpleHTTPRequestHandler.do_GET(self)
+ pass
+ else:
+ self.do_AUTHHEAD()
+ pass
+
+ def do_PUT(self):
+ global key
+ if self.headers.get('Authorization') == None:
+ self.do_AUTHHEAD()
+ pass
+ elif self.headers.get('Authorization') == 'Basic ' + key:
+ length = int(self.headers["Content-Length"])
+
+ path = self.translate_path(self.path)
+ with open(path, "wb") as dst:
+ dst.write(self.rfile.read(length))
+
+ self.send_response(200)
+ self.end_headers()
+ else:
+ self.do_AUTHHEAD()
+ pass
+
+
+class ThreadingSimpleServer(ThreadingMixIn, HTTPServer):
+ pass
+
+
+if __name__ == '__main__':
+ if len(sys.argv) == 3:
+ port = int(sys.argv[1])
+ key = sys.argv[2]
+ print(key)
+ else:
+ print("./auth_http_server.py $port $key")
+ sys.exit(-1)
+ socketserver.TCPServer.allow_reuse_address = True
+ with ThreadingSimpleServer(('0.0.0.0', port), HTTPRequestHandler) as httpd:
+ print("serving at port", port)
+ httpd.serve_forever()
diff --git a/tests/unit/app/Cargo.toml b/tests/unit/app/Cargo.toml
index 836295e..8f50e0c 100644
--- a/tests/unit/app/Cargo.toml
+++ b/tests/unit/app/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_unit_tests"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Enclave test driver"
license = "Apache-2.0"
@@ -28,7 +28,7 @@ edition = "2018"
default = ["teaclave_binder/app_unit_test"]
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
env_logger = { version = "0.7.1" }
anyhow = { version = "1.0.26" }
diff --git a/tests/unit/enclave/Cargo.toml b/tests/unit/enclave/Cargo.toml
index 57c750a..6df75a4 100644
--- a/tests/unit/enclave/Cargo.toml
+++ b/tests/unit/enclave/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_unit_tests_enclave"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Enclave Unit Test"
license = "Apache-2.0"
@@ -71,7 +71,7 @@ mesalock_sgx = [
cov = ["teaclave_service_enclave_utils/cov"]
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
anyhow = { version = "1.0.26" }
serde = { version = "1.0.92" }
thiserror = { version = "1.0.9" }
diff --git a/tests/unit/enclave/Enclave.config.xml b/tests/unit/enclave/Enclave.config.xml
index 8f2d590..3fe846a 100644
--- a/tests/unit/enclave/Enclave.config.xml
+++ b/tests/unit/enclave/Enclave.config.xml
@@ -22,10 +22,15 @@
<ProdID>0</ProdID>
<ISVSVN>0</ISVSVN>
<StackMaxSize>0x200000</StackMaxSize>
- <HeapMaxSize>0x8000000</HeapMaxSize>
+ <HeapMaxSize>0x10000000</HeapMaxSize>
<TCSNum>22</TCSNum>
<TCSPolicy>0</TCSPolicy>
<DisableDebug>0</DisableDebug>
<MiscSelect>0</MiscSelect>
<MiscMask>0xFFFFFFFF</MiscMask>
+ <ReservedMemMinSize> 0x2000000</ReservedMemMinSize>
+ <ReservedMemInitSize>0x2000000</ReservedMemInitSize>
+ <ReservedMemMaxSize> 0x8000000</ReservedMemMaxSize>
+ <!-- On SGX1 platform, ReservedMemExecutable==1 means set reserved memory as read, write and execute (RWX) -->
+ <ReservedMemExecutable>1</ReservedMemExecutable>
</EnclaveConfiguration>
diff --git a/tests/unit/enclave/src/lib.rs b/tests/unit/enclave/src/lib.rs
index 5262123..da22cf2 100644
--- a/tests/unit/enclave/src/lib.rs
+++ b/tests/unit/enclave/src/lib.rs
@@ -53,7 +53,6 @@ fn handle_run_test(_: &RunTestInput) -> TeeServiceResult<RunTestOutput> {
#[cfg(not(sgx_sim))]
assert!(teaclave_attestation::tests::run_tests());
-
Ok(RunTestOutput)
}
diff --git a/tests/utils/Cargo.toml b/tests/utils/Cargo.toml
index f9d25c7..9995c31 100644
--- a/tests/utils/Cargo.toml
+++ b/tests/utils/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_test_utils"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave test utility"
license = "Apache-2.0"
diff --git a/third_party/wamr.patch b/third_party/wamr.patch
deleted file mode 100644
index 793b07d..0000000
--- a/third_party/wamr.patch
+++ /dev/null
@@ -1,651 +0,0 @@
-diff --git a/core/shared/platform/teaclave-sgx/platform_internal.h b/core/shared/platform/teaclave-sgx/platform_internal.h
-new file mode 100644
-index 0000000..93417b4
---- /dev/null
-+++ b/core/shared/platform/teaclave-sgx/platform_internal.h
-@@ -0,0 +1,58 @@
-+/*
-+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
-+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-+ */
-+
-+#ifndef _PLATFORM_INTERNAL_H
-+#define _PLATFORM_INTERNAL_H
-+
-+#include <inttypes.h>
-+#include <stdbool.h>
-+#include <assert.h>
-+#include <time.h>
-+#include <string.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <math.h>
-+#include <unistd.h>
-+#include <stdarg.h>
-+#include <ctype.h>
-+#include <limits.h>
-+#include <errno.h>
-+#include <sgx_thread.h>
-+#include <pthread.h>
-+
-+#include "sgx_error.h"
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#ifndef BH_PLATFORM_LINUX_SGX
-+#define BH_PLATFORM_LINUX_SGX
-+#endif
-+
-+#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
-+
-+/* Stack size of applet threads's native part. */
-+#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
-+
-+/* Default thread priority */
-+#define BH_THREAD_DEFAULT_PRIORITY 0
-+
-+typedef pthread_t korp_thread;
-+typedef pthread_t korp_tid;
-+typedef pthread_mutex_t korp_mutex;
-+typedef pthread_cond_t korp_cond;
-+
-+typedef void (*os_print_function_t)(const char* message);
-+void os_set_print_function(os_print_function_t pf);
-+
-+char *strcpy(char *dest, const char *src);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif /* end of _PLATFORM_INTERNAL_H */
-+
-diff --git a/core/shared/platform/teaclave-sgx/sgx_platform.c b/core/shared/platform/teaclave-sgx/sgx_platform.c
-new file mode 100644
-index 0000000..e819f26
---- /dev/null
-+++ b/core/shared/platform/teaclave-sgx/sgx_platform.c
-@@ -0,0 +1,172 @@
-+/*
-+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
-+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-+ */
-+
-+#include "platform_api_vmcore.h"
-+#include "platform_api_extension.h"
-+#include "sgx_rsrv_mem_mngr.h"
-+
-+#define FIXED_BUFFER_SIZE (1<<9)
-+
-+static os_print_function_t print_function = NULL;
-+
-+int bh_platform_init()
-+{
-+ return 0;
-+}
-+
-+void
-+bh_platform_destroy()
-+{
-+}
-+
-+void *
-+os_malloc(unsigned size)
-+{
-+ return malloc(size);
-+}
-+
-+void *
-+os_realloc(void *ptr, unsigned size)
-+{
-+ return realloc(ptr, size);
-+}
-+
-+void
-+os_free(void *ptr)
-+{
-+ free(ptr);
-+}
-+
-+int putchar(int c)
-+{
-+ return 0;
-+}
-+
-+int puts(const char *s)
-+{
-+ return 0;
-+}
-+
-+void os_set_print_function(os_print_function_t pf)
-+{
-+ print_function = pf;
-+}
-+
-+int os_printf(const char *message, ...)
-+{
-+ if (print_function != NULL) {
-+ char msg[FIXED_BUFFER_SIZE] = { '\0' };
-+ va_list ap;
-+ va_start(ap, message);
-+ vsnprintf(msg, FIXED_BUFFER_SIZE, message, ap);
-+ va_end(ap);
-+ print_function(msg);
-+ }
-+
-+ return 0;
-+}
-+
-+int os_vprintf(const char * format, va_list arg)
-+{
-+ if (print_function != NULL) {
-+ char msg[FIXED_BUFFER_SIZE] = { '\0' };
-+ vsnprintf(msg, FIXED_BUFFER_SIZE, format, arg);
-+ print_function(msg);
-+ }
-+
-+ return 0;
-+}
-+
-+char *strcpy(char *dest, const char *src)
-+{
-+ const unsigned char *s = src;
-+ unsigned char *d = dest;
-+
-+ while ((*d++ = *s++));
-+ return dest;
-+}
-+
-+void* os_mmap(void *hint, size_t size, int prot, int flags)
-+{
-+ int mprot = 0;
-+ uint64 aligned_size, page_size;
-+ void* ret = NULL;
-+ sgx_status_t st = 0;
-+
-+ page_size = getpagesize();
-+ aligned_size = (size + page_size - 1) & ~(page_size - 1);
-+
-+ if (aligned_size >= UINT32_MAX)
-+ return NULL;
-+
-+ ret = sgx_alloc_rsrv_mem(aligned_size);
-+ if (ret == NULL) {
-+ os_printf("os_mmap(size=%u, aligned size=%lu, prot=0x%x) failed.",
-+ size, aligned_size, prot);
-+ return NULL;
-+ }
-+
-+ if (prot & MMAP_PROT_READ)
-+ mprot |= SGX_PROT_READ;
-+ if (prot & MMAP_PROT_WRITE)
-+ mprot |= SGX_PROT_WRITE;
-+ if (prot & MMAP_PROT_EXEC)
-+ mprot |= SGX_PROT_EXEC;
-+
-+ st = sgx_tprotect_rsrv_mem(ret, aligned_size, mprot);
-+ if (st != SGX_SUCCESS) {
-+ os_printf("os_mmap(size=%u, prot=0x%x) failed to set protect.",
-+ size, prot);
-+ sgx_free_rsrv_mem(ret, aligned_size);
-+ return NULL;
-+ }
-+
-+ return ret;
-+}
-+
-+void os_munmap(void *addr, size_t size)
-+{
-+ uint64 aligned_size, page_size;
-+
-+ page_size = getpagesize();
-+ aligned_size = (size + page_size - 1) & ~(page_size - 1);
-+ sgx_free_rsrv_mem(addr, aligned_size);
-+}
-+
-+int os_mprotect(void *addr, size_t size, int prot)
-+{
-+ int mprot = 0;
-+ sgx_status_t st = 0;
-+ uint64 aligned_size, page_size;
-+
-+ page_size = getpagesize();
-+ aligned_size = (size + page_size - 1) & ~(page_size - 1);
-+
-+ if (prot & MMAP_PROT_READ)
-+ mprot |= SGX_PROT_READ;
-+ if (prot & MMAP_PROT_WRITE)
-+ mprot |= SGX_PROT_WRITE;
-+ if (prot & MMAP_PROT_EXEC)
-+ mprot |= SGX_PROT_EXEC;
-+ st = sgx_tprotect_rsrv_mem(addr, aligned_size, mprot);
-+ if (st != SGX_SUCCESS)
-+ os_printf("os_mprotect(addr=0x%"PRIx64", size=%u, prot=0x%x) failed.",
-+ (uintptr_t)addr, size, prot);
-+
-+ return (st == SGX_SUCCESS? 0:-1);
-+}
-+
-+uint64
-+os_time_get_boot_microsecond()
-+{
-+ /* TODO */
-+ return 0;
-+}
-+
-+void
-+os_dcache_flush(void)
-+{
-+}
-+
-diff --git a/core/shared/platform/teaclave-sgx/sgx_rsrv_mem_mngr.h b/core/shared/platform/teaclave-sgx/sgx_rsrv_mem_mngr.h
-new file mode 100644
-index 0000000..b32a68b
---- /dev/null
-+++ b/core/shared/platform/teaclave-sgx/sgx_rsrv_mem_mngr.h
-@@ -0,0 +1,90 @@
-+/*
-+ * Copyright (C) 2011-2019 Intel Corporation. All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in
-+ * the documentation and/or other materials provided with the
-+ * distribution.
-+ * * Neither the name of Intel Corporation nor the names of its
-+ * contributors may be used to endorse or promote products derived
-+ * from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ */
-+
-+/*
-+ * This file is copied from https://github.com/intel/linux-sgx/blob/4589daddd58bec7367a6a9de3fe301e6de17671a/common/inc/internal/sgx_rsrv_mem_mngr.h
-+ * The reason we copied here is that the official SGX SDK release has
-+ * not included this header file yet.
-+ */
-+
-+#pragma once
-+
-+#ifndef _SGX_RSRV_MEM_MNGR_H_
-+#define _SGX_RSRV_MEM_MNGR_H_
-+
-+#include "stdint.h"
-+#include "sgx_error.h"
-+
-+#define SGX_PROT_READ 0x1 /* page can be read */
-+#define SGX_PROT_WRITE 0x2 /* page can be written */
-+#define SGX_PROT_EXEC 0x4 /* page can be executed */
-+#define SGX_PROT_NONE 0x0 /* page can not be accessed */
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+ /* Allocate a range of EPC memory from the reserved memory area with RW permission
-+ *
-+ * Parameters:
-+ * Inputs: length [in]: Size of region to be allocated in bytes. Page aligned
-+ * Return: Starting address of the new allocated memory area on success; otherwise NULL
-+ */
-+ void * sgx_alloc_rsrv_mem(size_t length);
-+
-+
-+ /* Free a range of EPC memory from the reserved memory area
-+ *
-+ * Parameters:
-+ * Inputs: addr[in]: Starting address of region to be freed. Page aligned.
-+ * length[in]: The length of the memory to be freed in bytes. Page aligned
-+ * Return: 0 on success; otherwise -1
-+ */
-+ int sgx_free_rsrv_mem(void * addr, size_t length);
-+
-+
-+ /* Modify the access permissions of the pages in the reserved memory area.
-+ *
-+ * Parameters:
-+ * Inputs: addr[in]: Starting address of region which needs to change access permission. Page aligned.
-+ * length[in]: The length of the memory to be manipulated in bytes. Page aligned.
-+ * prot[in]: The target memory protection.
-+ * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h
-+ */
-+ sgx_status_t sgx_tprotect_rsrv_mem(void *addr, size_t len, int prot);
-+
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
-+
-diff --git a/core/shared/platform/teaclave-sgx/sgx_thread.c b/core/shared/platform/teaclave-sgx/sgx_thread.c
-new file mode 100644
-index 0000000..d1503b4
---- /dev/null
-+++ b/core/shared/platform/teaclave-sgx/sgx_thread.c
-@@ -0,0 +1,180 @@
-+/*
-+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
-+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-+ */
-+
-+#include "platform_api_vmcore.h"
-+#include "platform_api_extension.h"
-+
-+#ifndef SGX_DISABLE_PTHREAD
-+typedef struct {
-+ thread_start_routine_t start;
-+ void *arg;
-+} thread_wrapper_arg;
-+
-+static void *os_thread_wrapper(void *arg)
-+{
-+ thread_wrapper_arg * targ = arg;
-+ thread_start_routine_t start_func = targ->start;
-+ void *thread_arg = targ->arg;
-+ os_printf("THREAD CREATED %p\n", &targ);
-+ BH_FREE(targ);
-+ start_func(thread_arg);
-+ return NULL;
-+}
-+
-+int os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
-+ void *arg, unsigned int stack_size, int prio)
-+{
-+ thread_wrapper_arg *targ;
-+
-+ assert(tid);
-+ assert(start);
-+
-+ targ = (thread_wrapper_arg *) BH_MALLOC(sizeof(*targ));
-+ if (!targ) {
-+ return BHT_ERROR;
-+ }
-+
-+ targ->start = start;
-+ targ->arg = arg;
-+
-+ if (pthread_create(tid, NULL, os_thread_wrapper, targ) != 0) {
-+ BH_FREE(targ);
-+ return BHT_ERROR;
-+ }
-+
-+ return BHT_OK;
-+}
-+
-+int os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
-+ unsigned int stack_size)
-+{
-+ return os_thread_create_with_prio(tid, start, arg, stack_size,
-+ BH_THREAD_DEFAULT_PRIORITY);
-+}
-+#endif
-+
-+korp_tid os_self_thread()
-+{
-+#ifndef SGX_DISABLE_PTHREAD
-+ return pthread_self();
-+#else
-+ return 0;
-+#endif
-+}
-+
-+int os_mutex_init(korp_mutex *mutex)
-+{
-+#ifndef SGX_DISABLE_PTHREAD
-+ pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
-+ *mutex = m;
-+#endif
-+ return BHT_OK;
-+}
-+
-+int os_mutex_destroy(korp_mutex *mutex)
-+{
-+#ifndef SGX_DISABLE_PTHREAD
-+ pthread_mutex_destroy(mutex);
-+#endif
-+ return BHT_OK;
-+}
-+
-+int os_mutex_lock(korp_mutex *mutex)
-+{
-+#ifndef SGX_DISABLE_PTHREAD
-+ return pthread_mutex_lock(mutex);
-+#else
-+ return 0;
-+#endif
-+}
-+
-+int os_mutex_unlock(korp_mutex *mutex)
-+{
-+#ifndef SGX_DISABLE_PTHREAD
-+ return pthread_mutex_unlock(mutex);
-+#else
-+ return 0;
-+#endif
-+}
-+
-+int os_cond_init(korp_cond *cond)
-+{
-+#ifndef SGX_DISABLE_PTHREAD
-+ pthread_cond_t c = PTHREAD_COND_INITIALIZER;
-+ *cond = c;
-+#endif
-+ return BHT_OK;
-+}
-+
-+int os_cond_destroy(korp_cond *cond)
-+{
-+#ifndef SGX_DISABLE_PTHREAD
-+ pthread_cond_destroy(cond);
-+#endif
-+ return BHT_OK;
-+}
-+
-+int os_cond_wait(korp_cond *cond, korp_mutex *mutex)
-+{
-+#ifndef SGX_DISABLE_PTHREAD
-+ assert(cond);
-+ assert(mutex);
-+
-+ if (pthread_cond_wait(cond, mutex) != BHT_OK)
-+ return BHT_ERROR;
-+
-+#endif
-+ return BHT_OK;
-+}
-+
-+int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
-+{
-+ os_printf("warning: SGX pthread_cond_timedwait isn't supported, "
-+ "calling pthread_cond_wait instead!\n");
-+ return BHT_ERROR;
-+}
-+
-+int os_cond_signal(korp_cond *cond)
-+{
-+#ifndef SGX_DISABLE_PTHREAD
-+ assert(cond);
-+
-+ if (pthread_cond_signal(cond) != BHT_OK)
-+ return BHT_ERROR;
-+
-+#endif
-+ return BHT_OK;
-+}
-+
-+int os_thread_join(korp_tid thread, void **value_ptr)
-+{
-+#ifndef SGX_DISABLE_PTHREAD
-+ return pthread_join(thread, value_ptr);
-+#else
-+ return 0;
-+#endif
-+}
-+
-+int os_thread_detach(korp_tid thread)
-+{
-+ /* SGX pthread_detach isn't provided, return directly. */
-+ return 0;
-+}
-+
-+void os_thread_exit(void *retval)
-+{
-+#ifndef SGX_DISABLE_PTHREAD
-+ pthread_exit(retval);
-+#else
-+ return;
-+#endif
-+}
-+
-+uint8 *os_thread_get_stack_boundary()
-+{
-+ /* TODO: get sgx stack boundary */
-+ return NULL;
-+}
-+
-diff --git a/core/shared/platform/teaclave-sgx/shared_platform.cmake b/core/shared/platform/teaclave-sgx/shared_platform.cmake
-new file mode 100644
-index 0000000..fa3a7aa
---- /dev/null
-+++ b/core/shared/platform/teaclave-sgx/shared_platform.cmake
-@@ -0,0 +1,33 @@
-+# Copyright (C) 2019 Intel Corporation. All rights reserved.
-+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-+
-+set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
-+
-+add_definitions(-DBH_PLATFORM_LINUX_SGX)
-+
-+include_directories(${PLATFORM_SHARED_DIR})
-+include_directories(${PLATFORM_SHARED_DIR}/../include)
-+
-+if ("$ENV{SGX_SDK}" STREQUAL "")
-+ set (SGX_SDK_DIR "/opt/intel/sgxsdk")
-+else()
-+ set (SGX_SDK_DIR $ENV{SGX_SDK})
-+endif()
-+
-+include_directories (${SGX_SDK_DIR}/include)
-+if (NOT BUILD_UNTRUST_PART EQUAL 1)
-+ include_directories (${SGX_SDK_DIR}/include/tlibc
-+ ${SGX_SDK_DIR}/include/libcxx)
-+endif ()
-+
-+if (NOT WAMR_BUILD_LIBC_WASI EQUAL 1)
-+ add_definitions(-DSGX_DISABLE_WASI)
-+endif ()
-+
-+if (NOT WAMR_BUILD_THREAD_MGR EQUAL 1)
-+ add_definitions(-DSGX_DISABLE_PTHREAD)
-+endif ()
-+
-+file (GLOB source_all ${PLATFORM_SHARED_DIR}/*.c)
-+
-+set (PLATFORM_SHARED_SOURCE ${source_all})
-diff --git a/product-mini/platforms/teaclave-sgx/CMakeLists.txt b/product-mini/platforms/teaclave-sgx/CMakeLists.txt
-new file mode 100644
-index 0000000..d4c71d8
---- /dev/null
-+++ b/product-mini/platforms/teaclave-sgx/CMakeLists.txt
-@@ -0,0 +1,82 @@
-+# Copyright (C) 2019 Intel Corporation. All rights reserved.
-+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-+
-+cmake_minimum_required (VERSION 2.8)
-+
-+project (iwasm)
-+
-+set (WAMR_BUILD_PLATFORM "teaclave-sgx")
-+
-+# Reset default linker flags
-+set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
-+set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
-+
-+# Set WAMR_BUILD_TARGET
-+if (NOT DEFINED WAMR_BUILD_TARGET)
-+ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
-+ # Build as X86_64 by default in 64-bit platform
-+ set (WAMR_BUILD_TARGET "X86_64")
-+ else ()
-+ # Build as X86_32 by default in 32-bit platform
-+ set (WAMR_BUILD_TARGET "X86_32")
-+ endif ()
-+endif ()
-+
-+if (NOT CMAKE_BUILD_TYPE)
-+ set(CMAKE_BUILD_TYPE Release)
-+endif ()
-+
-+if (NOT DEFINED WAMR_BUILD_INTERP)
-+ # Enable Interpreter by default
-+ set (WAMR_BUILD_INTERP 1)
-+endif ()
-+
-+if (NOT DEFINED WAMR_BUILD_AOT)
-+ # Enable AOT by default
-+ # Please install Intel SGX SDKv2.8 or later.
-+ set (WAMR_BUILD_AOT 0)
-+endif ()
-+
-+if (NOT DEFINED WAMR_BUILD_JIT)
-+ # Disable JIT by default.
-+ set (WAMR_BUILD_JIT 0)
-+endif ()
-+
-+if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN)
-+ # Enable libc builtin support by default
-+ set (WAMR_BUILD_LIBC_BUILTIN 0)
-+endif ()
-+
-+if (NOT DEFINED WAMR_BUILD_LIBC_WASI)
-+ # Enable libc wasi support by default
-+ set (WAMR_BUILD_LIBC_WASI 0)
-+endif ()
-+
-+if (NOT DEFINED WAMR_BUILD_FAST_INTERP)
-+ # Enable fast interpreter
-+ set (WAMR_BUILD_FAST_INTERP 0)
-+endif ()
-+
-+if (NOT DEFINED WAMR_BUILD_MULTI_MODULE)
-+ # Enable multiple modules
-+ set (WAMR_BUILD_MULTI_MODULE 0)
-+endif ()
-+
-+if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
-+ # Enable pthread library by default
-+ set (WAMR_BUILD_LIB_PTHREAD 0)
-+endif ()
-+
-+if (COLLECT_CODE_COVERAGE EQUAL 1)
-+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
-+endif ()
-+
-+set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
-+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \
-+ -Wall -Wno-unused-parameter -Wno-pedantic \
-+ -nostdinc -fvisibility=hidden -fpie" )
-+
-+set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
-+
-+include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
-+add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
diff --git a/third_party/wasm-micro-runtime b/third_party/wasm-micro-runtime
index d856af6..f0b16f7 160000
--- a/third_party/wasm-micro-runtime
+++ b/third_party/wasm-micro-runtime
@@ -1 +1 @@
-Subproject commit d856af6c33591815ab4c890f0606bc99ee8135ad
+Subproject commit f0b16f7b5f8e02a1c876eeda7d36d166eae2ec8a
diff --git a/tool/app/Cargo.toml b/tool/app/Cargo.toml
index 83cad53..df28b19 100644
--- a/tool/app/Cargo.toml
+++ b/tool/app/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_sgx_tool"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave SGX Tool"
license = "Apache-2.0"
@@ -25,7 +25,7 @@ build = "build.rs"
edition = "2018"
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
env_logger = { version = "0.7.1" }
anyhow = { version = "1.0.26" }
serde = { version = "1.0.92", features = ["derive"] }
diff --git a/tool/app/src/main.rs b/tool/app/src/main.rs
index 6183de3..4d595d2 100644
--- a/tool/app/src/main.rs
+++ b/tool/app/src/main.rs
@@ -17,20 +17,24 @@
use anyhow::anyhow;
use anyhow::Result;
+use std::path::PathBuf;
use std::process;
use structopt::StructOpt;
-use teaclave_binder::proto::{ECallCommand, RawJsonInput, RawJsonOutput};
+use teaclave_binder::proto::{ECallCommand, RawJsonInput, RawJsonOutput, SubCmd};
use teaclave_binder::TeeBinder;
use teaclave_types::TeeServiceResult;
+fn backup_db(opt: &BackupDbOpt) -> anyhow::Result<()> {
+ let tee = TeeBinder::new(env!("CARGO_PKG_NAME"))?;
+ start_db_backup(&tee, opt)?;
+ tee.finalize();
+
+ Ok(())
+}
+
fn attestation(opt: &AttestationOpt) -> anyhow::Result<()> {
- env_logger::init_from_env(
- env_logger::Env::new()
- .filter_or("TEACLAVE_LOG", "RUST_LOG")
- .write_style_or("TEACLAVE_LOG_STYLE", "RUST_LOG_STYLE"),
- );
let tee = TeeBinder::new(env!("CARGO_PKG_NAME"))?;
- run(&tee, opt)?;
+ start_enclave_remote_attestation(&tee, opt)?;
tee.finalize();
Ok(())
@@ -39,7 +43,7 @@ fn attestation(opt: &AttestationOpt) -> anyhow::Result<()> {
fn start_enclave_remote_attestation(tee: &TeeBinder, opt: &AttestationOpt) -> anyhow::Result<()> {
let cmd = ECallCommand::Raw;
let json = serde_json::to_string(opt)?;
- let input = RawJsonInput::new(json);
+ let input = RawJsonInput::new(SubCmd::Attestation, json);
match tee.invoke::<RawJsonInput, TeeServiceResult<RawJsonOutput>>(cmd, input) {
Err(e) => Err(anyhow!("{:?}", e)),
Ok(Err(e)) => Err(anyhow!("{:?}", e)),
@@ -47,10 +51,15 @@ fn start_enclave_remote_attestation(tee: &TeeBinder, opt: &AttestationOpt) -> an
}
}
-fn run(tee: &TeeBinder, opt: &AttestationOpt) -> anyhow::Result<()> {
- start_enclave_remote_attestation(tee, opt)?;
-
- Ok(())
+fn start_db_backup(tee: &TeeBinder, opt: &BackupDbOpt) -> anyhow::Result<()> {
+ let cmd = ECallCommand::Raw;
+ let json = serde_json::to_string(opt)?;
+ let input = RawJsonInput::new(SubCmd::BackupDb, json);
+ match tee.invoke::<RawJsonInput, TeeServiceResult<RawJsonOutput>>(cmd, input) {
+ Err(e) => Err(anyhow!("{:?}", e)),
+ Ok(Err(e)) => Err(anyhow!("{:?}", e)),
+ _ => Ok(()),
+ }
}
#[derive(Debug, StructOpt)]
@@ -60,6 +69,16 @@ struct Opt {
command: Command,
}
+#[derive(Debug, StructOpt, serde::Serialize)]
+struct BackupDbOpt {
+ #[structopt(parse(from_os_str))]
+ db_old: PathBuf,
+ #[structopt(parse(from_os_str))]
+ db_new: PathBuf,
+ #[structopt(long, default_value = "00000000000000000000000000000000")]
+ key: String,
+}
+
#[derive(Debug, StructOpt, serde::Serialize)]
struct AttestationOpt {
/// Attestation algorithm, supported algorithms are "sgx_epid" for IAS
@@ -88,6 +107,9 @@ enum Command {
/// Dump remote attestationation report
#[structopt(name = "attestation")]
Attestation(AttestationOpt),
+ /// Backup DB
+ #[structopt(name = "backup")]
+ BackupDb(BackupDbOpt),
}
fn status() {
@@ -188,10 +210,16 @@ fn status() {
}
fn main() -> Result<()> {
+ env_logger::init_from_env(
+ env_logger::Env::new()
+ .filter_or("TEACLAVE_LOG", "RUST_LOG")
+ .write_style_or("TEACLAVE_LOG_STYLE", "RUST_LOG_STYLE"),
+ );
let args = Opt::from_args();
match args.command {
Command::Status => status(),
Command::Attestation(opt) => attestation(&opt)?,
+ Command::BackupDb(opt) => backup_db(&opt)?,
};
Ok(())
}
diff --git a/tool/enclave/Cargo.toml b/tool/enclave/Cargo.toml
index b04ef7d..10c84d6 100644
--- a/tool/enclave/Cargo.toml
+++ b/tool/enclave/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_sgx_tool_enclave"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave SGX Tool"
license = "Apache-2.0"
@@ -35,18 +35,21 @@ mesalock_sgx = [
"teaclave_binder/mesalock_sgx",
"teaclave_types/mesalock_sgx",
"teaclave_service_enclave_utils/mesalock_sgx",
+ "rusty-leveldb/mesalock_sgx",
]
cov = ["teaclave_service_enclave_utils/cov"]
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
anyhow = { version = "1.0.26" }
serde = { version = "1.0.92" }
-serde_json = { version = "1.0.39" }
-base64 = { version = "0.13.0" }
+serde_json = { version = "1.0.39" }
+base64 = { version = "0.13.0" }
thiserror = { version = "1.0.9" }
+hex = { version = "0.4.0" }
+rusty-leveldb = { path = "../../common/rusty_leveldb_sgx" }
teaclave_attestation = { path = "../../attestation" }
teaclave_binder = { path = "../../binder" }
teaclave_service_enclave_utils = { path = "../../services/utils/service_enclave_utils" }
diff --git a/tool/enclave/src/db.rs b/tool/enclave/src/db.rs
new file mode 100644
index 0000000..9d6733c
--- /dev/null
+++ b/tool/enclave/src/db.rs
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use anyhow::Result;
+use rusty_leveldb::LdbIterator;
+use rusty_leveldb::{DBReader, Options};
+use std::path::Path;
+
+pub fn backup_db(db_old: impl AsRef<Path>, db_new: impl AsRef<Path>, key: [u8; 16]) -> Result<()> {
+ let opt = Options::new_disk_db_with(key);
+ let mut new_db = rusty_leveldb::DB::open(&db_new, opt).unwrap();
+
+ let mut count = 0;
+ log::info!("Backup log files: {:?}", db_old.as_ref());
+ let opt = rusty_leveldb::Options::new_disk_db_with(key);
+ match rusty_leveldb::DB::open(&db_old, opt) {
+ Ok(mut db) => {
+ let mut iter = db.new_iter()?;
+ while iter.advance() {
+ let (mut k, mut v) = (vec![], vec![]);
+ iter.current(&mut k, &mut v);
+ new_db.put(&k, &v)?;
+ count += 1;
+ }
+ log::info!("Finish backup log to new_db: total {:?} entries ", count);
+ }
+ Err(e) => {
+ log::error!("DB normal open failed: {:?}", e);
+ // backup ldb
+ log::info!("Backup ldb files: {:?}", db_old.as_ref());
+ let opt = Options::new_disk_db_with(key);
+ let reader = DBReader::new(db_old.as_ref(), opt).unwrap();
+ for (k, v) in reader.into_iter() {
+ new_db.put(&k, &v)?;
+ count += 1;
+ }
+ log::info!("Finish backup ldb to new_db: total {:?} entries ", count);
+ }
+ }
+
+ new_db.flush()?;
+
+ Ok(())
+}
diff --git a/tool/enclave/src/lib.rs b/tool/enclave/src/lib.rs
index 80f8bdf..87a3234 100644
--- a/tool/enclave/src/lib.rs
+++ b/tool/enclave/src/lib.rs
@@ -20,6 +20,9 @@
#[macro_use]
extern crate sgx_tstd as std;
+use anyhow::{anyhow, Context};
+use std::convert::TryInto;
+use std::path::PathBuf;
use std::prelude::v1::*;
use serde_json::Value;
@@ -28,13 +31,15 @@ use teaclave_attestation::EndorsedAttestationReport;
use teaclave_attestation::{key, AttestationConfig};
use teaclave_binder::proto::{
ECallCommand, FinalizeEnclaveInput, FinalizeEnclaveOutput, InitEnclaveInput, InitEnclaveOutput,
- RawJsonInput, RawJsonOutput,
+ RawJsonInput, RawJsonOutput, SubCmd,
};
use teaclave_binder::{handle_ecall, register_ecall_handler};
use teaclave_service_enclave_utils::ServiceEnclave;
use teaclave_types::TeeServiceError;
use teaclave_types::{self, TeeServiceResult};
+mod db;
+
fn attestation(raw_json_input: &RawJsonInput) -> anyhow::Result<()> {
let v: serde_json::Value = serde_json::from_str(&raw_json_input.json)?;
let attestation_config = AttestationConfig::new(
@@ -66,12 +71,37 @@ fn attestation(raw_json_input: &RawJsonInput) -> anyhow::Result<()> {
Ok(())
}
+#[derive(Debug, serde::Deserialize)]
+struct BackupDbOpt {
+ db_old: PathBuf,
+ db_new: PathBuf,
+ key: String,
+}
+
+fn backup_db(raw_json_input: &RawJsonInput) -> anyhow::Result<()> {
+ let v: BackupDbOpt = serde_json::from_str(&raw_json_input.json)?;
+ let key: [u8; 16] = hex::decode(v.key)
+ .context("Illegal database key provided")?
+ .try_into()
+ .map_err(|_| anyhow!("not 16 bytes key"))?;
+ let db_old = v.db_old;
+ let db_new = v.db_new;
+
+ db::backup_db(&db_old, &db_new, key)?;
+ Ok(())
+}
+
#[handle_ecall]
-fn handle_remote_attestation(input: &RawJsonInput) -> TeeServiceResult<RawJsonOutput> {
- match attestation(input) {
+fn handle_raw_json(input: &RawJsonInput) -> TeeServiceResult<RawJsonOutput> {
+ let result = match input.sub_cmd {
+ SubCmd::Attestation => attestation(input),
+ SubCmd::BackupDb => backup_db(input),
+ };
+
+ match result {
Ok(_) => Ok(RawJsonOutput::default()),
Err(e) => {
- log::error!("Failed to start the service: {}", e);
+ log::error!("Failed to execute command: {}", e);
Err(TeeServiceError::ServiceError)
}
}
diff --git a/types/Cargo.toml b/types/Cargo.toml
index 293cc29..e1a5df7 100644
--- a/types/Cargo.toml
+++ b/types/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_types"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave types"
license = "Apache-2.0"
@@ -36,7 +36,7 @@ mesalock_sgx = [
enclave_unit_test = ["teaclave_test_utils/mesalock_sgx"]
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
anyhow = { version = "1.0.26" }
sgx_types = { version = "1.1.3" }
rand = { version = "0.7.0" }
diff --git a/types/src/function.rs b/types/src/function.rs
index b2ee267..ca475b2 100644
--- a/types/src/function.rs
+++ b/types/src/function.rs
@@ -54,6 +54,44 @@ impl FunctionOutput {
}
}
+#[derive(Debug, Deserialize, Serialize)]
+pub struct FunctionArgument {
+ pub key: String,
+ pub default_value: String,
+ pub allow_overwrite: bool,
+}
+
+impl FunctionArgument {
+ pub fn new(
+ key: impl Into<String>,
+ default_value: impl Into<String>,
+ allow_overwrite: bool,
+ ) -> Self {
+ Self {
+ key: key.into(),
+ default_value: default_value.into(),
+ allow_overwrite,
+ }
+ }
+}
+
+#[derive(Debug, Deserialize, Serialize, Default)]
+pub struct FunctionExpirationDate {
+ pub expired: bool,
+ pub seconds: i64,
+ pub nanos: i32,
+}
+
+impl FunctionExpirationDate {
+ pub fn new(expired: bool, seconds: i64, nanos: i32) -> Self {
+ Self {
+ expired,
+ seconds,
+ nanos,
+ }
+ }
+}
+
const USER_PREFIX: &str = "user";
#[derive(Default, Debug, Deserialize, Serialize)]
@@ -83,11 +121,13 @@ pub struct Function {
pub public: bool,
pub executor_type: ExecutorType,
pub payload: Vec<u8>,
- pub arguments: Vec<String>,
+ pub arguments: Vec<FunctionArgument>,
pub inputs: Vec<FunctionInput>,
pub outputs: Vec<FunctionOutput>,
pub owner: UserID,
pub user_allowlist: Vec<String>,
+ pub usage_quota: i32,
+ pub expiration_date: FunctionExpirationDate,
}
#[derive(Default)]
@@ -132,7 +172,7 @@ impl FunctionBuilder {
self
}
- pub fn arguments(mut self, arguments: Vec<String>) -> Self {
+ pub fn arguments(mut self, arguments: Vec<FunctionArgument>) -> Self {
self.function.arguments = arguments;
self
}
@@ -157,6 +197,16 @@ impl FunctionBuilder {
self
}
+ pub fn usage_quota(mut self, usage_quota: i32) -> Self {
+ self.function.usage_quota = usage_quota;
+ self
+ }
+
+ pub fn expiration_date(mut self, expiration_date: FunctionExpirationDate) -> Self {
+ self.function.expiration_date = expiration_date;
+ self
+ }
+
pub fn build(self) -> Function {
self.function
}
@@ -171,3 +221,22 @@ impl Storable for Function {
self.id
}
}
+
+const FUNCION_USAGE_PREFIX: &str = "usage";
+
+#[derive(Default, Debug, Deserialize, Serialize)]
+pub struct FunctionUsage {
+ pub function_id: Uuid,
+ pub use_numbers: i32,
+ pub group_name: String,
+}
+
+impl Storable for FunctionUsage {
+ fn key_prefix() -> &'static str {
+ FUNCION_USAGE_PREFIX
+ }
+
+ fn uuid(&self) -> Uuid {
+ Uuid::new_v5(&self.function_id, self.group_name.as_bytes())
+ }
+}
diff --git a/types/src/macros.rs b/types/src/macros.rs
index 2b5bfb4..8890dc1 100644
--- a/types/src/macros.rs
+++ b/types/src/macros.rs
@@ -14,7 +14,6 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-
#[macro_export]
macro_rules! hashmap {
($( $key: expr => $value: expr, )+) => { hashmap!($($key => $value),+) };
@@ -24,3 +23,18 @@ macro_rules! hashmap {
map
}}
}
+
+#[macro_export]
+macro_rules! profile_highlight {
+ ($desc:expr, $blk:block) => {{
+ let before = std::time::Instant::now();
+ let result = $blk;
+ let elapsed = before.elapsed().as_secs_f64();
+ if elapsed < 0.5 {
+ log::debug!(" {}: Elapsed time: {:?}", $desc, elapsed);
+ } else {
+ log::info!(" {}: Elapsed time: \x1B[1;31m{:?}\x1B[0m", $desc, elapsed);
+ }
+ result
+ }};
+}
diff --git a/types/src/staged_file.rs b/types/src/staged_file.rs
index 9d11f43..c210680 100644
--- a/types/src/staged_file.rs
+++ b/types/src/staged_file.rs
@@ -189,6 +189,14 @@ impl StagedFiles {
pub fn is_empty(&self) -> bool {
self.len() == 0
}
+
+ pub fn insert(&mut self, name: &str, fileinfo: StagedFileInfo) {
+ self.entries.insert(name.to_owned(), fileinfo);
+ }
+
+ pub fn contain(&mut self, name: &str) -> bool {
+ self.entries.contains_key(name)
+ }
}
impl std::iter::FromIterator<(String, StagedFileInfo)> for StagedFiles {
diff --git a/types/src/staged_function.rs b/types/src/staged_function.rs
index 0b5799a..b301bb2 100644
--- a/types/src/staged_function.rs
+++ b/types/src/staged_function.rs
@@ -101,6 +101,10 @@ impl FunctionArguments {
pub fn into_string(self) -> String {
ArgumentValue::Object(self.inner).to_string()
}
+
+ pub fn insert(&mut self, k: String, v: ArgumentValue) -> Option<ArgumentValue> {
+ self.inner.insert(k, v)
+ }
}
#[derive(Debug, Default)]
@@ -115,6 +119,13 @@ pub struct StagedFunction {
pub runtime_name: String,
}
+impl std::fmt::Display for StagedFunction {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "name: {}, args: {:?}, payload: {}, input_files: {:?}, output_files: {:?}, exec_type: {:?}, executor: {:?}, runtime_name: {}",
+ self.name, self.arguments, self.payload.len(), self.input_files, self.output_files, self.executor_type, self.executor, self.runtime_name)
+ }
+}
+
#[derive(Default)]
pub struct StagedFunctionBuilder {
function: StagedFunction,
diff --git a/types/src/staged_task.rs b/types/src/staged_task.rs
index a8cbc09..9291f36 100644
--- a/types/src/staged_task.rs
+++ b/types/src/staged_task.rs
@@ -43,6 +43,10 @@ impl FunctionInputFiles {
pub fn iter(&self) -> Iter<String, FunctionInputFile> {
self.inner.iter()
}
+
+ pub fn placeholder_filter(&mut self) {
+ self.inner.retain(|_, v| !v.is_placeholder());
+ }
}
impl IntoIterator for FunctionInputFiles {
@@ -139,6 +143,11 @@ impl FunctionInputFile {
crypto_info: crypto.into(),
}
}
+
+ pub fn is_placeholder(&self) -> bool {
+ let scheme = self.url.scheme();
+ scheme.eq("placeholder")
+ }
}
impl From<TeaclaveInputFile> for FunctionInputFile {
diff --git a/types/src/task_state.rs b/types/src/task_state.rs
index 54227d5..68e2325 100644
--- a/types/src/task_state.rs
+++ b/types/src/task_state.rs
@@ -129,10 +129,24 @@ impl Task<Create> {
}
//check function compatibility
- let fn_args_spec: HashSet<&String> = function.arguments.iter().collect();
+ let fn_args_spec: HashSet<&String> = function
+ .arguments
+ .iter()
+ .filter(|arg| arg.allow_overwrite)
+ .map(|arg| &arg.key)
+ .collect();
let req_args: HashSet<&String> = req_func_args.inner().keys().collect();
- ensure!(fn_args_spec == req_args, "function_arguments mismatch");
-
+ ensure!(req_args == fn_args_spec, "function_arguments mismatch");
+
+ let mut func_args = req_func_args.clone();
+ for arg in &function.arguments {
+ if !arg.allow_overwrite || !func_args.inner().contains_key(&arg.key) {
+ func_args.insert(
+ arg.key.clone(),
+ serde_json::Value::String(arg.default_value.clone()),
+ );
+ }
+ }
// check input fkeys
let inputs_spec: HashSet<&String> = function.inputs.iter().map(|f| &f.name).collect();
let mut req_input_fkeys: HashSet<&String> = req_input_owners.keys().collect();
@@ -166,7 +180,7 @@ impl Task<Create> {
executor: req_executor,
function_id: function.external_id(),
function_owner: function.owner.clone(),
- function_arguments: req_func_args,
+ function_arguments: func_args,
inputs_ownership: req_input_owners,
outputs_ownership: req_output_owners,
participants,
diff --git a/types/src/worker.rs b/types/src/worker.rs
index a3cc5be..343878d 100644
--- a/types/src/worker.rs
+++ b/types/src/worker.rs
@@ -42,6 +42,7 @@ pub enum ExecutorType {
Builtin,
Python,
WAMicroRuntime,
+ CleanroomRuntime,
}
impl std::default::Default for ExecutorType {
@@ -58,6 +59,7 @@ impl std::convert::TryFrom<&str> for ExecutorType {
"python" => ExecutorType::Python,
"builtin" => ExecutorType::Builtin,
"wamr" => ExecutorType::WAMicroRuntime,
+ "cleanroom" => ExecutorType::CleanroomRuntime,
_ => anyhow::bail!("Invalid executor type: {}", selector),
};
Ok(executor_type)
@@ -84,6 +86,7 @@ impl std::fmt::Display for ExecutorType {
ExecutorType::Builtin => write!(f, "builtin"),
ExecutorType::Python => write!(f, "python"),
ExecutorType::WAMicroRuntime => write!(f, "wamr"),
+ ExecutorType::CleanroomRuntime => write!(f, "cleanroom"),
}
}
}
@@ -93,6 +96,7 @@ pub enum Executor {
MesaPy,
Builtin,
WAMicroRuntime,
+ CleanroomRuntime,
}
impl std::default::Default for Executor {
@@ -109,6 +113,7 @@ impl std::convert::TryFrom<&str> for Executor {
"mesapy" => Executor::MesaPy,
"builtin" => Executor::Builtin,
"wamr" => Executor::WAMicroRuntime,
+ "cleanroom" => Executor::CleanroomRuntime,
_ => anyhow::bail!("Unsupported executor: {}", selector),
};
Ok(executor)
@@ -129,6 +134,7 @@ impl std::fmt::Display for Executor {
Executor::MesaPy => write!(f, "mesapy"),
Executor::Builtin => write!(f, "builtin"),
Executor::WAMicroRuntime => write!(f, "wamr"),
+ Executor::CleanroomRuntime => write!(f, "cleanroom"),
}
}
}
diff --git a/worker/Cargo.toml b/worker/Cargo.toml
index edae189..a5d53cb 100644
--- a/worker/Cargo.toml
+++ b/worker/Cargo.toml
@@ -17,7 +17,7 @@
[package]
name = "teaclave_worker"
-version = "0.4.0"
+version = "0.2.0"
authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
description = "Teaclave worker"
license = "Apache-2.0"
@@ -39,7 +39,7 @@ cov = ["sgx_cov"]
enclave_unit_test = ["teaclave_test_utils/mesalock_sgx"]
[dependencies]
-log = { version = "0.4.6", features = ["release_max_level_info"] }
+log = { version = "0.4.6", features = ["release_max_level_debug"] }
anyhow = { version = "1.0.26" }
serde_json = { version = "1.0.39" }
thiserror = { version = "1.0.9" }
diff --git a/worker/src/worker.rs b/worker/src/worker.rs
index 27cc419..add9d0a 100644
--- a/worker/src/worker.rs
+++ b/worker/src/worker.rs
@@ -65,6 +65,10 @@ impl Default for Worker {
(ExecutorType::WAMicroRuntime, Executor::WAMicroRuntime),
|| Box::new(WAMicroRuntime::default()),
);
+ worker.register_executor(
+ (ExecutorType::CleanroomRuntime, Executor::CleanroomRuntime),
+ || Box::new(CleanroomRuntime::default()),
+ );
worker
}
@@ -87,6 +91,7 @@ impl Worker {
}
pub fn invoke_function(&self, function: StagedFunction) -> anyhow::Result<String> {
+ log::info!("staged function: {}", function);
let executor = self.get_executor(function.executor_type, function.executor)?;
let runtime = self.get_runtime(
&function.runtime_name,