- 
                Notifications
    You must be signed in to change notification settings 
- Fork 54
Description
Prerequisites
- Write a descriptive title.
- Make sure you are able to repro it on the latest version
- Search the existing issues.
Summary
I noticed initially that the JSON Schema returned for the Microsoft.DSC.Debug/Echo resource seemed strange, particularly the last entry in the anyOf keyword, which is just true.
Schema for the Echo resource
$schema: https://json-schema.org/draft/2020-12/schema                                                                             
title: Echo
type: object
properties:
  output:
    $ref: '#/$defs/Output'
  showSecrets:
    type:
    - boolean
    - 'null'
additionalProperties: false
required:
- output
$defs:
  Output:
    anyOf:
    - type: array
      items: true
    - type: boolean
    - type: integer
      format: int64
    - $ref: '#/$defs/SecureObject'
    - $ref: '#/$defs/SecureString'
    - type: string
    - true
  SecureObject:
    type: object
    properties:
      secureObject: true
    additionalProperties: false
    required:
    - secureObject
  SecureString:
    type: object
    properties:
      secureString:
        type: string
    additionalProperties: false
    required:
    - secureStringThis relates back to how the type is defined:
DSC/resources/dscecho/src/echo.rs
Lines 8 to 26 in 726a323
| #[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)] | |
| #[serde(untagged)] | |
| pub enum Output { | |
| #[serde(rename = "array")] | |
| Array(Vec<Value>), | |
| #[serde(rename = "bool")] | |
| Bool(bool), | |
| #[serde(rename = "number")] | |
| Number(i64), | |
| #[serde(rename = "secureObject")] | |
| SecureObject(SecureObject), | |
| #[serde(rename = "secureString")] | |
| SecureString(SecureString), | |
| #[serde(rename = "string")] | |
| String(String), | |
| // Object has to be last so it doesn't get matched first | |
| #[serde(rename = "object")] | |
| Object(Value), | |
| } | 
Where line 25 defines the Object variant as taking a type of Value, which schemars generates as true. This effectively means that any value is always valid and negates the other entries in the anyOf keyword, but makes parsing the type more confusing.
Analysis
More correctly, Object should be of type Map<String, Value>, which is what the serde_json::Value::as_object() function returns when a Value instance is a JSON object.
Then the generated schema would be an object. This still has some wriggly complications for the actual schema, because validation more correctly only cares about when secureObject or secureString are defined at the top-level of the instance.
In other words, DSC today validates the following instance with the generated schema:
output:
  secureString:   'my secret'       # `secureString` is a string
  secureObject:                     # `secureObject` is an object
    count: 5
    name:  foo
  insecureObject:
    secureString: 5                 # `insecureObject.secureString` is an integer
    secureObject: foo               # `insecureObject.secureObject` is a stringAs Object because it wasn't any of the prior items.
Fix proposal
I think the easiest fix is to make Object wrap Map<String, Value> instead of Value. However, it's not obvious based on the generated schema that secureString and secureObject as nested properties or array items are also subject to redaction.
To handle that, we probably need to do a more resilient schema definition which is unlikely to be readily generatable from schemars.
Steps to reproduce
dsc schema -r Microsoft.DSC.Debug/EchoExpected behavior
Schema from dsc resource schema command
$schema: https://json-schema.org/draft/2020-12/schema                                                                             
title: Echo
type: object
properties:
  output:
    $ref: '#/$defs/Output'
  showSecrets:
    type:
    - boolean
    - 'null'
additionalProperties: false
required:
- output
$defs:
  Output:
    anyOf:
    - type: array
      items: true
    - type: boolean
    - type: integer
      format: int64
    - $ref: '#/$defs/SecureObject'
    - $ref: '#/$defs/SecureString'
    - type: string
    - type: object
      allOf:
      - not:
        required: [secureObject]
      - not:
        required: [secureString]
  SecureObject:
    type: object
    properties:
      secureObject: true
    additionalProperties: false
    required:
    - secureObject
  SecureString:
    type: object
    properties:
      secureString:
        type: string
    additionalProperties: false
    required:
    - secureStringActual behavior
Schema from dsc resource schema command
$schema: https://json-schema.org/draft/2020-12/schema                                                                             
title: Echo
type: object
properties:
  output:
    $ref: '#/$defs/Output'
  showSecrets:
    type:
    - boolean
    - 'null'
additionalProperties: false
required:
- output
$defs:
  Output:
    anyOf:
    - type: array
      items: true
    - type: boolean
    - type: integer
      format: int64
    - $ref: '#/$defs/SecureObject'
    - $ref: '#/$defs/SecureString'
    - type: string
    - true
  SecureObject:
    type: object
    properties:
      secureObject: true
    additionalProperties: false
    required:
    - secureObject
  SecureString:
    type: object
    properties:
      secureString:
        type: string
    additionalProperties: false
    required:
    - secureStringError details
N/A
Environment data
Name                           Value
----                           -----
PSVersion                      7.5.3
PSEdition                      Core
GitCommitId                    7.5.3
OS                             Microsoft Windows 10.0.26200
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0Version
Latest main
Visuals
No response