Skip to content

Commit

Permalink
Merge pull request #290 from umccr/fix/deny-unknown-fields
Browse files Browse the repository at this point in the history
feat: deny unknown fields in config
  • Loading branch information
mmalenic authored Jan 6, 2025
2 parents 27ddce2 + f553d30 commit a5af714
Show file tree
Hide file tree
Showing 20 changed files with 40 additions and 25 deletions.
4 changes: 2 additions & 2 deletions htsget-config/src/config/advanced/allow_guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub trait QueryAllowed {

/// A query guard represents query parameters that can be allowed to storage for a given query.
#[derive(Serialize, Clone, Debug, Deserialize, PartialEq, Eq)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct AllowGuard {
allow_reference_names: ReferenceNames,
allow_fields: Fields,
Expand All @@ -39,7 +39,7 @@ impl Default for AllowGuard {

/// Reference names that can be matched.
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(untagged)]
#[serde(untagged, deny_unknown_fields)]
pub enum ReferenceNames {
Tagged(TaggedTypeAll),
List(HashSet<String>),
Expand Down
5 changes: 3 additions & 2 deletions htsget-config/src/config/advanced/cors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const CORS_MAX_AGE: usize = 2592000;

/// Tagged allow headers for cors config, either Mirror or Any.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub enum TaggedAllowTypes {
#[serde(alias = "mirror", alias = "MIRROR")]
Mirror,
Expand All @@ -27,7 +28,7 @@ pub enum TaggedAllowTypes {

/// Allowed type for cors config which is used to configure cors behaviour.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(untagged)]
#[serde(untagged, deny_unknown_fields)]
pub enum AllowType<T, Tagged = TaggedAllowTypes> {
Tagged(Tagged),
#[serde(bound(serialize = "T: Display", deserialize = "T: FromStr, T::Err: Display"))]
Expand Down Expand Up @@ -159,7 +160,7 @@ impl Display for HeaderValue {

/// Cors configuration for the htsget server.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct CorsConfig {
allow_credentials: bool,
allow_origins: AllowType<HeaderValue>,
Expand Down
1 change: 1 addition & 0 deletions htsget-config/src/config/advanced/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod url;

/// Determines which tracing formatting style to use.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, Default)]
#[serde(deny_unknown_fields)]
pub enum FormattingStyle {
#[default]
Full,
Expand Down
2 changes: 1 addition & 1 deletion htsget-config/src/config/advanced/regex_location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};

/// A regex storage is a storage that matches ids using Regex.
#[derive(Serialize, Debug, Clone, Deserialize)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct RegexLocation {
#[serde(with = "serde_regex")]
regex: Regex,
Expand Down
1 change: 1 addition & 0 deletions htsget-config/src/config/advanced/url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use serde::{Deserialize, Serialize};

/// Options for the remote URL server config.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct Url {
#[serde(with = "http_serde::uri")]
url: Uri,
Expand Down
5 changes: 3 additions & 2 deletions htsget-config/src/config/data_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ use std::path::{Path, PathBuf};

/// Tagged allow headers for cors config, either Mirror or Any.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub enum DataServerTagged {
#[serde(alias = "none", alias = "NONE", alias = "null")]
None,
}

/// Whether the data server is enabled or not.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
#[serde(untagged, deny_unknown_fields)]
#[allow(clippy::large_enum_variant)]
pub enum DataServerEnabled {
None(DataServerTagged),
Expand All @@ -38,7 +39,7 @@ impl DataServerEnabled {

/// Configuration for the htsget server.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct DataServerConfig {
addr: SocketAddr,
local_path: PathBuf,
Expand Down
4 changes: 2 additions & 2 deletions htsget-config/src/config/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use {crate::config::advanced::url::Url, crate::error, http::Uri};

/// The locations of data.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(default, from = "LocationsOneOrMany")]
#[serde(default, deny_unknown_fields, from = "LocationsOneOrMany")]
pub struct Locations(Vec<LocationEither>);

impl Locations {
Expand Down Expand Up @@ -48,7 +48,7 @@ impl Default for Locations {

/// Either simple or regex based location
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
#[serde(untagged, deny_unknown_fields)]
pub enum LocationEither {
Simple(Location),
Regex(RegexLocation),
Expand Down
2 changes: 1 addition & 1 deletion htsget-config/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ struct Args {

/// Simplified config.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct Config {
ticket_server: TicketServerConfig,
data_server: DataServerEnabled,
Expand Down
2 changes: 1 addition & 1 deletion htsget-config/src/config/service_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::collections::HashMap;

/// Service info config.
#[derive(Serialize, Debug, Clone, Default, PartialEq, Eq)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct ServiceInfo(HashMap<String, Value>);

impl ServiceInfo {
Expand Down
2 changes: 1 addition & 1 deletion htsget-config/src/config/ticket_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::net::SocketAddr;

/// Configuration for the htsget ticket server.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct TicketServerConfig {
addr: SocketAddr,
#[serde(skip_serializing)]
Expand Down
1 change: 1 addition & 0 deletions htsget-config/src/storage/c4gh/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::path::PathBuf;

/// Local C4GH key storage.
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct C4GHLocal {
private: PathBuf,
public: PathBuf,
Expand Down
4 changes: 2 additions & 2 deletions htsget-config/src/storage/c4gh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub mod secrets_manager;

/// Config for Crypt4GH keys.
#[derive(Deserialize, Debug, Clone)]
#[serde(try_from = "C4GHKeyLocation")]
#[serde(try_from = "C4GHKeyLocation", deny_unknown_fields)]
pub struct C4GHKeys {
// Store a cloneable future so that it can be resolved outside serde.
keys: Shared<BoxFuture<'static, Result<Vec<crypt4gh::Keys>>>>,
Expand Down Expand Up @@ -74,7 +74,7 @@ impl TryFrom<C4GHKeyLocation> for C4GHKeys {

/// The location of C4GH keys.
#[derive(Deserialize, Debug, Clone)]
#[serde(tag = "kind")]
#[serde(tag = "kind", deny_unknown_fields)]
#[non_exhaustive]
pub enum C4GHKeyLocation {
#[serde(alias = "file", alias = "FILE")]
Expand Down
1 change: 1 addition & 0 deletions htsget-config/src/storage/c4gh/secrets_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use tempfile::TempDir;

/// C4GH secrets manager key storage.
#[derive(Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)]
pub struct C4GHSecretsManager {
private: String,
public: String,
Expand Down
2 changes: 1 addition & 1 deletion htsget-config/src/storage/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::str::FromStr;

/// Local file based storage.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct File {
scheme: Scheme,
#[serde(with = "http_serde::authority")]
Expand Down
2 changes: 1 addition & 1 deletion htsget-config/src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl ResolvedId {

/// Specify the storage backend to use as config values.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "kind")]
#[serde(tag = "kind", deny_unknown_fields)]
#[non_exhaustive]
pub enum Backend {
#[serde(alias = "file", alias = "FILE")]
Expand Down
2 changes: 1 addition & 1 deletion htsget-config/src/storage/s3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};

/// Configuration struct for S3 storage.
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct S3 {
bucket: String,
endpoint: Option<String>,
Expand Down
2 changes: 1 addition & 1 deletion htsget-config/src/storage/url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};

/// Remote URL server storage struct.
#[derive(Deserialize, Serialize, Debug, Clone)]
#[serde(try_from = "advanced::url::Url")]
#[serde(try_from = "advanced::url::Url", deny_unknown_fields)]
pub struct Url {
#[serde(with = "http_serde::uri")]
url: Uri,
Expand Down
2 changes: 1 addition & 1 deletion htsget-config/src/tls/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use serde::Deserialize;
/// A certificate and key pair used for TLS. Serialization is not implemented because there
/// is no way to convert back to a `PathBuf`.
#[derive(Deserialize, Debug, Clone, Default)]
#[serde(try_from = "RootCertStorePair")]
#[serde(try_from = "RootCertStorePair", deny_unknown_fields)]
pub struct TlsClientConfig {
cert: Option<Vec<Certificate>>,
identity: Option<Identity>,
Expand Down
4 changes: 3 additions & 1 deletion htsget-config/src/tls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub trait KeyPairScheme {
/// A certificate and key pair used for TLS. Serialization is not implemented because there
/// is no way to convert back to a `PathBuf`.
#[derive(Deserialize, Debug, Clone)]
#[serde(try_from = "CertificateKeyPairPath")]
#[serde(try_from = "CertificateKeyPairPath", deny_unknown_fields)]
pub struct TlsServerConfig {
server_config: ServerConfig,
}
Expand All @@ -49,6 +49,7 @@ impl TlsServerConfig {
/// The location of a certificate and key pair used for TLS.
/// This is the path to the PEM formatted X.509 certificate and private key.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct CertificateKeyPairPath {
cert: PathBuf,
key: PathBuf,
Expand Down Expand Up @@ -76,6 +77,7 @@ impl CertificateKeyPair {
/// The location of a certificate and key pair used for TLS.
/// This is the path to the PEM formatted X.509 certificate and private key.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct RootCertStorePair {
#[serde(flatten)]
key_pair: Option<CertificateKeyPairPath>,
Expand Down
17 changes: 12 additions & 5 deletions htsget-config/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub type Result<T> = result::Result<T, HtsGetError>;

/// An enumeration with all the possible formats.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all(serialize = "UPPERCASE"))]
#[serde(rename_all(serialize = "UPPERCASE"), deny_unknown_fields)]
pub enum Format {
#[serde(alias = "bam", alias = "BAM")]
Bam,
Expand Down Expand Up @@ -112,7 +112,7 @@ impl Display for Format {

/// Class component of htsget response.
#[derive(Copy, Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
#[serde(rename_all(serialize = "lowercase"))]
#[serde(rename_all(serialize = "lowercase"), deny_unknown_fields)]
pub enum Class {
#[serde(alias = "header", alias = "HEADER")]
Header,
Expand All @@ -123,6 +123,7 @@ pub enum Class {
/// An interval represents the start (0-based, inclusive) and end (0-based exclusive) ranges of the
/// query.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Interval {
start: Option<u32>,
end: Option<u32>,
Expand Down Expand Up @@ -205,7 +206,7 @@ impl Interval {

/// Schemes that can be used with htsget.
#[derive(Serialize, Deserialize, Debug, Default, Clone, Copy, PartialEq, Eq)]
#[serde(rename_all = "UPPERCASE")]
#[serde(rename_all = "UPPERCASE", deny_unknown_fields)]
pub enum Scheme {
#[default]
#[serde(alias = "Http", alias = "http")]
Expand All @@ -225,14 +226,15 @@ impl Display for Scheme {

/// Tagged Any allow type for cors config.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub enum TaggedTypeAll {
#[serde(alias = "all", alias = "ALL")]
All,
}

/// Possible values for the fields parameter.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(untagged)]
#[serde(untagged, deny_unknown_fields)]
pub enum Fields {
/// Include all fields
Tagged(TaggedTypeAll),
Expand All @@ -242,7 +244,7 @@ pub enum Fields {

/// Possible values for the tags parameter.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(untagged)]
#[serde(untagged, deny_unknown_fields)]
pub enum Tags {
/// Include all tags
Tagged(TaggedTypeAll),
Expand All @@ -252,6 +254,7 @@ pub enum Tags {

/// The no tags parameter.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct NoTags(pub Option<HashSet<String>>);

/// A struct containing the information from the HTTP request.
Expand Down Expand Up @@ -516,6 +519,7 @@ impl From<io::Error> for HtsGetError {

/// The headers that need to be supplied when requesting data from a url.
#[derive(Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Headers(HashMap<String, String>);

impl Headers {
Expand Down Expand Up @@ -585,6 +589,7 @@ impl TryFrom<&HeaderMap> for Headers {

/// A url from which raw data can be retrieved.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Url {
pub url: String,
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down Expand Up @@ -635,6 +640,7 @@ impl Url {

/// Wrapped json response for htsget.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct JsonResponse {
pub htsget: Response,
}
Expand All @@ -654,6 +660,7 @@ impl From<Response> for JsonResponse {

/// The response for a HtsGet query.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Response {
pub format: Format,
pub urls: Vec<Url>,
Expand Down

0 comments on commit a5af714

Please sign in to comment.