This is an automated email from the ASF dual-hosted git repository.
mssun pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git
The following commit(s) were added to refs/heads/develop by this push:
new 0634007 [authentication] Split authentication service into api and
internal services (#213)
0634007 is described below
commit 06340078c08a6a41a61283976a43251329c6bf1c
Author: TX <[email protected]>
AuthorDate: Thu Jan 30 14:18:55 2020 -0800
[authentication] Split authentication service into api and internal
services (#213)
---
services/authentication/enclave/src/api_service.rs | 150 +++++++++++
.../authentication/enclave/src/internal_service.rs | 203 +++++++++++++++
services/authentication/enclave/src/lib.rs | 69 ++++-
services/authentication/enclave/src/service.rs | 282 ---------------------
services/authentication/enclave/src/user_db.rs | 4 +-
services/frontend/enclave/src/service.rs | 6 +-
services/proto/proto_gen/templates/proto.j2 | 18 +-
.../proto/teaclave_authentication_service.proto | 7 +-
.../proto/src/teaclave_authentication_service.rs | 12 +-
.../enclave/src/teaclave_authentication_service.rs | 69 +++--
10 files changed, 482 insertions(+), 338 deletions(-)
diff --git a/services/authentication/enclave/src/api_service.rs
b/services/authentication/enclave/src/api_service.rs
new file mode 100644
index 0000000..da5eb66
--- /dev/null
+++ b/services/authentication/enclave/src/api_service.rs
@@ -0,0 +1,150 @@
+use crate::user_db::{DbClient, DbError};
+use crate::user_info::UserInfo;
+use std::prelude::v1::*;
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
+use std::untrusted::time::SystemTimeEx;
+use teaclave_proto::teaclave_authentication_service::{
+ TeaclaveAuthenticationApi, UserLoginRequest, UserLoginResponse,
UserRegisterRequest,
+ UserRegisterResponse,
+};
+use teaclave_rpc::Request;
+use teaclave_service_enclave_utils::teaclave_service;
+use teaclave_types::{TeaclaveServiceResponseError,
TeaclaveServiceResponseResult};
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+enum TeaclaveAuthenticationApiError {
+ #[error("permission denied")]
+ PermissionDenied,
+ #[error("invalid userid")]
+ InvalidUserId,
+ #[error("invalid password")]
+ InvalidPassword,
+ #[error("service unavailable")]
+ ServiceUnavailable,
+}
+
+impl From<TeaclaveAuthenticationApiError> for TeaclaveServiceResponseError {
+ fn from(error: TeaclaveAuthenticationApiError) -> Self {
+ TeaclaveServiceResponseError::RequestError(error.to_string())
+ }
+}
+
+#[teaclave_service(
+ teaclave_authentication_service,
+ TeaclaveAuthenticationApi,
+ TeaclaveAuthenticationError
+)]
+#[derive(Clone)]
+pub(crate) struct TeaclaveAuthenticationApiService {
+ pub(crate) db_client: DbClient,
+ pub(crate) jwt_secret: Vec<u8>,
+}
+
+impl TeaclaveAuthenticationApi for TeaclaveAuthenticationApiService {
+ fn user_register(
+ &self,
+ request: Request<UserRegisterRequest>,
+ ) -> TeaclaveServiceResponseResult<UserRegisterResponse> {
+ let request = request.message;
+ if request.id.is_empty() {
+ return Err(TeaclaveAuthenticationApiError::InvalidUserId.into());
+ }
+ if self.db_client.get_user(&request.id).is_ok() {
+ return Err(TeaclaveAuthenticationApiError::InvalidUserId.into());
+ }
+ let new_user = UserInfo::new(&request.id, &request.password);
+ match self.db_client.create_user(&new_user) {
+ Ok(_) => Ok(UserRegisterResponse {}),
+ Err(DbError::UserExist) =>
Err(TeaclaveAuthenticationApiError::InvalidUserId.into()),
+ Err(_) =>
Err(TeaclaveAuthenticationApiError::ServiceUnavailable.into()),
+ }
+ }
+
+ fn user_login(
+ &self,
+ request: Request<UserLoginRequest>,
+ ) -> TeaclaveServiceResponseResult<UserLoginResponse> {
+ let request = request.message;
+ if request.id.is_empty() {
+ return Err(TeaclaveAuthenticationApiError::InvalidUserId.into());
+ }
+ if request.password.is_empty() {
+ return Err(TeaclaveAuthenticationApiError::InvalidPassword.into());
+ }
+ let user = self
+ .db_client
+ .get_user(&request.id)
+ .map_err(|_| TeaclaveAuthenticationApiError::PermissionDenied)?;
+ if !user.verify_password(&request.password) {
+ Err(TeaclaveAuthenticationApiError::PermissionDenied.into())
+ } else {
+ let now = SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .map_err(|_|
TeaclaveAuthenticationApiError::ServiceUnavailable)?;
+ let exp = (now + Duration::from_secs(24 * 60)).as_secs();
+ match user.get_token(exp, &self.jwt_secret) {
+ Ok(token) => Ok(UserLoginResponse { token }),
+ Err(_) =>
Err(TeaclaveAuthenticationApiError::ServiceUnavailable.into()),
+ }
+ }
+ }
+}
+
+#[cfg(feature = "enclave_unit_test")]
+pub mod tests {
+ use super::*;
+ use crate::user_db::*;
+ use crate::user_info::*;
+ use rand::RngCore;
+ use std::vec;
+
+ fn get_mock_service() -> TeaclaveAuthenticationApiService {
+ let database = Database::open().unwrap();
+ let mut jwt_secret = vec![0; JWT_SECRET_LEN];
+ let mut rng = rand::thread_rng();
+ rng.fill_bytes(&mut jwt_secret);
+ TeaclaveAuthenticationApiService {
+ db_client: database.get_client(),
+ jwt_secret,
+ }
+ }
+
+ pub fn test_user_register() {
+ let request = UserRegisterRequest {
+ id: "test_register_id".to_string(),
+ password: "test_password".to_string(),
+ };
+ let request = Request::new(request);
+ let service = get_mock_service();
+ assert!(service.user_register(request).is_ok());
+ }
+
+ pub fn test_user_login() {
+ let service = get_mock_service();
+ let request = UserRegisterRequest {
+ id: "test_login_id".to_string(),
+ password: "test_password".to_string(),
+ };
+ let request = Request::new(request);
+ assert!(service.user_register(request).is_ok());
+ let request = UserLoginRequest {
+ id: "test_login_id".to_string(),
+ password: "test_password".to_string(),
+ };
+ let request = Request::new(request);
+ let response = service.user_login(request);
+ assert!(response.is_ok());
+ let token = response.unwrap().token;
+ let user = service.db_client.get_user("test_login_id").unwrap();
+ assert!(user.validate_token(&service.jwt_secret, &token));
+
+ info!("saved user_info: {:?}", user);
+ let request = UserLoginRequest {
+ id: "test_login_id".to_string(),
+ password: "test_password1".to_string(),
+ };
+ let request = Request::new(request);
+ assert!(service.user_login(request).is_err());
+ }
+}
diff --git a/services/authentication/enclave/src/internal_service.rs
b/services/authentication/enclave/src/internal_service.rs
new file mode 100644
index 0000000..72360a3
--- /dev/null
+++ b/services/authentication/enclave/src/internal_service.rs
@@ -0,0 +1,203 @@
+use crate::user_db::DbClient;
+use crate::user_info::UserInfo;
+use std::prelude::v1::*;
+use teaclave_proto::teaclave_authentication_service::{
+ TeaclaveAuthenticationInternal, UserAuthenticateRequest,
UserAuthenticateResponse,
+};
+use teaclave_rpc::Request;
+use teaclave_service_enclave_utils::teaclave_service;
+use teaclave_types::TeaclaveServiceResponseResult;
+
+#[teaclave_service(teaclave_authentication_service,
TeaclaveAuthenticationInternal)]
+#[derive(Clone)]
+pub(crate) struct TeaclaveAuthenticationInternalService {
+ pub(crate) db_client: DbClient,
+ pub(crate) jwt_secret: Vec<u8>,
+}
+
+impl TeaclaveAuthenticationInternal for TeaclaveAuthenticationInternalService {
+ fn user_authenticate(
+ &self,
+ request: Request<UserAuthenticateRequest>,
+ ) -> TeaclaveServiceResponseResult<UserAuthenticateResponse> {
+ let request = request.message;
+ if request.credential.id.is_empty() ||
request.credential.token.is_empty() {
+ return Ok(UserAuthenticateResponse { accept: false });
+ }
+ let user: UserInfo = match
self.db_client.get_user(&request.credential.id) {
+ Ok(value) => value,
+ Err(_) => return Ok(UserAuthenticateResponse { accept: false }),
+ };
+ Ok(UserAuthenticateResponse {
+ accept: user.validate_token(&self.jwt_secret,
&request.credential.token),
+ })
+ }
+}
+
+#[cfg(feature = "enclave_unit_test")]
+pub mod tests {
+ use super::*;
+ use crate::user_db::*;
+ use crate::user_info::*;
+ use rand::RngCore;
+ use std::time::{Duration, SystemTime, UNIX_EPOCH};
+ use std::untrusted::time::SystemTimeEx;
+ use std::vec;
+ use teaclave_proto::teaclave_common::UserCredential;
+
+ fn get_mock_service() -> TeaclaveAuthenticationInternalService {
+ let database = Database::open().unwrap();
+ let mut jwt_secret = vec![0; JWT_SECRET_LEN];
+ let mut rng = rand::thread_rng();
+ rng.fill_bytes(&mut jwt_secret);
+ let user = UserInfo::new("test_authenticate_id",
"test_authenticate_id");
+ database.get_client().create_user(&user).unwrap();
+ TeaclaveAuthenticationInternalService {
+ db_client: database.get_client(),
+ jwt_secret,
+ }
+ }
+
+ pub fn test_user_authenticate() {
+ let id = "test_authenticate_id";
+ let service = get_mock_service();
+ let user = service.db_client.get_user(id).unwrap();
+
+ let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+ let exp = (now + Duration::from_secs(24 * 60)).as_secs();
+ let token = user.get_token(exp, &service.jwt_secret).unwrap();
+
+ let response = get_authenticate_response(id, &token, &service);
+ assert!(response.accept);
+ let token = validate_token(id, &service.jwt_secret, &token);
+ info!("valid token: {:?}", token.unwrap());
+ }
+
+ pub fn test_invalid_algorithm() {
+ let id = "test_authenticate_id";
+ let service = get_mock_service();
+ let my_claims = get_correct_claim(id);
+ let token = gen_token(
+ my_claims,
+ Some(jsonwebtoken::Algorithm::HS256),
+ &service.jwt_secret,
+ );
+ let response = get_authenticate_response(id, &token, &service);
+ assert!(!response.accept);
+ let error = validate_token(id, &service.jwt_secret, &token);
+ assert!(error.is_err());
+ match *error.unwrap_err().kind() {
+ jsonwebtoken::errors::ErrorKind::InvalidAlgorithm => (),
+ _ => panic!("wrong error type"),
+ }
+ }
+
+ pub fn test_invalid_issuer() {
+ let id = "test_authenticate_id";
+ let service = get_mock_service();
+ let mut my_claims = get_correct_claim(id);
+ my_claims.iss = "wrong issuer".to_string();
+ let token = gen_token(my_claims, None, &service.jwt_secret);
+ let response = get_authenticate_response(id, &token, &service);
+ assert!(!response.accept);
+ let error = validate_token(id, &service.jwt_secret, &token);
+ assert!(error.is_err());
+ match *error.unwrap_err().kind() {
+ jsonwebtoken::errors::ErrorKind::InvalidIssuer => (),
+ _ => panic!("wrong error type"),
+ }
+ }
+
+ pub fn test_expired_token() {
+ let id = "test_authenticate_id";
+ let service = get_mock_service();
+ let mut my_claims = get_correct_claim(id);
+ my_claims.exp -= 24 * 60 + 1;
+ let token = gen_token(my_claims, None, &service.jwt_secret);
+ let response = get_authenticate_response(id, &token, &service);
+ assert!(!response.accept);
+ let error = validate_token(id, &service.jwt_secret, &token);
+ assert!(error.is_err());
+ match *error.unwrap_err().kind() {
+ jsonwebtoken::errors::ErrorKind::ExpiredSignature => (),
+ _ => panic!("wrong error type"),
+ }
+ }
+
+ pub fn test_invalid_user() {
+ let id = "test_authenticate_id";
+ let service = get_mock_service();
+ let mut my_claims = get_correct_claim(id);
+ my_claims.sub = "wrong user".to_string();
+ let token = gen_token(my_claims, None, &service.jwt_secret);
+ let response = get_authenticate_response(id, &token, &service);
+ assert!(!response.accept);
+ let error = validate_token(id, &service.jwt_secret, &token);
+ assert!(error.is_err());
+ match *error.unwrap_err().kind() {
+ jsonwebtoken::errors::ErrorKind::InvalidSubject => (),
+ _ => panic!("wrong error type"),
+ }
+ }
+
+ pub fn test_wrong_secret() {
+ let id = "test_authenticate_id";
+ let service = get_mock_service();
+ let my_claims = get_correct_claim(id);
+ let token = gen_token(my_claims, None, b"bad secret");
+ let response = get_authenticate_response(id, &token, &service);
+ assert!(!response.accept);
+ let error = validate_token(id, &service.jwt_secret, &token);
+ assert!(error.is_err());
+ match *error.unwrap_err().kind() {
+ jsonwebtoken::errors::ErrorKind::InvalidSignature => (),
+ _ => panic!("wrong error type"),
+ }
+ }
+
+ fn get_correct_claim(id: &str) -> Claims {
+ let now = SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .unwrap()
+ .as_secs();
+ Claims {
+ sub: id.to_string(),
+ iss: ISSUER_NAME.to_string(),
+ exp: now + 24 * 60,
+ }
+ }
+
+ fn gen_token(claim: Claims, bad_alg: Option<jsonwebtoken::Algorithm>,
secret: &[u8]) -> String {
+ let mut header = jsonwebtoken::Header::default();
+ header.alg = bad_alg.unwrap_or(JWT_ALG);
+ jsonwebtoken::encode(&header, &claim, secret).unwrap()
+ }
+
+ fn get_authenticate_response(
+ id: &str,
+ token: &str,
+ service: &TeaclaveAuthenticationInternalService,
+ ) -> UserAuthenticateResponse {
+ let credential = UserCredential {
+ id: id.to_string(),
+ token: token.to_string(),
+ };
+ let request = UserAuthenticateRequest { credential };
+ let request = Request::new(request);
+ service.user_authenticate(request).unwrap()
+ }
+
+ fn validate_token(
+ id: &str,
+ secret: &[u8],
+ token: &str,
+ ) -> jsonwebtoken::errors::Result<jsonwebtoken::TokenData<Claims>> {
+ let validation = jsonwebtoken::Validation {
+ iss: Some(ISSUER_NAME.to_string()),
+ sub: Some(id.to_string()),
+ algorithms: vec![JWT_ALG],
+ ..Default::default()
+ };
+ jsonwebtoken::decode::<crate::user_info::Claims>(token, secret,
&validation)
+ }
+}
diff --git a/services/authentication/enclave/src/lib.rs
b/services/authentication/enclave/src/lib.rs
index a57bc9b..7bfbcab 100644
--- a/services/authentication/enclave/src/lib.rs
+++ b/services/authentication/enclave/src/lib.rs
@@ -24,6 +24,7 @@ extern crate sgx_tstd as std;
extern crate log;
use anyhow::Result;
+use rand::RngCore;
use std::prelude::v1::*;
use std::sync::Arc;
use std::thread;
@@ -34,19 +35,22 @@ use teaclave_ipc::proto::{
};
use teaclave_ipc::{handle_ecall, register_ecall_handler};
use teaclave_proto::teaclave_authentication_service::{
- TeaclaveAuthenticationRequest, TeaclaveAuthenticationResponse,
+ TeaclaveAuthenticationApiRequest, TeaclaveAuthenticationApiResponse,
+ TeaclaveAuthenticationInternalRequest,
TeaclaveAuthenticationInternalResponse,
};
use teaclave_rpc::config::SgxTrustedTlsServerConfig;
use teaclave_rpc::server::SgxTrustedTlsServer;
use teaclave_service_enclave_utils::ServiceEnclave;
-mod service;
+mod api_service;
+mod internal_service;
mod user_db;
mod user_info;
-fn start_endpoint(
+fn start_internal_endpoint(
listener: std::net::TcpListener,
db_client: user_db::DbClient,
+ jwt_secret: Vec<u8>,
attestation: Arc<RemoteAttestation>,
) {
let config = SgxTrustedTlsServerConfig::new_without_verifier(
@@ -56,11 +60,45 @@ fn start_endpoint(
.unwrap();
let mut server = SgxTrustedTlsServer::<
- TeaclaveAuthenticationResponse,
- TeaclaveAuthenticationRequest,
+ TeaclaveAuthenticationInternalResponse,
+ TeaclaveAuthenticationInternalRequest,
>::new(listener, &config);
- let service =
service::TeaclaveAuthenticationService::new(db_client).unwrap();
+ let service = internal_service::TeaclaveAuthenticationInternalService {
+ db_client,
+ jwt_secret,
+ };
+
+ match server.start(service) {
+ Ok(_) => (),
+ Err(e) => {
+ error!("Service exit, error: {}.", e);
+ }
+ }
+}
+
+fn start_api_endpoint(
+ listener: std::net::TcpListener,
+ db_client: user_db::DbClient,
+ jwt_secret: Vec<u8>,
+ attestation: Arc<RemoteAttestation>,
+) {
+ let config = SgxTrustedTlsServerConfig::new_without_verifier(
+ &attestation.cert,
+ &attestation.private_key,
+ )
+ .unwrap();
+
+ let mut server = SgxTrustedTlsServer::<
+ TeaclaveAuthenticationApiResponse,
+ TeaclaveAuthenticationApiRequest,
+ >::new(listener, &config);
+
+ let service = api_service::TeaclaveAuthenticationApiService {
+ db_client,
+ jwt_secret,
+ };
+
match server.start(service) {
Ok(_) => (),
Err(e) => {
@@ -79,16 +117,20 @@ fn handle_start_service(args: &StartServiceInput) ->
Result<StartServiceOutput>
RemoteAttestation::generate_and_endorse(&ias_config.ias_key,
&ias_config.ias_spid).unwrap(),
);
let database = user_db::Database::open()?;
+ let mut api_jwt_secret = vec![0; user_info::JWT_SECRET_LEN];
+ let mut rng = rand::thread_rng();
+ rng.fill_bytes(&mut api_jwt_secret);
+ let internal_jwt_secret = api_jwt_secret.to_owned();
let attestation_ref = attestation.clone();
let client = database.get_client();
let api_endpoint_thread_handler = thread::spawn(move || {
- start_endpoint(api_listener, client, attestation_ref);
+ start_api_endpoint(api_listener, client, api_jwt_secret,
attestation_ref);
});
let client = database.get_client();
let internal_endpoint_thread_handler = thread::spawn(move || {
- start_endpoint(internal_listener, client, attestation);
+ start_internal_endpoint(internal_listener, client,
internal_jwt_secret, attestation);
});
api_endpoint_thread_handler.join().unwrap();
@@ -123,9 +165,14 @@ pub mod tests {
pub fn run_tests() -> bool {
run_tests!(
- service::tests::test_user_login,
- service::tests::test_user_authenticate,
- service::tests::test_user_register,
+ api_service::tests::test_user_login,
+ api_service::tests::test_user_register,
+ internal_service::tests::test_user_authenticate,
+ internal_service::tests::test_invalid_algorithm,
+ internal_service::tests::test_invalid_issuer,
+ internal_service::tests::test_expired_token,
+ internal_service::tests::test_invalid_user,
+ internal_service::tests::test_wrong_secret,
)
}
}
diff --git a/services/authentication/enclave/src/service.rs
b/services/authentication/enclave/src/service.rs
deleted file mode 100644
index a0abbe5..0000000
--- a/services/authentication/enclave/src/service.rs
+++ /dev/null
@@ -1,282 +0,0 @@
-use crate::user_db::{DbClient, DbError};
-use crate::user_info::{UserInfo, JWT_SECRET_LEN};
-use rand::RngCore;
-use std::prelude::v1::*;
-use std::time::{Duration, SystemTime, UNIX_EPOCH};
-use std::untrusted::time::SystemTimeEx;
-use teaclave_proto::teaclave_authentication_service::{
- TeaclaveAuthentication, UserAuthenticateRequest, UserAuthenticateResponse,
UserLoginRequest,
- UserLoginResponse, UserRegisterRequest, UserRegisterResponse,
-};
-use teaclave_rpc::Request;
-use teaclave_service_enclave_utils::teaclave_service;
-use teaclave_types::{TeaclaveServiceResponseError,
TeaclaveServiceResponseResult};
-use thiserror::Error;
-
-#[derive(Error, Debug)]
-enum TeaclaveAuthenticationError {
- #[error("permission denied")]
- PermissionDenied,
- #[error("invalid userid")]
- InvalidUserId,
- #[error("invalid password")]
- InvalidPassword,
- #[error("service unavailable")]
- ServiceUnavailable,
-}
-
-impl From<TeaclaveAuthenticationError> for TeaclaveServiceResponseError {
- fn from(error: TeaclaveAuthenticationError) -> Self {
- TeaclaveServiceResponseError::RequestError(error.to_string())
- }
-}
-
-#[teaclave_service(
- teaclave_authentication_service,
- TeaclaveAuthentication,
- TeaclaveAuthenticationError
-)]
-#[derive(Clone)]
-pub(crate) struct TeaclaveAuthenticationService {
- db_client: DbClient,
- jwt_secret: Vec<u8>,
-}
-
-impl TeaclaveAuthenticationService {
- pub(crate) fn new(db_client: DbClient) -> anyhow::Result<Self> {
- let mut jwt_secret = vec![0; JWT_SECRET_LEN];
- let mut rng = rand::thread_rng();
- rng.fill_bytes(&mut jwt_secret);
- Ok(Self {
- db_client,
- jwt_secret,
- })
- }
-}
-
-impl TeaclaveAuthentication for TeaclaveAuthenticationService {
- fn user_register(
- &self,
- request: Request<UserRegisterRequest>,
- ) -> TeaclaveServiceResponseResult<UserRegisterResponse> {
- let request = request.message;
- if request.id.is_empty() {
- return Err(TeaclaveAuthenticationError::InvalidUserId.into());
- }
- if self.db_client.get_user(&request.id).is_ok() {
- return Err(TeaclaveAuthenticationError::InvalidUserId.into());
- }
- let new_user = UserInfo::new(&request.id, &request.password);
- match self.db_client.create_user(&new_user) {
- Ok(_) => Ok(UserRegisterResponse {}),
- Err(DbError::UserExist) =>
Err(TeaclaveAuthenticationError::InvalidUserId.into()),
- Err(_) =>
Err(TeaclaveAuthenticationError::ServiceUnavailable.into()),
- }
- }
-
- fn user_login(
- &self,
- request: Request<UserLoginRequest>,
- ) -> TeaclaveServiceResponseResult<UserLoginResponse> {
- let request = request.message;
- if request.id.is_empty() {
- return Err(TeaclaveAuthenticationError::InvalidUserId.into());
- }
- if request.password.is_empty() {
- return Err(TeaclaveAuthenticationError::InvalidPassword.into());
- }
- let user = self
- .db_client
- .get_user(&request.id)
- .map_err(|_| TeaclaveAuthenticationError::PermissionDenied)?;
- if !user.verify_password(&request.password) {
- Err(TeaclaveAuthenticationError::PermissionDenied.into())
- } else {
- let now = SystemTime::now()
- .duration_since(UNIX_EPOCH)
- .map_err(|_| TeaclaveAuthenticationError::ServiceUnavailable)?;
- let exp = (now + Duration::from_secs(24 * 60)).as_secs();
- match user.get_token(exp, &self.jwt_secret) {
- Ok(token) => Ok(UserLoginResponse { token }),
- Err(_) =>
Err(TeaclaveAuthenticationError::ServiceUnavailable.into()),
- }
- }
- }
-
- fn user_authenticate(
- &self,
- request: Request<UserAuthenticateRequest>,
- ) -> TeaclaveServiceResponseResult<UserAuthenticateResponse> {
- let request = request.message;
- if request.credential.id.is_empty() ||
request.credential.token.is_empty() {
- return Ok(UserAuthenticateResponse { accept: false });
- }
- let user: UserInfo = match
self.db_client.get_user(&request.credential.id) {
- Ok(value) => value,
- Err(_) => return Ok(UserAuthenticateResponse { accept: false }),
- };
- Ok(UserAuthenticateResponse {
- accept: user.validate_token(&self.jwt_secret,
&request.credential.token),
- })
- }
-}
-
-#[cfg(feature = "enclave_unit_test")]
-pub mod tests {
- use super::*;
- use crate::user_db::*;
- use crate::user_info::*;
- use std::vec;
- use teaclave_proto::teaclave_common::UserCredential;
-
- fn get_mock_service() -> TeaclaveAuthenticationService {
- let database = Database::open().unwrap();
- TeaclaveAuthenticationService::new(database.get_client()).unwrap()
- }
-
- pub fn test_user_register() {
- let request = UserRegisterRequest {
- id: "test_register_id".to_string(),
- password: "test_password".to_string(),
- };
- let request = Request::new(request);
- let service = get_mock_service();
- assert!(service.user_register(request).is_ok());
- }
-
- pub fn test_user_login() {
- let service = get_mock_service();
- let request = UserRegisterRequest {
- id: "test_login_id".to_string(),
- password: "test_password".to_string(),
- };
- let request = Request::new(request);
- assert!(service.user_register(request).is_ok());
- let request = UserLoginRequest {
- id: "test_login_id".to_string(),
- password: "test_password".to_string(),
- };
- let request = Request::new(request);
- assert!(service.user_login(request).is_ok());
-
- info!(
- "saved user_info: {:?}",
- service.db_client.get_user("test_login_id").unwrap()
- );
- let request = UserLoginRequest {
- id: "test_login_id".to_string(),
- password: "test_password1".to_string(),
- };
- let request = Request::new(request);
- assert!(service.user_login(request).is_err());
- }
-
- pub fn test_user_authenticate() {
- let id = "test_authenticate_id";
- let service = get_mock_service();
- let request = UserRegisterRequest {
- id: id.to_string(),
- password: "test_password".to_string(),
- };
- let request = Request::new(request);
- assert!(service.user_register(request).is_ok());
-
- let request = UserLoginRequest {
- id: id.to_string(),
- password: "test_password".to_string(),
- };
- let request = Request::new(request);
- let token = service.user_login(request).unwrap().token;
- info!("login token: {}", token);
- dump_token(&service.jwt_secret, &token);
-
- let response = get_authenticate_response(id, &token, &service);
- assert!(response.accept);
-
- info!("test wrong algorithm");
- let my_claims = get_correct_claim();
- let token = gen_token(
- my_claims,
- Some(jsonwebtoken::Algorithm::HS256),
- &service.jwt_secret,
- );
- dump_token(&service.jwt_secret, &token);
- let response = get_authenticate_response(id, &token, &service);
- assert!(!response.accept);
-
- info!("test wrong issuer");
- let mut my_claims = get_correct_claim();
- my_claims.iss = "wrong issuer".to_string();
- let token = gen_token(my_claims, None, &service.jwt_secret);
- dump_token(&service.jwt_secret, &token);
- let response = get_authenticate_response(id, &token, &service);
- assert!(!response.accept);
-
- info!("test wrong user");
- let mut my_claims = get_correct_claim();
- my_claims.sub = "wrong user".to_string();
- let token = gen_token(my_claims, None, &service.jwt_secret);
- dump_token(&service.jwt_secret, &token);
- let response = get_authenticate_response(id, &token, &service);
- assert!(!response.accept);
-
- info!("test expired token");
- let mut my_claims = get_correct_claim();
- my_claims.exp -= 24 * 60 + 1;
- let token = gen_token(my_claims, None, &service.jwt_secret);
- dump_token(&service.jwt_secret, &token);
- let response = get_authenticate_response(id, &token, &service);
- assert!(!response.accept);
-
- info!("test wrong secret");
- let my_claims = get_correct_claim();
- let token = gen_token(my_claims, None, b"bad secret");
- dump_token(&service.jwt_secret, &token);
- let response = get_authenticate_response(id, &token, &service);
- assert!(!response.accept);
- }
-
- fn get_correct_claim() -> Claims {
- let now = SystemTime::now()
- .duration_since(UNIX_EPOCH)
- .unwrap()
- .as_secs();
- Claims {
- sub: "test_authenticate_id".to_string(),
- iss: ISSUER_NAME.to_string(),
- exp: now + 24 * 60,
- }
- }
-
- fn gen_token(claim: Claims, bad_alg: Option<jsonwebtoken::Algorithm>,
secret: &[u8]) -> String {
- let mut header = jsonwebtoken::Header::default();
- header.alg = bad_alg.unwrap_or(JWT_ALG);
- jsonwebtoken::encode(&header, &claim, secret).unwrap()
- }
-
- fn get_authenticate_response(
- id: &str,
- token: &str,
- service: &TeaclaveAuthenticationService,
- ) -> UserAuthenticateResponse {
- let credential = UserCredential {
- id: id.to_string(),
- token: token.to_string(),
- };
- let request = UserAuthenticateRequest { credential };
- let request = Request::new(request);
- service.user_authenticate(request).unwrap()
- }
-
- fn dump_token(secret: &[u8], token: &str) {
- let validation = jsonwebtoken::Validation {
- iss: Some(ISSUER_NAME.to_string()),
- sub: Some("test_authenticate_id".to_string()),
- algorithms: vec![JWT_ALG],
- ..Default::default()
- };
- let token_data =
- jsonwebtoken::decode::<crate::user_info::Claims>(token, secret,
&validation);
- info!("token {:?}", token_data);
- }
-}
diff --git a/services/authentication/enclave/src/user_db.rs
b/services/authentication/enclave/src/user_db.rs
index 7ff422a..c0f79a8 100644
--- a/services/authentication/enclave/src/user_db.rs
+++ b/services/authentication/enclave/src/user_db.rs
@@ -99,7 +99,7 @@ impl Database {
let call: DBCall = match receiver.recv() {
Ok(req) => req,
Err(e) => {
- error!("mspc receive error: {}", e);
+ info!("mspc receive error: {}", e);
break;
}
};
@@ -120,7 +120,7 @@ impl Database {
};
match sender.send(response) {
Ok(_) => (),
- Err(e) => error!("mpsc send error: {}", e),
+ Err(e) => info!("mpsc send error: {}", e),
}
}
});
diff --git a/services/frontend/enclave/src/service.rs
b/services/frontend/enclave/src/service.rs
index 983e0b8..b5fb700 100644
--- a/services/frontend/enclave/src/service.rs
+++ b/services/frontend/enclave/src/service.rs
@@ -1,7 +1,7 @@
use std::prelude::v1::*;
use std::sync::{Arc, SgxMutex as Mutex};
use teaclave_config::RuntimeConfig;
-use
teaclave_proto::teaclave_authentication_service::TeaclaveAuthenticationClient;
+use
teaclave_proto::teaclave_authentication_service::TeaclaveAuthenticationInternalClient;
use teaclave_proto::teaclave_authentication_service::UserAuthenticateRequest;
use teaclave_proto::teaclave_common::UserCredential;
use teaclave_proto::teaclave_frontend_service::{
@@ -29,7 +29,7 @@ impl From<TeaclaveFrontendError> for
TeaclaveServiceResponseError {
#[teaclave_service(teaclave_frontend_service, TeaclaveFrontend,
TeaclaveFrontendError)]
#[derive(Clone)]
pub(crate) struct TeaclaveFrontendService {
- authentication_client: Arc<Mutex<TeaclaveAuthenticationClient>>,
+ authentication_client: Arc<Mutex<TeaclaveAuthenticationInternalClient>>,
}
impl TeaclaveFrontendService {
@@ -37,7 +37,7 @@ impl TeaclaveFrontendService {
let channel =
Endpoint::new(&config.internal_endpoints.authentication.advertised_address)
.connect()
.unwrap();
- let client = TeaclaveAuthenticationClient::new(channel).unwrap();
+ let client =
TeaclaveAuthenticationInternalClient::new(channel).unwrap();
Self {
authentication_client: Arc::new(Mutex::new(client)),
}
diff --git a/services/proto/proto_gen/templates/proto.j2
b/services/proto/proto_gen/templates/proto.j2
index 8980405..665ac76 100644
--- a/services/proto/proto_gen/templates/proto.j2
+++ b/services/proto/proto_gen/templates/proto.j2
@@ -1,10 +1,3 @@
-use anyhow;
-use teaclave_types;
-use teaclave_rpc;
-use core::convert::TryFrom;
-use teaclave_types::TeaclaveServiceResponseError;
-use std::prelude::v1::*;
-
#[derive(Clone, serde::Serialize, serde::Deserialize, Debug)]
#[serde(tag = "request", rename_all = "snake_case")]
pub enum {{ service.proto_name }}Request {
@@ -27,11 +20,13 @@ pub trait {{ service.proto_name }} {
{%- endfor %}
fn dispatch(&self, request: teaclave_rpc::Request<{{ service.proto_name
}}Request>) -> teaclave_types::TeaclaveServiceResponseResult<{{
service.proto_name }}Response> {
+ use core::convert::TryFrom;
+ use std::string::ToString;
match request.message {
{%- for m in service.methods %}
{{ service.proto_name }}Request::{{ m.proto_name }}(r) => {
let r = crate::{{ proto_impl_mod_name }}::{{ m.input_type
}}::try_from(r)
- .map_err(|_|
TeaclaveServiceResponseError::InternalError("internal".to_string()))?;
+ .map_err(|_|
teaclave_types::TeaclaveServiceResponseError::InternalError("internal".to_string()))?;
let r = teaclave_rpc::Request {
metadata: request.metadata,
message: r,
@@ -66,13 +61,16 @@ impl {{ service.proto_name }}Client {
{{ service.proto_name }}Request,
{{ service.proto_name }}Response
>,
- metadata: std::collections::HashMap<String, String>,
+ metadata: std::collections::HashMap<std::string::String,
std::string::String>,
) -> anyhow::Result<Self> {
Ok(Self { channel, metadata })
}
{%- for m in service.methods %}
pub fn {{ m.name }}<T: Into<{{ m.input_type }}>>(&mut self, request: T) ->
teaclave_types::TeaclaveServiceResponseResult<{{ m.output_type }}> {
+ {%- if service.methods.len() > 1 %}
+ use std::string::ToString;
+ {%- endif %}
let request = {{ service.proto_name }}Request::{{ m.proto_name
}}(request.into());
let request = teaclave_rpc::Request {
metadata: self.metadata.clone(),
@@ -83,7 +81,7 @@ impl {{ service.proto_name }}Client {
Ok({{ service.proto_name }}Response::{{ m.proto_name }}(response))
=> Ok(response),
Err(e) => Err(e),
{%- if service.methods.len() > 1 %}
- _ =>
Err(TeaclaveServiceResponseError::InternalError("internal".to_string())),
+ _ =>
Err(teaclave_types::TeaclaveServiceResponseError::InternalError("internal".to_string())),
{%- endif %}
}
}
diff --git a/services/proto/src/proto/teaclave_authentication_service.proto
b/services/proto/src/proto/teaclave_authentication_service.proto
index 12b7edf..bf483c6 100644
--- a/services/proto/src/proto/teaclave_authentication_service.proto
+++ b/services/proto/src/proto/teaclave_authentication_service.proto
@@ -27,8 +27,11 @@ message UserAuthenticateResponse {
bool accept = 1;
}
-service TeaclaveAuthentication {
+service TeaclaveAuthenticationApi {
rpc UserRegister(UserRegisterRequest) returns (UserRegisterResponse);
rpc UserLogin (UserLoginRequest) returns (UserLoginResponse);
- rpc UserAuthenticate (UserAuthenticateRequest) returns
(UserAuthenticateResponse);
}
+
+service TeaclaveAuthenticationInternal {
+ rpc UserAuthenticate (UserAuthenticateRequest) returns
(UserAuthenticateResponse);
+}
\ No newline at end of file
diff --git a/services/proto/src/teaclave_authentication_service.rs
b/services/proto/src/teaclave_authentication_service.rs
index 71db70e..7409c98 100644
--- a/services/proto/src/teaclave_authentication_service.rs
+++ b/services/proto/src/teaclave_authentication_service.rs
@@ -5,10 +5,14 @@ use serde::{Deserialize, Serialize};
use crate::teaclave_authentication_service_proto as proto;
use crate::teaclave_common;
-pub use proto::TeaclaveAuthentication;
-pub use proto::TeaclaveAuthenticationClient;
-pub use proto::TeaclaveAuthenticationRequest;
-pub use proto::TeaclaveAuthenticationResponse;
+pub use proto::TeaclaveAuthenticationApi;
+pub use proto::TeaclaveAuthenticationApiClient;
+pub use proto::TeaclaveAuthenticationApiRequest;
+pub use proto::TeaclaveAuthenticationApiResponse;
+pub use proto::TeaclaveAuthenticationInternal;
+pub use proto::TeaclaveAuthenticationInternalClient;
+pub use proto::TeaclaveAuthenticationInternalRequest;
+pub use proto::TeaclaveAuthenticationInternalResponse;
#[derive(Serialize, Deserialize, Debug)]
pub struct UserRegisterRequest {
diff --git
a/tests/functional_tests/enclave/src/teaclave_authentication_service.rs
b/tests/functional_tests/enclave/src/teaclave_authentication_service.rs
index 61887b8..fc39059 100644
--- a/tests/functional_tests/enclave/src/teaclave_authentication_service.rs
+++ b/tests/functional_tests/enclave/src/teaclave_authentication_service.rs
@@ -21,7 +21,7 @@ pub fn run_tests() -> bool {
)
}
-fn test_login_success() {
+fn get_api_client() -> TeaclaveAuthenticationApiClient {
let runtime_config =
RuntimeConfig::from_toml("runtime.config.toml").expect("runtime");
let enclave_info =
EnclaveInfo::from_bytes(&runtime_config.audit.enclave_info_bytes.as_ref().unwrap());
@@ -38,7 +38,36 @@ fn test_login_success() {
.config(config)
.connect()
.unwrap();
- let mut client = TeaclaveAuthenticationClient::new(channel).unwrap();
+ TeaclaveAuthenticationApiClient::new(channel).unwrap()
+}
+
+fn get_internal_client() -> TeaclaveAuthenticationInternalClient {
+ let runtime_config =
RuntimeConfig::from_toml("runtime.config.toml").expect("runtime");
+ let enclave_info =
+
EnclaveInfo::from_bytes(&runtime_config.audit.enclave_info_bytes.as_ref().unwrap());
+ let enclave_attr = enclave_info
+ .get_enclave_attr("teaclave_authentication_service")
+ .expect("authentication");
+ let config =
SgxTrustedTlsClientConfig::new_with_attestation_report_verifier(
+ vec![enclave_attr],
+ BUILD_CONFIG.ias_root_ca_cert,
+ verifier::universal_quote_verifier,
+ );
+
+ let channel = Endpoint::new(
+ &runtime_config
+ .internal_endpoints
+ .authentication
+ .advertised_address,
+ )
+ .config(config)
+ .connect()
+ .unwrap();
+ TeaclaveAuthenticationInternalClient::new(channel).unwrap()
+}
+
+fn test_login_success() {
+ let mut client = get_api_client();
let request = UserRegisterRequest {
id: "test_login_id1".to_string(),
password: "test_password".to_string(),
@@ -56,8 +85,7 @@ fn test_login_success() {
}
fn test_login_fail() {
- let channel = Endpoint::new("localhost:7776").connect().unwrap();
- let mut client = TeaclaveAuthenticationClient::new(channel).unwrap();
+ let mut client = get_api_client();
let request = UserRegisterRequest {
id: "test_login_id2".to_string(),
password: "test_password".to_string(),
@@ -75,60 +103,54 @@ fn test_login_fail() {
}
fn test_authenticate_success() {
- let channel = Endpoint::new("localhost:17776").connect().unwrap();
- let mut client = TeaclaveAuthenticationClient::new(channel).unwrap();
+ let mut api_client = get_api_client();
+ let mut internal_client = get_internal_client();
let request = UserRegisterRequest {
id: "test_authenticate_id1".to_string(),
password: "test_password".to_string(),
};
- let response_result = client.user_register(request);
+ let response_result = api_client.user_register(request);
assert!(response_result.is_ok());
let request = UserLoginRequest {
id: "test_authenticate_id1".to_string(),
password: "test_password".to_string(),
};
- let response_result = client.user_login(request);
+ let response_result = api_client.user_login(request);
assert!(response_result.is_ok());
let credential = UserCredential {
id: "test_authenticate_id1".to_string(),
token: response_result.unwrap().token,
};
let request = UserAuthenticateRequest { credential };
- let response_result = client.user_authenticate(request);
+ let response_result = internal_client.user_authenticate(request);
info!("{:?}", response_result);
assert!(response_result.unwrap().accept);
}
fn test_authenticate_fail() {
- let channel = Endpoint::new("localhost:17776").connect().unwrap();
- let mut client = TeaclaveAuthenticationClient::new(channel).unwrap();
+ let mut api_client = get_api_client();
+ let mut internal_client = get_internal_client();
+
let request = UserRegisterRequest {
id: "test_authenticate_id2".to_string(),
password: "test_password".to_string(),
};
- let response_result = client.user_register(request);
+ let response_result = api_client.user_register(request);
assert!(response_result.is_ok());
- let request = UserLoginRequest {
- id: "test_authenticate_id2".to_string(),
- password: "test_password".to_string(),
- };
- let response_result = client.user_login(request);
- assert!(response_result.is_ok());
let credential = UserCredential {
id: "test_authenticate_id2".to_string(),
token: "wrong_token".to_string(),
};
let request = UserAuthenticateRequest { credential };
- let response_result = client.user_authenticate(request);
+ let response_result = internal_client.user_authenticate(request);
info!("{:?}", response_result);
assert!(!response_result.unwrap().accept);
}
fn test_register_success() {
- let channel = Endpoint::new("localhost:7776").connect().unwrap();
- let mut client = TeaclaveAuthenticationClient::new(channel).unwrap();
+ let mut client = get_api_client();
let request = UserRegisterRequest {
id: "test_register_id1".to_string(),
password: "test_password".to_string(),
@@ -139,8 +161,7 @@ fn test_register_success() {
}
fn test_register_fail() {
- let channel = Endpoint::new("localhost:7776").connect().unwrap();
- let mut client = TeaclaveAuthenticationClient::new(channel).unwrap();
+ let mut client = get_api_client();
let request = UserRegisterRequest {
id: "test_register_id2".to_string(),
password: "test_password".to_string(),
@@ -149,7 +170,7 @@ fn test_register_fail() {
assert!(response_result.is_ok());
let request = UserRegisterRequest {
id: "test_register_id2".to_string(),
- password: "test_password".to_string(),
+ password: "test_password2".to_string(),
};
let response_result = client.user_register(request);
info!("{:?}", response_result);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]