You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by ms...@apache.org on 2020/04/22 21:37:21 UTC

[incubator-teaclave] branch master updated: [fusion] Support fusion data creation with example (#271)

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 f45e7de  [fusion] Support fusion data creation with example (#271)
f45e7de is described below

commit f45e7dee68156a45199a4cf3deb35d38ae2f356c
Author: Zhaofeng Chen <zf...@apache.org>
AuthorDate: Wed Apr 22 14:37:10 2020 -0700

    [fusion] Support fusion data creation with example (#271)
---
 cmake/scripts/test.sh                              |  14 ++
 config/runtime.config.toml                         |   3 +
 config/src/runtime.rs                              |   8 +-
 crypto/Cargo.toml                                  |   1 +
 crypto/src/lib.rs                                  |  17 +-
 services/execution/enclave/src/lib.rs              |  14 ++
 services/execution/enclave/src/service.rs          |   1 +
 services/management/enclave/src/lib.rs             |   5 +-
 services/management/enclave/src/service.rs         |  42 ++++-
 tests/fixtures/fusion/input1.txt                   |   2 +
 tests/fixtures/fusion/input2.txt                   |   3 +
 .../enclave/src/end_to_end/mesapy_data_fusion.rs   | 171 +++++++++++++++++++++
 .../enclave/src/end_to_end/mesapy_echo.rs          |   2 +-
 tests/functional/enclave/src/end_to_end/mod.rs     |   1 +
 .../enclave/src/end_to_end/native_echo.rs          |   2 +-
 .../enclave/src/end_to_end/native_gbdt_training.rs |   2 +-
 tests/functional/enclave/src/frontend_service.rs   |   2 +-
 tests/functional/enclave/src/utils.rs              |  11 +-
 types/src/file.rs                                  |  15 --
 19 files changed, 282 insertions(+), 34 deletions(-)

diff --git a/cmake/scripts/test.sh b/cmake/scripts/test.sh
index 7fb06a2..af0b9c1 100755
--- a/cmake/scripts/test.sh
+++ b/cmake/scripts/test.sh
@@ -94,6 +94,20 @@ run_functional_tests() {
     scheduler_service \
     storage_service
 
+  ${TEACLAVE_CLI_INSTALL_DIR}/teaclave_cli encrypt \
+           --algorithm aes-gcm-128 \
+           --input-file ./fixtures/fusion/input1.txt \
+           --key 00000000000000000000000000000001 \
+           --iv 123456781234567812345678 \
+           --output-file ./fixtures/fusion/input1.enc
+
+  ${TEACLAVE_CLI_INSTALL_DIR}/teaclave_cli encrypt \
+           --algorithm aes-gcm-256 \
+           --input-file ./fixtures/fusion/input2.txt \
+           --key 0000000000000000000000000000000000000000000000000000000000000002 \
+           --iv 012345670123456701234567 \
+           --output-file ./fixtures/fusion/input2.enc
+
   start_storage_server
 
   # Run tests of execution service separately
diff --git a/config/runtime.config.toml b/config/runtime.config.toml
index 5debce3..c6213d3 100644
--- a/config/runtime.config.toml
+++ b/config/runtime.config.toml
@@ -29,3 +29,6 @@ algorithm = "sgx_epid"
 url = "https://api.trustedservices.intel.com:443"
 key = "00000000000000000000000000000000"
 spid = "00000000000000000000000000000000"
+
+[mount]
+fusion_base_dir = "/tmp/fusion_data"
\ No newline at end of file
diff --git a/config/src/runtime.rs b/config/src/runtime.rs
index ec2b8bf..f8b324f 100644
--- a/config/src/runtime.rs
+++ b/config/src/runtime.rs
@@ -27,7 +27,7 @@ use anyhow::{bail, Context, Result};
 use serde::{Deserialize, Serialize};
 use std::env;
 use std::net;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::string::String;
 use std::vec::Vec;
 
@@ -37,6 +37,7 @@ pub struct RuntimeConfig {
     pub internal_endpoints: InternalEndpointsConfig,
     pub audit: AuditConfig,
     pub attestation: AttestationServiceConfig,
+    pub mount: MountConfig,
 }
 
 #[derive(Debug, Serialize, Deserialize)]
@@ -84,6 +85,11 @@ pub struct AttestationServiceConfig {
     pub spid: String,
 }
 
+#[derive(Debug, Serialize, Deserialize)]
+pub struct MountConfig {
+    pub fusion_base_dir: PathBuf,
+}
+
 impl RuntimeConfig {
     pub fn from_toml<T: AsRef<Path>>(path: T) -> Result<Self> {
         let contents = fs::read_to_string(path.as_ref())
diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml
index abc63e5..9e2e298 100644
--- a/crypto/Cargo.toml
+++ b/crypto/Cargo.toml
@@ -24,6 +24,7 @@ rand         = { version = "0.7.0" }
 serde        = { version = "1.0.92", features = ["derive"] }
 serde_json   = { version = "1.0.39" }
 ring         = { version = "0.16.5" }
+hex          = { version = "0.4.0" }
 
 teaclave_test_utils = { path = "../tests/utils", optional = true }
 
diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs
index 7998939..bef86b9 100644
--- a/crypto/src/lib.rs
+++ b/crypto/src/lib.rs
@@ -22,7 +22,7 @@ extern crate sgx_tstd as std;
 #[cfg(feature = "mesalock_sgx")]
 use std::prelude::v1::*;
 
-use anyhow::{anyhow, ensure, Result};
+use anyhow::{anyhow, ensure, Context, Result};
 use protected_fs::ProtectedFile;
 use rand::prelude::RngCore;
 use ring::aead;
@@ -35,7 +35,6 @@ const AES_GCM_128_IV_LENGTH: usize = 12;
 
 const AES_GCM_256_KEY_LENGTH: usize = 32;
 const AES_GCM_256_IV_LENGTH: usize = 12;
-
 const TEACLAVE_FILE_128_ROOT_KEY_LENGTH: usize = 16;
 
 #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
@@ -66,6 +65,12 @@ impl AesGcm256Key {
         Ok(AesGcm256Key { key, iv })
     }
 
+    pub fn from_hex(in_key: impl AsRef<str>, in_iv: impl AsRef<str>) -> Result<Self> {
+        let key = hex::decode(in_key.as_ref()).context("Illegal AesGcm256 key provided")?;
+        let iv = hex::decode(in_iv.as_ref()).context("Illegal AesGcm256 iv provided")?;
+        Self::new(&key, &iv)
+    }
+
     pub fn random() -> Self {
         Self::default()
     }
@@ -78,7 +83,7 @@ impl AesGcm256Key {
     }
 
     pub fn encrypt(&self, in_out: &mut Vec<u8>) -> Result<()> {
-        aead_encrypt(&aead::AES_128_GCM, in_out, &self.key, &self.iv)
+        aead_encrypt(&aead::AES_256_GCM, in_out, &self.key, &self.iv)
     }
 }
 
@@ -124,6 +129,12 @@ impl AesGcm128Key {
         Ok(AesGcm128Key { key, iv })
     }
 
+    pub fn from_hex(in_key: impl AsRef<str>, in_iv: impl AsRef<str>) -> Result<Self> {
+        let key = hex::decode(in_key.as_ref()).context("Illegal AesGcm128 key provided")?;
+        let iv = hex::decode(in_iv.as_ref()).context("Illegal AesGcm128 iv provided")?;
+        Self::new(&key, &iv)
+    }
+
     pub fn random() -> Self {
         Self::default()
     }
diff --git a/services/execution/enclave/src/lib.rs b/services/execution/enclave/src/lib.rs
index 603b8bb..babefa8 100644
--- a/services/execution/enclave/src/lib.rs
+++ b/services/execution/enclave/src/lib.rs
@@ -22,6 +22,7 @@ extern crate sgx_tstd as std;
 
 #[cfg(feature = "mesalock_sgx")]
 use std::prelude::v1::*;
+use std::untrusted::path::PathEx;
 
 use teaclave_attestation::verifier;
 use teaclave_binder::proto::{
@@ -61,6 +62,19 @@ fn start_service(config: &RuntimeConfig) -> anyhow::Result<()> {
         verifier::universal_quote_verifier,
     );
 
+    let fusion_base = config.mount.fusion_base_dir.clone();
+
+    // 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)?;
+
+    anyhow::ensure!(
+        fusion_base.exists(),
+        "Fusion base directory is not mounted: {}",
+        fusion_base.display()
+    );
+
     let mut service = service::TeaclaveExecutionService::new(scheduler_service_endpoint).unwrap();
     let _ = service.start();
 
diff --git a/services/execution/enclave/src/service.rs b/services/execution/enclave/src/service.rs
index c49f9f7..ec89165 100644
--- a/services/execution/enclave/src/service.rs
+++ b/services/execution/enclave/src/service.rs
@@ -51,6 +51,7 @@ impl TeaclaveExecutionService {
             std::thread::sleep(std::time::Duration::from_secs(3));
         };
         let scheduler_client = Arc::new(Mutex::new(TeaclaveSchedulerClient::new(channel)?));
+
         Ok(TeaclaveExecutionService {
             worker: Arc::new(Worker::default()),
             scheduler_client,
diff --git a/services/management/enclave/src/lib.rs b/services/management/enclave/src/lib.rs
index ba29069..2eefa6d 100644
--- a/services/management/enclave/src/lib.rs
+++ b/services/management/enclave/src/lib.rs
@@ -93,7 +93,10 @@ fn start_service(config: &RuntimeConfig) -> anyhow::Result<()> {
         verifier::universal_quote_verifier,
     );
 
-    let service = service::TeaclaveManagementService::new(storage_service_endpoint)?;
+    let service = service::TeaclaveManagementService::new(
+        storage_service_endpoint,
+        config.mount.fusion_base_dir.clone(),
+    )?;
     match server.start(service) {
         Ok(_) => (),
         Err(e) => {
diff --git a/services/management/enclave/src/service.rs b/services/management/enclave/src/service.rs
index 57d9873..54c65b2 100644
--- a/services/management/enclave/src/service.rs
+++ b/services/management/enclave/src/service.rs
@@ -17,6 +17,7 @@
 
 use anyhow::{anyhow, Result};
 use std::collections::HashMap;
+use std::path::PathBuf;
 use std::prelude::v1::*;
 use std::sync::{Arc, SgxMutex as Mutex};
 use teaclave_proto::teaclave_frontend_service::{
@@ -40,6 +41,7 @@ use teaclave_types::Function;
 #[cfg(test_mode)]
 use teaclave_types::*;
 use thiserror::Error;
+use url::Url;
 use uuid::Uuid;
 
 #[derive(Error, Debug)]
@@ -66,6 +68,7 @@ impl From<ServiceError> for TeaclaveServiceResponseError {
 #[derive(Clone)]
 pub(crate) struct TeaclaveManagementService {
     storage_client: Arc<Mutex<TeaclaveStorageClient>>,
+    fusion_base_dir: PathBuf,
 }
 
 impl TeaclaveManagement for TeaclaveManagementService {
@@ -119,8 +122,9 @@ impl TeaclaveManagement for TeaclaveManagementService {
             ServiceError::PermissionDenied
         );
 
-        let output_file =
-            TeaclaveOutputFile::new_fusion_data(owner_list).map_err(|_| ServiceError::DataError)?;
+        let output_file = self
+            .create_fusion_data(owner_list)
+            .map_err(|_| ServiceError::DataError)?;
 
         self.write_to_db(&output_file)
             .map_err(|_| ServiceError::StorageError)?;
@@ -488,7 +492,10 @@ impl TeaclaveManagement for TeaclaveManagementService {
 }
 
 impl TeaclaveManagementService {
-    pub(crate) fn new(storage_service_endpoint: Endpoint) -> Result<Self> {
+    pub(crate) fn new(
+        storage_service_endpoint: Endpoint,
+        fusion_base_dir: PathBuf,
+    ) -> Result<Self> {
         let mut i = 0;
         let channel = loop {
             match storage_service_endpoint.connect() {
@@ -502,13 +509,34 @@ 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,
+            fusion_base_dir,
+        };
 
         #[cfg(test_mode)]
         service.add_mock_data()?;
 
         Ok(service)
     }
+    pub fn create_fusion_data(&self, owner: impl Into<OwnerList>) -> Result<TeaclaveOutputFile> {
+        let uuid = Uuid::new_v4();
+        let url = format!(
+            "file://{}/{}",
+            self.fusion_base_dir.display(),
+            uuid.to_string()
+        );
+        let url = Url::parse(&url).map_err(|_| anyhow!("invalid url"))?;
+        let crypto_info = FileCrypto::default();
+
+        Ok(TeaclaveOutputFile {
+            url,
+            cmac: None,
+            crypto_info,
+            owner: owner.into(),
+            uuid,
+        })
+    }
 
     fn get_request_user_id(
         &self,
@@ -558,14 +586,12 @@ impl TeaclaveManagementService {
 
     #[cfg(test_mode)]
     fn add_mock_data(&self) -> Result<()> {
-        let mut output_file =
-            TeaclaveOutputFile::new_fusion_data(vec!["mock_user1", "frontend_user"])?;
+        let mut output_file = self.create_fusion_data(vec!["mock_user1", "frontend_user"])?;
         output_file.uuid = Uuid::parse_str("00000000-0000-0000-0000-000000000001")?;
         output_file.cmac = Some(FileAuthTag::mock());
         self.write_to_db(&output_file)?;
 
-        let mut output_file =
-            TeaclaveOutputFile::new_fusion_data(vec!["mock_user2", "mock_user3"])?;
+        let mut output_file = self.create_fusion_data(vec!["mock_user2", "mock_user3"])?;
         output_file.uuid = Uuid::parse_str("00000000-0000-0000-0000-000000000002")?;
         output_file.cmac = Some(FileAuthTag::mock());
         self.write_to_db(&output_file)?;
diff --git a/tests/fixtures/fusion/input1.txt b/tests/fixtures/fusion/input1.txt
new file mode 100644
index 0000000..7117d82
--- /dev/null
+++ b/tests/fixtures/fusion/input1.txt
@@ -0,0 +1,2 @@
+u1_hello
+u1_teaclave
\ No newline at end of file
diff --git a/tests/fixtures/fusion/input2.txt b/tests/fixtures/fusion/input2.txt
new file mode 100644
index 0000000..39a1596
--- /dev/null
+++ b/tests/fixtures/fusion/input2.txt
@@ -0,0 +1,3 @@
+u2_welcome
+u2_to
+u2_teaclave
\ No newline at end of file
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
new file mode 100644
index 0000000..27538c2
--- /dev/null
+++ b/tests/functional/enclave/src/end_to_end/mesapy_data_fusion.rs
@@ -0,0 +1,171 @@
+// 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 super::*;
+use std::collections::HashMap;
+use teaclave_crypto::{AesGcm128Key, AesGcm256Key};
+use teaclave_test_utils::test_case;
+
+fn setup_client() -> anyhow::Result<(TeaclaveFrontendClient, TeaclaveFrontendClient)> {
+    // Authenticate user before talking to frontend service
+    let mut api_client =
+        create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR)?;
+    let cred = login(&mut api_client, USERNAME1, TEST_PASSWORD)?;
+    let client1 = create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred)?;
+    let cred = login(&mut api_client, USERNAME2, TEST_PASSWORD)?;
+    let client2 = create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred)?;
+    Ok((client1, client2))
+}
+
+fn register_function(client: &mut TeaclaveFrontendClient) -> ExternalID {
+    let script = r#"
+def readlines(fid):
+    lines = None
+    with teaclave_open(fid, "rb") as f:
+        lines = f.readlines()
+    return lines
+
+def entrypoint(argv):
+    outfile = "OutFusionData"
+    infiles = ["InPartyA", "InPartyB"]
+    cnt = 0
+    with teaclave_open(outfile, "wb") as of:
+        for fid in infiles:
+            for line in readlines(fid):
+                of.write(line)
+                cnt += 1
+    summary = "Mixed %d lines of data" % cnt
+    return summary
+"#;
+
+    let input1 = FunctionInput::new("InPartyA", "Input from party A");
+    let input2 = FunctionInput::new("InPartyB", "Input from party B");
+    let fusion_output = FunctionOutput::new("OutFusionData", "Output fusion data");
+    let request = RegisterFunctionRequest::new()
+        .name("mesapy_data_fusion_demo")
+        .description("Mesapy Data Fusion Function")
+        .payload(script.into())
+        .executor_type(ExecutorType::Python)
+        .public(true)
+        .inputs(vec![input1, input2])
+        .outputs(vec![fusion_output]);
+    let response = client.register_function(request).unwrap();
+    log::info!("Resgister function: {:?}", response);
+    response.function_id
+}
+
+fn register_input_file(
+    client: &mut TeaclaveFrontendClient,
+    url: impl AsRef<str>,
+    crypto: impl Into<FileCrypto>,
+    auth_tag: impl AsRef<str>,
+) -> ExternalID {
+    let url = Url::parse(url.as_ref()).unwrap();
+    let cmac = FileAuthTag::from_hex(auth_tag.as_ref()).unwrap();
+    let request = RegisterInputFileRequest::new(url, cmac, crypto);
+    let response = client.register_input_file(request).unwrap();
+    log::info!("Register input: {:?}", response);
+    response.data_id
+}
+
+fn register_fusion_output(
+    client: &mut TeaclaveFrontendClient,
+    file_owners: impl Into<OwnerList>,
+) -> ExternalID {
+    let request = RegisterFusionOutputRequest::new(file_owners);
+    let response = client.register_fusion_output(request).unwrap();
+    response.data_id
+}
+
+fn create_task(client: &mut TeaclaveFrontendClient, function_id: &ExternalID) -> ExternalID {
+    let request = CreateTaskRequest::new()
+        .function_id(function_id.to_owned())
+        .input_owners_map(hashmap!(
+            "InPartyA" => vec![USERNAME1],
+            "InPartyB" => vec![USERNAME2]
+        ))
+        .output_owners_map(hashmap!("OutFusionData" => vec![USERNAME1, USERNAME2]))
+        .executor(Executor::MesaPy);
+    let response = client.create_task(request).unwrap();
+    log::info!("Create task: {:?}", response);
+    response.task_id
+}
+
+fn assign_data_for_task(
+    client: &mut TeaclaveFrontendClient,
+    task_id: &ExternalID,
+    input_map: HashMap<String, ExternalID>,
+    output_map: HashMap<String, ExternalID>,
+) {
+    let request = AssignDataRequest::new(task_id.clone(), input_map, output_map);
+    let response = client.assign_data(request).unwrap();
+    log::info!("Assign data: {:?}", response);
+}
+
+#[test_case]
+pub fn test_data_fusion_success() {
+    let (mut c1, mut c2) = setup_client().unwrap();
+
+    let function_id = register_function(&mut c1);
+
+    // Create Task
+    let task_id = create_task(&mut c1, &function_id);
+
+    // Register Data and Assign Data To Task
+    // input1 is owned by user1
+    let path = "http://localhost:6789/fixtures/fusion/input1.enc";
+    let key = "00000000000000000000000000000001";
+    let iv = "123456781234567812345678";
+    let cmac = "e8afd048b339fc835733e16c761a301c";
+    let crypto = AesGcm128Key::from_hex(key, iv).unwrap();
+    let input1 = register_input_file(&mut c1, path, crypto, cmac);
+
+    // fusion_output is owned by user1 and user2
+    let fusion_output = register_fusion_output(&mut c1, vec![USERNAME1, USERNAME2]);
+
+    assign_data_for_task(
+        &mut c1,
+        &task_id,
+        hashmap!("InPartyA" => input1),
+        hashmap!("OutFusionData" => fusion_output),
+    );
+
+    // input2 is owned by user2
+    let path = "http://localhost:6789/fixtures/fusion/input2.enc";
+    let key = "0000000000000000000000000000000000000000000000000000000000000002";
+    let iv = "012345670123456701234567";
+    let cmac = "75d7cf7a7843dee709e29ba0dcb865d2";
+    let crypto = AesGcm256Key::from_hex(key, iv).unwrap();
+    let input2 = register_input_file(&mut c2, path, crypto, cmac);
+    assign_data_for_task(
+        &mut c2,
+        &task_id,
+        hashmap!("InPartyB" => input2),
+        hashmap!(),
+    );
+
+    // Approve Task
+    approve_task(&mut c1, &task_id);
+    approve_task(&mut c2, &task_id);
+
+    // Invoke Task by the creator
+    invoke_task(&mut c1, &task_id);
+
+    // Get Task
+    let ret_val = get_task_until(&mut c1, &task_id, TaskStatus::Finished);
+    assert_eq!(&ret_val, "Mixed 5 lines of data");
+}
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 e286ddc..420dd40 100644
--- a/tests/functional/enclave/src/end_to_end/mesapy_echo.rs
+++ b/tests/functional/enclave/src/end_to_end/mesapy_echo.rs
@@ -23,7 +23,7 @@ pub fn test_echo_task_success() {
     // Authenticate user before talking to frontend service
     let mut api_client =
         create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
-    let cred = login(&mut api_client, USERNAME, PASSWORD).unwrap();
+    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD).unwrap();
     let mut client =
         create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).unwrap();
 
diff --git a/tests/functional/enclave/src/end_to_end/mod.rs b/tests/functional/enclave/src/end_to_end/mod.rs
index f725f3d..eb807ea 100644
--- a/tests/functional/enclave/src/end_to_end/mod.rs
+++ b/tests/functional/enclave/src/end_to_end/mod.rs
@@ -21,6 +21,7 @@ use teaclave_proto::teaclave_frontend_service::*;
 use teaclave_types::*;
 use url::Url;
 
+mod mesapy_data_fusion;
 mod mesapy_echo;
 mod native_echo;
 mod native_gbdt_training;
diff --git a/tests/functional/enclave/src/end_to_end/native_echo.rs b/tests/functional/enclave/src/end_to_end/native_echo.rs
index d86eade..73c2090 100644
--- a/tests/functional/enclave/src/end_to_end/native_echo.rs
+++ b/tests/functional/enclave/src/end_to_end/native_echo.rs
@@ -23,7 +23,7 @@ pub fn test_echo_task_success() {
     // Authenticate user before talking to frontend service
     let mut api_client =
         create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
-    let cred = login(&mut api_client, USERNAME, PASSWORD).unwrap();
+    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD).unwrap();
     let mut client =
         create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).unwrap();
 
diff --git a/tests/functional/enclave/src/end_to_end/native_gbdt_training.rs b/tests/functional/enclave/src/end_to_end/native_gbdt_training.rs
index ecb1cbe..5407668 100644
--- a/tests/functional/enclave/src/end_to_end/native_gbdt_training.rs
+++ b/tests/functional/enclave/src/end_to_end/native_gbdt_training.rs
@@ -41,7 +41,7 @@ pub fn test_gbdt_training_task() {
 fn authorized_frontend_client() -> TeaclaveFrontendClient {
     let mut api_client =
         create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
-    let cred = login(&mut api_client, USERNAME, PASSWORD).unwrap();
+    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD).unwrap();
     create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).unwrap()
 }
 
diff --git a/tests/functional/enclave/src/frontend_service.rs b/tests/functional/enclave/src/frontend_service.rs
index 792fa44..594c269 100644
--- a/tests/functional/enclave/src/frontend_service.rs
+++ b/tests/functional/enclave/src/frontend_service.rs
@@ -28,7 +28,7 @@ use url::Url;
 fn authorized_client() -> TeaclaveFrontendClient {
     let mut api_client =
         create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
-    let cred = login(&mut api_client, USERNAME, PASSWORD).unwrap();
+    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD).unwrap();
     create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).unwrap()
 }
 
diff --git a/tests/functional/enclave/src/utils.rs b/tests/functional/enclave/src/utils.rs
index 01f707e..4ef0c68 100644
--- a/tests/functional/enclave/src/utils.rs
+++ b/tests/functional/enclave/src/utils.rs
@@ -166,12 +166,19 @@ pub fn login(
 }
 
 pub const USERNAME: &str = "frontend_user";
-pub const PASSWORD: &str = "test_password";
+pub const USERNAME1: &str = "frontend_user1";
+pub const USERNAME2: &str = "frontend_user2";
+pub const USERNAME3: &str = "frontend_user3";
+
+pub const TEST_PASSWORD: &str = "test_password";
 
 pub fn setup() {
     // Register user for the first time
     let mut api_client =
         create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
+
     // Ignore error if register failed.
-    let _ = register_new_account(&mut api_client, USERNAME, PASSWORD);
+    for uname in vec![USERNAME, USERNAME1, USERNAME2, USERNAME3].iter() {
+        let _ = register_new_account(&mut api_client, uname, TEST_PASSWORD);
+    }
 }
diff --git a/types/src/file.rs b/types/src/file.rs
index ec3e597..35fece2 100644
--- a/types/src/file.rs
+++ b/types/src/file.rs
@@ -102,21 +102,6 @@ impl TeaclaveOutputFile {
             uuid: create_uuid(),
         }
     }
-
-    pub fn new_fusion_data(owner: impl Into<OwnerList>) -> Result<TeaclaveOutputFile> {
-        let uuid = create_uuid();
-        let url = format!("fusion://path/{}?token=fusion_token", uuid.to_string());
-        let url = Url::parse(&url).map_err(|_| anyhow!("invalid url"))?;
-        let crypto_info = FileCrypto::default();
-
-        Ok(TeaclaveOutputFile {
-            url,
-            cmac: None,
-            crypto_info,
-            owner: owner.into(),
-            uuid,
-        })
-    }
 }
 
 impl Storable for TeaclaveOutputFile {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org