Skip to content

Commit 1b9eb6a

Browse files
committed
store denied IPs in table ip_aliases
1 parent 88bb66f commit 1b9eb6a

16 files changed

+145
-70
lines changed

Cargo.lock

Lines changed: 26 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

firewall.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
{
3535
"type": "predicate",
3636
"condition": "contains",
37-
"source_ip": "alias_name"
37+
"source_ip": [
38+
"alias_name"
39+
]
3840
}
3941
]
4042
},

src/app_guard_impl.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub struct AppGuardImpl {
4040
ip_info_handler: IpInfoHandler,
4141
tx_store: UnboundedSender<DbEntry>,
4242
ctx: AppContext,
43+
quarantine_alias_id: u64,
4344
// tx_ai: Sender<AiEntry>,
4445
}
4546

@@ -60,12 +61,18 @@ pub fn terminate_app_guard(exit_code: i32) -> Result<(), Error> {
6061
}
6162

6263
impl AppGuardImpl {
63-
pub fn new(ctx: AppContext) -> AppGuardImpl {
64-
let ds = ctx.datastore.clone();
64+
pub async fn new(ctx: AppContext) -> Result<AppGuardImpl, Error> {
65+
let mut ds = ctx.datastore.clone();
6566
let ds_2 = ctx.datastore.clone();
6667

6768
log::info!("Connected to Datastore");
6869

70+
// upsert the 'ip_quarantine' host alias in datastore retrieving its ID
71+
let root_token_provider = ctx.root_token_provider.clone();
72+
let quarantine_alias_id = ds
73+
.upsert_quarantine_alias(&root_token_provider.get().await?.jwt)
74+
.await?;
75+
6976
let config_2 = ctx.config_pair.clone();
7077

7178
let ip_info_handler = ip_info_handler();
@@ -105,15 +112,16 @@ impl AppGuardImpl {
105112
store_entries(&ds, &mut rx_store).await;
106113
});
107114

108-
AppGuardImpl {
115+
Ok(AppGuardImpl {
109116
entry_ids: EntryIds::default(),
110117
unanswered_connections: Arc::new(Mutex::new(HashMap::new())),
111118
ip_info_cache,
112119
ip_info_handler,
113120
tx_store,
114121
// tx_ai,
115122
ctx,
116-
}
123+
quarantine_alias_id,
124+
})
117125
}
118126

119127
fn config_log_requests(&self) -> Result<bool, Error> {
@@ -192,11 +200,11 @@ impl AppGuardImpl {
192200
if res.policy == FirewallPolicy::Deny {
193201
let denied_ip = DeniedIp {
194202
ip: item.get_remote_ip(),
195-
deny_reasons: res.reasons.clone(),
203+
_deny_reasons: res.reasons.clone(),
196204
};
197205
self.tx_store
198206
.send(DbEntry::DeniedIp((
199-
app_id.clone(),
207+
self.quarantine_alias_id,
200208
denied_ip,
201209
token.to_string(),
202210
)))

src/db/datastore_wrapper.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,67 @@ impl DatastoreWrapper {
11591159

11601160
Ok(ret_val)
11611161
}
1162+
1163+
pub(crate) async fn upsert_quarantine_alias(&mut self, token: &str) -> Result<u64, Error> {
1164+
let record = json!(
1165+
{
1166+
"type": "host",
1167+
"name": "quarantine",
1168+
"description": "Alias for quarantined IPs",
1169+
"alias_status": "Applied",
1170+
}
1171+
)
1172+
.to_string();
1173+
let table = "aliases";
1174+
1175+
let request = UpsertRequest {
1176+
params: Some(Params {
1177+
id: String::new(),
1178+
table: table.into(),
1179+
r#type: String::new(),
1180+
}),
1181+
query: Some(Query {
1182+
pluck: String::from("id"),
1183+
durability: String::from("soft"),
1184+
}),
1185+
body: Some(UpsertBody {
1186+
data: record,
1187+
conflict_columns: vec!["name".to_string()],
1188+
}),
1189+
};
1190+
1191+
log::trace!("Before upsert to {table}");
1192+
let result = self.inner.upsert(request, token).await?;
1193+
log::trace!("After upsert to {table}");
1194+
1195+
let id = Self::internal_upsert_quarantine_alias_parse_response_data(result.data)?;
1196+
Ok(id)
1197+
}
1198+
1199+
fn internal_upsert_quarantine_alias_parse_response_data(data: String) -> Result<u64, Error> {
1200+
let array_val = serde_json::from_str::<serde_json::Value>(&data).handle_err(location!())?;
1201+
let array = array_val
1202+
.as_array()
1203+
.ok_or("Failed to parse response")
1204+
.handle_err(location!())?;
1205+
1206+
let i = array
1207+
.first()
1208+
.ok_or("Error upserting quarantine alias")
1209+
.handle_err(location!())?;
1210+
1211+
let map = i
1212+
.as_object()
1213+
.ok_or("Invalid data")
1214+
.handle_err(location!())?;
1215+
let id = map
1216+
.get("id")
1217+
.and_then(serde_json::Value::as_u64)
1218+
.ok_or("Invalid data")
1219+
.handle_err(location!())?;
1220+
1221+
Ok(id)
1222+
}
11621223
}
11631224

11641225
#[cfg(test)]

src/db/entries.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub enum DbEntry {
2121
TcpConnection((AppGuardTcpConnection, u64)),
2222
// Blacklist((Vec<String>, String)),
2323
Firewall((String, Firewall, String)),
24-
DeniedIp((String, DeniedIp, String)),
24+
DeniedIp((u64, DeniedIp, String)),
2525
Config((Config, String)),
2626
}
2727

@@ -70,13 +70,9 @@ impl DbEntry {
7070
log::info!("Firewall inserted in datastore");
7171
}
7272
DbEntry::DeniedIp((_, denied_ip, _)) => {
73-
// todo: change this to a custom query to aliases
73+
// insert the denied IP into the ip_aliases table
7474
let _ = ds.insert(self, token.as_str()).await?;
75-
log::info!(
76-
"Denied IP inserted in datastore: {} {:?}",
77-
denied_ip.ip,
78-
denied_ip.deny_reasons
79-
);
75+
log::info!("Denied IP inserted in datastore: {}", denied_ip.ip);
8076
}
8177
DbEntry::Config((configs, _)) => {
8278
let _ = ds.insert(self, token.as_str()).await?;
@@ -104,7 +100,9 @@ impl DbEntry {
104100
// Ok(json)
105101
// }
106102
DbEntry::Firewall((app_id, f, _)) => f.to_json(app_id),
107-
DbEntry::DeniedIp((app_id, denied_ip, _)) => denied_ip.to_json(app_id),
103+
DbEntry::DeniedIp((quarantine_alias_id, denied_ip, _)) => {
104+
denied_ip.to_json(*quarantine_alias_id)
105+
}
108106
DbEntry::Config((configs, _)) => serde_json::to_string(configs).handle_err(location!()),
109107
}
110108
}
@@ -119,7 +117,7 @@ impl DbEntry {
119117
DbEntry::TcpConnection(_) => DbTable::TcpConnection,
120118
// DbEntry::Blacklist(_) => DbTable::Blacklist,
121119
DbEntry::Firewall(_) => DbTable::Firewall,
122-
DbEntry::DeniedIp(_) => DbTable::Alias,
120+
DbEntry::DeniedIp(_) => DbTable::IpAlias,
123121
DbEntry::Config(_) => DbTable::Config,
124122
}
125123
}

src/db/store/denied_ip.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
use crate::firewall::denied_ip::DeniedIp;
2-
use nullnet_liberror::{location, Error, ErrorHandler, Location};
2+
use nullnet_liberror::Error;
33
use serde_json::json;
44

55
impl DeniedIp {
6-
pub(crate) fn to_json(&self, app_id: &str) -> Result<String, Error> {
6+
pub(crate) fn to_json(&self, quarantine_alias_id: u64) -> Result<String, Error> {
7+
// a denied IP is always a single IP and (not a subnet)
8+
let prefix = if self.ip.is_ipv4() { 32 } else { 128 };
79
Ok(json!({
8-
"app_id": app_id,
10+
"alias_id": quarantine_alias_id,
911
"ip": self.ip,
10-
"deny_reasons": serde_json::to_string(&self.deny_reasons).handle_err(location!())?,
12+
"prefix": prefix,
1113
})
1214
.to_string())
1315
}

src/entrypoint.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ pub async fn start_appguard(ctx: AppContext) -> Result<(), Error> {
2323

2424
server_builder()?
2525
.add_service(
26-
AppGuardServer::new(init_app_guard(ctx)?).max_decoding_message_size(50 * 1024 * 1024),
26+
AppGuardServer::new(init_app_guard(ctx).await?)
27+
.max_decoding_message_size(50 * 1024 * 1024),
2728
)
2829
.serve(addr)
2930
.await
@@ -41,7 +42,7 @@ pub async fn start_appguard(ctx: AppContext) -> Result<(), Error> {
4142
// Logger::init(logger_config);
4243
// }
4344

44-
fn init_app_guard(ctx: AppContext) -> Result<AppGuardImpl, Error> {
45+
async fn init_app_guard(ctx: AppContext) -> Result<AppGuardImpl, Error> {
4546
if cfg!(not(debug_assertions)) {
4647
// custom panic hook to correctly clean up the server, even in case a secondary thread fails
4748
let orig_hook = panic::take_hook();
@@ -58,9 +59,7 @@ fn init_app_guard(ctx: AppContext) -> Result<AppGuardImpl, Error> {
5859
})
5960
.handle_err(location!())?;
6061

61-
let app_guard_impl = AppGuardImpl::new(ctx);
62-
63-
Ok(app_guard_impl)
62+
AppGuardImpl::new(ctx).await
6463
}
6564

6665
fn server_builder() -> Result<Server, Error> {

0 commit comments

Comments
 (0)