diff --git a/rust/connlib/tunnel/src/gateway.rs b/rust/connlib/tunnel/src/gateway.rs index 928e27e1c..b729e09e0 100644 --- a/rust/connlib/tunnel/src/gateway.rs +++ b/rust/connlib/tunnel/src/gateway.rs @@ -300,6 +300,20 @@ impl GatewayState { Ok(()) } + pub fn update_access_authorization_expiry( + &mut self, + client: ClientId, + resource: ResourceId, + expires_at: DateTime, + ) -> anyhow::Result<()> { + self.peers + .get_mut(&client) + .context("No peer state")? + .update_resource_expiry(resource, expires_at); + + Ok(()) + } + pub fn handle_domain_resolved( &mut self, req: ResolveDnsRequest, diff --git a/rust/connlib/tunnel/src/messages/gateway.rs b/rust/connlib/tunnel/src/messages/gateway.rs index ea0ffc363..a1b2549aa 100644 --- a/rust/connlib/tunnel/src/messages/gateway.rs +++ b/rust/connlib/tunnel/src/messages/gateway.rs @@ -4,7 +4,10 @@ use crate::messages::{ GatewayResponse, IceCredentials, Interface, Key, Peer, Relay, RelaysPresence, ResolveRequest, SecretKey, }; -use chrono::{DateTime, Utc, serde::ts_seconds_option}; +use chrono::{ + DateTime, Utc, + serde::{ts_seconds, ts_seconds_option}, +}; use connlib_model::{ClientId, ResourceId}; use ip_network::IpNetwork; use serde::{Deserialize, Serialize}; @@ -195,6 +198,7 @@ pub enum IngressMessages { RelaysPresence(RelaysPresence), ResourceUpdated(ResourceDescription), AuthorizeFlow(AuthorizeFlow), + AccessAuthorizationExpiryUpdated(AccessAuthorizationExpiryUpdated), } #[derive(Debug, Deserialize, Clone)] @@ -220,6 +224,14 @@ pub struct AuthorizeFlow { pub expires_at: Option>, } +#[derive(Debug, Deserialize, Clone)] +pub struct AccessAuthorizationExpiryUpdated { + pub client_id: ClientId, + pub resource_id: ResourceId, + #[serde(with = "ts_seconds")] + pub expires_at: DateTime, +} + /// A client's ice candidate message. #[derive(Debug, Serialize, Clone)] pub struct ClientsIceCandidates { diff --git a/rust/connlib/tunnel/src/peer.rs b/rust/connlib/tunnel/src/peer.rs index 6c3cbed8f..4aaf133b8 100644 --- a/rust/connlib/tunnel/src/peer.rs +++ b/rust/connlib/tunnel/src/peer.rs @@ -233,6 +233,28 @@ impl ClientOnGateway { self.recalculate_filters(); } + pub(crate) fn update_resource_expiry( + &mut self, + resource: ResourceId, + new_expiry: DateTime, + ) { + let Some(resource) = self.resources.get_mut(&resource) else { + tracing::debug!(%resource, "Unknown resource"); + + return; + }; + + let new_expiry_rfc3339 = new_expiry.to_rfc3339(); + + let old_expiry = match resource { + ResourceOnGateway::Cidr { expires_at, .. } => expires_at.replace(new_expiry), + ResourceOnGateway::Dns { expires_at, .. } => expires_at.replace(new_expiry), + ResourceOnGateway::Internet { expires_at } => expires_at.replace(new_expiry), + }; + + tracing::info!(old = ?old_expiry.map(|e| e.to_rfc3339()), new = %new_expiry_rfc3339, "Updated resource expiry"); + } + pub(crate) fn retain_authorizations(&mut self, authorization: BTreeSet) { for (resource, _) in self .resources diff --git a/rust/gateway/src/eventloop.rs b/rust/gateway/src/eventloop.rs index 5ae70e88e..353b7257d 100644 --- a/rust/gateway/src/eventloop.rs +++ b/rust/gateway/src/eventloop.rs @@ -7,8 +7,8 @@ use firezone_bin_shared::TunDeviceManager; use firezone_telemetry::{Telemetry, analytics}; use firezone_tunnel::messages::gateway::{ - AllowAccess, ClientIceCandidates, ClientsIceCandidates, ConnectionReady, EgressMessages, - IngressMessages, InitGateway, RejectAccess, RequestConnection, + AccessAuthorizationExpiryUpdated, AllowAccess, ClientIceCandidates, ClientsIceCandidates, + ConnectionReady, EgressMessages, IngressMessages, InitGateway, RejectAccess, RequestConnection, }; use firezone_tunnel::messages::{ConnectionAccepted, GatewayResponse, Interface, RelaysPresence}; use firezone_tunnel::{ @@ -448,6 +448,25 @@ impl Eventloop { .state_mut() .update_resource(resource_description); } + phoenix_channel::Event::InboundMessage { + msg: + IngressMessages::AccessAuthorizationExpiryUpdated( + AccessAuthorizationExpiryUpdated { + client_id, + resource_id, + expires_at, + }, + ), + .. + } => { + if let Err(e) = self.tunnel.state_mut().update_access_authorization_expiry( + client_id, + resource_id, + expires_at, + ) { + tracing::warn!(%client_id, %resource_id, "Failed to update expiry of access authorization: {e:#}") + }; + } phoenix_channel::Event::ErrorResponse { topic, req_id, res } => { tracing::warn!(%topic, %req_id, "Request failed: {res:?}"); }