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

fix(dgw)!: jet_rec claim is now a string #957

Merged
merged 3 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions crates/devolutions-gateway-generators/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use devolutions_gateway::session::{ConnectionModeDetails, SessionInfo};
use devolutions_gateway::target_addr::TargetAddr;
use devolutions_gateway::token::{
self, AccessScope, ApplicationProtocol, Protocol, MAX_SUBKEY_TOKEN_VALIDITY_DURATION_SECS,
self, AccessScope, ApplicationProtocol, Protocol, RecordingPolicy, MAX_SUBKEY_TOKEN_VALIDITY_DURATION_SECS,
};
use proptest::collection::vec;
use proptest::option;
Expand Down Expand Up @@ -50,6 +50,15 @@ pub fn application_protocol() -> impl Strategy<Value = ApplicationProtocol> {
.no_shrink()
}

pub fn recording_policy() -> impl Strategy<Value = RecordingPolicy> {
prop_oneof![
Just(RecordingPolicy::None),
Just(RecordingPolicy::External),
Just(RecordingPolicy::Proxy),
]
.no_shrink()
}

pub fn target_addr() -> impl Strategy<Value = TargetAddr> {
"[a-z]{1,10}\\.[a-z]{1,5}:[0-9]{3,4}".prop_map(|addr| TargetAddr::parse(&addr, None).unwrap())
}
Expand Down Expand Up @@ -157,7 +166,7 @@ pub struct AssociationClaims {
pub jet_ap: ApplicationProtocol,
#[serde(flatten)]
pub jet_cm: ConnectionMode,
pub jet_rec: bool,
pub jet_rec: RecordingPolicy,
pub jet_flt: bool,
pub nbf: i64,
pub exp: i64,
Expand All @@ -174,7 +183,7 @@ pub fn any_association_claims(now: i64, validity_duration: i64) -> impl Strategy
(
uuid_typed(),
jet_ap_and_jet_cm(),
any::<bool>(),
recording_policy(),
any::<bool>(),
uuid_typed(),
)
Expand Down Expand Up @@ -239,6 +248,7 @@ pub fn any_bridge_claims(now: i64, validity_duration: i64) -> impl Strategy<Valu
#[derive(Debug, Clone, Serialize)]
pub struct JmuxClaims {
pub jet_aid: Uuid,
pub jet_rec: RecordingPolicy,
pub dst_hst: String,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub dst_addl: Vec<String>,
Expand All @@ -251,13 +261,15 @@ pub struct JmuxClaims {
pub fn any_jmux_claims(now: i64, validity_duration: i64) -> impl Strategy<Value = JmuxClaims> {
(
uuid_typed(),
recording_policy(),
host(),
alternate_hosts(),
application_protocol(),
uuid_typed(),
)
.prop_map(move |(jet_aid, dst_hst, dst_addl, jet_ap, jti)| JmuxClaims {
.prop_map(move |(jet_aid, jet_rec, dst_hst, dst_addl, jet_ap, jti)| JmuxClaims {
jet_aid,
jet_rec,
dst_hst,
dst_addl,
jet_ap,
Expand Down
7 changes: 4 additions & 3 deletions devolutions-gateway/src/api/fwd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::http::HttpError;
use crate::proxy::Proxy;
use crate::session::{ConnectionModeDetails, SessionInfo, SessionMessageSender};
use crate::subscriber::SubscriberSender;
use crate::token::{ApplicationProtocol, AssociationTokenClaims, ConnectionMode, Protocol};
use crate::token::{ApplicationProtocol, AssociationTokenClaims, ConnectionMode, Protocol, RecordingPolicy};
use crate::{utils, DgwState};

pub fn make_router<S>(state: DgwState) -> Router<S> {
Expand Down Expand Up @@ -144,8 +144,9 @@ where
with_tls,
} = self;

if claims.jet_rec {
anyhow::bail!("can't meet recording policy");
match claims.jet_rec {
RecordingPolicy::None | RecordingPolicy::External => (),
RecordingPolicy::Proxy => anyhow::bail!("can't meet recording policy"),
}

let ConnectionMode::Fwd { targets, .. } = claims.jet_cm else {
Expand Down
6 changes: 3 additions & 3 deletions devolutions-gateway/src/api/webapp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::config::{WebAppAuth, WebAppConf, WebAppUser};
use crate::extract::WebAppToken;
use crate::http::HttpError;
use crate::target_addr::TargetAddr;
use crate::token::ApplicationProtocol;
use crate::token::{ApplicationProtocol, RecordingPolicy};
use crate::DgwState;

pub fn make_router<S>(state: DgwState) -> Router<S> {
Expand Down Expand Up @@ -334,7 +334,7 @@ pub(crate) async fn sign_session_token(
targets: nonempty::NonEmpty::new(destination.clone()),
creds: None,
},
jet_rec: false,
jet_rec: RecordingPolicy::None,
jet_flt: false,
jet_ttl: crate::token::SessionTtl::Unlimited,
exp,
Expand All @@ -361,7 +361,7 @@ pub(crate) async fn sign_session_token(
JmuxTokenClaims {
jet_aid: session_id,
jet_ap: protocol,
jet_rec: false,
jet_rec: RecordingPolicy::None,
hosts: nonempty::NonEmpty::new(destination.clone()),
jet_ttl: crate::token::SessionTtl::Unlimited,
exp,
Expand Down
7 changes: 4 additions & 3 deletions devolutions-gateway/src/generic_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::rdp_pcb::{extract_association_claims, read_pcb};
use crate::recording::ActiveRecordings;
use crate::session::{ConnectionModeDetails, SessionInfo, SessionMessageSender};
use crate::subscriber::SubscriberSender;
use crate::token::{ConnectionMode, CurrentJrl, TokenCache};
use crate::token::{ConnectionMode, CurrentJrl, RecordingPolicy, TokenCache};
use crate::utils;

#[derive(TypedBuilder)]
Expand Down Expand Up @@ -73,8 +73,9 @@ where
anyhow::bail!("TCP rendezvous not supported");
}
ConnectionMode::Fwd { targets, creds: None } => {
if claims.jet_rec {
anyhow::bail!("can't meet recording policy");
match claims.jet_rec {
RecordingPolicy::None | RecordingPolicy::External => (),
RecordingPolicy::Proxy => anyhow::bail!("can't meet recording policy"),
}

trace!("Select and connect to target");
Expand Down
7 changes: 6 additions & 1 deletion devolutions-gateway/src/jmux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::sync::Arc;

use crate::session::{ConnectionModeDetails, SessionInfo, SessionMessageSender};
use crate::subscriber::SubscriberSender;
use crate::token::JmuxTokenClaims;
use crate::token::{JmuxTokenClaims, RecordingPolicy};

use anyhow::Context as _;
use devolutions_gateway_task::ChildTask;
Expand All @@ -20,6 +20,11 @@ pub async fn handle(
) -> anyhow::Result<()> {
use jmux_proxy::{FilteringRule, JmuxConfig};

match claims.jet_rec {
RecordingPolicy::None | RecordingPolicy::External => (),
RecordingPolicy::Proxy => anyhow::bail!("can't meet recording policy"),
}

let (reader, writer) = tokio::io::split(stream);
let reader = Box::new(reader) as ErasedRead;
let writer = Box::new(writer) as ErasedWrite;
Expand Down
2 changes: 1 addition & 1 deletion devolutions-gateway/src/recording.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ pub async fn remux(input_path: Utf8PathBuf) {
fn remux_impl(input_path: Utf8PathBuf) -> anyhow::Result<()> {
let input_file_name = input_path
.file_name()
.ok_or(anyhow::anyhow!("input file has no file name"))?;
.ok_or_else(|| anyhow::anyhow!("invalid path (not a file): {input_path}"))?;

let remuxed_file_name = format!("remuxed_{input_file_name}");

Expand Down
1 change: 0 additions & 1 deletion devolutions-gateway/src/service.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use anyhow::Context as _;
use camino::Utf8PathBuf;
use devolutions_gateway::config::{Conf, ConfHandle};
use devolutions_gateway::listener::GatewayListener;
use devolutions_gateway::log::GatewayLog;
Expand Down
6 changes: 3 additions & 3 deletions devolutions-gateway/src/session.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::recording::RecordingMessageSender;
use crate::subscriber;
use crate::target_addr::TargetAddr;
use crate::token::{ApplicationProtocol, SessionTtl};
use crate::token::{ApplicationProtocol, RecordingPolicy, SessionTtl};
use anyhow::Context as _;
use async_trait::async_trait;
use core::fmt;
Expand Down Expand Up @@ -52,8 +52,8 @@ impl SessionInfo {
}

#[must_use]
pub fn with_recording_policy(mut self, value: bool) -> Self {
self.recording_policy = value;
pub fn with_recording_policy(mut self, value: RecordingPolicy) -> Self {
self.recording_policy = value != RecordingPolicy::None;
self
}

Expand Down
23 changes: 18 additions & 5 deletions devolutions-gateway/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl AccessTokenClaims {
}
}

// ----- Known application protocols -----
// ----- Application protocols -----

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(untagged)]
Expand Down Expand Up @@ -308,6 +308,19 @@ impl RecordingOperation {
}
}

// ----- recording policy ----- //

#[derive(Serialize, Deserialize, Default, Clone, Copy, Debug, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum RecordingPolicy {
#[default]
None,
/// An external application (e.g.: RDM) must push the recording stream via a separate websocket connection
External,
/// Session must be recorded directly at Devolutions Gateway level
Proxy,
}

// ----- association claims ----- //

#[derive(Clone)]
Expand Down Expand Up @@ -370,7 +383,7 @@ pub struct AssociationTokenClaims {
pub jet_cm: ConnectionMode,

/// Recording Policy
pub jet_rec: bool,
pub jet_rec: RecordingPolicy,

/// Filtering Policy
pub jet_flt: bool,
Expand Down Expand Up @@ -465,7 +478,7 @@ pub struct JmuxTokenClaims {
pub jet_ap: ApplicationProtocol,

/// Recording Policy
pub jet_rec: bool,
pub jet_rec: RecordingPolicy,

/// Max duration
pub jet_ttl: SessionTtl,
Expand Down Expand Up @@ -1175,7 +1188,7 @@ mod serde_impl {
#[serde(flatten)]
jet_cm: ConnectionModeHelper,
#[serde(default)]
jet_rec: bool,
jet_rec: RecordingPolicy,
#[serde(default)]
jet_flt: bool,
#[serde(default)]
Expand All @@ -1194,7 +1207,7 @@ mod serde_impl {
#[serde(default)]
jet_ap: ApplicationProtocol,
#[serde(default)]
jet_rec: bool,
jet_rec: RecordingPolicy,
jet_aid: Uuid,
#[serde(default)]
jet_ttl: SessionTtl,
Expand Down
35 changes: 29 additions & 6 deletions tools/tokengen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ fn main() -> Result<(), Box<dyn Error>> {
dst_hst: Some(&dst_hst),
jet_cm: "fwd",
jet_ap: jet_ap.unwrap_or(ApplicationProtocol::Unknown),
jet_rec,
jet_rec: if jet_rec {
RecordingPolicy::External
} else {
RecordingPolicy::None
},
jet_aid: jet_aid.unwrap_or_else(Uuid::new_v4),
jet_ttl,
jet_gw_id: app.jet_gw_id,
Expand All @@ -64,7 +68,7 @@ fn main() -> Result<(), Box<dyn Error>> {
dst_hst: Some(&dst_hst),
jet_cm: "fwd",
jet_ap: ApplicationProtocol::Rdp,
jet_rec: false,
jet_rec: RecordingPolicy::None,
jet_aid: jet_aid.unwrap_or_else(Uuid::new_v4),
jet_ttl: None,
jet_gw_id: app.jet_gw_id,
Expand All @@ -89,7 +93,11 @@ fn main() -> Result<(), Box<dyn Error>> {
dst_hst: None,
jet_cm: "rdv",
jet_ap: jet_ap.unwrap_or(ApplicationProtocol::Unknown),
jet_rec,
jet_rec: if jet_rec {
RecordingPolicy::External
} else {
RecordingPolicy::None
},
jet_aid: jet_aid.unwrap_or_else(Uuid::new_v4),
jet_ttl: None,
jet_gw_id: app.jet_gw_id,
Expand Down Expand Up @@ -119,7 +127,11 @@ fn main() -> Result<(), Box<dyn Error>> {
dst_hst: &dst_hst,
dst_addl: dst_addl.iter().map(|o| o.as_str()).collect(),
jet_ap: jet_ap.unwrap_or(ApplicationProtocol::Unknown),
jet_rec,
jet_rec: if jet_rec {
RecordingPolicy::External
} else {
RecordingPolicy::None
},
jet_aid: jet_aid.unwrap_or_else(Uuid::new_v4),
jet_ttl,
jet_gw_id: app.jet_gw_id,
Expand Down Expand Up @@ -303,7 +315,7 @@ struct AssociationClaims<'a> {
jti: Uuid,
jet_cm: &'a str,
jet_ap: ApplicationProtocol,
jet_rec: bool,
jet_rec: RecordingPolicy,
jet_aid: Uuid,
#[serde(skip_serializing_if = "Option::is_none")]
jet_ttl: Option<u64>,
Expand Down Expand Up @@ -337,7 +349,7 @@ struct JmuxClaims<'a> {
dst_hst: &'a str,
dst_addl: Vec<&'a str>,
jet_ap: ApplicationProtocol,
jet_rec: bool,
jet_rec: RecordingPolicy,
jet_aid: Uuid,
#[serde(skip_serializing_if = "Option::is_none")]
jet_ttl: Option<u64>,
Expand Down Expand Up @@ -436,6 +448,17 @@ pub enum RecordingOperation {
Pull,
}

#[derive(Serialize, Deserialize, Default, Clone, Copy, Debug, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum RecordingPolicy {
#[default]
None,
/// An external application (e.g.: RDM) must push the recording stream via a separate websocket connection
External,
/// Session must be recorded directly at Devolutions Gateway level
Proxy,
}

macro_rules! impl_from_str {
($ty:ty) => {
impl std::str::FromStr for $ty {
Expand Down