1

为我缺乏 powershell 知识而道歉,因为我不是一个程序员,所以一直在寻找解决方案。

背景:

我目前正在尝试标准化 Incapsula 中的一些站点设置。为此,我想维护一个带有规则的本地 XML,并使用一些 powershell 来拉下现有规则并将它们与现有规则进行比较,以确保我不会加倍。我正在采用这种方法尝试仅将增量应用为:

  1. 对于大多数设置,incapsula 不够聪明,无法知道它已经存在
  2. 可以发布到 API 的内容与 API 返回的内容不同

例子:

以下是 API 将根据请求返回的示例,这是 JSON 格式。

JSON FROM WEBSITE

{
"security": {
        "waf": {
            "rules": [{
                "id": "api.threats.sql_injection",
                "exceptions": [{
                    "values": [{
                        "urls": [{
                            "value": "google.com/thisurl",
                            "pattern": "EQUALS"
                        }],
                        "id": "api.rule_exception_type.url",
                        "name": "URL"
                    }],
                    "id": 256354634
                }]
            }, {
                "id": "api.threats.cross_site_scripting",
                "action": "api.threats.action.block_request",
                "exceptions": [{
                    "values": [{
                        "urls": [{
                            "value": "google.com/anotherurl",
                            "pattern": "EQUALS"
                        }],
                        "id": "api.rule_exception_type.url",
                        "name": "URL"
                    }],
                    "id": 78908790780
                }]
            }]
        }
    }
}

这是带有我们特定站点设置的 XML 格式

OUR XML RULES
    <waf>
    <ruleset>
        <rule>
            <id>api.threats.sql_injection</id>
                <exceptions>
                    <exception>
                        <type>api.rule_exception_type.url</type>
                        <url>google.com/thisurl</url>   
                    </exception>
                    <exception>
                        <type>api.rule_exception_type.url</type>
                        <url>google.com/thisanotherurl</url>
                    </exception>
                </exceptions>
        </rule>
        <rule> 
            <id>api.threats.cross_site_scripting</id>
                <exceptions>
                    <exception>
                        <type>api.rule_exception_type.url</type>
                        <url>google.com/anotherurl</url>
                    </exception>
                    <exception>
                        <type>api.rule_exception_type.url</type>
                        <url>google.com/anotherurl2</url>
                    </exception> 
                </exceptions>
        </rule> 
    </ruleset>
</waf>

我已经成功地能够使用 compare-object 命令将站点中的其他设置与 XML 进行比较,但是它们的嵌套更简单一些,并没有给我带来太多麻烦。我坚持这是逻辑问题还是比较对象的限制。下面是一个示例代码,它将要求将提供的 json 和 xml 保存为同一目录中的 stack.json/xml 并应产生上述结果:

    $existingWaf = Get-Content -Path stack.json | ConvertFrom-Json
    [xml]$xmlFile = Get-Content -Path stack.xml 

    foreach ($rule in $xmlFile)
    {
        $ruleSet = $rule.waf.ruleset
    }

    foreach ($siteRule in $ExistingWaf.security.waf.rules)
        {
            foreach ($xmlRule in $ruleSet)
            {
                if ($xmlRule.rule.id -eq $siteRule.id)
                    {
                        write-output "yes"
                        $delta = Compare-Object -ReferenceObject @($siteRule.exceptions.values.urls.value | Select-Object) -DifferenceObject @($xmlRule.rule.exceptions.exception.url | Select-Object) -IncludeEqual | where {$xmlRule.rule.id -eq $siteRule.id}
                        $delta

                    }
            }
        }

这是一种工作,但不是我想要的。我确实得到了对象之间的比较,但没有得到特定 id 的比较,它向我显示了以下结果:

    InputObject                                 SideIndicator
    -----------                                 -------------
    google.com/thisurl                               ==
    google.com/thisanotherurl                        =>
    google.com/anotherurl                            =>
    google.com/anotherurl2                           =>

    google.com/anotherurl                            ==
    google.com/thisurl                               =>
    google.com/thisanotherurl                        =>
    google.com/anotherurl2                           =>

我更在哪里

    InputObject                                 SideIndicator
    -----------                                 -------------
    google.com/thisurl                               ==
    google.com/thisanotherurl                        =>

    google.com/anotherurl                            ==
    google.com/anotherurl2                           =>

希望这是有道理的。

是否可以仅对 id 匹配的值进行比较?

如果您有任何其他问题,请告诉我。

谢谢。

4

1 回答 1

0

问题在于您的迭代逻辑,它在一次迭代中错误地处理了 XML 文档中的多个规则:

  • foreach ($xmlRule in $ruleSet)没有枚举任何东西——而是处理了单个<ruleset>元素;要枚举子<rule>元素,您必须使用$ruleSet.rule.

  • $xmlRule.rule.exceptions.exception.url然后隐式迭代所有 <rule>子节点,因此报告所有子节点的 URL 这解释了输出中的额外行Compare-Object

这是您的代码的简化、带注释的版本:

$existingWaf = Get-Content -LiteralPath stack.json | ConvertFrom-Json
$xmlFile = [xml] (Get-Content -raw -LiteralPath stack.xml )

# No need for a loop; $xmlFile is a single [System.Xml.XmlDocument] instance.
$ruleSet = $xmlFile.waf.ruleset

foreach ($siteRule in $ExistingWaf.security.waf.rules)
{
    # !! Note the addition of `.rule`, which ensures that the rules
    # !! are enumerated *one by one*. 
    foreach ($xmlRule in $ruleSet.rule)
    {
        if ($xmlRule.id -eq $siteRule.id)
        {
          # !! Note: `$xmlRule` is now a single, rule, therefore:
          # `$xmlRule.rule.[...]-> `$xmlRule.[...]`
          # Also note that neither @(...) nor Select-Object are needed, and
          # the `| where ...` (Where-Object) is not needed.
          Compare-Object -ReferenceObject $siteRule.exceptions.values.urls.value `
                         -DifferenceObject $xmlRule.exceptions.exception.url -IncludeEqual
        }
    }
}

关于您的代码的其他意见

  • 无需确保传递给的操作数Compare-Object数组,因此无需将它们包装在数组子表达式 operator@(...)中。Compare-Object可以很好地处理标量操作数。

  • ... | Select-Object是一个虚拟无操作- 输入对象通过[1]

  • ... | Where-Object {$xmlRule.rule.id -eq $siteRule.id}毫无意义,因为它重复了封闭foreach循环的条件。

    • 一般来说,因为您没有通过自动变量引用手头的管道输入对象$_,所以您的Where-Object过滤器是静态的,并且将匹配所有输入对象(如您的情况)或none

[1] 有一个微妙的、不可见的副作用,通常不会产生影响:在输入对象周围Select-Object添加一个不可见的[psobject]包装器,这在极少数情况下会导致稍后出现不同的行为 - 请参阅此 GitHub 问题

于 2018-02-22T05:44:14.583 回答