Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 1 addition & 52 deletions src/app_guard_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,58 +208,6 @@ impl AppGuardImpl {
Ok(res)
}

// pub(crate) async fn heartbeat_impl(
// &self,
// request: Request<AuthenticationData>,
// ) -> Result<Response<<AppGuardImpl as AppGuard>::HeartbeatStream>, Error> {
// let datastore = self.ctx.datastore.clone();
// let remote_address = request
// .remote_addr()
// .map_or_else(|| "Unknown".to_string(), |addr| addr.ip().to_string());
// log::info!("Received heartbeat request from {remote_address}");
//
// let authenticate_request = request.into_inner();
// let token_provider = TokenProvider::new(
// authenticate_request.app_id.unwrap_or_default().clone(),
// authenticate_request.app_secret.unwrap_or_default().clone(),
// false,
// datastore.clone(),
// );
// let token = token_provider.get().await?.jwt.clone();
// let (_, token_info) = authenticate(token.clone())?;
// let Some(device) = token_info.account.device else {
// return Err("Device not found in token").handle_err(location!());
// };
// let device_id = device.id;
//
// let status = datastore.device_status(device_id.clone(), &token).await?;
// if status == DeviceStatus::Draft {
// datastore
// .device_setup(&token, device_id.clone(), remote_address)
// .await?;
// }
//
// let (tx, rx) = mpsc::channel(6);
//
// tokio::spawn(async move {
// loop {
// if let Ok(t) = token_provider.get().await {
// let token = t.jwt.clone();
// if let Ok(response) = datastore.heartbeat(&token, device_id.clone()).await {
// let response = HeartbeatResponse {
// token,
// status: response.status.into(),
// };
// tx.send(Ok(response)).await.unwrap();
// }
// }
// tokio::time::sleep(Duration::from_secs(10)).await;
// }
// });
//
// Ok(Response::new(ReceiverStream::new(rx)))
// }

pub(crate) fn control_channel_impl(
&self,
request: Request<Streaming<ClientMessage>>,
Expand All @@ -277,6 +225,7 @@ impl AppGuardImpl {
let logs = request.into_inner();
let (jwt_token, _) = authenticate(logs.token)?;

// TODO: call tx_store to store logs
let _ = self
.ctx
.datastore
Expand Down
183 changes: 85 additions & 98 deletions src/db/datastore_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ impl DatastoreWrapper {
}

// SELECT MIN(timestamp) FROM {table}
// TODO: An error occurred while processing your request
pub(crate) async fn get_oldest_timestamp(
&mut self,
table: DbTable,
Expand Down Expand Up @@ -236,7 +235,6 @@ impl DatastoreWrapper {
}

// DELETE FROM {table} WHERE timestamp <= {timestamp}
/// todo: error 'missing FROM-clause entry for table "ip_blacklists"'
pub(crate) async fn delete_old_entries(
&mut self,
table: DbTable,
Expand Down Expand Up @@ -267,13 +265,20 @@ impl DatastoreWrapper {
Ok(count)
}

// SELECT app_id, firewall FROM {table}
pub(crate) async fn get_firewalls(
&mut self,
token: String,
) -> Result<HashMap<String, Firewall>, Error> {
let table = DbTable::Firewall.to_str();

let filter = AdvanceFilter {
r#type: String::from("criteria"),
field: String::from("active"),
operator: String::from("equal"),
entity: table.to_string(),
values: "[true]".to_string(),
};

let request = GetByFilterRequest {
params: Some(Params {
id: String::new(),
Expand All @@ -282,7 +287,7 @@ impl DatastoreWrapper {
}),
body: Some(GetByFilterBody {
pluck: vec!["app_id".to_string(), "firewall".to_string()],
advance_filters: vec![],
advance_filters: vec![filter],
order_by: String::new(),
limit: i32::MAX,
offset: 0,
Expand Down Expand Up @@ -339,6 +344,14 @@ impl DatastoreWrapper {
pub(crate) async fn get_configs(&mut self, token: String) -> Result<Config, Error> {
let table = DbTable::Config.to_str();

let filter = AdvanceFilter {
r#type: String::from("criteria"),
field: String::from("active"),
operator: String::from("equal"),
entity: table.to_string(),
values: "[true]".to_string(),
};

let request = GetByFilterRequest {
params: Some(Params {
id: String::new(),
Expand All @@ -352,7 +365,7 @@ impl DatastoreWrapper {
"retention_sec".to_string(),
"ip_info_cache_size".to_string(),
],
advance_filters: vec![],
advance_filters: vec![filter],
order_by: String::new(),
limit: 1,
offset: 0,
Expand Down Expand Up @@ -381,7 +394,7 @@ impl DatastoreWrapper {

let i = array
.first()
.ok_or("No data found")
.ok_or("No active configs found for AppGuard")
.handle_err(location!())?;

let map = i
Expand Down Expand Up @@ -519,44 +532,6 @@ impl DatastoreWrapper {
Ok(response)
}

// pub async fn register_device(
// &self,
// token: &str,
// account_id: &str,
// account_secret: &str,
// device: &Device,
// ) -> Result<Response, Error> {
// let request = RegisterDeviceRequestBuilder::new()
// .account_id(account_id)
// .account_secret(account_secret)
// .account_organization_status("Active")
// .is_new_user(true)
// .add_account_organization_category("Device")
// .add_device_category("Device")
// .organization_id(&device.organization)
// .device_id(&device.id)
// .build();
//
// let response = self.inner.clone().register_device(request, token).await?;
//
// Ok(response)
// }

// pub async fn heartbeat(
// &self,
// token: &str,
// device_id: String,
// ) -> Result<LatestDeviceInfo, Error> {
// let (create_result, fetch_result) = tokio::join!(
// Self::internal_hb_create_hb_record(self.inner.clone(), device_id.clone(), token),
// Self::internal_hb_fetch_device_info(self.inner.clone(), device_id, token)
// );
//
// let _ = create_result?;
//
// fetch_result
// }

pub async fn logs_insert(&self, token: &str, logs: Vec<Log>) -> Result<ResponseData, Error> {
match logs.as_slice() {
[] => Ok(ResponseData {
Expand All @@ -569,7 +544,6 @@ impl DatastoreWrapper {
}
}

// TODO: There was an error while creating the new record
async fn logs_insert_single(&mut self, log: Log, token: &str) -> Result<ResponseData, Error> {
let record = serde_json::to_string(&log).handle_err(location!())?;

Expand Down Expand Up @@ -616,59 +590,6 @@ impl DatastoreWrapper {
Ok(res)
}

// TODO: There was an error while creating the new record
// async fn internal_hb_create_hb_record(
// mut client: DatastoreClient,
// device_id: String,
// token: &str,
// ) -> Result<ResponseData, Error> {
// let request = CreateRequest {
// params: Some(CreateParams {
// table: String::from("device_heartbeats"),
// }),
// query: Some(Query {
// pluck: String::new(),
// durability: String::from("soft"),
// }),
// body: Some(CreateBody {
// record: json!({
// "device_id": device_id.clone(),
// "timestamp": Utc::now().to_rfc3339(),
// })
// .to_string(),
// }),
// };
//
// log::trace!("Before create heartbeat record");
// let res = client.create(request, token).await?;
// log::trace!("After create heartbeat record");
//
// Ok(res)
// }

// async fn internal_hb_fetch_device_info(
// mut client: DatastoreClient,
// device_id: String,
// token: &str,
// ) -> Result<LatestDeviceInfo, Error> {
// let request = GetByIdRequest {
// params: Some(Params {
// id: device_id,
// table: String::from("devices"),
// r#type: String::new(),
// }),
// query: Some(Query {
// pluck: String::from("status,is_monitoring_enabled,is_remote_access_enabled"),
// durability: String::from("soft"),
// }),
// };
//
// log::trace!("Before fetch heartbeat device info");
// let response = client.get_by_id(request, token).await?;
// log::trace!("After fetch heartbeat device info");
// LatestDeviceInfo::from_response_data(&response)
// }

pub async fn obtain_device_by_id(
&self,
token: &str,
Expand Down Expand Up @@ -1000,6 +921,72 @@ impl DatastoreWrapper {

Ok(())
}

pub(crate) async fn deactivate_old_configs(&mut self, token: &str) -> Result<i32, Error> {
let table = DbTable::Config.to_str();

let filter = AdvanceFilter {
r#type: "criteria".to_string(),
field: "active".to_string(),
operator: "equal".to_string(),
entity: table.to_string(),
values: "[true]".to_string(),
};

let updates = json!({"active": false}).to_string();

let request = BatchUpdateRequest {
params: Some(Params {
id: String::new(),
table: table.into(),
r#type: String::from("root"),
}),
body: Some(BatchUpdateBody {
advance_filters: vec![filter],
updates,
}),
};

log::trace!("Before batch update to {table}");
let count = self.inner.batch_update(request, token).await?.count;
log::trace!("After batch update to {table}: {count}");
Ok(count)
}

pub(crate) async fn deactivate_old_firewalls(
&mut self,
token: &str,
device_id: &str,
) -> Result<i32, Error> {
let table = DbTable::Firewall.to_str();

let filter = AdvanceFilter {
r#type: "criteria".to_string(),
field: "app_id".to_string(),
operator: "equal".to_string(),
entity: table.to_string(),
values: format!("[\"{device_id}\"]"),
};

let updates = json!({"active": false}).to_string();

let request = BatchUpdateRequest {
params: Some(Params {
id: String::new(),
table: table.into(),
r#type: String::from("root"),
}),
body: Some(BatchUpdateBody {
advance_filters: vec![filter],
updates,
}),
};

log::trace!("Before batch update to {table}");
let count = self.inner.batch_update(request, token).await?.count;
log::trace!("After batch update to {table}: {count}");
Ok(count)
}
}

#[cfg(test)]
Expand Down
4 changes: 1 addition & 3 deletions src/db/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ impl DbEntry {
let _ = ds.insert_batch(self, token.as_str()).await?;
}
DbEntry::Firewall(_) => {
let _ = ds
.upsert(self, vec!["app_id".to_string()], token.as_str())
.await?;
let _ = ds.insert(self, token.as_str()).await?;
log::info!("Firewall inserted in datastore");
}
DbEntry::DeniedIp((_, denied_ip, _)) => {
Expand Down
20 changes: 17 additions & 3 deletions src/firewall/firewall.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use rpn_predicate_interpreter::PredicateEvaluator;
use serde::{Deserialize, Serialize};

use crate::constants::BLACKLIST_LINK;
use crate::firewall::infix_firewall::InfixFirewall;
use crate::firewall::rules::{FirewallExpression, FirewallRule};
use crate::proto::appguard_commands::FirewallPolicy;
Expand Down Expand Up @@ -47,7 +48,14 @@ impl Firewall {
) -> FirewallResult {
// first let's check if this is blacklisted
if item.is_blacklisted() {
return FirewallResult::new(FirewallPolicy::Deny, vec!["blacklist".to_string()]);
return FirewallResult::new(
FirewallPolicy::Deny,
vec![format!(
"IP {} is blacklisted by {}",
item.get_remote_ip(),
BLACKLIST_LINK.as_str()
)],
);
}
// if not blacklisted, check the firewall expressions one by one
for expr in &self.expressions {
Expand Down Expand Up @@ -260,7 +268,10 @@ mod tests {
firewall.match_item(&item_1),
FirewallResult::new(
FirewallPolicy::Deny,
vec!["protocol".to_string(), "country".to_string()]
vec![
"{\"condition\":\"equal\",\"protocol\":[\"HTTP\",\"HTTPS\"],\"direction\":\"in\"}".to_string(),
"{\"condition\":\"equal\",\"country\":[\"US\"]}".to_string()
]
)
);

Expand All @@ -270,7 +281,10 @@ mod tests {
item_2.body = Some("Hey! Hello World!!!".to_string());
assert_eq!(
firewall.match_item(&item_2),
FirewallResult::new(FirewallPolicy::Allow, vec!["smtp_request_body".to_string()])
FirewallResult::new(
FirewallPolicy::Allow,
vec!["{\"condition\":\"contains\",\"smtp_request_body\":[\"Hello\"]}".to_string()]
)
);

item_2.body = Some("Hey! World!!!".to_string());
Expand Down
Loading
Loading