@@ -45,6 +45,8 @@ use secrecy::{CloneableSecret, SecretBox, SerializableSecret, zeroize::Zeroize};
4545use serde:: { Deserialize , Serialize } ;
4646use tracing:: level_filters:: LevelFilter ;
4747
48+ use crate :: killswitches:: Killswitches ;
49+
4850/// Environment variable prefix for all configuration options.
4951const ENV_PREFIX : & str = "OS__" ;
5052
@@ -92,7 +94,7 @@ impl Zeroize for ConfigSecret {
9294/// The `type` field in YAML or `__TYPE` in environment variables determines which variant is used.
9395///
9496/// Used in: [`Config::high_volume_storage`], [`Config::long_term_storage`]
95- #[ derive( Debug , Clone , Deserialize , Serialize ) ]
97+ #[ derive( Debug , Deserialize , Serialize ) ]
9698#[ serde( tag = "type" , rename_all = "lowercase" ) ]
9799pub enum Storage {
98100 /// Local filesystem storage backend (type `"filesystem"`).
@@ -306,7 +308,7 @@ pub enum Storage {
306308/// Controls the threading behavior of the server's async runtime.
307309///
308310/// Used in: [`Config::runtime`]
309- #[ derive( Debug , Clone , Deserialize , Serialize ) ]
311+ #[ derive( Debug , Deserialize , Serialize ) ]
310312#[ serde( default ) ]
311313pub struct Runtime {
312314 /// Number of worker threads for the server runtime.
@@ -355,7 +357,7 @@ impl Default for Runtime {
355357/// tracing. Sentry is disabled by default and only enabled when a DSN is provided.
356358///
357359/// Used in: [`Config::sentry`]
358- #[ derive( Debug , Clone , Deserialize , Serialize ) ]
360+ #[ derive( Debug , Deserialize , Serialize ) ]
359361pub struct Sentry {
360362 /// Sentry DSN (Data Source Name).
361363 ///
@@ -607,7 +609,7 @@ mod display_fromstr {
607609/// Controls the verbosity and format of log output. Logs are always written to stderr.
608610///
609611/// Used in: [`Config::logging`]
610- #[ derive( Debug , Clone , Deserialize , Serialize ) ]
612+ #[ derive( Debug , Deserialize , Serialize ) ]
611613pub struct Logging {
612614 /// Minimum log level to output.
613615 ///
@@ -664,7 +666,7 @@ impl Default for Logging {
664666/// Metrics configuration.
665667///
666668/// Configures submission of internal metrics to Datadog.
667- #[ derive( Clone , Debug , Default , Deserialize , Serialize ) ]
669+ #[ derive( Debug , Default , Deserialize , Serialize ) ]
668670pub struct Metrics {
669671 /// Datadog [API key] for metrics.
670672 ///
@@ -710,7 +712,7 @@ pub struct Metrics {
710712
711713/// A key that may be used to verify a request's `Authorization` header and its
712714/// associated permissions. May contain multiple key versions to facilitate rotation.
713- #[ derive( Debug , Clone , Deserialize , Serialize ) ]
715+ #[ derive( Debug , Deserialize , Serialize ) ]
714716pub struct AuthZVerificationKey {
715717 /// Versions of this key's key material which may be used to verify signatures.
716718 ///
@@ -729,7 +731,7 @@ pub struct AuthZVerificationKey {
729731}
730732
731733/// Configuration for content-based authorization.
732- #[ derive( Debug , Default , Clone , Deserialize , Serialize ) ]
734+ #[ derive( Debug , Default , Deserialize , Serialize ) ]
733735pub struct AuthZ {
734736 /// Whether to enforce content-based authorization or not.
735737 ///
@@ -758,7 +760,7 @@ pub struct AuthZ {
758760///
759761/// See individual field documentation for details on each configuration option, including
760762/// defaults and environment variables.
761- #[ derive( Debug , Clone , Deserialize , Serialize ) ]
763+ #[ derive( Debug , Deserialize , Serialize ) ]
762764pub struct Config {
763765 /// HTTP server bind address.
764766 ///
@@ -864,6 +866,9 @@ pub struct Config {
864866 /// Controls the verification and enforcement of content-based access control based on the
865867 /// JWT in a request's `Authorization` header.
866868 pub auth : AuthZ ,
869+
870+ /// A list of matchers for requests to discard without processing.
871+ pub killswitches : Killswitches ,
867872}
868873
869874impl Default for Config {
@@ -883,6 +888,7 @@ impl Default for Config {
883888 sentry : Sentry :: default ( ) ,
884889 metrics : Metrics :: default ( ) ,
885890 auth : AuthZ :: default ( ) ,
891+ killswitches : Killswitches :: default ( ) ,
886892 }
887893 }
888894}
@@ -920,6 +926,8 @@ mod tests {
920926
921927 use secrecy:: ExposeSecret ;
922928
929+ use crate :: killswitches:: Killswitch ;
930+
923931 use super :: * ;
924932
925933 #[ test]
@@ -1071,29 +1079,30 @@ mod tests {
10711079 Ok ( ( ) )
10721080 } ) ;
10731081 }
1082+
10741083 #[ test]
10751084 fn configure_auth_with_yaml ( ) {
10761085 let mut tempfile = tempfile:: NamedTempFile :: new ( ) . unwrap ( ) ;
10771086 tempfile
10781087 . write_all (
10791088 br#"
1080- auth:
1081- enforce: true
1082- keys:
1083- kid1:
1084- key_versions:
1085- - "abcde"
1086- - "fghij"
1087- - |
1088- this is a test
1089- multiline string
1090- end of string
1091- max_permissions:
1092- - "object.read"
1093- - "object.write"
1094- kid2:
1095- key_versions:
1096- - "12345"
1089+ auth:
1090+ enforce: true
1091+ keys:
1092+ kid1:
1093+ key_versions:
1094+ - "abcde"
1095+ - "fghij"
1096+ - |
1097+ this is a test
1098+ multiline string
1099+ end of string
1100+ max_permissions:
1101+ - "object.read"
1102+ - "object.write"
1103+ kid2:
1104+ key_versions:
1105+ - "12345"
10971106 "# ,
10981107 )
10991108 . unwrap ( ) ;
@@ -1122,4 +1131,54 @@ mod tests {
11221131 Ok ( ( ) )
11231132 } ) ;
11241133 }
1134+
1135+ #[ test]
1136+ fn configure_killswitches_with_yaml ( ) {
1137+ let mut tempfile = tempfile:: NamedTempFile :: new ( ) . unwrap ( ) ;
1138+ tempfile
1139+ . write_all (
1140+ br#"
1141+ killswitches:
1142+ - usecase: broken_usecase
1143+ - scopes:
1144+ org: "42"
1145+ - scopes:
1146+ org: "42"
1147+ project: "4711"
1148+ - usecase: attachments
1149+ scopes:
1150+ org: "42"
1151+ "# ,
1152+ )
1153+ . unwrap ( ) ;
1154+
1155+ figment:: Jail :: expect_with ( |_jail| {
1156+ let expected = [
1157+ Killswitch {
1158+ usecase : Some ( "broken_usecase" . into ( ) ) ,
1159+ scopes : BTreeMap :: new ( ) ,
1160+ } ,
1161+ Killswitch {
1162+ usecase : None ,
1163+ scopes : BTreeMap :: from ( [ ( "org" . into ( ) , "42" . into ( ) ) ] ) ,
1164+ } ,
1165+ Killswitch {
1166+ usecase : None ,
1167+ scopes : BTreeMap :: from ( [
1168+ ( "org" . into ( ) , "42" . into ( ) ) ,
1169+ ( "project" . into ( ) , "4711" . into ( ) ) ,
1170+ ] ) ,
1171+ } ,
1172+ Killswitch {
1173+ usecase : Some ( "attachments" . into ( ) ) ,
1174+ scopes : BTreeMap :: from ( [ ( "org" . into ( ) , "42" . into ( ) ) ] ) ,
1175+ } ,
1176+ ] ;
1177+
1178+ let config = Config :: load ( Some ( tempfile. path ( ) ) ) . unwrap ( ) ;
1179+ assert_eq ! ( & config. killswitches. 0 , & expected, ) ;
1180+
1181+ Ok ( ( ) )
1182+ } ) ;
1183+ }
11251184}
0 commit comments