Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rust): add optional --identity argument to secure-channel create #4018

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,16 @@ pub struct CreateSecureChannelRequest<'a> {
#[b(1)] pub addr: CowStr<'a>,
#[b(2)] pub authorized_identifiers: Option<Vec<CowStr<'a>>>,
#[n(3)] pub credential_exchange_mode: CredentialExchangeMode,
#[n(4)] pub timeout: Option<Duration>
#[n(4)] pub timeout: Option<Duration>,
#[b(5)] pub identity: Option<CowStr<'a>>,
}

impl<'a> CreateSecureChannelRequest<'a> {
pub fn new(
addr: &MultiAddr,
authorized_identifiers: Option<Vec<IdentityIdentifier>>,
credential_exchange_mode: CredentialExchangeMode,
identity: Option<String>,
) -> Self {
Self {
#[cfg(feature = "tag")]
Expand All @@ -50,6 +52,7 @@ impl<'a> CreateSecureChannelRequest<'a> {
.map(|x| x.into_iter().map(|y| y.to_string().into()).collect()),
credential_exchange_mode,
timeout: None,
identity: identity.map(|x| x.into()),
}
}
}
Expand Down
17 changes: 12 additions & 5 deletions implementations/rust/ockam/ockam_api/src/nodes/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ impl NodeManager {
addr: &MultiAddr,
auth: Option<IdentityIdentifier>,
timeout: Option<Duration>,
ctx: &Context,
) -> Result<(MultiAddr, MultiAddr)> {
if let Some(p) = addr.first() {
if p.code() == Project::CODE {
Expand All @@ -346,7 +347,9 @@ impl NodeManager {
multiaddr_to_route(&a).ok_or_else(|| ApiError::generic("invalid multiaddr"))?;
let i = Some(vec![i]);
let m = CredentialExchangeMode::Oneway;
let w = self.create_secure_channel_impl(r, i, m, timeout).await?;
let w = self
.create_secure_channel_impl(r, i, m, timeout, None, ctx)
.await?;
let a = MultiAddr::default().try_with(addr.iter().skip(1))?;
return Ok((try_address_to_multiaddr(&w)?, a));
}
Expand All @@ -358,7 +361,9 @@ impl NodeManager {
let r = multiaddr_to_route(&a).ok_or_else(|| ApiError::generic("invalid multiaddr"))?;
let i = auth.clone().map(|i| vec![i]);
let m = CredentialExchangeMode::Mutual;
let w = self.create_secure_channel_impl(r, i, m, timeout).await?;
let w = self
.create_secure_channel_impl(r, i, m, timeout, None, ctx)
.await?;
return Ok((try_address_to_multiaddr(&w)?, b));
}

Expand All @@ -368,7 +373,9 @@ impl NodeManager {
multiaddr_to_route(addr).ok_or_else(|| ApiError::generic("invalid multiaddr"))?;
let i = auth.clone().map(|i| vec![i]);
let m = CredentialExchangeMode::Mutual;
let w = self.create_secure_channel_impl(r, i, m, timeout).await?;
let w = self
.create_secure_channel_impl(r, i, m, timeout, None, ctx)
.await?;
return Ok((try_address_to_multiaddr(&w)?, MultiAddr::default()));
}

Expand Down Expand Up @@ -487,7 +494,7 @@ impl NodeManagerWorker {
.to_vec()?
}
(Post, ["node", "secure_channel"]) => {
self.create_secure_channel(req, dec).await?.to_vec()?
self.create_secure_channel(req, dec, ctx).await?.to_vec()?
}
(Delete, ["node", "secure_channel"]) => {
self.delete_secure_channel(req, dec).await?.to_vec()?
Expand Down Expand Up @@ -553,7 +560,7 @@ impl NodeManagerWorker {
let node_manager = self.node_manager.read().await;
self.get_outlets(req, &node_manager.registry).to_vec()?
}
(Post, ["node", "inlet"]) => self.create_inlet(req, dec).await?.to_vec()?,
(Post, ["node", "inlet"]) => self.create_inlet(req, dec, ctx).await?.to_vec()?,
(Post, ["node", "outlet"]) => self.create_outlet(req, dec).await?.to_vec()?,
(Delete, ["node", "portal"]) => todo!(),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl NodeManagerWorker {
debug!(addr = %req.address(), alias = ?req.alias(), "Handling CreateForwarder request");

let (sec_chan, suffix) = node_manager
.connect(req.address(), req.authorized(), None)
.connect(req.address(), req.authorized(), None, ctx)
.await?;

let full = sec_chan.clone().try_with(&suffix)?;
Expand Down Expand Up @@ -117,7 +117,7 @@ fn replacer(
let mut this = manager.write().await;
let _ = this.delete_secure_channel(&prev).await;
let timeout = Some(util::MAX_CONNECT_TIME);
let (sec, rest) = this.connect(&addr, auth, timeout).await?;
let (sec, rest) = this.connect(&addr, auth, timeout, ctx.as_ref()).await?;
let a = sec.clone().try_with(&rest)?;
let r = multiaddr_to_route(&a)
.ok_or_else(|| ApiError::message(format!("invalid multiaddr: {a}")))?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ use crate::{multiaddr_to_route, try_multiaddr_to_addr};
use minicbor::Decoder;
use ockam::compat::asynchronous::RwLock;
use ockam::compat::tokio::time::timeout;
use ockam::{Address, Result};
use ockam::{Address, AsyncTryClone, Result};
use ockam_abac::expr::{and, eq, ident, str};
use ockam_abac::{Action, Env, PolicyAccessControl, PolicyStorage, Resource};
use ockam_core::api::{Request, Response, ResponseBuilder};
use ockam_core::{AllowAll, IncomingAccessControl};
use ockam_identity::IdentityIdentifier;
use ockam_multiaddr::proto::{Project, Secure, Service};
use ockam_multiaddr::{MultiAddr, Protocol};
use ockam_node::Context;
use std::sync::Arc;

use super::{NodeManager, NodeManagerWorker};
Expand Down Expand Up @@ -106,6 +107,7 @@ impl NodeManagerWorker {
&mut self,
req: &Request<'_>,
dec: &mut Decoder<'_>,
ctx: &Context,
) -> Result<ResponseBuilder<InletStatus<'a>>> {
let manager = self.node_manager.clone();
let mut node_manager = self.node_manager.write().await;
Expand Down Expand Up @@ -134,11 +136,11 @@ impl NodeManagerWorker {
// to another node.
let (outer, rest) = {
let (sec1, rest) = node_manager
.connect(req.outlet_addr(), req.authorized(), None)
.connect(req.outlet_addr(), req.authorized(), None, ctx)
.await?;
if !sec1.is_empty() && rest.matches(0, &[Service::CODE.into(), Secure::CODE.into()]) {
let addr = sec1.clone().try_with(rest.iter().take(2))?;
let (sec2, _) = node_manager.connect(&addr, None, None).await?;
let (sec2, _) = node_manager.connect(&addr, None, None, ctx).await?;
(sec1, sec2.try_with(rest.iter().skip(2))?)
} else {
(MultiAddr::default(), sec1.try_with(&rest)?)
Expand Down Expand Up @@ -206,13 +208,15 @@ impl NodeManagerWorker {
let mut s = Session::new(without_outlet_address(rest));
s.data().put(INLET_WORKER, worker_addr.clone());
s.data().put(OUTER_CHAN, outer);
let ctx = Arc::new(ctx.async_try_clone().await?);
let repl = replacer(
manager,
s.data(),
listen_addr.clone(),
req.outlet_addr().clone(),
req.authorized(),
access_control.clone(),
ctx,
);
s.set_replacer(repl);
node_manager.sessions.lock().unwrap().add(s);
Expand Down Expand Up @@ -332,6 +336,7 @@ fn replacer(
addr: MultiAddr,
auth: Option<IdentityIdentifier>,
access: Arc<dyn IncomingAccessControl>,
ctx: Arc<Context>,
) -> Replacer {
Box::new(move |prev| {
let addr = addr.clone();
Expand All @@ -340,6 +345,7 @@ fn replacer(
let manager = manager.clone();
let access = access.clone();
let data = data.clone();
let ctx = ctx.clone();
Box::pin(async move {
debug!(%prev, %addr, "creating new tcp inlet");
// The future that recreates the inlet:
Expand All @@ -360,7 +366,7 @@ fn replacer(
// Now a connection attempt is made:

let rest = {
let (sec1, rest) = this.connect(&addr, auth, timeout).await?;
let (sec1, rest) = this.connect(&addr, auth, timeout, ctx.as_ref()).await?;
if !sec1.is_empty()
&& rest.matches(0, &[Service::CODE.into(), Secure::CODE.into()])
{
Expand All @@ -370,7 +376,7 @@ fn replacer(
data.put(OUTER_CHAN, sec1.clone());

let addr = sec1.clone().try_with(rest.iter().take(2))?;
let (sec2, _) = this.connect(&addr, None, timeout).await?;
let (sec2, _) = this.connect(&addr, None, timeout, ctx.as_ref()).await?;
sec2.try_with(rest.iter().skip(2))?
} else {
sec1.try_with(&rest)?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::time::Duration;

use super::{map_multiaddr_err, NodeManagerWorker};
use crate::cli_state::CliState;
use crate::error::ApiError;
use crate::nodes::models::secure_channel::{
CreateSecureChannelListenerRequest, CreateSecureChannelRequest, CreateSecureChannelResponse,
Expand All @@ -14,9 +15,10 @@ use minicbor::Decoder;
use ockam::identity::TrustEveryonePolicy;
use ockam::{Address, Result, Route};
use ockam_core::api::{Request, Response, ResponseBuilder};
use ockam_core::{route, AsyncTryClone};
use ockam_core::{route, AsyncTryClone, CowStr};
use ockam_identity::{Identity, IdentityIdentifier, TrustMultiIdentifiersPolicy};
use ockam_multiaddr::MultiAddr;
use ockam_node::Context;
use ockam_vault::Vault;

impl NodeManager {
Expand Down Expand Up @@ -90,8 +92,22 @@ impl NodeManager {
authorized_identifiers: Option<Vec<IdentityIdentifier>>,
credential_exchange_mode: CredentialExchangeMode,
timeout: Option<Duration>,
identity_name: Option<CowStr<'_>>,
ctx: &Context,
) -> Result<Address> {
let identity = self.identity()?.async_try_clone().await?;
let identity = if let Some(identity) = identity_name {
let state = CliState::new()?;
let idt_config = state.identities.get(&identity)?.config;
match idt_config.get(ctx, self.vault()?).await {
Ok(idt) => idt,
Err(_) => {
let default_vault = &state.vaults.default()?.config.get().await?;
idt_config.get(ctx, default_vault).await?
}
}
} else {
self.identity()?.async_try_clone().await?
};

let sc_addr = self
.create_secure_channel_internal(&identity, sc_route, authorized_identifiers, timeout)
Expand Down Expand Up @@ -217,13 +233,15 @@ impl NodeManagerWorker {
&mut self,
req: &Request<'_>,
dec: &mut Decoder<'_>,
ctx: &Context,
) -> Result<ResponseBuilder<CreateSecureChannelResponse<'a>>> {
let mut node_manager = self.node_manager.write().await;
let CreateSecureChannelRequest {
addr,
authorized_identifiers,
credential_exchange_mode,
timeout,
identity,
..
} = dec.decode()?;

Expand Down Expand Up @@ -252,6 +270,8 @@ impl NodeManagerWorker {
authorized_identifiers,
credential_exchange_mode,
timeout,
identity,
ctx,
)
.await?;

Expand Down
21 changes: 14 additions & 7 deletions implementations/rust/ockam/ockam_command/src/project/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ use std::io::Write;
use std::str::FromStr;

use anyhow::{anyhow, Context as _, Result};
use ockam_core::api::Request;
use tracing::debug;

use ockam::identity::IdentityIdentifier;
use ockam::TcpTransport;
use ockam_api::cloud::project::Project;
use ockam_api::config::lookup::{LookupMeta, ProjectAuthority, ProjectLookup};
use ockam_api::multiaddr_to_addr;
use ockam_api::nodes::models::secure_channel::*;
use ockam_api::nodes::models::{self, secure_channel::*};
use ockam_multiaddr::{MultiAddr, Protocol};

use crate::util::api::CloudOpts;
Expand Down Expand Up @@ -108,12 +109,16 @@ async fn create_secure_channel_to_project(
) -> crate::Result<MultiAddr> {
let authorized_identifier = vec![IdentityIdentifier::from_str(project_identity)?];
let mut rpc = RpcBuilder::new(ctx, opts, api_node).tcp(tcp)?.build();
rpc.request(api::create_secure_channel(

let payload = models::secure_channel::CreateSecureChannelRequest::new(
project_access_route,
Some(authorized_identifier),
credential_exchange_mode,
))
.await?;
None,
);
let req = Request::post("/node/secure_channel").body(payload);
rpc.request(req).await?;

let sc = rpc.parse_response::<CreateSecureChannelResponse>()?;
Ok(sc.addr()?)
}
Expand All @@ -128,12 +133,14 @@ pub async fn create_secure_channel_to_authority(
let mut rpc = RpcBuilder::new(ctx, opts, node_name).build();
debug!(%addr, "establishing secure channel to project authority");
let allowed = vec![authority.identity_id().clone()];
rpc.request(api::create_secure_channel(
let payload = models::secure_channel::CreateSecureChannelRequest::new(
addr,
Some(allowed),
CredentialExchangeMode::None,
))
.await?;
None,
);
let req = Request::post("/node/secure_channel").body(payload);
rpc.request(req).await?;
let res = rpc.parse_response::<CreateSecureChannelResponse>()?;
let addr = res.addr()?;
Ok(addr)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
use crate::{
help,
util::{api, exitcode, extract_address_value, node_rpc},
util::{exitcode, extract_address_value, node_rpc},
CommandGlobalOpts, OutputFormat, Result,
};

use anyhow::Context as _;
use clap::Args;
use colorful::Colorful;
use ockam_core::api::Request;
use serde_json::json;

use crate::secure_channel::HELP_DETAIL;
use crate::util::api::CloudOpts;
use crate::util::{is_tty, RpcBuilder};
use ockam::{identity::IdentityIdentifier, route, Context, TcpTransport};
use ockam_api::config::lookup::ConfigLookup;
use ockam_api::nodes::models::secure_channel::CredentialExchangeMode;
use ockam_api::{
clean_multiaddr, nodes::models::secure_channel::CreateSecureChannelResponse, route_to_multiaddr,
};
use ockam_api::{config::lookup::ConfigLookup, nodes::models};
use ockam_multiaddr::MultiAddr;

/// Create Secure Channels
Expand All @@ -39,6 +40,9 @@ pub struct CreateCommand {
/// Orchestrator address to resolve projects present in the `at` argument
#[command(flatten)]
cloud_opts: CloudOpts,

#[arg(value_name = "IDENTITY", long, display_order = 802)]
identity: Option<String>,
}

impl CreateCommand {
Expand Down Expand Up @@ -162,8 +166,14 @@ async fn rpc(ctx: Context, (opts, cmd): (CommandGlobalOpts, CreateCommand)) -> R

// Delegate the request to create a secure channel to the from node.
let mut rpc = RpcBuilder::new(&ctx, &opts, from).tcp(&tcp)?.build();
let request =
api::create_secure_channel(to, authorized_identifiers, CredentialExchangeMode::Mutual);

let payload = models::secure_channel::CreateSecureChannelRequest::new(
to,
authorized_identifiers,
CredentialExchangeMode::Mutual,
cmd.identity.clone(),
);
let request = Request::post("/node/secure_channel").body(payload);

rpc.request(request).await?;
let response = rpc.parse_response::<CreateSecureChannelResponse>()?;
Expand Down
15 changes: 0 additions & 15 deletions implementations/rust/ockam/ockam_command/src/util/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use tracing::trace;
use ockam::identity::IdentityIdentifier;
use ockam::Result;
use ockam_api::cloud::{BareCloudRequestWrapper, CloudRequestWrapper};
use ockam_api::nodes::models::secure_channel::CredentialExchangeMode;
use ockam_api::nodes::*;
use ockam_core::api::RequestBuilder;
use ockam_core::api::{Request, Response};
Expand Down Expand Up @@ -76,20 +75,6 @@ pub(crate) fn list_secure_channels() -> RequestBuilder<'static, ()> {
Request::get("/node/secure_channel")
}

/// Construct a request to create Secure Channels
pub(crate) fn create_secure_channel(
addr: &MultiAddr,
authorized_identifiers: Option<Vec<IdentityIdentifier>>,
credential_exchange_mode: CredentialExchangeMode,
) -> RequestBuilder<'static, models::secure_channel::CreateSecureChannelRequest<'static>> {
let payload = models::secure_channel::CreateSecureChannelRequest::new(
addr,
authorized_identifiers,
credential_exchange_mode,
);
Request::post("/node/secure_channel").body(payload)
}

pub(crate) fn delete_secure_channel(
addr: &Address,
) -> RequestBuilder<'static, models::secure_channel::DeleteSecureChannelRequest<'static>> {
Expand Down