【问题标题】:How to test that one object is a subset of another object in rego如何在rego中测试一个对象是另一个对象的子集
【发布时间】:2020-08-08 02:32:47
【问题描述】:

我想编写一个 Rego 规则,根据模板中声明的标签检查 Kubernetes 部署选择器。如果spec.selector.matchLabels 中存在的每个键/值都存在于spec.template.metadata.labels 中,则该规则应该通过。

如果我用 Javascript 编写它,它看起来像这样:

for(let key of input.spec.selector.matchLabels) {
  assert(input.spec.selector.matchLabels[key] === input.spec.template.metadata.labels[key], `${key} doesn't match`)
}

我不知道如何在 Rego 中编写等效项。我想出了一种方法来检查键是否存在,但我不知道如何检查值。这是我目前所拥有的:

selector_match_labels {
    # keys in matchLabels are present in the template labels
    matchLabels := { label | input.spec.selector.matchLabels[label] }
    labels := { label | input.spec.template.metadata.labels[label] }
    count(matchLabels - labels) == 0
    # How to check the values of each key matches?
}

【问题讨论】:

    标签: open-policy-agent rego


    【解决方案1】:

    你快到了。只需创建一组键值对而不是一组键。

    matchLabels := { [label, value] | some label; value := input.spec.selector.matchLabels[label] }
    labels := { [label, value] | some label; value := input.spec.template.metadata.labels[label] }
    count(matchLabels - labels) == 0
    

    【讨论】:

    • 谢谢。我看到理解现在是如何工作的。您的解决方案会生成一组 [ label, value ] 对,然后比较这些组。这是我最初的方法,因为这就是我在编程语言中的想法。我认为我的answer 更符合rego 的做法。你怎么看?
    【解决方案2】:

    这里是another solution,它可以找到任何不匹配的值。

    deny[msg] {
        some label
        val := input.spec.selector.matchLabels[label]
        val != input.spec.template.metadata.labels[label]
        msg = sprintf("template label %s must match selector", [ label ])
    }
    

    此解决方案使用some 查找任何不匹配的密钥。这足以创建拒绝规则。这与“如果所有键/值匹配则允许”相反,后者适用于拒绝规则。

    【讨论】:

    • 事实证明,如果缺少密钥,我的答案将无法正常工作。它仅在具有不同值的两个对象中都存在键时才有效。使用this answer 处理所有情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 2019-05-18
    • 2021-11-09
    • 2012-11-25
    • 1970-01-01
    相关资源
    最近更新 更多