繁体   English   中英

'oneOf'没有按预期工作 - json验证必须失败,但它正在通过

[英]'oneOf' not working as expected - json validation must fail but it is passing

我正在尝试编写一个模式来验证AWS IAM安全组不得指定传入的IP地址“0.0.0.0/0”可以连接到端口22。

我正在使用oneOf运算符并定义两组属性,我的直觉是如果两个属性都满足,JSON模式应该会失败,但事实并非如此。

示例JSON -

{
  "ipPermissions": [
    {
      "toPort": -1,
      "fromPort": -1,
      "ipRanges": [
        "10.0.0.0/16"
      ]
    },
    {
      "toPort": 22,
      "fromPort": 53,
      "ipRanges": [
        "0.0.0.0/0"
      ],
      "ipProtocol": "tcp"
    }
  ]
}

上面的JSON 应该失败,因为ipPermission[1]对象是 -

{
      "toPort": 22,
      "fromPort": 53,
      "ipRanges": [
        "0.0.0.0/0"
      ],
      "ipProtocol": "tcp"
}

作为ipRanges具有值0.0.0.0/0toPort22

以下JSON文档应通过验证 -

{
      "ipPermissions": [
        {
          "toPort": 22,
          "fromPort": -1,
          "ipRanges": [
            "10.0.0.0/16"
          ]
        },
        {
          "toPort": 22,
          "fromPort": 53,
          "ipRanges": [
            "somethingElse"
          ],
          "ipProtocol": "tcp"
        }
      ]
    }

因为ipPermissions index [0]对象的toPort值为22ipRanges[0]值为10.0.0.0/16 ,而不是0.0.0.0/0

以下JSON不应通过验证 -

{
  "ipPermissions": [
    {
      "toPort": 22,
      "fromPort": -1,
      "ipRanges": [
        "10.0.0.0/16"
      ]
    },
    {
      "toPort": 22,
      "fromPort": 53,
      "ipRanges": [
        "somethingElse",
        "0.0.0.0/0"
      ],
      "ipProtocol": "tcp"
    }
  ]
}

as ipPermissions[1].ipRanges[1]值是0.0.0.0/0

我的JSON架构 -

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "required": [
    "ipPermissions"
  ],
  "properties": {
    "ipPermissions": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "oneOf": {
            "ipRanges": {
              "type": "array",
              "items": {
                "type": "string",
                "value": "0.0.0.0/0"
              }
            },
            "toPort": {
              "type": "integer",
              "minimum": 23
            }
          }
        }
      }
    }
  }
}

这个有点复杂,所以我使用definitions将其分解,以便更容易理解。

#/定义/ ipPermission

一般策略是首先定义属性,然后使用anyOfoneOfallOfnot和/或dependencies分别添加复杂约束。 在这种情况下,我采用的方法是定义一个与您要禁止的情况相匹配的模式,如果该模式匹配not使用验证失败。

#/定义/端口22和 - 0.0.0.0-0

这是验证“toPort”是否为“22”且“ipRanges”数组是否包含“0.0.0.0/0”的模式。 不幸的是,JSON Schema没有一个contains关键字(还),所以我们必须做一些布尔逻辑体操来表达这种约束。

#/定义/阵列包含-0.0.0.0-0

我们不能直接约束数组包含“0.0.0.0/0”,但我们可以创建一个禁止“0.0.0.0/0”在数组中的模式。 如果此类模式在数组中不存在“0.0.0.0 \\ 0”时有效,则任何未验证的JSON必须至少包含一个“0.0.0.0/0”实例。

#/定义/阵列而不-0.0.0.0-0

这描述了禁止用于实现contains约束的“0.0.0.0/0”的数组。

{
  "type": "object",
  "required": ["ipPermissions"],
  "properties": {
    "ipPermissions": {
      "type": "array",
      "items": { "$ref": "#/definitions/ipPermission" }
    }
  },
  "definitions": {
    "ipPermission": {
      "type": "object",
      "properties": {
        "toPort": { ... },
        "fromPort": { ... },
        "ipRanges": { ... },
        "ipProtocol": { ... }
      }
      "not": { "$ref": "#/definitions/port-22-and-0.0.0.0-0"}
    },
    "port-22-and-0.0.0.0-0": {
      "type": "object",
      "properties": {
        "toPort": { "enum": [22] },
        "ipRanges": { "$ref": "#/definitions/array-contains-0.0.0.0-0" }
      },
      "required": ["toPort", "ipRanges"]
    },
    "array-contains-0.0.0.0-0": {
      "not": { "$ref": "#/definitions/array-without-0.0.0.0-0" }
    },
    "array-without-0.0.0.0-0": {
      "type": "array",
      "items": {
        "not": { "enum": ["0.0.0.0/0"] }
      }
    }
  }
}

您需要在架构中添加“必需”节点。 但是,在这种情况下,它还需要指定N个允许节点中的一个:

{
    "$schema":"http://json-schema.org/draft-04/schema#",
    "required":[
        "ipPermissions"
    ],
    "properties":{
        "ipPermissions":{
            "type":"array",
            "items":{
                "type":"object",
                "properties":{
                    "oneOf":{
                        "ipRanges":{
                            "type":"array",
                            "items":{
                                "type":"string",
                                "value":"0.0.0.0/0"
                            }
                        },
                        "toPort":{
                            "type":"integer",
                            "minimum":23
                        }
                    }
                },
                "oneOf":[
                    {
                        "required":[
                            "ipRanges"
                        ]
                    },
                    {
                        "required":[
                            "toPort"
                        ]
                    }
                ]
            }
        }
    }
}

这将使用ipRanges节点或toPort节点验证实例,但不能同时验证两者,例如:

{
    "ipPermissions":[
        {
            "toPort":-1,
            "fromPort":-1
        },
        {
            "fromPort":53,
            "ipRanges":[
                "0.0.0.0/0"
            ],
            "ipProtocol":"tcp"
        }
    ]
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM