From ad136e757d4a1e86089bf1b2fb98bde4f20a3a28 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Fri, 16 Jul 2021 11:19:03 +0200 Subject: [PATCH] initial config schema --- Cargo.lock | 44 +++++++++++++++++++ matrix-authentication-service/Cargo.toml | 1 + .../src/config/csrf.rs | 19 ++++++-- .../src/config/database.rs | 13 +++--- .../src/config/http.rs | 11 ++--- .../src/config/mod.rs | 15 ++++--- .../src/config/oauth2.rs | 15 ++++--- .../src/config/session.rs | 14 ++++-- 8 files changed, 100 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 95cdb57d8..10d2e864f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -908,6 +908,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" +[[package]] +name = "dyn-clone" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" + [[package]] name = "either" version = "1.6.1" @@ -1496,6 +1502,7 @@ dependencies = [ "figment", "mime", "oauth2-types", + "schemars", "serde", "serde_with", "sqlx", @@ -2059,6 +2066,32 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schemars" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6ab463ae35acccb5cba66c0084c985257b797d288b6050cc2f6ac1b266cb78" +dependencies = [ + "chrono", + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", + "url", +] + +[[package]] +name = "schemars_derive" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "902fdfbcf871ae8f653bddf4b2c05905ddaabc08f69d32a915787e3be0d31356" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -2110,6 +2143,17 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_derive_internals" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serde_json" version = "1.0.64" diff --git a/matrix-authentication-service/Cargo.toml b/matrix-authentication-service/Cargo.toml index c5f58d891..985ec474e 100644 --- a/matrix-authentication-service/Cargo.toml +++ b/matrix-authentication-service/Cargo.toml @@ -25,3 +25,4 @@ tide-tracing = "0.0.11" mime = "0.3.16" sqlx = { version = "0.5.5", features = ["runtime-async-std-rustls", "postgres", "migrate", "chrono"] } serde_with = { version = "1.9.4", features = ["hex", "chrono"] } +schemars = { version = "0.8.3", features = ["url", "chrono"] } diff --git a/matrix-authentication-service/src/config/csrf.rs b/matrix-authentication-service/src/config/csrf.rs index 479365a41..c0548c081 100644 --- a/matrix-authentication-service/src/config/csrf.rs +++ b/matrix-authentication-service/src/config/csrf.rs @@ -15,7 +15,8 @@ use std::time::Duration; use csrf::{AesGcmCsrfProtection, CsrfProtection}; -use serde::Deserialize; +use schemars::{gen::SchemaGenerator, schema::Schema, JsonSchema}; +use serde::{Deserialize, Serialize}; use serde_with::serde_as; use tide::Middleware; @@ -29,21 +30,31 @@ fn default_cookie_name() -> String { "csrf".to_string() } +fn key_schema(gen: &mut SchemaGenerator) -> Schema { + String::json_schema(gen) +} + +fn ttl_schema(gen: &mut SchemaGenerator) -> Schema { + u64::json_schema(gen) +} + #[serde_as] -#[derive(Debug, Clone, Deserialize)] -pub struct Config { +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +pub struct CsrfConfig { + #[schemars(schema_with = "key_schema")] #[serde_as(as = "serde_with::hex::Hex")] key: [u8; 32], #[serde(default = "default_cookie_name")] cookie_name: String, + #[schemars(schema_with = "ttl_schema")] #[serde(default = "default_ttl")] #[serde_as(as = "serde_with::DurationSeconds")] ttl: Duration, } -impl Config { +impl CsrfConfig { pub fn into_protection(self) -> impl CsrfProtection { AesGcmCsrfProtection::from_key(self.key) } diff --git a/matrix-authentication-service/src/config/database.rs b/matrix-authentication-service/src/config/database.rs index 493242a06..e39f958cb 100644 --- a/matrix-authentication-service/src/config/database.rs +++ b/matrix-authentication-service/src/config/database.rs @@ -14,7 +14,9 @@ use std::time::Duration; -use serde::Deserialize; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use serde_with::skip_serializing_none; use sqlx::postgres::{PgPool, PgPoolOptions}; fn default_uri() -> String { @@ -39,7 +41,7 @@ fn default_max_lifetime() -> Option { Some(Duration::from_secs(30 * 60)) } -impl Default for Config { +impl Default for DatabaseConfig { fn default() -> Self { Self { uri: default_uri(), @@ -52,8 +54,9 @@ impl Default for Config { } } -#[derive(Debug, Deserialize)] -pub struct Config { +#[skip_serializing_none] +#[derive(Debug, Serialize, Deserialize, JsonSchema)] +pub struct DatabaseConfig { #[serde(default = "default_uri")] uri: String, @@ -73,7 +76,7 @@ pub struct Config { max_lifetime: Option, } -impl Config { +impl DatabaseConfig { #[tracing::instrument(err)] pub async fn connect(&self) -> Result { PgPoolOptions::new() diff --git a/matrix-authentication-service/src/config/http.rs b/matrix-authentication-service/src/config/http.rs index 5a4825592..19ce581c5 100644 --- a/matrix-authentication-service/src/config/http.rs +++ b/matrix-authentication-service/src/config/http.rs @@ -12,21 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -use serde::Deserialize; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; fn default_http_address() -> String { "[::]:8080".into() } -#[derive(Debug, Deserialize)] -pub struct Config { +#[derive(Debug, Serialize, Deserialize, JsonSchema)] +pub struct HttpConfig { #[serde(default = "default_http_address")] pub address: String, } -impl Default for Config { +impl Default for HttpConfig { fn default() -> Self { - Config { + Self { address: default_http_address(), } } diff --git a/matrix-authentication-service/src/config/mod.rs b/matrix-authentication-service/src/config/mod.rs index 83742fd23..9203f10eb 100644 --- a/matrix-authentication-service/src/config/mod.rs +++ b/matrix-authentication-service/src/config/mod.rs @@ -17,7 +17,8 @@ use figment::{ providers::{Env, Format, Yaml}, Figment, }; -use serde::Deserialize; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; mod csrf; mod database; @@ -26,14 +27,14 @@ mod oauth2; mod session; pub use self::{ - csrf::Config as CsrfConfig, - database::Config as DatabaseConfig, - http::Config as HttpConfig, - oauth2::{ClientConfig as OAuth2ClientConfig, Config as OAuth2Config}, - session::Config as SessionConfig, + csrf::CsrfConfig, + database::DatabaseConfig, + http::HttpConfig, + oauth2::{OAuth2ClientConfig, OAuth2Config}, + session::SessionConfig, }; -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct RootConfig { #[serde(default)] pub oauth2: OAuth2Config, diff --git a/matrix-authentication-service/src/config/oauth2.rs b/matrix-authentication-service/src/config/oauth2.rs index 2e78e756b..af4384870 100644 --- a/matrix-authentication-service/src/config/oauth2.rs +++ b/matrix-authentication-service/src/config/oauth2.rs @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use serde::Deserialize; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Debug, Deserialize)] -pub struct ClientConfig { +#[derive(Debug, Serialize, Deserialize, JsonSchema)] +pub struct OAuth2ClientConfig { pub client_id: String, #[serde(default)] @@ -27,16 +28,16 @@ fn default_oauth2_issuer() -> Url { "http://[::]:8080".parse().unwrap() } -#[derive(Debug, Deserialize)] -pub struct Config { +#[derive(Debug, Serialize, Deserialize, JsonSchema)] +pub struct OAuth2Config { #[serde(default = "default_oauth2_issuer")] pub issuer: Url, #[serde(default)] - pub clients: Vec, + pub clients: Vec, } -impl Default for Config { +impl Default for OAuth2Config { fn default() -> Self { Self { issuer: default_oauth2_issuer(), diff --git a/matrix-authentication-service/src/config/session.rs b/matrix-authentication-service/src/config/session.rs index a2ba080b8..b1caf1e89 100644 --- a/matrix-authentication-service/src/config/session.rs +++ b/matrix-authentication-service/src/config/session.rs @@ -12,21 +12,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -use serde::Deserialize; +use schemars::{gen::SchemaGenerator, schema::Schema, JsonSchema}; +use serde::{Deserialize, Serialize}; use serde_with::serde_as; use tide::{ sessions::{SessionMiddleware, SessionStore}, Middleware, }; +fn secret_schema(gen: &mut SchemaGenerator) -> Schema { + String::json_schema(gen) +} + #[serde_as] -#[derive(Debug, Deserialize)] -pub struct Config { +#[derive(Debug, Serialize, Deserialize, JsonSchema)] +pub struct SessionConfig { + #[schemars(schema_with = "secret_schema")] #[serde_as(as = "serde_with::hex::Hex")] secret: Vec, } -impl Config { +impl SessionConfig { pub fn to_middleware( &self, store: impl SessionStore,