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 f730fe9 refactor(authentication): polish authentication error (#618)
f730fe9 is described below
commit f730fe9c99c03c2879410f01ceaeca48e08c3ecc
Author: Mingshen Sun <[email protected]>
AuthorDate: Fri Feb 11 09:36:54 2022 -0800
refactor(authentication): polish authentication error (#618)
---
services/authentication/enclave/src/api_service.rs | 108 ++++++++++-----------
services/authentication/enclave/src/error.rs | 53 +++++++---
.../authentication/enclave/src/internal_service.rs | 15 +--
tests/scripts/functional_tests.py | 3 +-
4 files changed, 102 insertions(+), 77 deletions(-)
diff --git a/services/authentication/enclave/src/api_service.rs
b/services/authentication/enclave/src/api_service.rs
index 2a00b53..874edc1 100644
--- a/services/authentication/enclave/src/api_service.rs
+++ b/services/authentication/enclave/src/api_service.rs
@@ -15,10 +15,11 @@
// specific language governing permissions and limitations
// under the License.
-use crate::error::TeaclaveAuthenticationApiError;
-use crate::user_db::{DbClient, DbError};
+use crate::error::AuthenticationError;
+use crate::error::AuthenticationServiceError;
+use crate::user_db::DbClient;
use crate::user_info::UserInfo;
-use anyhow::anyhow;
+
use std::prelude::v1::*;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use std::untrusted::time::SystemTimeEx;
@@ -50,15 +51,19 @@ impl TeaclaveAuthenticationApiService {
&self,
id: &str,
token: &str,
- ) -> Result<UserRole, TeaclaveAuthenticationApiError> {
+ ) -> Result<UserRole, AuthenticationError> {
let user: UserInfo = match self.db_client.get_user(&id) {
Ok(value) => value,
- Err(_) => bail!(TeaclaveAuthenticationApiError::PermissionDenied),
+ Err(_) => bail!(AuthenticationError::InvalidUserId),
};
+ if token.is_empty() {
+ bail!(AuthenticationError::InvalidToken);
+ }
+
match user.validate_token(&self.jwt_secret, &token) {
Ok(claims) => Ok(claims.get_role()),
- Err(_) => bail!(TeaclaveAuthenticationApiError::PermissionDenied),
+ Err(_) => bail!(AuthenticationError::IncorrectToken),
}
}
}
@@ -71,12 +76,12 @@ impl TeaclaveAuthenticationApi for
TeaclaveAuthenticationApiService {
let id: String = request
.metadata
.get("id")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingUserId)?
.into();
let token: String = request
.metadata
.get("token")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingToken)?
.into();
let requester_role = self.validate_user_credential(&id, &token)?;
@@ -84,27 +89,26 @@ impl TeaclaveAuthenticationApi for
TeaclaveAuthenticationApiService {
let request = request.message;
ensure!(
!request.id.is_empty(),
- TeaclaveAuthenticationApiError::InvalidUserId
+ AuthenticationServiceError::InvalidUserId
);
if self.db_client.get_user(&request.id).is_ok() {
- bail!(TeaclaveAuthenticationApiError::InvalidUserId);
+ bail!(AuthenticationServiceError::UserIdExist);
}
let role = UserRole::new(&request.role, &request.attribute);
ensure!(
role != UserRole::Invalid,
- TeaclaveAuthenticationApiError::InvalidRole
+ AuthenticationServiceError::InvalidRole
);
ensure!(
authorize_user_register(&requester_role, &request),
- TeaclaveAuthenticationApiError::InvalidRole
+ AuthenticationServiceError::PermissionDenied
);
let new_user = UserInfo::new(&request.id, &request.password, role);
match self.db_client.create_user(&new_user) {
Ok(_) => Ok(UserRegisterResponse {}),
- Err(DbError::UserExist) =>
Err(TeaclaveAuthenticationApiError::InvalidUserId.into()),
- Err(_) =>
Err(TeaclaveAuthenticationApiError::ServiceUnavailable.into()),
+ Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
}
}
@@ -115,39 +119,38 @@ impl TeaclaveAuthenticationApi for
TeaclaveAuthenticationApiService {
let id: String = request
.metadata
.get("id")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingUserId)?
.into();
let token: String = request
.metadata
.get("token")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingToken)?
.into();
let requester_role = self.validate_user_credential(&id, &token)?;
let request = request.message;
ensure!(
!request.id.is_empty(),
- TeaclaveAuthenticationApiError::InvalidUserId
+ AuthenticationServiceError::InvalidUserId
);
if self.db_client.get_user(&request.id).is_err() {
- bail!(TeaclaveAuthenticationApiError::InvalidUserId);
+ bail!(AuthenticationServiceError::InvalidUserId);
}
let role = UserRole::new(&request.role, &request.attribute);
ensure!(
role != UserRole::Invalid,
- TeaclaveAuthenticationApiError::InvalidRole
+ AuthenticationServiceError::InvalidRole
);
ensure!(
authorize_user_update(&requester_role, &request),
- TeaclaveAuthenticationApiError::InvalidRole
+ AuthenticationServiceError::PermissionDenied
);
let updated_user = UserInfo::new(&request.id, &request.password, role);
match self.db_client.update_user(&updated_user) {
Ok(_) => Ok(UserUpdateResponse {}),
- Err(DbError::UserNotExist) =>
Err(TeaclaveAuthenticationApiError::InvalidUserId.into()),
- Err(_) =>
Err(TeaclaveAuthenticationApiError::ServiceUnavailable.into()),
+ Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
}
}
@@ -156,28 +159,25 @@ impl TeaclaveAuthenticationApi for
TeaclaveAuthenticationApiService {
request: Request<UserLoginRequest>,
) -> TeaclaveServiceResponseResult<UserLoginResponse> {
let request = request.message;
- ensure!(
- !request.id.is_empty(),
- TeaclaveAuthenticationApiError::InvalidUserId
- );
+ ensure!(!request.id.is_empty(), AuthenticationError::InvalidUserId);
ensure!(
!request.password.is_empty(),
- TeaclaveAuthenticationApiError::InvalidPassword
+ AuthenticationError::InvalidPassword
);
let user = self
.db_client
.get_user(&request.id)
- .map_err(|_| TeaclaveAuthenticationApiError::PermissionDenied)?;
+ .map_err(|_| AuthenticationError::UserIdNotFound)?;
if !user.verify_password(&request.password) {
- bail!(TeaclaveAuthenticationApiError::PermissionDenied)
+ bail!(AuthenticationError::IncorrectPassword)
} else {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
- .map_err(|_|
TeaclaveAuthenticationApiError::ServiceUnavailable)?;
+ .map_err(|e| AuthenticationServiceError::Service(e.into()))?;
let exp = (now + Duration::from_secs(24 * 60 * 60)).as_secs();
match user.get_token(exp, &self.jwt_secret) {
Ok(token) => Ok(UserLoginResponse { token }),
- Err(_) =>
Err(TeaclaveAuthenticationApiError::ServiceUnavailable.into()),
+ Err(e) => bail!(AuthenticationServiceError::Service(e)),
}
}
}
@@ -189,26 +189,25 @@ impl TeaclaveAuthenticationApi for
TeaclaveAuthenticationApiService {
let id: String = request
.metadata
.get("id")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingUserId)?
.into();
let token: String = request
.metadata
.get("token")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingToken)?
.into();
let requester_role = self.validate_user_credential(&id, &token)?;
let request = request.message;
ensure!(
!request.password.is_empty(),
- TeaclaveAuthenticationApiError::InvalidPassword
+ AuthenticationError::InvalidPassword
);
let updated_user = UserInfo::new(&id, &request.password,
requester_role);
match self.db_client.update_user(&updated_user) {
Ok(_) => Ok(UserChangePasswordResponse {}),
- Err(DbError::UserNotExist) =>
Err(TeaclaveAuthenticationApiError::InvalidUserId.into()),
- Err(_) =>
Err(TeaclaveAuthenticationApiError::ServiceUnavailable.into()),
+ Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
}
}
@@ -219,28 +218,28 @@ impl TeaclaveAuthenticationApi for
TeaclaveAuthenticationApiService {
let id: String = request
.metadata
.get("id")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingUserId)?
.into();
let token: String = request
.metadata
.get("token")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingToken)?
.into();
let requester_role = self.validate_user_credential(&id, &token)?;
let request = request.message;
ensure!(
!request.id.is_empty(),
- TeaclaveAuthenticationApiError::InvalidUserId
+ AuthenticationServiceError::InvalidUserId
);
let user = self
.db_client
.get_user(&request.id)
- .map_err(|_| TeaclaveAuthenticationApiError::InvalidUserId)?;
+ .map_err(|_| AuthenticationServiceError::PermissionDenied)?;
ensure!(
authorize_reset_user_password(&requester_role, &user),
- TeaclaveAuthenticationApiError::InvalidRole
+ AuthenticationServiceError::PermissionDenied
);
let mut encode_buffer = uuid::Uuid::encode_buffer();
@@ -252,8 +251,7 @@ impl TeaclaveAuthenticationApi for
TeaclaveAuthenticationApiService {
Ok(_) => Ok(ResetUserPasswordResponse {
password: new_password.to_string(),
}),
- Err(DbError::UserNotExist) =>
Err(TeaclaveAuthenticationApiError::InvalidUserId.into()),
- Err(_) =>
Err(TeaclaveAuthenticationApiError::ServiceUnavailable.into()),
+ Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
}
}
@@ -264,33 +262,32 @@ impl TeaclaveAuthenticationApi for
TeaclaveAuthenticationApiService {
let id: String = request
.metadata
.get("id")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingUserId)?
.into();
let token: String = request
.metadata
.get("token")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingToken)?
.into();
let requester_role = self.validate_user_credential(&id, &token)?;
let request = request.message;
ensure!(
!request.id.is_empty(),
- TeaclaveAuthenticationApiError::InvalidUserId
+ AuthenticationServiceError::InvalidUserId
);
let user = self
.db_client
.get_user(&request.id)
- .map_err(|_| TeaclaveAuthenticationApiError::InvalidUserId)?;
+ .map_err(|_| AuthenticationServiceError::PermissionDenied)?;
ensure!(
authorize_delete_user(&requester_role, &user),
- TeaclaveAuthenticationApiError::InvalidRole
+ AuthenticationServiceError::PermissionDenied
);
match self.db_client.delete_user(&request.id) {
Ok(_) => Ok(DeleteUserResponse {}),
- Err(DbError::UserNotExist) =>
Err(TeaclaveAuthenticationApiError::InvalidUserId.into()),
- Err(_) =>
Err(TeaclaveAuthenticationApiError::ServiceUnavailable.into()),
+ Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
}
}
@@ -301,24 +298,24 @@ impl TeaclaveAuthenticationApi for
TeaclaveAuthenticationApiService {
let id: String = request
.metadata
.get("id")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingUserId)?
.into();
let token: String = request
.metadata
.get("token")
- .ok_or_else(|| anyhow!("Missing credential"))?
+ .ok_or(AuthenticationServiceError::MissingToken)?
.into();
let requester_role = self.validate_user_credential(&id, &token)?;
let request = request.message;
ensure!(
!request.id.is_empty(),
- TeaclaveAuthenticationApiError::InvalidUserId
+ AuthenticationServiceError::InvalidUserId
);
ensure!(
authorize_list_users(&requester_role, &request),
- TeaclaveAuthenticationApiError::InvalidRole
+ AuthenticationServiceError::PermissionDenied
);
let users = match requester_role {
@@ -328,8 +325,7 @@ impl TeaclaveAuthenticationApi for
TeaclaveAuthenticationApiService {
match users {
Ok(ids) => Ok(ListUsersResponse { ids }),
- Err(DbError::UserNotExist) =>
Err(TeaclaveAuthenticationApiError::InvalidUserId.into()),
- Err(_) =>
Err(TeaclaveAuthenticationApiError::ServiceUnavailable.into()),
+ Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
}
}
}
diff --git a/services/authentication/enclave/src/error.rs
b/services/authentication/enclave/src/error.rs
index 27106c3..bb35629 100644
--- a/services/authentication/enclave/src/error.rs
+++ b/services/authentication/enclave/src/error.rs
@@ -21,33 +21,58 @@ use teaclave_types::TeaclaveServiceResponseError;
use thiserror::Error;
#[derive(Error, Debug)]
-pub(crate) enum TeaclaveAuthenticationApiError {
- #[error("permission denied")]
- PermissionDenied,
- #[error("invalid userid")]
+pub(crate) enum AuthenticationError {
+ #[error("invalid user id")]
InvalidUserId,
+ #[error("invalid token")]
+ InvalidToken,
#[error("invalid password")]
InvalidPassword,
- #[error("invalid role")]
- InvalidRole,
- #[error("service unavailable")]
- ServiceUnavailable,
+ #[error("user id not found")]
+ UserIdNotFound,
+ #[error("incorrect password")]
+ IncorrectPassword,
+ #[error("incorrect token")]
+ IncorrectToken,
}
-impl From<TeaclaveAuthenticationApiError> for TeaclaveServiceResponseError {
- fn from(error: TeaclaveAuthenticationApiError) -> Self {
- TeaclaveServiceResponseError::RequestError(error.to_string())
+impl From<AuthenticationError> for AuthenticationServiceError {
+ fn from(error: AuthenticationError) -> Self {
+ AuthenticationServiceError::Authentication(error)
+ }
+}
+
+impl From<AuthenticationError> for TeaclaveServiceResponseError {
+ fn from(error: AuthenticationError) -> Self {
+ TeaclaveServiceResponseError::RequestError(
+ AuthenticationServiceError::from(error).to_string(),
+ )
}
}
#[derive(Error, Debug)]
-pub(crate) enum TeaclaveAuthenticationInternalError {
+pub(crate) enum AuthenticationServiceError {
#[error("permission denied")]
PermissionDenied,
+ #[error("authentication failed")]
+ Authentication(AuthenticationError),
+ #[error("invalid user id")]
+ InvalidUserId,
+ #[error("invalid role")]
+ InvalidRole,
+ #[error("user id exist")]
+ UserIdExist,
+ #[error("service internal error")]
+ Service(#[from] anyhow::Error),
+ #[error("missing user id")]
+ MissingUserId,
+ #[error("missing token")]
+ MissingToken,
}
-impl From<TeaclaveAuthenticationInternalError> for
TeaclaveServiceResponseError {
- fn from(error: TeaclaveAuthenticationInternalError) -> Self {
+impl From<AuthenticationServiceError> for TeaclaveServiceResponseError {
+ fn from(error: AuthenticationServiceError) -> Self {
+ log::debug!("AuthenticationServiceError: {:?}", error);
TeaclaveServiceResponseError::RequestError(error.to_string())
}
}
diff --git a/services/authentication/enclave/src/internal_service.rs
b/services/authentication/enclave/src/internal_service.rs
index 876131a..1f07a10 100644
--- a/services/authentication/enclave/src/internal_service.rs
+++ b/services/authentication/enclave/src/internal_service.rs
@@ -15,7 +15,7 @@
// specific language governing permissions and limitations
// under the License.
-use crate::error::TeaclaveAuthenticationInternalError;
+use crate::error::AuthenticationError;
use crate::user_db::DbClient;
use crate::user_info::UserInfo;
use std::prelude::v1::*;
@@ -23,7 +23,7 @@ use teaclave_proto::teaclave_authentication_service::{
TeaclaveAuthenticationInternal, UserAuthenticateRequest,
UserAuthenticateResponse,
};
use teaclave_rpc::Request;
-use teaclave_service_enclave_utils::teaclave_service;
+use teaclave_service_enclave_utils::{bail, teaclave_service};
use teaclave_types::TeaclaveServiceResponseResult;
#[teaclave_service(teaclave_authentication_service,
TeaclaveAuthenticationInternal)]
@@ -48,16 +48,19 @@ impl TeaclaveAuthenticationInternal for
TeaclaveAuthenticationInternalService {
request: Request<UserAuthenticateRequest>,
) -> TeaclaveServiceResponseResult<UserAuthenticateResponse> {
let request = request.message;
- if request.credential.id.is_empty() ||
request.credential.token.is_empty() {
- return
Err(TeaclaveAuthenticationInternalError::PermissionDenied.into());
+ if request.credential.id.is_empty() {
+ bail!(AuthenticationError::InvalidUserId);
+ }
+ if request.credential.token.is_empty() {
+ bail!(AuthenticationError::InvalidToken);
}
let user: UserInfo = match
self.db_client.get_user(&request.credential.id) {
Ok(value) => value,
- Err(_) => return
Err(TeaclaveAuthenticationInternalError::PermissionDenied.into()),
+ Err(_) => bail!(AuthenticationError::InvalidUserId),
};
let claims = user
.validate_token(&self.jwt_secret, &request.credential.token)
- .map_err(|_|
TeaclaveAuthenticationInternalError::PermissionDenied)?;
+ .map_err(|_| AuthenticationError::IncorrectToken)?;
Ok(UserAuthenticateResponse { claims })
}
}
diff --git a/tests/scripts/functional_tests.py
b/tests/scripts/functional_tests.py
index 7b06095..b7e248b 100755
--- a/tests/scripts/functional_tests.py
+++ b/tests/scripts/functional_tests.py
@@ -163,7 +163,8 @@ class TestAuthenticationService(unittest.TestCase):
response = read_message(self.socket)
self.assertEqual(
- response, b'{"result":"err","request_error":"permission denied"}')
+ response,
+ b'{"result":"err","request_error":"authentication failed"}')
if __name__ == '__main__':
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]