sos_audit/
encoding.rs

1use crate::{AuditData, AuditEvent, AuditLogFlags};
2use async_trait::async_trait;
3use binary_stream::futures::{
4    BinaryReader, BinaryWriter, Decodable, Encodable,
5};
6use sos_core::{
7    encoding::{decode_uuid, encoding_error},
8    UtcDateTime,
9};
10use std::io::{Error, Result};
11use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite};
12
13#[async_trait]
14impl Encodable for AuditEvent {
15    async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
16        &self,
17        writer: &mut BinaryWriter<W>,
18    ) -> Result<()> {
19        // Context bit flags
20        let flags = self.log_flags();
21        writer.write_u16(flags.bits()).await?;
22        // Time - the when
23        self.time.encode(&mut *writer).await?;
24        // EventKind - the what
25        self.event_kind.encode(&mut *writer).await?;
26        // Account identifier - by whom
27        writer.write_bytes(self.account_id.as_ref()).await?;
28        // Data - context
29        if flags.contains(AuditLogFlags::DATA) {
30            let data = self.data.as_ref().unwrap();
31            data.encode(&mut *writer).await?;
32        }
33        Ok(())
34    }
35}
36
37#[async_trait]
38impl Decodable for AuditEvent {
39    async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
40        &mut self,
41        reader: &mut BinaryReader<R>,
42    ) -> Result<()> {
43        // Context bit flags
44        let bits = reader.read_u16().await?;
45        // Time - the when
46        let mut timestamp: UtcDateTime = Default::default();
47        timestamp.decode(&mut *reader).await?;
48        self.time = timestamp;
49        // EventKind - the what
50        self.event_kind.decode(&mut *reader).await?;
51        // Account identifier - by whom
52        let address = reader.read_bytes(20).await?;
53        let address: [u8; 20] =
54            address.as_slice().try_into().map_err(encoding_error)?;
55        self.account_id = address.into();
56        // Data - context
57        if let Some(flags) = AuditLogFlags::from_bits(bits) {
58            if flags.contains(AuditLogFlags::DATA) {
59                if flags.contains(AuditLogFlags::DATA_VAULT) {
60                    let vault_id = decode_uuid(&mut *reader).await?;
61                    if !flags.contains(AuditLogFlags::DATA_SECRET) {
62                        self.data = Some(AuditData::Vault(vault_id));
63                    } else {
64                        let secret_id = decode_uuid(&mut *reader).await?;
65                        self.data =
66                            Some(AuditData::Secret(vault_id, secret_id));
67                    }
68                } else if flags.contains(AuditLogFlags::MOVE_SECRET) {
69                    let from_vault_id = decode_uuid(&mut *reader).await?;
70                    let from_secret_id = decode_uuid(&mut *reader).await?;
71                    let to_vault_id = decode_uuid(&mut *reader).await?;
72                    let to_secret_id = decode_uuid(&mut *reader).await?;
73                    self.data = Some(AuditData::MoveSecret {
74                        from_vault_id,
75                        from_secret_id,
76                        to_vault_id,
77                        to_secret_id,
78                    });
79                }
80            }
81        } else {
82            return Err(Error::other(
83                "log data flags has bad bits",
84            ));
85        }
86        Ok(())
87    }
88}
89
90#[async_trait]
91impl Encodable for AuditData {
92    async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
93        &self,
94        writer: &mut BinaryWriter<W>,
95    ) -> Result<()> {
96        match self {
97            AuditData::Vault(vault_id) => {
98                writer.write_bytes(vault_id.as_bytes()).await?;
99            }
100            AuditData::Secret(vault_id, secret_id) => {
101                writer.write_bytes(vault_id.as_bytes()).await?;
102                writer.write_bytes(secret_id.as_bytes()).await?;
103            }
104            AuditData::MoveSecret {
105                from_vault_id,
106                from_secret_id,
107                to_vault_id,
108                to_secret_id,
109            } => {
110                writer.write_bytes(from_vault_id.as_bytes()).await?;
111                writer.write_bytes(from_secret_id.as_bytes()).await?;
112                writer.write_bytes(to_vault_id.as_bytes()).await?;
113                writer.write_bytes(to_secret_id.as_bytes()).await?;
114            }
115            AuditData::Device(public_key) => {
116                writer.write_bytes(public_key.as_ref()).await?;
117            }
118        }
119        Ok(())
120    }
121}