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
141 changes: 140 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/ember-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ keywords.workspace = true
categories.workspace = true
readme = "README.md"

[features]
encryption = ["ember-persistence/encryption"]

[lib]
name = "ember_core"

Expand Down
51 changes: 48 additions & 3 deletions crates/ember-core/src/shard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ pub struct ShardPersistenceConfig {
pub append_only: bool,
/// When to fsync the AOF file.
pub fsync_policy: FsyncPolicy,
/// Optional encryption key for encrypting data at rest.
/// When set, AOF and snapshot files use the v3 encrypted format.
#[cfg(feature = "encryption")]
pub encryption_key: Option<ember_persistence::encryption::EncryptionKey>,
}

/// A protocol-agnostic command sent to a shard.
Expand Down Expand Up @@ -392,6 +396,13 @@ async fn run_shard(

// -- recovery --
if let Some(ref pcfg) = persistence {
#[cfg(feature = "encryption")]
let result = if let Some(ref key) = pcfg.encryption_key {
recovery::recover_shard_encrypted(&pcfg.data_dir, shard_id, key.clone())
} else {
recovery::recover_shard(&pcfg.data_dir, shard_id)
};
#[cfg(not(feature = "encryption"))]
let result = recovery::recover_shard(&pcfg.data_dir, shard_id);
let count = result.entries.len();
for entry in result.entries {
Expand Down Expand Up @@ -425,7 +436,15 @@ async fn run_shard(
let mut aof_writer: Option<AofWriter> = match &persistence {
Some(pcfg) if pcfg.append_only => {
let path = ember_persistence::aof::aof_path(&pcfg.data_dir, shard_id);
match AofWriter::open(path) {
#[cfg(feature = "encryption")]
let result = if let Some(ref key) = pcfg.encryption_key {
AofWriter::open_encrypted(path, key.clone())
} else {
AofWriter::open(path)
};
#[cfg(not(feature = "encryption"))]
let result = AofWriter::open(path);
match result {
Ok(w) => Some(w),
Err(e) => {
warn!(shard_id, "failed to open AOF writer: {e}");
Expand Down Expand Up @@ -956,7 +975,14 @@ fn handle_snapshot(
};

let path = snapshot::snapshot_path(&pcfg.data_dir, shard_id);
match write_snapshot(keyspace, &path, shard_id) {
let result = write_snapshot(
keyspace,
&path,
shard_id,
#[cfg(feature = "encryption")]
pcfg.encryption_key.as_ref(),
);
match result {
Ok(count) => {
info!(shard_id, entries = count, "snapshot written");
ShardResponse::Ok
Expand All @@ -981,7 +1007,14 @@ fn handle_rewrite(
};

let path = snapshot::snapshot_path(&pcfg.data_dir, shard_id);
match write_snapshot(keyspace, &path, shard_id) {
let result = write_snapshot(
keyspace,
&path,
shard_id,
#[cfg(feature = "encryption")]
pcfg.encryption_key.as_ref(),
);
match result {
Ok(count) => {
// truncate AOF after successful snapshot
if let Some(ref mut writer) = aof_writer {
Expand All @@ -1004,7 +1037,17 @@ fn write_snapshot(
keyspace: &Keyspace,
path: &std::path::Path,
shard_id: u16,
#[cfg(feature = "encryption")] encryption_key: Option<
&ember_persistence::encryption::EncryptionKey,
>,
) -> Result<u32, ember_persistence::format::FormatError> {
#[cfg(feature = "encryption")]
let mut writer = if let Some(key) = encryption_key {
SnapshotWriter::create_encrypted(path, shard_id, key.clone())?
} else {
SnapshotWriter::create(path, shard_id)?
};
#[cfg(not(feature = "encryption"))]
let mut writer = SnapshotWriter::create(path, shard_id)?;
let mut count = 0u32;

Expand Down Expand Up @@ -1234,6 +1277,8 @@ mod tests {
data_dir: dir.path().to_owned(),
append_only: true,
fsync_policy: FsyncPolicy::Always,
#[cfg(feature = "encryption")]
encryption_key: None,
};
let config = ShardConfig {
shard_id: 0,
Expand Down
7 changes: 7 additions & 0 deletions crates/ember-persistence/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,18 @@ keywords.workspace = true
categories.workspace = true
readme = "README.md"

[features]
encryption = ["aes-gcm", "rand"]

[dependencies]
thiserror = { workspace = true }
bytes = { workspace = true }
crc32fast = { workspace = true }
tracing = { workspace = true }

# optional: encryption at rest (AES-256-GCM)
aes-gcm = { version = "0.10", optional = true }
rand = { workspace = true, optional = true }

[dev-dependencies]
tempfile = "3"
Loading