diff --git a/Cargo.lock b/Cargo.lock index 854b48d5b..5b53bc18b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2848,6 +2848,7 @@ dependencies = [ "openssl", "prost", "rand", + "reference-value-provider-service", "regex", "regorus", "reqwest 0.12.9", diff --git a/attestation-service/config.json b/attestation-service/config.json index fc2406d10..19951dbfb 100644 --- a/attestation-service/config.json +++ b/attestation-service/config.json @@ -2,10 +2,12 @@ "work_dir": "/var/lib/attestation-service/", "rvps_config": { "type": "BuiltIn", - "store_type": "LocalFs" + "storage": { + "type": "LocalFs" + } }, "attestation_token_broker": { "type": "Simple", "duration_min": 5 } -} \ No newline at end of file +} diff --git a/attestation-service/docs/config.md b/attestation-service/docs/config.md index 855e5710d..801bc6a6b 100644 --- a/attestation-service/docs/config.md +++ b/attestation-service/docs/config.md @@ -74,10 +74,9 @@ If `type` is set to `BuiltIn`, the following extra properties can be set | Property | Type | Description | Required | Default | |----------------|-------------------------|-----------------------------------------------------------------------|----------|----------| -| `store_type` | String | The underlying storage type of RVPS. (`LocalFs` or `LocalJson`) | No | `LocalFs`| -| `store_config` | JSON Map | The optional configurations to the underlying storage. | No | Null | +| `storage` | ReferenceValueStorageConfig | Configuration of storage for reference values (`LocalFs` or `LocalJson`) | No | `LocalFs`| -Different `store_type` will have different `store_config` items. +`ReferenceValueStorageConfig` can contain either a `LocalFs` configuration or a `LocalJson` configuration. For `LocalFs`, the following properties can be set @@ -110,8 +109,8 @@ Running with a built-in RVPS: "policy_engine": "opa", "rvps_config": { "type": "BuiltIn", - "store_type": "LocalFs", - "store_config": { + "storage": { + "type": "LocalFs" "file_path": "/var/lib/attestation-service/reference-values" } }, diff --git a/attestation-service/src/config.rs b/attestation-service/src/config.rs index 48ac206fa..7ad6dbf04 100644 --- a/attestation-service/src/config.rs +++ b/attestation-service/src/config.rs @@ -58,9 +58,10 @@ impl TryFrom<&Path> for Config { /// "work_dir": "/var/lib/attestation-service/", /// "policy_engine": "opa", /// "rvps_config": { - /// "store_type": "LocalFs", + /// "storage": { + /// "type": "LocalFs" + /// } /// "store_config": {}, - /// "remote_addr": "" /// }, /// "attestation_token_broker": { /// "type": "Ear", @@ -76,10 +77,8 @@ impl TryFrom<&Path> for Config { #[cfg(test)] mod tests { - use std::path::PathBuf; - use rstest::rstest; - use serde_json::json; + use std::path::PathBuf; use super::Config; use crate::rvps::RvpsCrateConfig; @@ -87,13 +86,13 @@ mod tests { rvps::RvpsConfig, token::{ear_broker, simple, AttestationTokenConfig}, }; + use reference_value_provider_service::storage::{local_fs, ReferenceValueStorageConfig}; #[rstest] #[case("./tests/configs/example1.json", Config { work_dir: PathBuf::from("/var/lib/attestation-service/"), rvps_config: RvpsConfig::BuiltIn(RvpsCrateConfig { - store_type: "LocalFs".into(), - store_config: json!({}), + storage: ReferenceValueStorageConfig::LocalFs(local_fs::Config::default()), }), attestation_token_broker: AttestationTokenConfig::Simple(simple::Configuration { duration_min: 5, @@ -105,8 +104,7 @@ mod tests { #[case("./tests/configs/example2.json", Config { work_dir: PathBuf::from("/var/lib/attestation-service/"), rvps_config: RvpsConfig::BuiltIn(RvpsCrateConfig { - store_type: "LocalFs".into(), - store_config: json!({}), + storage: ReferenceValueStorageConfig::LocalFs(local_fs::Config::default()), }), attestation_token_broker: AttestationTokenConfig::Simple(simple::Configuration { duration_min: 5, @@ -122,8 +120,7 @@ mod tests { #[case("./tests/configs/example3.json", Config { work_dir: PathBuf::from("/var/lib/attestation-service/"), rvps_config: RvpsConfig::BuiltIn(RvpsCrateConfig { - store_type: "LocalFs".into(), - store_config: json!({}), + storage: ReferenceValueStorageConfig::LocalFs(local_fs::Config::default()), }), attestation_token_broker: AttestationTokenConfig::Ear(ear_broker::Configuration { duration_min: 5, @@ -138,8 +135,7 @@ mod tests { #[case("./tests/configs/example4.json", Config { work_dir: PathBuf::from("/var/lib/attestation-service/"), rvps_config: RvpsConfig::BuiltIn(RvpsCrateConfig { - store_type: "LocalFs".into(), - store_config: json!({}), + storage: ReferenceValueStorageConfig::LocalFs(local_fs::Config::default()), }), attestation_token_broker: AttestationTokenConfig::Ear(ear_broker::Configuration { duration_min: 5, diff --git a/attestation-service/tests/configs/example1.json b/attestation-service/tests/configs/example1.json index da1c7a329..1c3696f8d 100644 --- a/attestation-service/tests/configs/example1.json +++ b/attestation-service/tests/configs/example1.json @@ -2,8 +2,9 @@ "work_dir": "/var/lib/attestation-service/", "rvps_config": { "type": "BuiltIn", - "store_type": "LocalFs", - "remote_addr": "" + "storage": { + "type": "LocalFs" + } }, "attestation_token_broker": { "type": "Simple", diff --git a/attestation-service/tests/configs/example2.json b/attestation-service/tests/configs/example2.json index 2000b5c78..d25a0c4f3 100644 --- a/attestation-service/tests/configs/example2.json +++ b/attestation-service/tests/configs/example2.json @@ -2,8 +2,9 @@ "work_dir": "/var/lib/attestation-service/", "rvps_config": { "type": "BuiltIn", - "store_type": "LocalFs", - "remote_addr": "" + "storage": { + "type": "LocalFs" + } }, "attestation_token_broker": { "type": "Simple", diff --git a/attestation-service/tests/configs/example3.json b/attestation-service/tests/configs/example3.json index 4ed2563df..30814e603 100644 --- a/attestation-service/tests/configs/example3.json +++ b/attestation-service/tests/configs/example3.json @@ -2,8 +2,9 @@ "work_dir": "/var/lib/attestation-service/", "rvps_config": { "type": "BuiltIn", - "store_type": "LocalFs", - "remote_addr": "" + "storage": { + "type": "LocalFs" + } }, "attestation_token_broker": { "type": "Ear", diff --git a/attestation-service/tests/configs/example4.json b/attestation-service/tests/configs/example4.json index a192969da..3770a887d 100644 --- a/attestation-service/tests/configs/example4.json +++ b/attestation-service/tests/configs/example4.json @@ -2,8 +2,9 @@ "work_dir": "/var/lib/attestation-service/", "rvps_config": { "type": "BuiltIn", - "store_type": "LocalFs", - "remote_addr": "" + "storage": { + "type": "LocalFs" + } }, "attestation_token_broker": { "type": "Ear", diff --git a/deps/verifier/src/se/README.md b/deps/verifier/src/se/README.md index 1df4d87cc..54298b672 100644 --- a/deps/verifier/src/se/README.md +++ b/deps/verifier/src/se/README.md @@ -103,17 +103,19 @@ insecure_http = true [attestation_token] insecure_key = true -[as_config] +[attestation_service] work_dir = "/opt/confidential-containers/attestation-service" policy_engine = "opa" -[as_config.attestation_token_broker] +[attestation_service.attestation_token_broker] type = "Ear" duration_min = 5 -[as_config.rvps_config] +[attestation_service.rvps_config] type = "BuiltIn" -store_type = "LocalFs" + +[attestation_service.rvps_config] +type = "LocalFs" ``` - Launch the KBS program diff --git a/docker-compose.yml b/docker-compose.yml index 7d72c7f7a..1e1b7e34a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -52,6 +52,11 @@ services: volumes: - ./kbs/data/reference-values:/opt/confidential-containers/attestation-service/reference_values:rw - ./kbs/config/rvps.json:/etc/rvps.json:rw + command: [ + "rvps", + "--address", + "0.0.0.0:50003" + ] keyprovider: image: ghcr.io/confidential-containers/coco-keyprovider:latest diff --git a/kbs/Cargo.toml b/kbs/Cargo.toml index 663dcc03a..a25994d11 100644 --- a/kbs/Cargo.toml +++ b/kbs/Cargo.toml @@ -82,9 +82,11 @@ attestation-service = { path = "../attestation-service", default-features = fals "se-verifier", ], optional = true } + [dev-dependencies] tempfile.workspace = true rstest.workspace = true +reference-value-provider-service.path = "../rvps" [build-dependencies] tonic-build = { workspace = true, optional = true } diff --git a/kbs/config/kbs-config.toml b/kbs/config/kbs-config.toml index f4f17b704..c5823fec5 100644 --- a/kbs/config/kbs-config.toml +++ b/kbs/config/kbs-config.toml @@ -15,7 +15,6 @@ duration_min = 5 [attestation_service.rvps_config] type = "BuiltIn" -store_type = "LocalFs" [policy_engine] policy_path = "/opa/confidential-containers/kbs/policy.rego" diff --git a/kbs/config/kubernetes/base/kbs-config.toml b/kbs/config/kubernetes/base/kbs-config.toml index dbad9b055..5d1b228d1 100644 --- a/kbs/config/kubernetes/base/kbs-config.toml +++ b/kbs/config/kubernetes/base/kbs-config.toml @@ -20,7 +20,6 @@ key_path = "/kbs/as-private-key.pem" [attestation_service.rvps_config] type = "BuiltIn" -store_type = "LocalFs" [admin] auth_public_key = "/kbs/kbs.pem" diff --git a/kbs/config/rvps.json b/kbs/config/rvps.json index fd0bdac3f..13e84414a 100644 --- a/kbs/config/rvps.json +++ b/kbs/config/rvps.json @@ -1,7 +1,6 @@ { - "address": "0.0.0.0:50003", - "store_type": "LocalFs", - "store_config": { - "file_path": "/opt/confidential-containers/attestation-service/reference_values" + "storage": { + "type":"LocalFs", + "file_path": "/opt/confidential-containers/attestation-service/reference_values" } -} \ No newline at end of file +} diff --git a/kbs/docs/config.md b/kbs/docs/config.md index a6b9348b8..ad9a840a7 100644 --- a/kbs/docs/config.md +++ b/kbs/docs/config.md @@ -143,10 +143,9 @@ If `type` is set to `BuiltIn`, the following extra properties can be set | Property | Type | Description | Required | Default | |----------------|-------------------------|-----------------------------------------------------------------------|----------|----------| -| `store_type` | String | The underlying storage type of RVPS. (`LocalFs` or `LocalJson`) | No | `LocalFs`| -| `store_config` | JSON Map | The optional configurations to the underlying storage. | No | Null | +| `storage` | ReferenceValueStorageConfig | Configuration of the storage for reference values (`LocalFs` or `LocalJson`) | No | `LocalFs`| -Different `store_type` will have different `store_config` items. +A `ReferenceValueStorageConfig` can either be of type `LocalFs` or `LocalJson` For `LocalFs`, the following properties can be set @@ -276,7 +275,9 @@ policy_engine = "opa" [attestation_service.rvps_config] type = "BuiltIn" - store_type = "LocalFs" + + [attestation_service.rvps_config.storage] + type = "LocalFs" [[plugins]] name = "resource" diff --git a/kbs/docs/self-signed-https.md b/kbs/docs/self-signed-https.md index 94625a0e2..494f86d77 100644 --- a/kbs/docs/self-signed-https.md +++ b/kbs/docs/self-signed-https.md @@ -88,7 +88,9 @@ policy_engine = "opa" [attestation_service.rvps_config] type = "BuiltIn" - store_type = "LocalFs" + + [attestation_service.rvps_config.storage] + type = "LocalFs" [[plugins]] name = "resource" diff --git a/kbs/src/config.rs b/kbs/src/config.rs index b42b2af10..851c7e580 100644 --- a/kbs/src/config.rs +++ b/kbs/src/config.rs @@ -124,8 +124,9 @@ mod tests { token::{simple, AttestationTokenConfig, COCO_AS_ISSUER_NAME, DEFAULT_TOKEN_DURATION}, }; + use reference_value_provider_service::storage::{local_fs, ReferenceValueStorageConfig}; + use rstest::rstest; - use serde_json::json; #[rstest] #[case("test_data/configs/coco-as-grpc-1.toml", KbsConfig { @@ -293,9 +294,10 @@ mod tests { crate::attestation::config::AttestationServiceConfig::CoCoASBuiltIn( attestation_service::config::Config { work_dir: "/opt/confidential-containers/attestation-service".into(), - rvps_config: RvpsConfig::BuiltIn(RvpsCrateConfig { - store_type: "LocalFs".into(), - store_config: json!({}), + rvps_config: RvpsConfig::BuiltIn(RvpsCrateConfig{ + storage: ReferenceValueStorageConfig::LocalFs(local_fs::Config{ + file_path: "/opt/confidential-containers/attestation-service/reference_values".into(), + }), }), attestation_token_broker: AttestationTokenConfig::Simple(simple::Configuration{ duration_min: 5, @@ -423,10 +425,7 @@ mod tests { crate::attestation::config::AttestationServiceConfig::CoCoASBuiltIn( attestation_service::config::Config { work_dir: "/opt/confidential-containers/attestation-service".into(), - rvps_config: RvpsConfig::BuiltIn(RvpsCrateConfig { - store_type: "LocalFs".into(), - ..Default::default() - }), + rvps_config: RvpsConfig::BuiltIn(RvpsCrateConfig::default()), attestation_token_broker: AttestationTokenConfig::Simple(simple::Configuration { duration_min: 5, policy_dir: "/opt/confidential-containers/attestation-service/simple-policies".into(), diff --git a/kbs/test/config/kbs.toml b/kbs/test/config/kbs.toml index f2f0d26dd..386d18390 100644 --- a/kbs/test/config/kbs.toml +++ b/kbs/test/config/kbs.toml @@ -22,7 +22,6 @@ cert_path = "./work/token-cert-chain.pem" [attestation_service.rvps_config] type = "BuiltIn" -store_type = "LocalFs" [policy_engine] policy_path = "./work/kbs-policy.rego" diff --git a/kbs/test_data/configs/coco-as-builtin-2.toml b/kbs/test_data/configs/coco-as-builtin-2.toml index 070b6190b..42fc5a7f5 100644 --- a/kbs/test_data/configs/coco-as-builtin-2.toml +++ b/kbs/test_data/configs/coco-as-builtin-2.toml @@ -17,7 +17,9 @@ duration_min = 5 [attestation_service.rvps_config] type = "BuiltIn" -store_type = "LocalFs" + +[attestation_service.rvps_config.storage] +type = "LocalFs" [admin] auth_public_key = "/kbs/kbs.pem" diff --git a/kbs/test_data/configs/coco-as-builtin-3.toml b/kbs/test_data/configs/coco-as-builtin-3.toml index f42049d6e..7be20d03a 100644 --- a/kbs/test_data/configs/coco-as-builtin-3.toml +++ b/kbs/test_data/configs/coco-as-builtin-3.toml @@ -16,7 +16,9 @@ policy_dir = "/opt/confidential-containers/attestation-service/simple-policies" [attestation_service.rvps_config] type = "BuiltIn" -store_type = "LocalFs" + +[attestation_service.rvps_config.storage] +type = "LocalFs" [policy_engine] policy_path = "/opa/confidential-containers/kbs/policy.rego" diff --git a/rvps/README.md b/rvps/README.md index f2fb5fb49..42d5526ee 100644 --- a/rvps/README.md +++ b/rvps/README.md @@ -77,7 +77,7 @@ cd .. && docker build -t rvps -f rvps/docker/Dockerfile . Run ```bash -docker run -d -p 50003:50003 rvps +docker run -d -p 50003:50003 rvps --address 0.0.0.0:50003 ``` ### Configuration file @@ -85,14 +85,12 @@ docker run -d -p 50003:50003 rvps RVPS can be launched with a specified configuration file by `-c` flag. A configuration file looks lile ```json { - "address": "0.0.0.0:50003", - "store_type": "LocalFs", - "store_config": { + "storage": { + "type": "LocalFs", "file_path": "/opt/confidential-containers/attestation-service/reference_values" } } ``` -- `address`: socket listening to requests. - `store_type`: backend storage type to store reference values. Currently `LocalFs` and `LocalJson` are supported. - `store_config`: optional extra parameters for different kinds of `store_type`. This is also a JSON map object. The concrete content is different due to different `store_type`. @@ -126,7 +124,7 @@ A client tool helps to perform as a client to rvps. It can Run RVPS in docker or the following commands ```bash RVPS_ADDR=127.0.0.1:50003 -rvps --socket $RVPS_ADDR +rvps --address $RVPS_ADDR ``` Edit an test message in [sample format](./src/extractors/extractor_modules/sample/README.md) diff --git a/rvps/src/bin/rvps.rs b/rvps/src/bin/rvps.rs index 819db98b4..b701193f3 100644 --- a/rvps/src/bin/rvps.rs +++ b/rvps/src/bin/rvps.rs @@ -1,18 +1,20 @@ use anyhow::{Context, Result}; use clap::Parser; use log::{info, warn}; -use server::config::Config; use shadow_rs::shadow; pub mod rvps_api { tonic::include_proto!("reference"); } +use reference_value_provider_service::config::Config; + shadow!(build); mod server; const DEFAULT_CONFIG_PATH: &str = "/etc/rvps.json"; +const DEFAULT_ADDRESS: &str = "127.0.0.1:50003"; /// RVPS command-line arguments. #[derive(Debug, Parser)] @@ -23,6 +25,13 @@ pub struct Cli { /// `--config /etc/rvps.toml` #[arg(short = 'c', long, default_value = DEFAULT_CONFIG_PATH)] pub config: String, + + /// The address that the RVPS server will listen on. + /// The default is 127.0.0.1:50003 + /// + /// `--address 127.0.0.1:55554` + #[arg(short = 'a', long, default_value = DEFAULT_ADDRESS)] + pub address: String, } #[tokio::main] @@ -47,9 +56,9 @@ async fn main() -> Result<()> { Config::default() }); - info!("Listen socket: {}", config.address); + info!("Listen socket: {}", &cli.address); - let socket = config.address.parse().context("parse socket addr failed")?; + let socket = cli.address.parse().context("parse socket addr failed")?; - server::start(socket, config.into()).await + server::start(socket, config).await } diff --git a/rvps/src/bin/server/config.rs b/rvps/src/bin/server/config.rs deleted file mode 100644 index 303853171..000000000 --- a/rvps/src/bin/server/config.rs +++ /dev/null @@ -1,43 +0,0 @@ -use anyhow::{Context, Result}; -use reference_value_provider_service::{config::DEFAULT_STORAGE_TYPE, Config as CrateConfig}; -use serde::Deserialize; -use serde_json::{json, Value}; - -const DEFAULT_ADDR: &str = "127.0.0.1:50003"; - -#[derive(Deserialize, Clone, Debug)] -pub struct Config { - pub address: String, - pub store_type: String, - pub store_config: Value, -} - -impl From for CrateConfig { - fn from(val: Config) -> CrateConfig { - CrateConfig { - store_type: val.store_type, - store_config: val.store_config, - } - } -} - -impl Default for Config { - fn default() -> Self { - Self { - store_type: DEFAULT_STORAGE_TYPE.to_string(), - store_config: json!({}), - address: DEFAULT_ADDR.to_string(), - } - } -} - -impl Config { - pub fn from_file(config_path: &str) -> Result { - let c = config::Config::builder() - .add_source(config::File::with_name(config_path)) - .build()?; - - let res = c.try_deserialize().context("invalid config")?; - Ok(res) - } -} diff --git a/rvps/src/bin/server/mod.rs b/rvps/src/bin/server/mod.rs index 94473876e..3afd34166 100644 --- a/rvps/src/bin/server/mod.rs +++ b/rvps/src/bin/server/mod.rs @@ -15,8 +15,6 @@ use crate::rvps_api::{ ReferenceValueRegisterResponse, }; -pub mod config; - pub struct RVPSServer { rvps: Arc>, } diff --git a/rvps/src/config.rs b/rvps/src/config.rs index 98bf34f58..2555ff33c 100644 --- a/rvps/src/config.rs +++ b/rvps/src/config.rs @@ -2,34 +2,24 @@ // // SPDX-License-Identifier: Apache-2.0 // - +use anyhow::{Context, Result}; use serde::Deserialize; -use serde_json::{json, Value}; -pub const DEFAULT_STORAGE_TYPE: &str = "LocalFs"; +use crate::storage::ReferenceValueStorageConfig; -#[derive(Deserialize, Clone, Debug, PartialEq)] +#[derive(Deserialize, Clone, Debug, PartialEq, Default)] pub struct Config { - #[serde(default = "default_store_type")] - pub store_type: String, - - #[serde(default = "default_store_config")] - pub store_config: Value, + #[serde(default)] + pub storage: ReferenceValueStorageConfig, } -fn default_store_type() -> String { - DEFAULT_STORAGE_TYPE.to_string() -} - -fn default_store_config() -> Value { - json!({}) -} +impl Config { + pub fn from_file(config_path: &str) -> Result { + let c = config::Config::builder() + .add_source(config::File::with_name(config_path)) + .build()?; -impl Default for Config { - fn default() -> Self { - Self { - store_type: default_store_type(), - store_config: json!({}), - } + let res = c.try_deserialize().context("invalid config")?; + Ok(res) } } diff --git a/rvps/src/lib.rs b/rvps/src/lib.rs index d12667b04..80f13a52b 100644 --- a/rvps/src/lib.rs +++ b/rvps/src/lib.rs @@ -7,7 +7,7 @@ pub mod config; pub mod extractors; pub mod pre_processor; pub mod reference_value; -pub mod store; +pub mod storage; pub use config::Config; @@ -17,7 +17,7 @@ pub use native::Core; use serde::{Deserialize, Serialize}; pub use reference_value::{ReferenceValue, TrustedDigest}; -pub use store::Store; +pub use storage::ReferenceValueStorage; /// Default version of Message static MESSAGE_VERSION: &str = "0.1.0"; diff --git a/rvps/src/native.rs b/rvps/src/native.rs index 30298e64d..391809931 100644 --- a/rvps/src/native.rs +++ b/rvps/src/native.rs @@ -7,35 +7,31 @@ use anyhow::{bail, Context, Result}; use log::{info, warn}; use std::collections::HashMap; -use crate::{store::StoreType, Config}; - use super::{ + config::Config, extractors::{Extractors, ExtractorsImpl}, pre_processor::{PreProcessor, PreProcessorAPI}, - Message, Store, MESSAGE_VERSION, + Message, ReferenceValueStorage, MESSAGE_VERSION, }; /// The core of the RVPS, s.t. componants except communication componants. pub struct Core { pre_processor: PreProcessor, extractors: ExtractorsImpl, - store: Box, + storage: Box, } impl Core { /// Instantiate a new RVPS Core pub fn new(config: Config) -> Result { let pre_processor = PreProcessor::default(); - let extractors = ExtractorsImpl::default(); - - let store_type = StoreType::try_from(&config.store_type[..])?; - let store = store_type.to_store(config.store_config)?; + let storage = config.storage.to_storage()?; Ok(Core { pre_processor, extractors, - store, + storage, }) } @@ -61,7 +57,7 @@ impl Core { let rv = self.extractors.process(message)?; for v in rv.iter() { - let old = self.store.set(v.name().to_string(), v.clone()).await?; + let old = self.storage.set(v.name().to_string(), v.clone()).await?; if let Some(old) = old { info!("Old Reference value of {} is replaced.", old.name()); } @@ -72,7 +68,7 @@ impl Core { pub async fn get_digests(&self) -> Result>> { let mut rv_map = HashMap::new(); - let reference_values = self.store.get_values().await?; + let reference_values = self.storage.get_values().await?; for rv in reference_values { if rv.expired() { diff --git a/rvps/src/store/local_fs/README.md b/rvps/src/storage/local_fs/README.md similarity index 100% rename from rvps/src/store/local_fs/README.md rename to rvps/src/storage/local_fs/README.md diff --git a/rvps/src/store/local_fs/mod.rs b/rvps/src/storage/local_fs/mod.rs similarity index 80% rename from rvps/src/store/local_fs/mod.rs rename to rvps/src/storage/local_fs/mod.rs index 19130c67b..d801dad3f 100644 --- a/rvps/src/store/local_fs/mod.rs +++ b/rvps/src/storage/local_fs/mod.rs @@ -8,17 +8,16 @@ use anyhow::*; use async_trait::async_trait; use serde::Deserialize; -use serde_json::Value; use crate::ReferenceValue; -use super::Store; +use super::ReferenceValueStorage; /// Local directory path to store the reference values, /// which is created by sled engine. const FILE_PATH: &str = "/opt/confidential-containers/attestation-service/reference_values"; -/// `LocalFs` implements [`Store`] trait. And +/// `LocalFs` implements [`ReferenceValueStorage`] trait. And /// it uses rocksdb inside. pub struct LocalFs { engine: sled::Db, @@ -28,23 +27,30 @@ fn default_file_path() -> String { FILE_PATH.to_string() } -#[derive(Deserialize, Default)] -struct Config { +#[derive(Clone, Debug, Deserialize, PartialEq)] +pub struct Config { #[serde(default = "default_file_path")] - file_path: String, + pub file_path: String, +} + +impl Default for Config { + fn default() -> Self { + Self { + file_path: default_file_path(), + } + } } impl LocalFs { /// Create a new [`LocalFs`] with given config - pub fn new(config: Value) -> Result { - let config: Config = serde_json::from_value(config)?; + pub fn new(config: Config) -> Result { let engine = sled::open(config.file_path)?; Ok(Self { engine }) } } #[async_trait] -impl Store for LocalFs { +impl ReferenceValueStorage for LocalFs { async fn set(&self, name: String, rv: ReferenceValue) -> Result> { let rv_serde = serde_json::to_vec(&rv)?; let res = match self @@ -86,12 +92,11 @@ impl Store for LocalFs { #[cfg(test)] mod tests { - use serde_json::json; use serial_test::serial; - use crate::{ReferenceValue, Store}; + use crate::{ReferenceValue, ReferenceValueStorage}; - use super::LocalFs; + use super::{Config, LocalFs}; const KEY: &str = "test1"; @@ -103,13 +108,11 @@ mod tests { let temp_dir = tempfile::tempdir().expect("create tempdir failed"); let dir_str = temp_dir.path().to_string_lossy().to_string(); { - let store = LocalFs::new(json!({ - "file_path": dir_str - })) - .expect("create local fs store failed."); + let storage = + LocalFs::new(Config { file_path: dir_str }).expect("create local fs store failed."); let rv = ReferenceValue::new().expect("create ReferenceValue failed."); assert!( - store + storage .set(KEY.to_owned(), rv.clone()) .await .expect("set rv failed.") @@ -117,7 +120,7 @@ mod tests { "the storage has previous key of {}", KEY ); - let got = store + let got = storage .get(KEY) .await .expect("get rv failed.") @@ -134,10 +137,8 @@ mod tests { let temp_dir = tempfile::tempdir().expect("create tempdir failed"); let dir_str = temp_dir.path().to_string_lossy().to_string(); { - let store = LocalFs::new(json!({ - "file_path": dir_str - })) - .expect("create local fs store failed."); + let storage = + LocalFs::new(Config { file_path: dir_str }).expect("create local fs store failed."); let rv_old = ReferenceValue::new() .expect("create ReferenceValue failed.") .set_name("old"); @@ -147,7 +148,7 @@ mod tests { .set_name("new"); assert!( - store + storage .set(KEY.to_owned(), rv_old.clone()) .await .expect("set rv failed.") @@ -156,7 +157,7 @@ mod tests { KEY ); - let got = store + let got = storage .set(KEY.to_owned(), rv_new) .await .expect("get rv failed.") @@ -175,21 +176,19 @@ mod tests { let temp_dir = tempfile::tempdir().expect("create tempdir failed"); let dir_str = temp_dir.path().to_string_lossy().to_string(); { - let store = LocalFs::new(json!({ - "file_path": dir_str - })) + let storage = LocalFs::new(Config { + file_path: dir_str.clone(), + }) .expect("create local fs store failed."); - store + storage .set(KEY.to_owned(), rv.clone()) .await .expect("set rv failed."); } { - let store = LocalFs::new(json!({ - "file_path": dir_str - })) - .expect("create local fs store failed."); - let got = store + let storage = + LocalFs::new(Config { file_path: dir_str }).expect("create local fs store failed."); + let got = storage .get(KEY) .await .expect("get rv failed.") diff --git a/rvps/src/store/local_json/mod.rs b/rvps/src/storage/local_json/mod.rs similarity index 86% rename from rvps/src/store/local_json/mod.rs rename to rvps/src/storage/local_json/mod.rs index b08bbeb0c..e0cb828fd 100644 --- a/rvps/src/store/local_json/mod.rs +++ b/rvps/src/storage/local_json/mod.rs @@ -1,12 +1,11 @@ use std::{fs, path::PathBuf}; -use super::Store; +use super::ReferenceValueStorage; use crate::ReferenceValue; use anyhow::{anyhow, Result}; use async_trait::async_trait; use log::debug; use serde::Deserialize; -use serde_json::Value; use tokio::sync::RwLock; const FILE_PATH: &str = "/opt/confidential-containers/attestation-service/reference_values.json"; @@ -20,16 +19,22 @@ fn default_file_path() -> String { FILE_PATH.to_string() } -#[derive(Deserialize, Default)] -struct Config { +#[derive(Clone, Debug, Deserialize, PartialEq)] +pub struct Config { #[serde(default = "default_file_path")] - file_path: String, + pub file_path: String, } -impl LocalJson { - pub fn new(config: Value) -> Result { - let config: Config = serde_json::from_value(config)?; +impl Default for Config { + fn default() -> Self { + Self { + file_path: default_file_path(), + } + } +} +impl LocalJson { + pub fn new(config: Config) -> Result { let mut path = PathBuf::new(); path.push(&config.file_path); @@ -46,7 +51,7 @@ impl LocalJson { } #[async_trait] -impl Store for LocalJson { +impl ReferenceValueStorage for LocalJson { async fn set(&self, name: String, rv: ReferenceValue) -> Result> { let _ = self.lock.write().await; let file = tokio::fs::read(&self.file_path).await?; diff --git a/rvps/src/store/mod.rs b/rvps/src/storage/mod.rs similarity index 50% rename from rvps/src/store/mod.rs rename to rvps/src/storage/mod.rs index 0fd951efd..236fcf2d5 100644 --- a/rvps/src/store/mod.rs +++ b/rvps/src/storage/mod.rs @@ -8,8 +8,7 @@ use anyhow::Result; use async_trait::async_trait; use serde::Deserialize; -use serde_json::Value; -use strum::EnumString; +use strum::Display; use self::local_fs::LocalFs; use self::local_json::LocalJson; @@ -19,29 +18,36 @@ use super::ReferenceValue; pub mod local_fs; pub mod local_json; -#[derive(Deserialize, Debug, Clone, EnumString)] -pub enum StoreType { - LocalFs, - LocalJson, +#[derive(Clone, Debug, Deserialize, Display, PartialEq)] +#[serde(tag = "type")] +pub enum ReferenceValueStorageConfig { + LocalFs(local_fs::Config), + LocalJson(local_json::Config), } -impl StoreType { - pub fn to_store(&self, config: Value) -> Result> { +impl Default for ReferenceValueStorageConfig { + fn default() -> Self { + ReferenceValueStorageConfig::LocalFs(local_fs::Config::default()) + } +} + +impl ReferenceValueStorageConfig { + pub fn to_storage(&self) -> Result> { match self { - StoreType::LocalFs => { - Ok(Box::new(LocalFs::new(config)?) as Box) - } - StoreType::LocalJson => { - Ok(Box::new(LocalJson::new(config)?) as Box) + ReferenceValueStorageConfig::LocalFs(cfg) => Ok(Box::new(LocalFs::new(cfg.clone())?) + as Box), + ReferenceValueStorageConfig::LocalJson(cfg) => { + Ok(Box::new(LocalJson::new(cfg.clone())?) + as Box) } } } } -/// Interface of a `Store`. +/// Interface for `ReferenceValueStorage`. /// Reference value storage facilities should implement this trait. #[async_trait] -pub trait Store { +pub trait ReferenceValueStorage { /// Store a reference value. If the given `name` exists, /// return the previous `Some`, otherwise return `None` async fn set(&self, name: String, rv: ReferenceValue) -> Result>;