Skip to content

Commit

Permalink
feat(rust): create 3 separate credential retriever types
Browse files Browse the repository at this point in the history
  • Loading branch information
SanjoDeundiak committed Mar 21, 2024
1 parent 5d8c380 commit c2d4472
Show file tree
Hide file tree
Showing 29 changed files with 1,220 additions and 945 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use ockam::{node, Context, Result, TcpOutletOptions, TcpTransportExtension};
use ockam_api::authenticator::enrollment_tokens::TokenAcceptor;
use ockam_api::authenticator::one_time_code::OneTimeCode;
use ockam_api::nodes::NodeManager;
use ockam_api::{multiaddr_to_route, multiaddr_to_transport_route, DefaultAddress};
use ockam_api::{multiaddr_to_route, multiaddr_to_transport_route};
use ockam_core::AsyncTryClone;
use ockam_multiaddr::MultiAddr;

Expand Down Expand Up @@ -80,11 +80,11 @@ async fn start_node(ctx: Context, project_information_path: &str, token: OneTime
node.context().async_try_clone().await?,
Arc::new(tcp.clone()),
node.secure_channels(),
RemoteCredentialRetrieverInfo::new(
RemoteCredentialRetrieverInfo::create_for_project_member(
project.authority_identifier(),
project_authority_route,
DefaultAddress::CREDENTIAL_ISSUER.into(),
),
"test".to_string(), // FIXME LATER CRED
));

// 3. create an access control policy checking the value of the "component" attribute of the caller
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use ockam::{route, Context, Result};
use ockam_api::authenticator::enrollment_tokens::TokenAcceptor;
use ockam_api::authenticator::one_time_code::OneTimeCode;
use ockam_api::nodes::NodeManager;
use ockam_api::{multiaddr_to_route, multiaddr_to_transport_route, DefaultAddress};
use ockam_api::{multiaddr_to_route, multiaddr_to_transport_route};
use ockam_core::compat::sync::Arc;
use ockam_core::AsyncTryClone;
use ockam_multiaddr::MultiAddr;
Expand Down Expand Up @@ -80,11 +80,11 @@ async fn start_node(ctx: Context, project_information_path: &str, token: OneTime
node.context().async_try_clone().await?,
Arc::new(tcp.clone()),
node.secure_channels(),
RemoteCredentialRetrieverInfo::new(
RemoteCredentialRetrieverInfo::create_for_project_member(
project.authority_identifier(),
project_authority_route,
DefaultAddress::CREDENTIAL_ISSUER.into(),
),
"test".to_string(), // FIXME LATER CRED
));

// 3. create an access control policy checking the value of the "component" attribute of the caller
Expand Down
262 changes: 163 additions & 99 deletions implementations/rust/ockam/ockam_api/src/cli_state/trust.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,164 @@
use crate::cloud::project::Project;
use crate::nodes::service::{NodeManagerCredentialRetrieverOptions, NodeManagerTrustOptions};
use crate::{multiaddr_to_transport_route, CliState, DefaultAddress};
use crate::nodes::NodeManager;
use crate::{multiaddr_to_transport_route, CliState};
use ockam::identity::{IdentitiesVerification, RemoteCredentialRetrieverInfo};
use ockam_core::errcode::{Kind, Origin};
use ockam_core::{Error, Result};
use ockam_multiaddr::MultiAddr;
use ockam_vault::SoftwareVaultForVerifyingSignatures;

impl CliState {
async fn retrieve_trust_options_explicit_project_authority(
&self,
authority_identity: &str,
authority_route: &Option<MultiAddr>,
expect_cached_credential: bool,
) -> Result<NodeManagerTrustOptions> {
let identities_verification = IdentitiesVerification::new(
self.change_history_repository(),
SoftwareVaultForVerifyingSignatures::create(),
);

let authority_identity = hex::decode(authority_identity).map_err(|_e| {
Error::new(
Origin::Api,
Kind::NotFound,
"Invalid authority identity hex",
)
})?;
let authority_identifier = identities_verification
.import(None, &authority_identity)
.await?;

if let Some(authority_multiaddr) = authority_route {
if expect_cached_credential {
return Err(Error::new(
Origin::Api,
Kind::NotFound,
"Authority address was provided but expect_cached_credential is true",
));
}

let authority_route =
multiaddr_to_transport_route(authority_multiaddr).ok_or(Error::new(
Origin::Api,
Kind::NotFound,
format!("Invalid authority route: {}", &authority_multiaddr),
))?;
let info = RemoteCredentialRetrieverInfo::create_for_project_member(
authority_identifier.clone(),
authority_route,
);

let trust_options = NodeManagerTrustOptions::new(
NodeManagerCredentialRetrieverOptions::Remote {
info,
project_id: "unknown".to_string(),
},
NodeManagerCredentialRetrieverOptions::None,
Some(authority_identifier.clone()),
NodeManagerCredentialRetrieverOptions::None,
);

info!(
"TrustOptions configured: Authority: {}. Credentials retrieved from Remote Authority: {}",
authority_identifier, authority_multiaddr
);

return Ok(trust_options);
}

if expect_cached_credential {
let trust_options = NodeManagerTrustOptions::new(
NodeManagerCredentialRetrieverOptions::CacheOnly {
issuer: authority_identifier.clone(),
project_id: "unknown".to_string(),
},
NodeManagerCredentialRetrieverOptions::None,
Some(authority_identifier.clone()),
NodeManagerCredentialRetrieverOptions::None,
);

info!(
"TrustOptions configured: Authority: {}. Expect credentials in cache",
authority_identifier
);

return Ok(trust_options);
}

let trust_options = NodeManagerTrustOptions::new(
NodeManagerCredentialRetrieverOptions::None,
NodeManagerCredentialRetrieverOptions::None,
Some(authority_identifier.clone()),
NodeManagerCredentialRetrieverOptions::None,
);

info!(
"TrustOptions configured: Authority: {}. Only verifying credentials",
authority_identifier
);

Ok(trust_options)
}

async fn retrieve_trust_options_with_project(
&self,
project: Project,
) -> Result<NodeManagerTrustOptions> {
let authority_identifier = project.authority_identifier()?;
let authority_multiaddr = project.authority_multiaddr()?;
let authority_route =
multiaddr_to_transport_route(authority_multiaddr).ok_or(Error::new(
Origin::Api,
Kind::NotFound,
format!("Invalid authority route: {}", &authority_multiaddr),
))?;

let project_id = project.project_id().to_string();
let project_member_retriever = NodeManagerCredentialRetrieverOptions::Remote {
info: RemoteCredentialRetrieverInfo::create_for_project_member(
authority_identifier.clone(),
authority_route,
),
project_id: project_id.clone(),
};

let controller_identifier = NodeManager::load_controller_identifier()?;
let controller_transport_route = NodeManager::controller_route().await?;

let project_admin_retriever = NodeManagerCredentialRetrieverOptions::Remote {
info: RemoteCredentialRetrieverInfo::create_for_project_admin(
controller_identifier.clone(),
controller_transport_route.clone(),
project_id.clone(),
),
project_id: project_id.clone(),
};

let account_admin_retriever = NodeManagerCredentialRetrieverOptions::Remote {
info: RemoteCredentialRetrieverInfo::create_for_account_admin(
controller_identifier.clone(),
controller_transport_route,
),
project_id: project_id.clone(), // FIXME CRED Should be account it
};

let trust_options = NodeManagerTrustOptions::new(
project_member_retriever,
project_admin_retriever,
Some(authority_identifier.clone()),
account_admin_retriever,
);

info!(
"TrustOptions configured: Authority: {}. Credentials retrieved from project: {}",
authority_identifier, authority_multiaddr
);
Ok(trust_options)
}

/// Create [`NodeManagerTrustOptions`] depending on what trust information we possess
/// 1. Either we explicitly know the Authority identity that we trust, and optionally route to its node to request
/// a new credential
Expand Down Expand Up @@ -35,82 +187,15 @@ impl CliState {
));
}

if authority_route.is_some() && expect_cached_credential {
return Err(Error::new(
Origin::Api,
Kind::NotFound,
"Authority address was provided but expect_cached_credential is true",
));
}

// We're using explicitly specified authority instead of a project
if let Some(authority_identity) = authority_identity {
let identities_verification = IdentitiesVerification::new(
self.change_history_repository(),
SoftwareVaultForVerifyingSignatures::create(),
);

let authority_identity = hex::decode(authority_identity).map_err(|_e| {
Error::new(
Origin::Api,
Kind::NotFound,
"Invalid authority identity hex",
)
})?;
let authority_identifier = identities_verification
.import(None, &authority_identity)
.await?;

let trust_options = if let Some(authority_multiaddr) = authority_route {
let authority_route =
multiaddr_to_transport_route(authority_multiaddr).ok_or(Error::new(
Origin::Api,
Kind::NotFound,
format!("Invalid authority route: {}", &authority_multiaddr),
))?;
let info = RemoteCredentialRetrieverInfo::new(
authority_identifier.clone(),
return self
.retrieve_trust_options_explicit_project_authority(
authority_identity,
authority_route,
DefaultAddress::CREDENTIAL_ISSUER.into(),
);

let trust_options = NodeManagerTrustOptions::new(
NodeManagerCredentialRetrieverOptions::Remote(info),
Some(authority_identifier.clone()),
);

info!(
"TrustOptions configured: Authority: {}. Credentials retrieved from Remote Authority: {}",
authority_identifier, authority_multiaddr
);

trust_options
} else if expect_cached_credential {
let trust_options = NodeManagerTrustOptions::new(
NodeManagerCredentialRetrieverOptions::CacheOnly(authority_identifier.clone()),
Some(authority_identifier.clone()),
);

info!(
"TrustOptions configured: Authority: {}. Expect credentials in cache",
authority_identifier
);

trust_options
} else {
let trust_options = NodeManagerTrustOptions::new(
NodeManagerCredentialRetrieverOptions::None,
Some(authority_identifier.clone()),
);

info!(
"TrustOptions configured: Authority: {}. Only verifying credentials",
authority_identifier
);

trust_options
};

return Ok(trust_options);
expect_cached_credential,
)
.await;
}

let project = match project_name {
Expand All @@ -123,35 +208,14 @@ impl CliState {
None => {
info!("TrustOptions configured: No Authority. No Credentials");
return Ok(NodeManagerTrustOptions::new(
NodeManagerCredentialRetrieverOptions::None,
NodeManagerCredentialRetrieverOptions::None,
None,
NodeManagerCredentialRetrieverOptions::None,
));
}
};

let authority_identifier = project.authority_identifier()?;
let authority_multiaddr = project.authority_multiaddr()?;
let authority_route =
multiaddr_to_transport_route(authority_multiaddr).ok_or(Error::new(
Origin::Api,
Kind::NotFound,
format!("Invalid authority route: {}", &authority_multiaddr),
))?;
let info = RemoteCredentialRetrieverInfo::new(
authority_identifier.clone(),
authority_route,
DefaultAddress::CREDENTIAL_ISSUER.into(),
);

let trust_options = NodeManagerTrustOptions::new(
NodeManagerCredentialRetrieverOptions::Remote(info),
Some(authority_identifier.clone()),
);

info!(
"TrustOptions configured: Authority: {}. Credentials retrieved from project: {}",
authority_identifier, authority_multiaddr
);
Ok(trust_options)
self.retrieve_trust_options_with_project(project).await
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ impl NodeManager {
project_identifier: &Identifier,
project_multiaddr: &MultiAddr,
caller_identifier: &Identifier,
credentials_enabled: CredentialsEnabled,
credentials_enabled: CredentialsEnabled, // FIXME: Choose as a member or as an admin
) -> Result<ProjectNodeClient> {
let credential_retriever_creator = match credentials_enabled {
CredentialsEnabled::On => self.credential_retriever_creator.clone(),
CredentialsEnabled::On => self.credential_retriever_creators.project_member.clone(),
CredentialsEnabled::Off => None,
};

Expand Down Expand Up @@ -246,7 +246,7 @@ impl NodeManager {
get_env_with_default::<MultiAddr>(OCKAM_CONTROLLER_ADDR, default_addr).unwrap()
}

async fn controller_route() -> Result<Route> {
pub async fn controller_route() -> Result<Route> {
let multiaddr = Self::controller_multiaddr();
multiaddr_to_transport_route(&multiaddr).ok_or_else(|| {
ApiError::core(format!(
Expand Down
2 changes: 1 addition & 1 deletion implementations/rust/ockam/ockam_api/src/nodes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub use service::background_node_client::*;
pub use service::in_memory_node::*;
pub use service::policy::*;
/// The main node-manager service running on remote nodes
pub use service::{IdentityOverride, NodeManager, NodeManagerWorker};
pub use service::{NodeManager, NodeManagerWorker};

/// A const address to bind and send messages to
pub const NODEMANAGER_ADDR: &str = "_internal.nodemanager";
Loading

0 comments on commit c2d4472

Please sign in to comment.