Skip to content

Commit

Permalink
Added KeyIdentity to replace KeyTriple
Browse files Browse the repository at this point in the history
KeyIdentity contains a ApplicationIdentity, ProviderIdentity and a key_name.
KeyTriple still exists but solely for the use by the on_disk_manager KIM.
This is preliminary work towards the new SQLite KIM as part of parallaxsecond#486

Closes parallaxsecond#488

Signed-off-by: Matt Davis <[email protected]>
  • Loading branch information
MattDavis00 committed Aug 23, 2021
1 parent 8632fef commit bfea080
Show file tree
Hide file tree
Showing 31 changed files with 1,148 additions and 503 deletions.
32 changes: 17 additions & 15 deletions src/authenticators/direct_authenticator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//! This authenticator does not offer any security value and should only be used in environments
//! where all the clients and the service are mutually trustworthy.

use super::{AdminList, Application, Authenticate};
use super::{AdminList, Application, ApplicationIdentity, Authenticate, AuthenticatorIdentity};
use crate::front::listener::ConnectionMetadata;
use crate::utils::config::Admin;
use log::error;
Expand Down Expand Up @@ -61,7 +61,13 @@ impl Authenticate for DirectAuthenticator {
Ok(str) => {
let app_name = String::from(str);
let is_admin = self.admins.is_admin(&app_name);
Ok(Application::new(app_name, is_admin))
Ok(Application {
identity: ApplicationIdentity {
name: app_name,
authenticator_id: AuthenticatorIdentity::Known(AuthType::Direct),
},
is_admin,
})
}
Err(_) => {
error!("Error parsing the authentication value as a UTF-8 string.");
Expand All @@ -76,7 +82,6 @@ impl Authenticate for DirectAuthenticator {
mod test {
use super::super::Authenticate;
use super::DirectAuthenticator;
use crate::authenticators::ApplicationName;
use parsec_interface::requests::request::RequestAuth;
use parsec_interface::requests::ResponseStatus;

Expand All @@ -90,12 +95,12 @@ mod test {
let req_auth = RequestAuth::new(app_name.clone().into_bytes());
let conn_metadata = None;

let app = authenticator
let application = authenticator
.authenticate(&req_auth, conn_metadata)
.expect("Failed to authenticate");

assert_eq!(app.get_name(), &ApplicationName::from_name(app_name));
assert!(!app.is_admin);
assert_eq!(application.identity.name, app_name);
assert!(!application.is_admin);
}

#[test]
Expand Down Expand Up @@ -136,22 +141,19 @@ mod test {
let req_auth = RequestAuth::new(app_name.clone().into_bytes());
let conn_metadata = None;

let auth_name = authenticator
let application = authenticator
.authenticate(&req_auth, conn_metadata)
.expect("Failed to authenticate");

assert_eq!(auth_name.get_name(), &ApplicationName::from_name(app_name));
assert!(!auth_name.is_admin);
assert_eq!(application.identity.name, app_name);
assert!(!application.is_admin);

let req_auth = RequestAuth::new(admin_name.clone().into_bytes());
let auth_name = authenticator
let application = authenticator
.authenticate(&req_auth, conn_metadata)
.expect("Failed to authenticate");

assert_eq!(
auth_name.get_name(),
&ApplicationName::from_name(admin_name)
);
assert!(auth_name.is_admin);
assert_eq!(application.identity.name, admin_name);
assert!(application.is_admin);
}
}
12 changes: 10 additions & 2 deletions src/authenticators/jwt_svid_authenticator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
//! JWT SVID authenticator

use super::{Admin, AdminList, Application, Authenticate};
use super::{
Admin, AdminList, Application, ApplicationIdentity, Authenticate, AuthenticatorIdentity,
};
use crate::front::listener::ConnectionMetadata;
use log::error;
use parsec_interface::operations::list_authenticators;
Expand Down Expand Up @@ -72,6 +74,12 @@ impl Authenticate for JwtSvidAuthenticator {
})?;
let app_name = spiffe_id.to_string();
let is_admin = self.admins.is_admin(&app_name);
Ok(Application::new(app_name, is_admin))
Ok(Application {
identity: ApplicationIdentity {
name: app_name,
authenticator_id: AuthenticatorIdentity::Known(AuthType::JwtSvid),
},
is_admin,
})
}
}
134 changes: 86 additions & 48 deletions src/authenticators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//!
//! [Authenticators](https://parallaxsecond.github.io/parsec-book/parsec_service/authenticators.html)
//! provide functionality to the service for verifying the authenticity of requests.
//! The result of an authentication is an `ApplicationName` which is parsed by the authenticator and
//! The result of an authentication is an `Application` which is parsed by the authenticator and
//! used throughout the service for identifying the request initiator. The input to an authentication
//! is the `RequestAuth` field of a request, which is parsed by the authenticator specified in the header.
//! The authentication functionality is abstracted through an `Authenticate` trait.
Expand All @@ -29,30 +29,107 @@ use crate::front::listener::ConnectionMetadata;
use crate::utils::config::Admin;
use parsec_interface::operations::list_authenticators;
use parsec_interface::requests::request::RequestAuth;
use parsec_interface::requests::Result;
use parsec_interface::requests::{AuthType, Result};
use std::fmt;
use std::ops::Deref;

/// String wrapper for app names
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct ApplicationName {
/// A unique identifier for an application.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ApplicationIdentity {
/// The name of the application.
name: String,
/// The id of the authenticator used to authenticate the application name.
authenticator_id: AuthenticatorIdentity,
}

impl Deref for ApplicationName {
type Target = String;
/// Used as an internal Parsec datatype to define whether the
/// KIM & Parsec knows what authentication was used to create a key.
/// If a key is retrieved from the OnDiskKeyInfoManager then the Unknown
/// type will be used. This is as AuthType was only used to differentiate
/// namespaces since the SQLiteKeyInfoManager.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
pub enum AuthenticatorIdentity {
/// The AuthType is known. The key was likely with a newer version of Parsec
Known(AuthType),
/// The AuthType is unknown. The key was likely stored in the OnDiskKIM
Unknown,
}

fn deref(&self) -> &Self::Target {
impl fmt::Display for AuthenticatorIdentity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AuthenticatorIdentity::Unknown => write!(f, "Unknown"),
AuthenticatorIdentity::Known(auth_type) => write!(f, "Known({})", auth_type),
}
}
}

impl fmt::Display for ApplicationIdentity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"ApplicationIdentity: [name=\"{}\", authenticator_id=\"{}\"]",
self.name, self.authenticator_id
)
}
}

impl ApplicationIdentity {
/// Creates a new instance of ProviderIdentity.
pub fn new(name: String, authenticator_id: AuthenticatorIdentity) -> ApplicationIdentity {
ApplicationIdentity {
name,
authenticator_id,
}
}

/// Get the identity of the application
pub fn name(&self) -> &String {
&self.name
}

/// Get whether the application has administrator rights
pub fn authenticator_id(&self) -> &AuthenticatorIdentity {
&self.authenticator_id
}
}

/// Wrapper for a Parsec application
#[derive(Debug, Clone)]
pub struct Application {
name: ApplicationName,
/// The identity of the Application
identity: ApplicationIdentity,
/// Whether the application has administrator rights
is_admin: bool,
}

impl fmt::Display for Application {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Application {{identity: {}, is_admin: {}}}",
self.identity, self.is_admin
)
}
}

impl Application {
/// Creates a new instance of ProviderIdentity.
pub fn new(identity: ApplicationIdentity, is_admin: bool) -> Application {
Application { identity, is_admin }
}

/// Get the identity of the application
pub fn identity(&self) -> &ApplicationIdentity {
&self.identity
}

/// Get whether the application has administrator rights
pub fn is_admin(&self) -> &bool {
&self.is_admin
}
}

/// Authentication interface
///
/// Interface that must be implemented for each authentication type available for the service.
Expand All @@ -78,45 +155,6 @@ pub trait Authenticate {
) -> Result<Application>;
}

impl ApplicationName {
/// Create ApplicationName from name string only
pub fn from_name(name: String) -> ApplicationName {
ApplicationName { name }
}
}

impl Application {
/// Create a new Application structure
pub fn new(name: String, is_admin: bool) -> Application {
Application {
name: ApplicationName::from_name(name),
is_admin,
}
}

/// Check whether the application is an admin
pub fn is_admin(&self) -> bool {
self.is_admin
}

/// Get a reference to the inner ApplicationName string
pub fn get_name(&self) -> &ApplicationName {
&self.name
}
}

impl From<Application> for ApplicationName {
fn from(auth: Application) -> Self {
auth.name
}
}

impl std::fmt::Display for ApplicationName {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name)
}
}

#[derive(Debug, Clone, Default)]
struct AdminList(Vec<Admin>);

Expand Down
29 changes: 14 additions & 15 deletions src/authenticators/unix_peer_credentials_authenticator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//!
//! Currently, the stringified UID is used as the application name.

use super::{AdminList, Application, Authenticate};
use super::{AdminList, Application, ApplicationIdentity, Authenticate, AuthenticatorIdentity};
use crate::front::listener::ConnectionMetadata;
use crate::utils::config::Admin;
use log::error;
Expand Down Expand Up @@ -89,7 +89,13 @@ impl Authenticate for UnixPeerCredentialsAuthenticator {
if uid == expected_uid {
let app_name = uid.to_string();
let is_admin = self.admins.is_admin(&app_name);
Ok(Application::new(app_name, is_admin))
Ok(Application {
identity: ApplicationIdentity {
name: app_name,
authenticator_id: AuthenticatorIdentity::Known(AuthType::UnixPeerCredentials),
},
is_admin,
})
} else {
error!("Declared UID in authentication request does not match the process's UID.");
Err(ResponseStatus::AuthenticationError)
Expand All @@ -101,7 +107,6 @@ impl Authenticate for UnixPeerCredentialsAuthenticator {
mod test {
use super::super::Authenticate;
use super::UnixPeerCredentialsAuthenticator;
use crate::authenticators::ApplicationName;
use crate::front::domain_socket::peer_credentials;
use crate::front::listener::ConnectionMetadata;
use parsec_interface::requests::request::RequestAuth;
Expand Down Expand Up @@ -134,15 +139,12 @@ mod test {
pid: None,
});

let auth_name = authenticator
let application = authenticator
.authenticate(&req_auth, conn_metadata)
.expect("Failed to authenticate");

assert_eq!(
auth_name.get_name(),
&ApplicationName::from_name(get_current_uid().to_string())
);
assert!(!auth_name.is_admin);
assert_eq!(application.identity.name, get_current_uid().to_string());
assert!(!application.is_admin);
}

#[test]
Expand Down Expand Up @@ -241,15 +243,12 @@ mod test {
pid: None,
});

let auth_name = authenticator
let application = authenticator
.authenticate(&req_auth, conn_metadata)
.expect("Failed to authenticate");

assert_eq!(
auth_name.get_name(),
&ApplicationName::from_name(get_current_uid().to_string())
);
assert!(auth_name.is_admin);
assert_eq!(application.identity.name, get_current_uid().to_string());
assert!(application.is_admin);
}

#[test]
Expand Down
Loading

0 comments on commit bfea080

Please sign in to comment.