From 5268756b60a60a9fe840fe9bf992e6aab4ff1e6b Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Thu, 18 Jul 2024 14:28:02 +1000 Subject: [PATCH] feat(connlib): add placeholder for Internet Resource (#5900) In preparation for #2667, we add an `internet` variant to our list of possible resource types. This is backwards-compatible with existing clients and ensures that, once the portal starts sending Internet resources to clients, they won't fail to deserialise these messages. The portal will have a version check to not send this to older clients anyway but the sooner we can land this, the better. It simplifies the initial development as we start preparing for the next client release. Adding new fields to a JSON message is always backwards-compatible so we can extend this later with whatever we need. --- rust/connlib/shared/src/callbacks.rs | 15 ++++++ rust/connlib/shared/src/messages/client.rs | 56 +++++++++++++++++++- rust/connlib/shared/src/messages/gateway.rs | 43 +++++++++++++++ rust/connlib/tunnel/src/client.rs | 2 + rust/connlib/tunnel/src/tests/stub_portal.rs | 1 + 5 files changed, 116 insertions(+), 1 deletion(-) diff --git a/rust/connlib/shared/src/callbacks.rs b/rust/connlib/shared/src/callbacks.rs index 8860fd09e..8ef07a5e5 100644 --- a/rust/connlib/shared/src/callbacks.rs +++ b/rust/connlib/shared/src/callbacks.rs @@ -19,6 +19,7 @@ pub enum Status { pub enum ResourceDescription { Dns(ResourceDescriptionDns), Cidr(ResourceDescriptionCidr), + Internet(ResourceDescriptionCidr), } impl ResourceDescription { @@ -26,6 +27,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => r.address_description.as_deref(), ResourceDescription::Cidr(r) => r.address_description.as_deref(), + ResourceDescription::Internet(_) => None, } } @@ -33,6 +35,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => &r.name, ResourceDescription::Cidr(r) => &r.name, + ResourceDescription::Internet(_) => "Internet", } } @@ -40,6 +43,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => r.status, ResourceDescription::Cidr(r) => r.status, + ResourceDescription::Internet(r) => r.status, } } @@ -47,6 +51,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => r.id, ResourceDescription::Cidr(r) => r.id, + ResourceDescription::Internet(r) => r.id, } } @@ -55,6 +60,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => Cow::from(&r.address), ResourceDescription::Cidr(r) => Cow::from(r.address.to_string()), + ResourceDescription::Internet(_) => Cow::default(), } } @@ -62,6 +68,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => &r.sites, ResourceDescription::Cidr(r) => &r.sites, + ResourceDescription::Internet(r) => &r.sites, } } } @@ -101,6 +108,14 @@ pub struct ResourceDescriptionCidr { pub status: Status, } +/// Description of an Internet resource +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct ResourceDescriptionInternet { + pub id: ResourceId, + pub sites: Vec, + pub status: Status, +} + /// Traits that will be used by connlib to callback the client upper layers. pub trait Callbacks: Clone + Send + Sync { /// Called when the tunnel address is set. diff --git a/rust/connlib/shared/src/messages/client.rs b/rust/connlib/shared/src/messages/client.rs index 372a6a265..f2ecf8ea3 100644 --- a/rust/connlib/shared/src/messages/client.rs +++ b/rust/connlib/shared/src/messages/client.rs @@ -70,6 +70,16 @@ impl ResourceDescriptionCidr { } } +/// Description of an internet resource. +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct ResourceDescriptionInternet { + /// Resource's id. + pub id: ResourceId, + // TBD + #[serde(rename = "gateway_groups")] + pub sites: Vec, +} + #[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialOrd, Ord)] pub struct Site { pub id: SiteId, @@ -110,7 +120,7 @@ impl ResourceDescription { pub fn dns_name(&self) -> Option<&str> { match self { ResourceDescription::Dns(r) => Some(&r.address), - ResourceDescription::Cidr(_) => None, + ResourceDescription::Cidr(_) | ResourceDescription::Internet(_) => None, } } @@ -118,6 +128,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => r.id, ResourceDescription::Cidr(r) => r.id, + ResourceDescription::Internet(r) => r.id, } } @@ -125,6 +136,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => HashSet::from_iter(r.sites.iter()), ResourceDescription::Cidr(r) => HashSet::from_iter(r.sites.iter()), + ResourceDescription::Internet(_) => HashSet::default(), } } @@ -132,6 +144,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => &mut r.sites, ResourceDescription::Cidr(r) => &mut r.sites, + ResourceDescription::Internet(r) => &mut r.sites, } } @@ -140,6 +153,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => &r.name, ResourceDescription::Cidr(r) => &r.name, + ResourceDescription::Internet(_) => "Internet", } } @@ -163,6 +177,7 @@ impl ResourceDescription { ResourceDescription::Cidr(r) => { crate::callbacks::ResourceDescription::Cidr(r.with_status(status)) } + ResourceDescription::Internet(_) => todo!(), } } } @@ -184,4 +199,43 @@ impl Ord for ResourceDescription { pub enum ResourceDescription { Dns(ResourceDescriptionDns), Cidr(ResourceDescriptionCidr), + Internet(ResourceDescriptionInternet), +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn can_deserialize_internet_resource() { + let resources = r#"[ + { + "id": "73037362-715d-4a83-a749-f18eadd970e6", + "type": "cidr", + "name": "172.172.0.0/16", + "address": "172.172.0.0/16", + "address_description": "cidr resource", + "gateway_groups": [{"name": "test", "id": "bf56f32d-7b2c-4f5d-a784-788977d014a4"}] + }, + { + "id": "03000143-e25e-45c7-aafb-144990e57dcd", + "type": "dns", + "name": "gitlab.mycorp.com", + "address": "gitlab.mycorp.com", + "address_description": "dns resource", + "gateway_groups": [{"name": "test", "id": "bf56f32d-7b2c-4f5d-a784-788977d014a4"}] + }, + { + "id": "1106047c-cd5d-4151-b679-96b93da7383b", + "type": "internet", + "gateway_groups": [{"name": "test", "id": "eb94482a-94f4-47cb-8127-14fb3afa5516"}], + "not": "relevant", + "some_other": [ + "field" + ] + } + ]"#; + + serde_json::from_str::>(resources).unwrap(); + } } diff --git a/rust/connlib/shared/src/messages/gateway.rs b/rust/connlib/shared/src/messages/gateway.rs index 0566339c1..77e5959a9 100644 --- a/rust/connlib/shared/src/messages/gateway.rs +++ b/rust/connlib/shared/src/messages/gateway.rs @@ -56,11 +56,18 @@ pub struct ResolvedResourceDescriptionDns { pub filters: Filters, } +/// Description of an Internet resource. +#[derive(Debug, Deserialize, Clone, PartialEq, Eq)] +pub struct ResourceDescriptionInternet { + pub id: ResourceId, +} + #[derive(Debug, Deserialize, Clone, PartialEq, Eq)] #[serde(tag = "type", rename_all = "snake_case")] pub enum ResourceDescription { Dns(TDNS), Cidr(ResourceDescriptionCidr), + Internet(ResourceDescriptionInternet), } #[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq, Hash)] @@ -111,6 +118,7 @@ impl ResourceDescription { filters, }), ResourceDescription::Cidr(c) => ResourceDescription::Cidr(c), + ResourceDescription::Internet(r) => ResourceDescription::Internet(r), } } } @@ -120,6 +128,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => r.id, ResourceDescription::Cidr(r) => r.id, + ResourceDescription::Internet(r) => r.id, } } @@ -127,6 +136,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => r.filters.clone(), ResourceDescription::Cidr(r) => r.filters.clone(), + ResourceDescription::Internet(_) => Vec::default(), } } } @@ -136,6 +146,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => r.addresses.iter().copied().map_into().collect_vec(), ResourceDescription::Cidr(r) => vec![r.address], + ResourceDescription::Internet(_) => vec![], } } @@ -143,6 +154,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => r.id, ResourceDescription::Cidr(r) => r.id, + ResourceDescription::Internet(r) => r.id, } } @@ -150,6 +162,7 @@ impl ResourceDescription { match self { ResourceDescription::Dns(r) => r.filters.clone(), ResourceDescription::Cidr(r) => r.filters.clone(), + ResourceDescription::Internet(_) => vec![], } } } @@ -219,4 +232,34 @@ mod tests { assert_eq!(expected_filter, actual_filter); } + + #[test] + fn can_deserialize_internet_resource() { + let resources = r#"[ + { + "id": "73037362-715d-4a83-a749-f18eadd970e6", + "type": "cidr", + "address": "172.172.0.0/16", + "name": "172.172.0.0/16", + "filters": [] + }, + { + "id": "03000143-e25e-45c7-aafb-144990e57dcd", + "type": "dns", + "name": "gitlab.mycorp.com", + "address": "gitlab.mycorp.com", + "filters": [] + }, + { + "id": "1106047c-cd5d-4151-b679-96b93da7383b", + "type": "internet", + "not": "relevant", + "some_other": [ + "field" + ] + } + ]"#; + + serde_json::from_str::>(resources).unwrap(); + } } diff --git a/rust/connlib/tunnel/src/client.rs b/rust/connlib/tunnel/src/client.rs index d9b496eca..c4e4183c7 100644 --- a/rust/connlib/tunnel/src/client.rs +++ b/rust/connlib/tunnel/src/client.rs @@ -937,6 +937,7 @@ impl ClientState { } } } + ResourceDescription::Internet(_) => {} } self.resource_ids @@ -1074,6 +1075,7 @@ fn get_addresses_for_awaiting_resource( .map_into() .collect_vec(), ResourceDescription::Cidr(r) => vec![r.address], + ResourceDescription::Internet(_) => vec![], } } diff --git a/rust/connlib/tunnel/src/tests/stub_portal.rs b/rust/connlib/tunnel/src/tests/stub_portal.rs index 0a1c64b75..2b5fe7093 100644 --- a/rust/connlib/tunnel/src/tests/stub_portal.rs +++ b/rust/connlib/tunnel/src/tests/stub_portal.rs @@ -55,6 +55,7 @@ impl StubPortal { client::ResourceDescription::Cidr(cidr) => { self.cidr_resources.insert(cidr.id, cidr); } + client::ResourceDescription::Internet(_) => {} } }