@@ -25,9 +25,6 @@ lazy_static! {
25
25
std:: env:: var( "HOSTNAME" ) . unwrap_or_else( |_| String :: from( "unknown" ) ) ;
26
26
}
27
27
28
- // TODO: be more strict when parsing the configuration file:
29
- // - error when unknown data is found
30
- // - validate the names of the policies and sub-policies: they cannot have `/` symbols
31
28
pub struct Config {
32
29
pub addr : SocketAddr ,
33
30
pub sources : Option < Sources > ,
@@ -195,13 +192,43 @@ fn tls_files(matches: &clap::ArgMatches) -> Result<(String, String)> {
195
192
196
193
fn policies ( matches : & clap:: ArgMatches ) -> Result < HashMap < String , PolicyOrPolicyGroup > > {
197
194
let policies_file = Path :: new ( matches. get_one :: < String > ( "policies" ) . unwrap ( ) ) ;
198
- read_policies_file ( policies_file) . map_err ( |e| {
195
+ let policies = read_policies_file ( policies_file) . map_err ( |e| {
199
196
anyhow ! (
200
197
"error while loading policies from {:?}: {}" ,
201
198
policies_file,
202
199
e
203
200
)
204
- } )
201
+ } ) ?;
202
+
203
+ validate_policies ( & policies) ?;
204
+
205
+ Ok ( policies)
206
+ }
207
+
208
+ // Validate the policies and policy groups:
209
+ // - ensure policy names do not contain a '/' character
210
+ // - ensure names of policy group members do not contain a '/' character
211
+ fn validate_policies ( policies : & HashMap < String , PolicyOrPolicyGroup > ) -> Result < ( ) > {
212
+ for ( name, policy) in policies. iter ( ) {
213
+ if name. contains ( '/' ) {
214
+ return Err ( anyhow ! ( "policy name '{}' contains a '/' character" , name) ) ;
215
+ }
216
+ if let PolicyOrPolicyGroup :: PolicyGroup { members, .. } = policy {
217
+ let members_with_invalid_name: Vec < String > = members
218
+ . iter ( )
219
+ . filter_map ( |( id, _) | if id. contains ( '/' ) { Some ( id) } else { None } )
220
+ . cloned ( )
221
+ . collect ( ) ;
222
+ if !members_with_invalid_name. is_empty ( ) {
223
+ return Err ( anyhow ! (
224
+ "policy group '{}' contains members with invalid names: {:?}" ,
225
+ name,
226
+ members_with_invalid_name
227
+ ) ) ;
228
+ }
229
+ }
230
+ }
231
+ Ok ( ( ) )
205
232
}
206
233
207
234
fn verification_config ( matches : & clap:: ArgMatches ) -> Result < Option < LatestVerificationConfig > > {
@@ -286,7 +313,7 @@ pub enum PolicyOrPolicyGroupSettings {
286
313
287
314
/// `PolicyGroupMember` represents a single policy that is part of a policy group.
288
315
#[ derive( Deserialize , Debug , Clone ) ]
289
- #[ serde( rename_all = "camelCase" ) ]
316
+ #[ serde( deny_unknown_fields , rename_all = "camelCase" ) ]
290
317
pub struct PolicyGroupMember {
291
318
/// Thge URL where the policy is located
292
319
pub url : String ,
@@ -306,7 +333,7 @@ impl PolicyGroupMember {
306
333
307
334
/// Describes a policy that can be either an individual policy or a group policy.
308
335
#[ derive( Deserialize , Debug , Clone ) ]
309
- #[ serde( untagged, rename_all = "camelCase" ) ]
336
+ #[ serde( deny_unknown_fields , untagged, rename_all = "camelCase" ) ]
310
337
pub enum PolicyOrPolicyGroup {
311
338
/// An individual policy
312
339
Policy {
@@ -491,4 +518,60 @@ example:
491
518
assert_eq ! ( provide_flag, config. metrics_enabled) ;
492
519
}
493
520
}
521
+
522
+ #[ rstest]
523
+ #[ case:: all_good(
524
+ r#"
525
+ ---
526
+ example:
527
+ url: file:///tmp/namespace-validate-policy.wasm
528
+ settings: {}
529
+ group_policy:
530
+ expression: "true"
531
+ message: "group policy message"
532
+ members:
533
+ policy1:
534
+ url: file:///tmp/namespace-validate-policy.wasm
535
+ settings: {}
536
+ policy2:
537
+ url: file:///tmp/namespace-validate-policy.wasm
538
+ settings: {}
539
+ "# ,
540
+ true
541
+ ) ]
542
+ #[ case:: policy_with_invalid_name(
543
+ r#"
544
+ ---
545
+ example/invalid:
546
+ url: file:///tmp/namespace-validate-policy.wasm
547
+ settings: {}
548
+ "# ,
549
+ false
550
+ ) ]
551
+ #[ case:: policy_group_member_with_invalid_name(
552
+ r#"
553
+ ---
554
+ example:
555
+ url: file:///tmp/namespace-validate-policy.wasm
556
+ settings: {}
557
+ group_policy:
558
+ expression: "true"
559
+ message: "group policy message"
560
+ members:
561
+ policy1/a:
562
+ url: file:///tmp/namespace-validate-policy.wasm
563
+ settings: {}
564
+ policy2:
565
+ url: file:///tmp/namespace-validate-policy.wasm
566
+ settings: {}
567
+ "# ,
568
+ false
569
+ ) ]
570
+ fn policy_validation ( #[ case] policies_yaml : & str , #[ case] is_valid : bool ) {
571
+ let policies: HashMap < String , PolicyOrPolicyGroup > =
572
+ serde_yaml:: from_str ( policies_yaml) . unwrap ( ) ;
573
+
574
+ let validation_result = validate_policies ( & policies) ;
575
+ assert_eq ! ( is_valid, validation_result. is_ok( ) ) ;
576
+ }
494
577
}
0 commit comments