Skip to content

Commit

Permalink
treewide: add opt-in passphrase param for encryption at rest
Browse files Browse the repository at this point in the history
You can now choose a passphrase and use it (plain text for now, sorry)
to set up an encryption-at-rest key.

Example:
cargo run -F encryption-at-rest -- --passphrase pekka
  • Loading branch information
psarna committed Jan 8, 2024
1 parent 6b4b871 commit bdd2d40
Show file tree
Hide file tree
Showing 15 changed files with 157 additions and 19 deletions.
3 changes: 3 additions & 0 deletions libsql-replication/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ bincode = "1.3.3"
tempfile = "3.8.0"
prost-build = "0.12.0"
tonic-build = "0.10"

[features]
encryption-at-rest = ["libsql-sys/encryption-at-rest"]
2 changes: 2 additions & 0 deletions libsql-replication/src/injector/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ impl Injector {
| OpenFlags::SQLITE_OPEN_NO_MUTEX,
wal_manager,
auto_checkpoint,
#[cfg(feature = "encryption-at-rest")]
None,
)?;

Ok(Self {
Expand Down
2 changes: 1 addition & 1 deletion libsql-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,4 @@ default = []
debug-tools = ["console-subscriber", "rusqlite/trace", "tokio/tracing"]
wasm-udfs = ["rusqlite/libsql-wasm-experimental"]
unix-excl-vfs = ["libsql-sys/unix-excl-vfs"]
encryption-at-rest = ["libsql-sys/encryption-at-rest"]
encryption-at-rest = ["libsql-sys/encryption-at-rest", "libsql-replication/encryption-at-rest"]
4 changes: 4 additions & 0 deletions libsql-server/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ pub struct DbConfig {
pub snapshot_exec: Option<String>,
pub checkpoint_interval: Option<Duration>,
pub snapshot_at_shutdown: bool,
#[cfg(feature = "encryption-at-rest")]
pub passphrase: Option<String>,
}

impl Default for DbConfig {
Expand All @@ -141,6 +143,8 @@ impl Default for DbConfig {
snapshot_exec: None,
checkpoint_interval: None,
snapshot_at_shutdown: false,
#[cfg(feature = "encryption-at-rest")]
passphrase: None,
}
}
}
Expand Down
38 changes: 35 additions & 3 deletions libsql-server/src/connection/libsql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub struct MakeLibSqlConn<T: WalManager> {
/// In wal mode, closing the last database takes time, and causes other databases creation to
/// return sqlite busy. To mitigate that, we hold on to one connection
_db: Option<LibSqlConnection<T::Wal>>,
#[cfg(feature = "encryption-at-rest")]
passphrase: Option<String>,
}

impl<T> MakeLibSqlConn<T>
Expand All @@ -62,6 +64,7 @@ where
max_total_response_size: u64,
auto_checkpoint: u32,
current_frame_no_receiver: watch::Receiver<Option<FrameNo>>,
#[cfg(feature = "encryption-at-rest")] passphrase: Option<String>,
) -> Result<Self> {
let mut this = Self {
db_path,
Expand All @@ -75,6 +78,8 @@ where
_db: None,
state: Default::default(),
wal_manager,
#[cfg(feature = "encryption-at-rest")]
passphrase,
};

let db = this.try_create_db().await?;
Expand Down Expand Up @@ -123,6 +128,8 @@ where
max_size: Some(self.max_response_size),
max_total_size: Some(self.max_total_response_size),
auto_checkpoint: self.auto_checkpoint,
#[cfg(feature = "encryption-at-rest")]
passphrase: self.passphrase.clone(),
},
self.current_frame_no_receiver.clone(),
self.state.clone(),
Expand Down Expand Up @@ -207,6 +214,7 @@ pub fn open_conn<T>(
path: &Path,
wal_manager: T,
flags: Option<OpenFlags>,
#[cfg(feature = "encryption-at-rest")] passphrase: Option<String>,
) -> Result<libsql_sys::Connection<InhibitCheckpoint<T::Wal>>, rusqlite::Error>
where
T: WalManager,
Expand All @@ -223,6 +231,8 @@ where
flags,
WalWrapper::new(InhibitCheckpointWalWrapper, wal_manager),
u32::MAX,
#[cfg(feature = "encryption-at-rest")]
passphrase,
)
}

Expand All @@ -232,6 +242,7 @@ pub fn open_conn_active_checkpoint<T>(
wal_manager: T,
flags: Option<OpenFlags>,
auto_checkpoint: u32,
#[cfg(feature = "encryption-at-rest")] passphrase: Option<String>,
) -> Result<libsql_sys::Connection<T::Wal>, rusqlite::Error>
where
T: WalManager,
Expand All @@ -243,7 +254,14 @@ where
| OpenFlags::SQLITE_OPEN_NO_MUTEX,
);

libsql_sys::Connection::open(path.join("data"), flags, wal_manager, auto_checkpoint)
libsql_sys::Connection::open(
path.join("data"),
flags,
wal_manager,
auto_checkpoint,
#[cfg(feature = "encryption-at-rest")]
passphrase,
)
}

impl<W> LibSqlConnection<W>
Expand Down Expand Up @@ -506,8 +524,14 @@ impl<W: Wal> Connection<W> {
current_frame_no_receiver: watch::Receiver<Option<FrameNo>>,
state: Arc<TxnState<W>>,
) -> Result<Self> {
let conn =
open_conn_active_checkpoint(path, wal_manager, None, builder_config.auto_checkpoint)?;
let conn = open_conn_active_checkpoint(
path,
wal_manager,
None,
builder_config.auto_checkpoint,
#[cfg(feature = "encryption-at-rest")]
builder_config.passphrase.clone(),
)?;

// register the lock-stealing busy handler
unsafe {
Expand Down Expand Up @@ -1049,6 +1073,8 @@ mod test {
100000000,
DEFAULT_AUTO_CHECKPOINT,
watch::channel(None).1,
#[cfg(feature = "encryption-at-rest")]
None,
)
.await
.unwrap();
Expand Down Expand Up @@ -1090,6 +1116,8 @@ mod test {
100000000,
DEFAULT_AUTO_CHECKPOINT,
watch::channel(None).1,
#[cfg(feature = "encryption-at-rest")]
None,
)
.await
.unwrap();
Expand Down Expand Up @@ -1132,6 +1160,8 @@ mod test {
100000000,
DEFAULT_AUTO_CHECKPOINT,
watch::channel(None).1,
#[cfg(feature = "encryption-at-rest")]
None,
)
.await
.unwrap();
Expand Down Expand Up @@ -1210,6 +1240,8 @@ mod test {
100000000,
DEFAULT_AUTO_CHECKPOINT,
watch::channel(None).1,
#[cfg(feature = "encryption-at-rest")]
None,
)
.await
.unwrap();
Expand Down
13 changes: 11 additions & 2 deletions libsql-server/src/connection/write_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub struct MakeWriteProxyConn {
namespace: NamespaceName,
primary_replication_index: Option<FrameNo>,
make_read_only_conn: MakeLibSqlConn<Sqlite3WalManager>,
#[cfg(feature = "encryption-at-rest")]
passphrase: Option<String>,
}

impl MakeWriteProxyConn {
Expand All @@ -60,6 +62,7 @@ impl MakeWriteProxyConn {
max_total_response_size: u64,
namespace: NamespaceName,
primary_replication_index: Option<FrameNo>,
#[cfg(feature = "encryption-at-rest")] passphrase: Option<String>,
) -> crate::Result<Self> {
let client = ProxyClient::with_origin(channel, uri);
let make_read_only_conn = MakeLibSqlConn::new(
Expand All @@ -72,6 +75,8 @@ impl MakeWriteProxyConn {
max_total_response_size,
DEFAULT_AUTO_CHECKPOINT,
applied_frame_no_receiver.clone(),
#[cfg(feature = "encryption-at-rest")]
passphrase.clone(),
)
.await?;

Expand All @@ -84,6 +89,8 @@ impl MakeWriteProxyConn {
namespace,
make_read_only_conn,
primary_replication_index,
#[cfg(feature = "encryption-at-rest")]
passphrase,
})
}
}
Expand All @@ -100,6 +107,8 @@ impl MakeConnection for MakeWriteProxyConn {
max_size: Some(self.max_response_size),
max_total_size: Some(self.max_total_response_size),
auto_checkpoint: DEFAULT_AUTO_CHECKPOINT,
#[cfg(feature = "encryption-at-rest")]
passphrase: self.passphrase.clone(),
},
self.namespace.clone(),
self.primary_replication_index,
Expand Down Expand Up @@ -188,7 +197,7 @@ impl WriteProxyConnection<RpcStream> {
self.stats.inc_write_requests_delegated();
*status = TxnStatus::Invalid;
let res = self
.with_remote_conn(auth, self.builder_config, |conn| {
.with_remote_conn(auth, self.builder_config.clone(), |conn| {
Box::pin(conn.execute(pgm, builder))
})
.await;
Expand Down Expand Up @@ -375,7 +384,7 @@ where
) -> crate::Result<(B, TxnStatus, Option<FrameNo>)> {
let mut txn_status = TxnStatus::Invalid;
let mut new_frame_no = None;
let builder_config = self.builder_config;
let builder_config = self.builder_config.clone();
let cb = move |response: exec_resp::Response, builder: &mut B| match response {
exec_resp::Response::ProgramResp(resp) => {
crate::rpc::streaming_exec::apply_program_resp_to_builder(
Expand Down
4 changes: 4 additions & 0 deletions libsql-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,8 @@ where
max_total_response_size: self.db_config.max_total_response_size,
checkpoint_interval: self.db_config.checkpoint_interval,
disable_namespace: self.disable_namespaces,
#[cfg(feature = "encryption-at-rest")]
passphrase: self.db_config.passphrase.clone(),
};

let factory = PrimaryNamespaceMaker::new(conf);
Expand Down Expand Up @@ -636,6 +638,8 @@ impl<C: Connector> Replica<C> {
base_path: self.base_path.clone(),
max_response_size: self.db_config.max_response_size,
max_total_response_size: self.db_config.max_total_response_size,
#[cfg(feature = "encryption-at-rest")]
passphrase: self.db_config.passphrase.clone(),
};

let factory = ReplicaNamespaceMaker::new(conf);
Expand Down
6 changes: 6 additions & 0 deletions libsql-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,10 @@ struct Cli {
/// S3 endpoint for the meta store backups
#[clap(long)]
meta_store_bucket_endpoint: Option<String>,
/// Passphrase for encryption at rest
#[cfg(feature = "encryption-at-rest")]
#[clap(long)]
passphrase: Option<String>,
}

#[derive(clap::Subcommand, Debug)]
Expand Down Expand Up @@ -338,6 +342,8 @@ fn make_db_config(config: &Cli) -> anyhow::Result<DbConfig> {
snapshot_exec: config.snapshot_exec.clone(),
checkpoint_interval: config.checkpoint_interval_s.map(Duration::from_secs),
snapshot_at_shutdown: config.snapshot_at_shutdown,
#[cfg(feature = "encryption-at-rest")]
passphrase: config.passphrase.clone(),
})
}

Expand Down
9 changes: 8 additions & 1 deletion libsql-server/src/namespace/meta_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,14 @@ impl MetaStore {
replicator.map(BottomlessWalWrapper::new),
Sqlite3WalManager::default(),
);
let conn = open_conn_active_checkpoint(&db_path, wal_manager.clone(), None, 1000)?;
let conn = open_conn_active_checkpoint(
&db_path,
wal_manager.clone(),
None,
1000,
#[cfg(feature = "encryption-at-rest")]
None,
)?;

let configs = restore(&conn)?;

Expand Down
Loading

0 comments on commit bdd2d40

Please sign in to comment.