This is an automated email from the ASF dual-hosted git repository.
mssun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git
The following commit(s) were added to refs/heads/master by this push:
new d670e6a Add Rust client SDK (#455)
d670e6a is described below
commit d670e6a1b2d1390af573fef11ce6931e0b3fee16
Author: Mingshen Sun <[email protected]>
AuthorDate: Mon Jan 18 22:22:41 2021 -0800
Add Rust client SDK (#455)
---
attestation/Cargo.toml | 3 +-
cmake/TeaclaveGenVars.cmake | 1 +
cmake/UtilTargets.cmake | 3 +
cmake/scripts/test.sh | 42 ++
docs/build-system.md | 1 +
sdk/rust/Cargo.toml | 16 +
sdk/rust/build.rs | 20 +
sdk/rust/src/lib.rs | 601 ++++++++++++++++++++++++
services/proto/build.rs | 18 +-
services/proto/proto_gen/templates/proto.j2 | 4 +
services/proto/src/teaclave_frontend_service.rs | 7 +-
types/Cargo.toml | 1 +
types/src/attestation.rs | 6 +
types/src/crypto.rs | 7 +
14 files changed, 720 insertions(+), 10 deletions(-)
diff --git a/attestation/Cargo.toml b/attestation/Cargo.toml
index 9f1c37f..75a0d46 100644
--- a/attestation/Cargo.toml
+++ b/attestation/Cargo.toml
@@ -15,6 +15,7 @@ mesalock_sgx = [
"sgx_tse",
"teaclave_types/mesalock_sgx",
"teaclave_config/mesalock_sgx",
+ "teaclave_config/build_config",
]
enclave_unit_test = ["teaclave_test_utils/mesalock_sgx"]
@@ -40,7 +41,7 @@ webpki-roots = { version = "0.19.0" }
yasna = { version = "0.3.0", features = ["bit-vec", "num-bigint",
"chrono"] }
teaclave_types = { path = "../types" }
-teaclave_config = { path = "../config", features = ["build_config"] }
+teaclave_config = { path = "../config" }
teaclave_test_utils = { path = "../tests/utils", optional = true }
sgx_rand = { version = "1.1.2", optional = true }
diff --git a/cmake/TeaclaveGenVars.cmake b/cmake/TeaclaveGenVars.cmake
index 1751356..8a00491 100644
--- a/cmake/TeaclaveGenVars.cmake
+++ b/cmake/TeaclaveGenVars.cmake
@@ -132,6 +132,7 @@ set(TEACLAVE_COMMON_ENVS
TEACLAVE_BUILD_CFG_DIR=${PROJECT_SOURCE_DIR}
TEACLAVE_EDL_DIR=${TEACLAVE_EDL_DIR}
TEACLAVE_SYMLINKS=${TEACLAVE_SYMLINKS}
+ RUSTFLAGS=${RUSTFLAGS}
SGX_SDK=${SGX_SDK}
SGX_MODE=${SGX_MODE}
DCAP=${DCAP}
diff --git a/cmake/UtilTargets.cmake b/cmake/UtilTargets.cmake
index 9614017..de388a6 100644
--- a/cmake/UtilTargets.cmake
+++ b/cmake/UtilTargets.cmake
@@ -70,6 +70,9 @@ if(TEST_MODE)
add_custom_target(
run-functional-tests COMMAND ${TEACLAVE_COMMON_ENVS}
${MT_SCRIPT_DIR}/test.sh functional)
+ add_custom_target(
+ run-sdk-tests COMMAND ${TEACLAVE_COMMON_ENVS}
+ ${MT_SCRIPT_DIR}/test.sh sdk)
else()
add_custom_target(
run-tests
diff --git a/cmake/scripts/test.sh b/cmake/scripts/test.sh
index ab3a5df..6702253 100755
--- a/cmake/scripts/test.sh
+++ b/cmake/scripts/test.sh
@@ -151,6 +151,44 @@ run_functional_tests() {
cleanup
}
+run_sdk_tests() {
+ trap cleanup INT TERM ERR
+
+ echo_title "SDK tests"
+ 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
+ pushd ${TEACLAVE_SERVICE_INSTALL_DIR}
+ ./teaclave_authentication_service &
+ ./teaclave_storage_service &
+ sleep 3 # wait for authentication and storage service
+ ./teaclave_management_service &
+ ./teaclave_scheduler_service &
+ sleep 3 # wait for management service and scheduler_service
+ ./teaclave_access_control_service &
+ ./teaclave_frontend_service &
+ sleep 3 # wait for other services
+
+ start_storage_server
+
+ # Run tests of execution service separately
+ ./teaclave_execution_service &
+ sleep 3 # wait for execution services
+ popd
+
+ pushd ${MT_SGXAPP_TOML_DIR}
+ RUSTFLAGS=${RUSTFLAGS} cargo test --manifest-path
${TEACLAVE_PROJECT_ROOT}/sdk/rust/Cargo.toml \
+ --target-dir ${TEACLAVE_TARGET_DIR}/untrusted
+ popd
+
+ # kill all background services
+ cleanup
+}
+
run_examples() {
trap cleanup INT TERM ERR
@@ -208,6 +246,9 @@ case "$1" in
"functional")
run_functional_tests
;;
+ "sdk")
+ run_sdk_tests
+ ;;
"example")
run_examples
;;
@@ -215,6 +256,7 @@ case "$1" in
run_unit_tests
run_integration_tests
run_functional_tests
+ run_sdk_tests
run_examples
;;
esac
diff --git a/docs/build-system.md b/docs/build-system.md
index 025cdae..23060be 100644
--- a/docs/build-system.md
+++ b/docs/build-system.md
@@ -117,6 +117,7 @@ Above targets are automatically generated from the
- `run-tests`: Run all test cases.
- `run-integration-tests`: Run integration tests only.
- `run-funtional-tests`: Run functional tests only.
+- `run-sdk-tests`: Run tests of client SDK only.
- `run-examples`: Run all examples.
- `cov`: Aggregate coverage results and generate report, needs to config cmake
with `-DCOV=ON`.
diff --git a/sdk/rust/Cargo.toml b/sdk/rust/Cargo.toml
new file mode 100644
index 0000000..4264c17
--- /dev/null
+++ b/sdk/rust/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "teaclave-client-sdk"
+version = "0.1.0"
+authors = ["Teaclave Contributors <[email protected]>"]
+description = "Teaclave Rust Client SDK"
+license = "Apache-2.0"
+edition = "2018"
+
+[dependencies]
+teaclave_types = { path = "../../types", features = ["app"] }
+teaclave_attestation = { path = "../../attestation" }
+teaclave_rpc = { path = "../../rpc" }
+teaclave_proto = { path = "../../services/proto" }
+anyhow = { version = "1.0.26" }
+url = { version = "2.1.1" }
+pem = "0.7.0"
diff --git a/sdk/rust/build.rs b/sdk/rust/build.rs
new file mode 100644
index 0000000..49c8b00
--- /dev/null
+++ b/sdk/rust/build.rs
@@ -0,0 +1,20 @@
+// 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.
+
+fn main() {
+ println!("cargo:rustc-env=MT_SGXAPP_TOML_DIR=../../");
+}
diff --git a/sdk/rust/src/lib.rs b/sdk/rust/src/lib.rs
new file mode 100644
index 0000000..7357d19
--- /dev/null
+++ b/sdk/rust/src/lib.rs
@@ -0,0 +1,601 @@
+// 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 std::collections::HashMap;
+use std::convert::TryInto;
+use teaclave_attestation::verifier;
+use
teaclave_proto::teaclave_authentication_service::TeaclaveAuthenticationApiClient;
+use teaclave_proto::teaclave_frontend_service::TeaclaveFrontendClient;
+use teaclave_rpc::config::SgxTrustedTlsClientConfig;
+use teaclave_rpc::endpoint::Endpoint;
+use teaclave_types::FileAuthTag;
+use url::Url;
+
+pub use teaclave_proto::teaclave_authentication_service::{
+ UserLoginRequest, UserLoginResponse, UserRegisterRequest,
UserRegisterResponse,
+};
+pub use teaclave_proto::teaclave_frontend_service::GetFunctionResponse as
Function;
+pub use teaclave_proto::teaclave_frontend_service::{
+ ApproveTaskRequest, ApproveTaskResponse, AssignDataRequest,
AssignDataResponse,
+ CreateTaskRequest, CreateTaskResponse, GetFunctionRequest,
GetFunctionResponse, GetTaskRequest,
+ GetTaskResponse, InvokeTaskRequest, InvokeTaskResponse,
RegisterFunctionRequest,
+ RegisterFunctionResponse, RegisterInputFileRequest,
RegisterInputFileResponse,
+ RegisterOutputFileRequest, RegisterOutputFileResponse,
+};
+pub use teaclave_types::{
+ EnclaveInfo, Executor, FileCrypto, FunctionInput, FunctionOutput,
TaskResult,
+};
+
+pub struct AuthenticationClient {
+ api_client: TeaclaveAuthenticationApiClient,
+}
+
+pub struct AuthenticationService;
+
+impl AuthenticationClient {
+ pub fn new(api_client: TeaclaveAuthenticationApiClient) -> Self {
+ Self { api_client }
+ }
+
+ pub fn user_register_with_request(
+ &mut self,
+ request: UserRegisterRequest,
+ ) -> Result<UserRegisterResponse> {
+ let response = self.api_client.user_register(request)?;
+
+ Ok(response)
+ }
+
+ pub fn user_register(&mut self, user_id: &str, user_password: &str) ->
Result<()> {
+ let request = UserRegisterRequest::new(user_id, user_password);
+ let _response = self.user_register_with_request(request)?;
+
+ Ok(())
+ }
+
+ pub fn user_login_with_request(
+ &mut self,
+ request: UserLoginRequest,
+ ) -> Result<UserLoginResponse> {
+ let response = self.api_client.user_login(request)?;
+
+ Ok(response)
+ }
+
+ pub fn user_login(&mut self, user_id: &str, user_password: &str) ->
Result<String> {
+ let request = UserLoginRequest::new(user_id, user_password);
+ let response = self.user_login_with_request(request)?;
+
+ Ok(response.token)
+ }
+}
+
+impl AuthenticationService {
+ pub fn connect(
+ url: &str,
+ enclave_info: &EnclaveInfo,
+ as_root_ca_cert: &[u8],
+ ) -> Result<AuthenticationClient> {
+ let enclave_attr = enclave_info
+ .get_enclave_attr("teaclave_authentication_service")
+ .expect("enclave attr");
+ let config =
SgxTrustedTlsClientConfig::new().attestation_report_verifier(
+ vec![enclave_attr],
+ as_root_ca_cert,
+ verifier::universal_quote_verifier,
+ );
+ let channel = Endpoint::new(url).config(config).connect()?;
+ let client = TeaclaveAuthenticationApiClient::new(channel)?;
+
+ Ok(AuthenticationClient::new(client))
+ }
+}
+
+pub struct FrontendService;
+
+impl FrontendService {
+ pub fn connect(
+ url: &str,
+ enclave_info: &EnclaveInfo,
+ as_root_ca_cert: &[u8],
+ ) -> Result<FrontendClient> {
+ let enclave_attr = enclave_info
+ .get_enclave_attr("teaclave_frontend_service")
+ .expect("enclave attr");
+ let config =
SgxTrustedTlsClientConfig::new().attestation_report_verifier(
+ vec![enclave_attr],
+ as_root_ca_cert,
+ verifier::universal_quote_verifier,
+ );
+ let channel = Endpoint::new(url).config(config).connect()?;
+ let client = TeaclaveFrontendClient::new(channel)?;
+
+ Ok(FrontendClient::new(client))
+ }
+}
+
+pub struct FrontendClient {
+ api_client: TeaclaveFrontendClient,
+}
+
+impl FrontendClient {
+ pub fn new(api_client: TeaclaveFrontendClient) -> Self {
+ Self { api_client }
+ }
+
+ pub fn set_credential(&mut self, id: &str, token: &str) {
+ let mut metadata = HashMap::new();
+ metadata.insert("id".to_string(), id.to_string());
+ metadata.insert("token".to_string(), token.to_string());
+ self.api_client.set_metadata(metadata);
+ }
+
+ pub fn register_function_with_request(
+ &mut self,
+ request: RegisterFunctionRequest,
+ ) -> Result<RegisterFunctionResponse> {
+ let response = self.api_client.register_function(request)?;
+
+ Ok(response)
+ }
+
+ pub fn register_function(
+ &mut self,
+ name: &str,
+ description: &str,
+ executor_type: &str,
+ payload: Option<&[u8]>,
+ arguments: Option<&[&str]>,
+ inputs: Option<Vec<FunctionInput>>,
+ outputs: Option<Vec<FunctionOutput>>,
+ ) -> Result<String> {
+ let executor_type = executor_type.try_into()?;
+ let mut request = RegisterFunctionRequest::new()
+ .name(name)
+ .description(description)
+ .executor_type(executor_type);
+ if let Some(payload) = payload {
+ request = request.payload(payload.into());
+ }
+ if let Some(arguments) = arguments {
+ request = request.arguments(arguments);
+ }
+ if let Some(inputs) = inputs {
+ request = request.inputs(inputs);
+ }
+ if let Some(outputs) = outputs {
+ request = request.outputs(outputs);
+ }
+ let response = self.register_function_with_request(request)?;
+
+ Ok(response.function_id.to_string())
+ }
+
+ pub fn get_function_with_request(
+ &mut self,
+ request: GetFunctionRequest,
+ ) -> Result<GetFunctionResponse> {
+ let response = self.api_client.get_function(request)?;
+
+ Ok(response)
+ }
+
+ pub fn get_function(&mut self, function_id: &str) -> Result<Function> {
+ let function_id = function_id.try_into()?;
+ let request = GetFunctionRequest::new(function_id);
+ let response = self.get_function_with_request(request)?;
+
+ Ok(response)
+ }
+
+ pub fn register_input_file_with_request(
+ &mut self,
+ request: RegisterInputFileRequest,
+ ) -> Result<RegisterInputFileResponse> {
+ let response = self.api_client.register_input_file(request)?;
+
+ Ok(response)
+ }
+
+ pub fn register_input_file(
+ &mut self,
+ url: &str,
+ cmac: &[u8],
+ file_crypto: FileCrypto,
+ ) -> Result<String> {
+ let url = Url::parse(url)?;
+ let cmac = FileAuthTag::from_bytes(cmac)?;
+ let request = RegisterInputFileRequest::new(url, cmac, file_crypto);
+ let response = self.register_input_file_with_request(request)?;
+
+ Ok(response.data_id.to_string())
+ }
+
+ pub fn register_output_file_with_request(
+ &mut self,
+ request: RegisterOutputFileRequest,
+ ) -> Result<RegisterOutputFileResponse> {
+ let response = self.api_client.register_output_file(request)?;
+
+ Ok(response)
+ }
+
+ pub fn register_output_file(&mut self, url: &str, file_crypto: FileCrypto)
-> Result<String> {
+ let url = Url::parse(url)?;
+ let request = RegisterOutputFileRequest::new(url, file_crypto);
+ let response = self.register_output_file_with_request(request)?;
+
+ Ok(response.data_id.to_string())
+ }
+
+ pub fn create_task_with_request(
+ &mut self,
+ request: CreateTaskRequest,
+ ) -> Result<CreateTaskResponse> {
+ let response = self.api_client.create_task(request)?;
+
+ Ok(response)
+ }
+
+ pub fn create_task(
+ &mut self,
+ function_id: &str,
+ function_arguments: Option<HashMap<String, String>>,
+ executor: &str,
+ inputs_ownership: Option<HashMap<String, Vec<String>>>,
+ outputs_ownership: Option<HashMap<String, Vec<String>>>,
+ ) -> Result<String> {
+ use teaclave_types::OwnerList;
+ let function_id = function_id.try_into()?;
+ let executor = executor.try_into()?;
+
+ let mut request = CreateTaskRequest::new()
+ .function_id(function_id)
+ .executor(executor);
+
+ if let Some(function_arguments) = function_arguments {
+ request = request.function_arguments(function_arguments);
+ }
+
+ if let Some(inputs_ownership) = inputs_ownership {
+ let mut inputs_task_file_owners: HashMap<String, OwnerList> =
HashMap::new();
+ for (k, v) in inputs_ownership.iter() {
+ inputs_task_file_owners.insert(k.into(), v.clone().into());
+ }
+ request = request.inputs_ownership(inputs_task_file_owners);
+ }
+
+ if let Some(outputs_ownership) = outputs_ownership {
+ let mut outputs_task_file_owners: HashMap<String, OwnerList> =
HashMap::new();
+ for (k, v) in outputs_ownership.iter() {
+ outputs_task_file_owners.insert(k.into(), v.clone().into());
+ }
+ request = request.outputs_ownership(outputs_task_file_owners);
+ }
+
+ let response = self.create_task_with_request(request)?;
+
+ Ok(response.task_id.to_string())
+ }
+
+ pub fn assign_data_with_request(
+ &mut self,
+ request: AssignDataRequest,
+ ) -> Result<AssignDataResponse> {
+ let response = self.api_client.assign_data(request)?;
+
+ Ok(response)
+ }
+
+ pub fn assign_data(
+ &mut self,
+ task_id: &str,
+ inputs: Option<HashMap<String, String>>,
+ outputs: Option<HashMap<String, String>>,
+ ) -> Result<()> {
+ let mut input_data = HashMap::new();
+ let mut output_data = HashMap::new();
+ if let Some(inputs) = inputs {
+ for (k, v) in inputs.iter() {
+ input_data.insert(k.into(), v.clone().try_into()?);
+ }
+ }
+
+ if let Some(outputs) = outputs {
+ for (k, v) in outputs.iter() {
+ output_data.insert(k.into(), v.clone().try_into()?);
+ }
+ }
+ let request = AssignDataRequest::new(task_id.try_into()?, input_data,
output_data);
+ let _ = self.assign_data_with_request(request)?;
+
+ Ok(())
+ }
+
+ pub fn approve_task_with_request(
+ &mut self,
+ request: ApproveTaskRequest,
+ ) -> Result<ApproveTaskResponse> {
+ let response = self.api_client.approve_task(request)?;
+
+ Ok(response)
+ }
+
+ pub fn approve_task(&mut self, task_id: &str) -> Result<()> {
+ let request = ApproveTaskRequest::new(task_id.try_into()?);
+ let _ = self.approve_task_with_request(request)?;
+
+ Ok(())
+ }
+
+ pub fn invoke_task_with_request(
+ &mut self,
+ request: InvokeTaskRequest,
+ ) -> Result<InvokeTaskResponse> {
+ let response = self.api_client.invoke_task(request)?;
+
+ Ok(response)
+ }
+
+ pub fn invoke_task(&mut self, task_id: &str) -> Result<()> {
+ let request = InvokeTaskRequest::new(task_id.try_into()?);
+ let _ = self.invoke_task_with_request(request)?;
+
+ Ok(())
+ }
+
+ pub fn get_task_with_request(&mut self, request: GetTaskRequest) ->
Result<GetTaskResponse> {
+ let response = self.api_client.get_task(request)?;
+
+ Ok(response)
+ }
+
+ pub fn get_task_result(&mut self, task_id: &str) -> Result<Vec<u8>> {
+ loop {
+ let request = GetTaskRequest::new(task_id.try_into()?);
+ let response = self.get_task_with_request(request)?;
+ if let TaskResult::Ok(task_outputs) = response.result {
+ return Ok(task_outputs.return_value);
+ }
+ let one_second = std::time::Duration::from_secs(1);
+ std::thread::sleep(one_second);
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::convert::TryInto;
+ use std::fs;
+ use teaclave_types::hashmap;
+
+ const ENCLAVE_INFO_PATH: &str = "../../release/services/enclave_info.toml";
+ #[cfg(dcap)]
+ const AS_ROOT_CA_CERT_PATH: &str = "../../keys/dcap_root_ca_cert.pem";
+ #[cfg(not(dcap))]
+ const AS_ROOT_CA_CERT_PATH: &str = "../../keys/ias_root_ca_cert.pem";
+ const USER_ID: &str = "rust_client_sdk_test_user";
+ const USER_PASSWORD: &str = "test_password";
+
+ #[test]
+ fn test_authentication_service() {
+ let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
+ let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
+ let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
+ let mut client =
+ AuthenticationService::connect("localhost:7776", &enclave_info,
&as_root_ca_cert)
+ .unwrap();
+ let _ = client.user_register(USER_ID, USER_PASSWORD);
+ client.user_login(USER_ID, USER_PASSWORD).unwrap();
+ }
+
+ #[test]
+ fn test_frontend_service() {
+ let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
+ let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
+ let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
+ let mut client =
+ AuthenticationService::connect("localhost:7776", &enclave_info,
&as_root_ca_cert)
+ .unwrap();
+ let _ = client.user_register(USER_ID, USER_PASSWORD);
+ let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
+
+ let mut client =
+ FrontendService::connect("localhost:7777", &enclave_info,
&as_root_ca_cert).unwrap();
+ client.set_credential(USER_ID, &token);
+ let function_id = client
+ .register_function(
+ "builtin-echo",
+ "An native echo function.",
+ "builtin",
+ None,
+ Some(&["message"]),
+ None,
+ None,
+ )
+ .unwrap();
+ let _ = client.get_function(&function_id).unwrap();
+ let function_arguments = hashmap!("message" => "Hello, Teaclave!");
+ let task_id = client
+ .create_task(
+ &function_id,
+ Some(function_arguments),
+ "builtin",
+ None,
+ None,
+ )
+ .unwrap();
+
+ let _ = client.invoke_task(&task_id).unwrap();
+ let result = client.get_task_result(&task_id).unwrap();
+ assert_eq!(result, b"Hello, Teaclave!")
+ }
+
+ #[test]
+ fn test_frontend_service_with_request() {
+ let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
+ let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
+ let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
+ let mut client =
+ AuthenticationService::connect("localhost:7776", &enclave_info,
&as_root_ca_cert)
+ .unwrap();
+ let _ = client.user_register(USER_ID, USER_PASSWORD);
+ let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
+
+ let mut client =
+ FrontendService::connect("localhost:7777", &enclave_info,
&as_root_ca_cert).unwrap();
+ client.set_credential(USER_ID, &token);
+ let request = RegisterFunctionRequest::default();
+ let function_id = client
+ .register_function_with_request(request)
+ .unwrap()
+ .function_id;
+
+ let request = GetFunctionRequest::new(function_id);
+ let response = client.get_function_with_request(request);
+ assert!(response.is_ok());
+
+ let function_id = "function-00000000-0000-0000-0000-000000000002"
+ .to_string()
+ .try_into()
+ .unwrap();
+ let request = CreateTaskRequest::new()
+ .function_id(function_id)
+ .function_arguments(hashmap!("arg1" => "arg1_value"))
+ .executor(Executor::MesaPy)
+ .outputs_ownership(hashmap!("output" => vec!["frontend_user",
"mock_user"]));
+ let response = client.create_task_with_request(request);
+ assert!(response.is_ok());
+ let task_id = response.unwrap().task_id;
+
+ let request = GetTaskRequest::new(task_id);
+ let response = client.get_task_with_request(request);
+ assert!(response.is_ok());
+ }
+
+ #[test]
+ fn test_assign_data() {
+ let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
+ let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
+ let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
+ let mut client =
+ AuthenticationService::connect("localhost:7776", &enclave_info,
&as_root_ca_cert)
+ .unwrap();
+ let _ = client.user_register(USER_ID, USER_PASSWORD);
+ let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
+
+ let mut client =
+ FrontendService::connect("localhost:7777", &enclave_info,
&as_root_ca_cert).unwrap();
+ client.set_credential(USER_ID, &token);
+ let function_id = "function-00000000-0000-0000-0000-000000000002";
+ let function_arguments = hashmap!("arg1" => "arg1_value");
+ let outputs_ownership = hashmap!("output" =>
vec![USER_ID.to_string()]);
+ let task_id = client
+ .create_task(
+ &function_id,
+ Some(function_arguments),
+ "mesapy",
+ None,
+ Some(outputs_ownership),
+ )
+ .unwrap();
+ let data_id = client
+ .register_output_file(
+ "https://external-storage.com/filepath?presigned_token",
+ FileCrypto::default(),
+ )
+ .unwrap();
+ let outputs = hashmap!("output" => data_id);
+ client.assign_data(&task_id, None, Some(outputs)).unwrap();
+ }
+
+ #[test]
+ fn test_assign_data_err() {
+ let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
+ let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
+ let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
+ let mut client =
+ AuthenticationService::connect("localhost:7776", &enclave_info,
&as_root_ca_cert)
+ .unwrap();
+ let _ = client.user_register(USER_ID, USER_PASSWORD);
+ let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
+
+ let mut client =
+ FrontendService::connect("localhost:7777", &enclave_info,
&as_root_ca_cert).unwrap();
+ client.set_credential(USER_ID, &token);
+ let function_id = "function-00000000-0000-0000-0000-000000000002";
+ let function_arguments = hashmap!("arg1" => "arg1_value");
+ let outputs_ownership = hashmap!("output" =>
vec!["incorrect_user".to_string()]);
+ let task_id = client
+ .create_task(
+ &function_id,
+ Some(function_arguments),
+ "mesapy",
+ None,
+ Some(outputs_ownership),
+ )
+ .unwrap();
+ let data_id = client
+ .register_output_file(
+ "https://external-storage.com/filepath?presigned_token",
+ FileCrypto::default(),
+ )
+ .unwrap();
+ let outputs = hashmap!("output" => data_id);
+ let result = client.assign_data(&task_id, None, Some(outputs));
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_approve_task() {
+ let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
+ let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
+ let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
+ let mut client =
+ AuthenticationService::connect("localhost:7776", &enclave_info,
&as_root_ca_cert)
+ .unwrap();
+ let _ = client.user_register(USER_ID, USER_PASSWORD);
+ let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
+
+ let mut client =
+ FrontendService::connect("localhost:7777", &enclave_info,
&as_root_ca_cert).unwrap();
+ client.set_credential(USER_ID, &token);
+ let function_id = "function-00000000-0000-0000-0000-000000000002";
+ let function_arguments = hashmap!("arg1" => "arg1_value");
+ let outputs_ownership = hashmap!("output" =>
vec![USER_ID.to_string()]);
+ let task_id = client
+ .create_task(
+ &function_id,
+ Some(function_arguments),
+ "mesapy",
+ None,
+ Some(outputs_ownership),
+ )
+ .unwrap();
+ let data_id = client
+ .register_output_file(
+ "https://external-storage.com/filepath?presigned_token",
+ FileCrypto::default(),
+ )
+ .unwrap();
+ let outputs = hashmap!("output" => data_id);
+ client.assign_data(&task_id, None, Some(outputs)).unwrap();
+ client.approve_task(&task_id).unwrap();
+ }
+}
diff --git a/services/proto/build.rs b/services/proto/build.rs
index b734a01..31ac30f 100644
--- a/services/proto/build.rs
+++ b/services/proto/build.rs
@@ -17,6 +17,7 @@
use std::env;
use std::path::Path;
+use std::path::PathBuf;
use std::process::Command;
use std::str;
@@ -40,11 +41,20 @@ fn main() {
println!("cargo:rerun-if-changed={}", pf);
}
- let target_dir =
Path::new(&env::var("TEACLAVE_SYMLINKS").expect("TEACLAVE_SYMLINKS"))
- .join("teaclave_build/target/proto_gen");
- let unix_toml_dir =
env::var("MT_SGXAPP_TOML_DIR").expect("MT_SGXAPP_TOML_DIR");
+ let target_dir = match env::var("TEACLAVE_SYMLINKS") {
+ Ok(teaclave_symlinks) => {
+
Path::new(&teaclave_symlinks).join("teaclave_build/target/proto_gen")
+ }
+ Err(_) => env::current_dir().unwrap().join("target/proto_gen"),
+ };
+ let current_dir: PathBuf = match env::var("MT_SGXAPP_TOML_DIR") {
+ Ok(sgxapp_toml_dir) => Path::new(&sgxapp_toml_dir).into(),
+ // This fallback is only for compiling rust client sdk with cargo
+ Err(_) => Path::new("../../").into(),
+ };
+
let c = Command::new("cargo")
- .current_dir(&unix_toml_dir)
+ .current_dir(¤t_dir)
.args(&[
"run",
"--target-dir",
diff --git a/services/proto/proto_gen/templates/proto.j2
b/services/proto/proto_gen/templates/proto.j2
index 361573f..0faf481 100644
--- a/services/proto/proto_gen/templates/proto.j2
+++ b/services/proto/proto_gen/templates/proto.j2
@@ -103,4 +103,8 @@ impl {{ service.proto_name }}Client {
pub fn metadata_mut(&mut self) -> &mut
std::collections::HashMap<std::string::String, std::string::String> {
&mut self.metadata
}
+
+ pub fn set_metadata(&mut self, metadata:
std::collections::HashMap<std::string::String, std::string::String>) {
+ self.metadata = metadata
+ }
}
diff --git a/services/proto/src/teaclave_frontend_service.rs
b/services/proto/src/teaclave_frontend_service.rs
index e784f59..311e397 100644
--- a/services/proto/src/teaclave_frontend_service.rs
+++ b/services/proto/src/teaclave_frontend_service.rs
@@ -420,11 +420,8 @@ impl CreateTaskRequest {
}
}
- pub fn executor(self, executor: impl Into<Executor>) -> Self {
- Self {
- executor: executor.into(),
- ..self
- }
+ pub fn executor(self, executor: Executor) -> Self {
+ Self { executor, ..self }
}
pub fn inputs_ownership(self, map: impl Into<TaskFileOwners>) -> Self {
diff --git a/types/Cargo.toml b/types/Cargo.toml
index f13043b..a2e3fc7 100644
--- a/types/Cargo.toml
+++ b/types/Cargo.toml
@@ -10,6 +10,7 @@ edition = "2018"
default = [
"protected_fs_rs/default",
]
+app = [ "default" ]
mesalock_sgx = [
"sgx_tstd",
"teaclave_crypto/mesalock_sgx",
diff --git a/types/src/attestation.rs b/types/src/attestation.rs
index 0b1e2c0..24f5139 100644
--- a/types/src/attestation.rs
+++ b/types/src/attestation.rs
@@ -91,6 +91,12 @@ impl EnclaveInfo {
Ok(Self::from_bytes(enclave_info))
}
+ #[cfg(feature = "app")]
+ pub fn from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
+ let bytes = std::fs::read(path)?;
+ Ok(Self::from_bytes(&bytes))
+ }
+
pub fn from_bytes(enclave_info: &[u8]) -> Self {
let config: EnclaveInfoToml = toml::from_slice(enclave_info)
.expect("Content not correct, unable to load enclave info.");
diff --git a/types/src/crypto.rs b/types/src/crypto.rs
index 85612a8..8c03586 100644
--- a/types/src/crypto.rs
+++ b/types/src/crypto.rs
@@ -33,6 +33,13 @@ pub struct FileAuthTag {
}
impl FileAuthTag {
+ pub fn from_bytes(input: &[u8]) -> Result<Self> {
+ ensure!(input.len() == FILE_AUTH_TAG_LENGTH, "Invalid length");
+ let mut file_auth_tag = FileAuthTag::default();
+ file_auth_tag.tag.clone_from_slice(&input);
+ Ok(file_auth_tag)
+ }
+
pub fn from_hex(input: impl AsRef<str>) -> Result<Self> {
let hex = hex::decode(input.as_ref()).context("Illegal AuthTag
provided")?;
let tag = hex
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]