Compare commits
2 commits
fork
...
signatures
Author | SHA1 | Date | |
---|---|---|---|
|
920b7118d5 | ||
|
e8c8164d78 |
16 changed files with 105 additions and 31 deletions
1
tvix/Cargo.lock
generated
1
tvix/Cargo.lock
generated
|
@ -4995,6 +4995,7 @@ dependencies = [
|
|||
"clap",
|
||||
"count-write",
|
||||
"data-encoding",
|
||||
"ed25519",
|
||||
"futures",
|
||||
"hyper-util",
|
||||
"lazy_static",
|
||||
|
|
|
@ -31,6 +31,3 @@ tonic-reflection = ["dep:tonic-reflection", "tvix-castore/tonic-reflection"]
|
|||
|
||||
[dev-dependencies]
|
||||
rstest = "0.19.0"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
@ -20,15 +20,15 @@ fn main() -> Result<()> {
|
|||
.extern_path(".tvix.castore.v1", "::tvix_castore::proto")
|
||||
.compile(
|
||||
&[
|
||||
"tvix/build/protos/build.proto",
|
||||
"tvix/build/protos/rpc_build.proto",
|
||||
"build/protos/build.proto",
|
||||
"build/protos/rpc_build.proto",
|
||||
],
|
||||
// If we are in running `cargo build` manually, using `../..` works fine,
|
||||
// but in case we run inside a nix build, we need to instead point PROTO_ROOT
|
||||
// to a sparseTree containing that structure.
|
||||
&[match std::env::var_os("PROTO_ROOT") {
|
||||
Some(proto_root) => proto_root.to_str().unwrap().to_owned(),
|
||||
None => "../..".to_string(),
|
||||
None => "..".to_string(),
|
||||
}],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ syntax = "proto3";
|
|||
|
||||
package tvix.build.v1;
|
||||
|
||||
import "tvix/castore/protos/castore.proto";
|
||||
import "castore/protos/castore.proto";
|
||||
|
||||
option go_package = "code.tvl.fyi/tvix/build-go;buildv1";
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ syntax = "proto3";
|
|||
|
||||
package tvix.build.v1;
|
||||
|
||||
import "tvix/build/protos/build.proto";
|
||||
import "build/protos/build.proto";
|
||||
|
||||
option go_package = "code.tvl.fyi/tvix/build-go;buildv1";
|
||||
|
||||
|
|
|
@ -126,6 +126,3 @@ tonic-reflection = ["dep:tonic-reflection"]
|
|||
# Requires the following packages in $PATH:
|
||||
# cbtemulator, google-cloud-bigtable-tool
|
||||
integration = []
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
@ -20,16 +20,16 @@ fn main() -> Result<()> {
|
|||
.type_attribute(".", "#[derive(Eq, Hash)]")
|
||||
.compile(
|
||||
&[
|
||||
"tvix/castore/protos/castore.proto",
|
||||
"tvix/castore/protos/rpc_blobstore.proto",
|
||||
"tvix/castore/protos/rpc_directory.proto",
|
||||
"castore/protos/castore.proto",
|
||||
"castore/protos/rpc_blobstore.proto",
|
||||
"castore/protos/rpc_directory.proto",
|
||||
],
|
||||
// If we are in running `cargo build` manually, using `../..` works fine,
|
||||
// but in case we run inside a nix build, we need to instead point PROTO_ROOT
|
||||
// to a sparseTree containing that structure.
|
||||
&[match std::env::var_os("PROTO_ROOT") {
|
||||
Some(proto_root) => proto_root.to_str().unwrap().to_owned(),
|
||||
None => "../..".to_string(),
|
||||
None => "..".to_string(),
|
||||
}],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ syntax = "proto3";
|
|||
|
||||
package tvix.castore.v1;
|
||||
|
||||
import "tvix/castore/protos/castore.proto";
|
||||
import "castore/protos/castore.proto";
|
||||
|
||||
option go_package = "code.tvl.fyi/tvix/castore-go;castorev1";
|
||||
|
||||
|
|
|
@ -40,6 +40,3 @@ otlp = ["tvix-tracing/otlp"]
|
|||
[dev-dependencies]
|
||||
hex-literal = "0.4.1"
|
||||
rstest = "0.19.0"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
@ -13,6 +13,7 @@ bytes = "1.4.0"
|
|||
clap = { version = "4.0", features = ["derive", "env"] }
|
||||
count-write = "0.1.0"
|
||||
data-encoding = "2.6.0"
|
||||
ed25519 = "2.2.3"
|
||||
futures = "0.3.30"
|
||||
lazy_static = "1.4.0"
|
||||
nix-compat = { path = "../nix-compat", features = ["async"] }
|
||||
|
@ -82,6 +83,3 @@ xp-store-composition = ["toml"]
|
|||
# Requires the following packages in $PATH:
|
||||
# cbtemulator, google-cloud-bigtable-tool
|
||||
integration = []
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
@ -20,15 +20,15 @@ fn main() -> Result<()> {
|
|||
.extern_path(".tvix.castore.v1", "::tvix_castore::proto")
|
||||
.compile(
|
||||
&[
|
||||
"tvix/store/protos/pathinfo.proto",
|
||||
"tvix/store/protos/rpc_pathinfo.proto",
|
||||
"store/protos/pathinfo.proto",
|
||||
"store/protos/rpc_pathinfo.proto",
|
||||
],
|
||||
// If we are in running `cargo build` manually, using `../..` works fine,
|
||||
// but in case we run inside a nix build, we need to instead point PROTO_ROOT
|
||||
// to a sparseTree containing that structure.
|
||||
&[match std::env::var_os("PROTO_ROOT") {
|
||||
Some(proto_root) => proto_root.to_str().unwrap().to_owned(),
|
||||
None => "../..".to_string(),
|
||||
None => "..".to_string(),
|
||||
}],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ syntax = "proto3";
|
|||
|
||||
package tvix.store.v1;
|
||||
|
||||
import "tvix/castore/protos/castore.proto";
|
||||
import "castore/protos/castore.proto";
|
||||
|
||||
option go_package = "code.tvl.fyi/tvix/store-go;storev1";
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ syntax = "proto3";
|
|||
|
||||
package tvix.store.v1;
|
||||
|
||||
import "tvix/castore/protos/castore.proto";
|
||||
import "tvix/store/protos/pathinfo.proto";
|
||||
import "castore/protos/castore.proto";
|
||||
import "store/protos/pathinfo.proto";
|
||||
|
||||
option go_package = "code.tvl.fyi/tvix/store-go;storev1";
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ mod lru;
|
|||
mod memory;
|
||||
mod nix_http;
|
||||
mod redb;
|
||||
mod signing_wrapper;
|
||||
mod sled;
|
||||
|
||||
#[cfg(any(feature = "fuse", feature = "virtiofs"))]
|
||||
|
@ -30,6 +31,7 @@ pub use self::lru::{LruPathInfoService, LruPathInfoServiceConfig};
|
|||
pub use self::memory::{MemoryPathInfoService, MemoryPathInfoServiceConfig};
|
||||
pub use self::nix_http::{NixHTTPPathInfoService, NixHTTPPathInfoServiceConfig};
|
||||
pub use self::redb::{RedbPathInfoService, RedbPathInfoServiceConfig};
|
||||
pub use self::signing_wrapper::{KeyFileSigningPathInfoServiceConfig, SigningPathInfoService};
|
||||
pub use self::sled::{SledPathInfoService, SledPathInfoServiceConfig};
|
||||
|
||||
#[cfg(feature = "cloud")]
|
||||
|
@ -91,6 +93,7 @@ pub(crate) fn register_pathinfo_services(reg: &mut Registry) {
|
|||
reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, NixHTTPPathInfoServiceConfig>("nix");
|
||||
reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, SledPathInfoServiceConfig>("sled");
|
||||
reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, RedbPathInfoServiceConfig>("redb");
|
||||
reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, KeyFileSigningPathInfoServiceConfig>("keyfile-signing");
|
||||
#[cfg(feature = "cloud")]
|
||||
{
|
||||
reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, BigtableParameters>(
|
||||
|
|
84
tvix/store/src/pathinfoservice/signing_wrapper.rs
Normal file
84
tvix/store/src/pathinfoservice/signing_wrapper.rs
Normal file
|
@ -0,0 +1,84 @@
|
|||
use super::PathInfoService;
|
||||
use crate::proto::PathInfo;
|
||||
use futures::stream::BoxStream;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use tonic::async_trait;
|
||||
|
||||
use tvix_castore::composition::{CompositionContext, ServiceBuilder};
|
||||
|
||||
use tvix_castore::Error;
|
||||
|
||||
use nix_compat::narinfo::{parse_keypair, SigningKey};
|
||||
use nix_compat::nixbase32;
|
||||
use tracing::{instrument, warn};
|
||||
|
||||
pub struct SigningPathInfoService<T, S> {
|
||||
inner: T,
|
||||
signing_key: Arc<SigningKey<S>>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T, S> PathInfoService for SigningPathInfoService<T, S>
|
||||
where
|
||||
T: PathInfoService,
|
||||
S: ed25519::signature::Signer<ed25519::Signature> + Sync + Send,
|
||||
{
|
||||
#[instrument(level = "trace", skip_all, fields(path_info.digest = nixbase32::encode(&digest)))]
|
||||
async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error> {
|
||||
self.inner.get(digest).await
|
||||
}
|
||||
|
||||
async fn put(&self, path_info: PathInfo) -> Result<PathInfo, Error> {
|
||||
let store_path = path_info.validate().map_err(|e| {
|
||||
warn!(err=%e, "invalid PathInfo");
|
||||
Error::StorageError(e.to_string())
|
||||
})?;
|
||||
let root_node = path_info.node.clone();
|
||||
let mut nar_info = path_info
|
||||
.to_narinfo(store_path)
|
||||
.ok_or(Error::StorageError("".to_string()))?;
|
||||
nar_info.add_signature(self.signing_key.as_ref());
|
||||
let mut signed_path_info = PathInfo::from(&nar_info);
|
||||
signed_path_info.node = root_node;
|
||||
self.inner.put(signed_path_info).await
|
||||
}
|
||||
|
||||
fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> {
|
||||
self.inner.list()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct KeyFileSigningPathInfoServiceConfig {
|
||||
pub inner: String,
|
||||
pub keyfile: Box<Path>,
|
||||
}
|
||||
|
||||
impl TryFrom<url::Url> for KeyFileSigningPathInfoServiceConfig {
|
||||
type Error = Box<dyn std::error::Error + Send + Sync>;
|
||||
fn try_from(_url: url::Url) -> Result<Self, Self::Error> {
|
||||
Err(Error::StorageError(
|
||||
"Instantiating a SigningPathInfoService from a url is not supported".into(),
|
||||
)
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ServiceBuilder for KeyFileSigningPathInfoServiceConfig {
|
||||
type Output = dyn PathInfoService;
|
||||
async fn build<'a>(
|
||||
&'a self,
|
||||
_instance_name: &str,
|
||||
context: &CompositionContext,
|
||||
) -> Result<Arc<dyn PathInfoService>, Box<dyn std::error::Error + Send + Sync + 'static>> {
|
||||
let inner = context.resolve(self.inner.clone()).await?;
|
||||
let signing_key = Arc::new(
|
||||
parse_keypair(tokio::fs::read_to_string(&self.keyfile).await?.trim())
|
||||
.map_err(|e| Error::StorageError(e.to_string()))?
|
||||
.0,
|
||||
);
|
||||
Ok(Arc::new(SigningPathInfoService { inner, signing_key }))
|
||||
}
|
||||
}
|
|
@ -49,6 +49,3 @@ reqwest = [
|
|||
axum = [
|
||||
"dep:axum",
|
||||
]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
Loading…
Reference in a new issue