Skip to content

Commit d07fb7e

Browse files
committed
Add trust and revoke events to audit trail.
Closes #246.
1 parent 0ad1756 commit d07fb7e

File tree

8 files changed

+66
-46
lines changed

8 files changed

+66
-46
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/audit/src/encoding.rs

+3
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ impl Encodable for AuditData {
113113
writer.write_bytes(to_vault_id.as_bytes()).await?;
114114
writer.write_bytes(to_secret_id.as_bytes()).await?;
115115
}
116+
AuditData::Device(public_key) => {
117+
writer.write_bytes(public_key.as_ref()).await?;
118+
}
116119
}
117120
Ok(())
118121
}

crates/audit/src/event.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Audit trail event.
22
use bitflags::bitflags;
33
use serde::{Deserialize, Serialize};
4+
use sos_core::device::DevicePublicKey;
45
use sos_core::events::{
56
AccountEvent, Event, EventKind, ReadEvent, WriteEvent,
67
};
@@ -17,6 +18,8 @@ bitflags! {
1718
const DATA_SECRET = 0b00000100;
1819
/// Indicates the data has a move event.
1920
const MOVE_SECRET = 0b00001000;
21+
/// Indicates the data is for a device event.
22+
const DEVICE = 0b00010000;
2023
}
2124
}
2225

@@ -101,6 +104,9 @@ impl AuditEvent {
101104
AuditData::MoveSecret { .. } => {
102105
flags.set(AuditLogFlags::MOVE_SECRET, true);
103106
}
107+
AuditData::Device { .. } => {
108+
flags.set(AuditLogFlags::DEVICE, true);
109+
}
104110
}
105111
flags
106112
} else {
@@ -213,6 +219,8 @@ pub enum AuditData {
213219
/// New secret identifier.
214220
to_secret_id: SecretId,
215221
},
222+
/// Device trust or revoke events.
223+
Device(DevicePublicKey),
216224
}
217225

218226
impl Default for AuditData {

crates/database/src/db/system_message.rs

-44
Original file line numberDiff line numberDiff line change
@@ -54,50 +54,6 @@ where
5454
Self { conn }
5555
}
5656

57-
/*
58-
fn find_server_statement(
59-
&self,
60-
) -> std::result::Result<CachedStatement, SqlError> {
61-
Ok(self.conn.prepare_cached(
62-
r#"
63-
SELECT
64-
system_message_id,
65-
created_at,
66-
modified_at,
67-
key,
68-
json_data
69-
FROM system_messages
70-
WHERE account_id=?1
71-
"#,
72-
)?)
73-
}
74-
75-
/// Find a system message in the database.
76-
pub fn find_one(
77-
&self,
78-
account_id: i64,
79-
) -> std::result::Result<SystemMessageRow, SqlError> {
80-
let mut stmt = self.find_server_statement()?;
81-
Ok(stmt.query_row((account_id), |row| {
82-
Ok(row.try_into()?)
83-
})?)
84-
}
85-
86-
/// Find an optional server in the database.
87-
pub fn find_optional(
88-
&self,
89-
account_id: i64,
90-
url: &Url,
91-
) -> std::result::Result<Option<SystemMessageRow>, SqlError> {
92-
let mut stmt = self.find_server_statement()?;
93-
Ok(stmt
94-
.query_row((account_id, url.to_string()), |row| {
95-
Ok(row.try_into()?)
96-
})
97-
.optional()?)
98-
}
99-
*/
100-
10157
/// Load system messages for an account.
10258
pub fn load_system_messages(
10359
&self,

crates/net/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ full = [
2727
"clipboard",
2828
]
2929

30+
audit = ["sos-audit", "sos-account/audit"]
3031
listen = ["sos-protocol/listen"]
3132
hashcheck = ["sos-protocol/hashcheck"]
32-
audit = ["sos-account/audit"]
3333
archive = ["sos-account/archive"]
3434
files = ["sos-sdk/files", "sos-protocol/files"]
3535
clipboard = ["sos-account/clipboard"]
@@ -56,6 +56,7 @@ sos-signer.workspace = true
5656
sos-sync.workspace = true
5757
sos-vault.workspace = true
5858

59+
sos-audit = { workspace = true, optional = true }
5960
sos-search = { workspace = true, optional = true }
6061
sos-migrate = { workspace = true, optional = true }
6162

crates/net/src/account/network_account.rs

+18
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ use sos_migrate::import::ImportTarget;
6868
#[cfg(feature = "listen")]
6969
use sos_protocol::network_client::WebSocketHandle;
7070

71+
#[cfg(feature = "audit")]
72+
use {
73+
sos_audit::{AuditData, AuditEvent},
74+
sos_backend::audit::append_audit_events,
75+
sos_core::events::EventKind,
76+
};
77+
7178
/*
7279
#[cfg(feature = "security-report")]
7380
use crate::sdk::account::security_report::{
@@ -248,6 +255,17 @@ impl NetworkAccount {
248255
storage.revoke_device(device_key).await?;
249256
}
250257

258+
#[cfg(feature = "audit")]
259+
{
260+
let audit_event = AuditEvent::new(
261+
Default::default(),
262+
EventKind::RevokeDevice,
263+
*self.account_id(),
264+
Some(AuditData::Device(*device_key)),
265+
);
266+
append_audit_events(&[audit_event]).await?;
267+
}
268+
251269
// Send the device event logs to the remote servers
252270
if let Some(e) = self.sync().await.first_error() {
253271
tracing::error!(error = ?e);

crates/sos/src/commands/tools/audit.rs

+9
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ fn print_event(event: AuditEvent, json: bool) -> Result<()> {
123123
to_secret_id,
124124
));
125125
}
126+
AuditData::Device(public_key) => {
127+
info(format!(
128+
"{} {} by {}, device = {}",
129+
event.time().to_rfc3339()?,
130+
event.event_kind(),
131+
event.account_id(),
132+
public_key,
133+
));
134+
}
126135
}
127136
} else {
128137
info(format!(

crates/storage/client/src/client.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ use tokio::sync::RwLock;
3737
use sos_backup_archive::RestoreTargets;
3838

3939
#[cfg(feature = "audit")]
40-
use {sos_audit::AuditEvent, sos_backend::audit::append_audit_events};
40+
use {
41+
sos_audit::{AuditData, AuditEvent},
42+
sos_backend::audit::append_audit_events,
43+
sos_core::events::EventKind,
44+
};
4145

4246
use sos_core::{
4347
device::{DevicePublicKey, TrustedDevice},
@@ -1738,6 +1742,7 @@ impl ClientStorage {
17381742
&mut self,
17391743
events: Vec<DeviceEvent>,
17401744
) -> Result<()> {
1745+
// Update the event log
17411746
let mut event_log = self.device_log.write().await;
17421747
event_log.apply(events.iter().collect()).await?;
17431748

@@ -1746,6 +1751,25 @@ impl ClientStorage {
17461751
let devices = reducer.reduce().await?;
17471752
self.devices = devices;
17481753

1754+
#[cfg(feature = "audit")]
1755+
{
1756+
let audit_events = events
1757+
.iter()
1758+
.filter_map(|event| match event {
1759+
DeviceEvent::Trust(device) => Some(AuditEvent::new(
1760+
Default::default(),
1761+
EventKind::TrustDevice,
1762+
*self.account_id(),
1763+
Some(AuditData::Device(*device.public_key())),
1764+
)),
1765+
_ => None,
1766+
})
1767+
.collect::<Vec<_>>();
1768+
if !audit_events.is_empty() {
1769+
append_audit_events(audit_events.as_slice()).await?;
1770+
}
1771+
}
1772+
17491773
Ok(())
17501774
}
17511775

0 commit comments

Comments
 (0)