1
1
// Copyright (c) Microsoft Corporation.
2
2
// Licensed under the MIT License.
3
3
4
- use crate :: { configure:: { config_doc:: { Configuration , ExecutionKind , Resource } , Configurator , context:: ProcessMode } , dscresources:: resource_manifest:: Kind } ;
4
+ use crate :: { configure:: { Configurator , config_doc:: { Configuration , ExecutionKind , Resource } , context:: ProcessMode , parameters :: is_secure_value } , dscresources:: resource_manifest:: Kind } ;
5
5
use crate :: dscresources:: invoke_result:: { ResourceGetResponse , ResourceSetResponse } ;
6
6
use dscerror:: DscError ;
7
7
use jsonschema:: Validator ;
@@ -311,7 +311,7 @@ impl Invoke for DscResource {
311
311
let TestResult :: Resource ( ref resource_result) = result. results [ 0 ] . result else {
312
312
return Err ( DscError :: Operation ( t ! ( "dscresources.dscresource.invokeReturnedWrongResult" , operation = "test" , resource = self . type_name) . to_string ( ) ) ) ;
313
313
} ;
314
- let desired_state = resource_result. desired_state
314
+ let mut desired_state = resource_result. desired_state
315
315
. as_object ( ) . ok_or ( DscError :: Operation ( t ! ( "dscresources.dscresource.propertyIncorrectType" , property = "desiredState" , property_type = "object" ) . to_string ( ) ) ) ?
316
316
. get ( "resources" ) . ok_or ( DscError :: Operation ( t ! ( "dscresources.dscresource.propertyNotFound" , property = "resources" ) . to_string ( ) ) ) ?
317
317
. as_array ( ) . ok_or ( DscError :: Operation ( t ! ( "dscresources.dscresource.propertyIncorrectType" , property = "resources" , property_type = "array" ) . to_string ( ) ) ) ?[ 0 ]
@@ -324,6 +324,7 @@ impl Invoke for DscResource {
324
324
. as_object ( ) . ok_or ( DscError :: Operation ( t ! ( "dscresources.dscresource.propertyIncorrectType" , property = "result" , property_type = "object" ) . to_string ( ) ) ) ?
325
325
. get ( "properties" ) . ok_or ( DscError :: Operation ( t ! ( "dscresources.dscresource.propertyNotFound" , property = "properties" ) . to_string ( ) ) ) ?. clone ( ) ;
326
326
let diff_properties = get_diff ( & desired_state, & actual_state) ;
327
+ desired_state = redact ( & desired_state) ;
327
328
let test_result = TestResult :: Resource ( ResourceTestResponse {
328
329
desired_state,
329
330
actual_state,
@@ -346,7 +347,7 @@ impl Invoke for DscResource {
346
347
let resource_manifest = import_manifest ( manifest. clone ( ) ) ?;
347
348
if resource_manifest. test . is_none ( ) {
348
349
let get_result = self . get ( expected) ?;
349
- let desired_state = serde_json:: from_str ( expected) ?;
350
+ let mut desired_state = serde_json:: from_str ( expected) ?;
350
351
let actual_state = match get_result {
351
352
GetResult :: Group ( results) => {
352
353
let mut result_array: Vec < Value > = Vec :: new ( ) ;
@@ -360,6 +361,7 @@ impl Invoke for DscResource {
360
361
}
361
362
} ;
362
363
let diff_properties = get_diff ( & desired_state, & actual_state) ;
364
+ desired_state = redact ( & desired_state) ;
363
365
let test_result = TestResult :: Resource ( ResourceTestResponse {
364
366
desired_state,
365
367
actual_state,
@@ -491,6 +493,37 @@ pub fn get_well_known_properties() -> HashMap<String, Value> {
491
493
] )
492
494
}
493
495
496
+ /// Checks if the JSON value is sensitive and should be redacted
497
+ ///
498
+ /// # Arguments
499
+ ///
500
+ /// * `value` - The JSON value to check
501
+ ///
502
+ /// # Returns
503
+ ///
504
+ /// Original value if not sensitive, otherwise a redacted value
505
+ pub fn redact ( value : & Value ) -> Value {
506
+ trace ! ( "Redacting value: {value}" ) ;
507
+ if is_secure_value ( value) {
508
+ return Value :: String ( "<secureValue>" . to_string ( ) ) ;
509
+ }
510
+
511
+ if let Some ( map) = value. as_object ( ) {
512
+ let mut new_map = Map :: new ( ) ;
513
+ for ( key, val) in map {
514
+ new_map. insert ( key. clone ( ) , redact ( val) ) ;
515
+ }
516
+ return Value :: Object ( new_map) ;
517
+ }
518
+
519
+ if let Some ( array) = value. as_array ( ) {
520
+ let new_array: Vec < Value > = array. iter ( ) . map ( |val| redact ( val) ) . collect ( ) ;
521
+ return Value :: Array ( new_array) ;
522
+ }
523
+
524
+ value. clone ( )
525
+ }
526
+
494
527
#[ must_use]
495
528
/// Performs a comparison of two JSON Values if the expected is a strict subset of the actual
496
529
///
@@ -524,6 +557,11 @@ pub fn get_diff(expected: &Value, actual: &Value) -> Vec<String> {
524
557
}
525
558
526
559
for ( key, value) in & * map {
560
+ if is_secure_value ( & value) {
561
+ // skip secure values as they are not comparable
562
+ continue ;
563
+ }
564
+
527
565
if value. is_object ( ) {
528
566
let sub_diff = get_diff ( value, & actual[ key] ) ;
529
567
if !sub_diff. is_empty ( ) {
0 commit comments