gatekeeper icon indicating copy to clipboard operation
gatekeeper copied to clipboard

Delete functionality in mutations

Open maartenvdezz opened this issue 4 years ago • 25 comments

I would like to see a feature that enables us to delete certain values instead of assign. For instance, to replace the RequireDropCapabilities functionality of PodSecurityPolicies, you not only need to add a value to the "spec.containers[].securityContext.capabilities.drop" array, but you also need to remove it specifically from the "spec.containers[].securityContext.capabilities.add" array.

For instance:

apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
  name: drop-all-capabilities-but
spec:
  applyTo:
  - groups: [""]
    kinds: ["Pod"]
    versions: ["v1"]
  match:
    scope: Namespaced
    kinds:
    - apiGroups: ["*"]
      kinds: ["Pod"]
  location: "spec.containers[name:*].securityContext.capabilities"
  parameters:
    assignIf:
      add:
        in: CAP_SETUID
    delete:
      add: CAP_SETUID

Environment:

  • Gatekeeper version: 3.4.0
  • Kubernetes version: 1.20.2

maartenvdezz avatar Jun 22 '21 10:06 maartenvdezz

I'd like to think through whether this could be used to create a divergent system, but support the idea in principle.

I think it's likely fine, as I don't see much difference between deleting a field and assigning it, say null or and empty object.

maxsmythe avatar Jun 22 '21 20:06 maxsmythe

@maxsmythe Thanks for your reply! My request is about deleting a specific value from an array though, not a complete field.

maartenvdezz avatar Jun 23 '21 08:06 maartenvdezz

Understood -- if Assign can do one, it can do both.

maxsmythe avatar Jun 23 '21 23:06 maxsmythe

Although capabilities is not a keyed array... that is different

maxsmythe avatar Jun 23 '21 23:06 maxsmythe

This sounds like the inverse of the ListInjector proposed mutator:

https://github.com/open-policy-agent/gatekeeper/issues/1358#issuecomment-864324114

instead of "append only if missing", it's "remove if present"

maxsmythe avatar Jun 23 '21 23:06 maxsmythe

I'd like to think through whether this could be used to create a divergent system

Though the example and capability that @maartenvdezz requested here is about set membership, being able to remove fields in general seems like you could create oscillation.

Consider:

  • Assign A
    If field "x" does not exist, assign 1 to field "y."
  • Assign B
    If field "y" exists, assign 1 to field "x."
  • Assign C
    If field "x" exists, remove field "x."

If that's possible with Gatekeeper, we'd wind up with the following sequence:

  • {}
  • {"y": 1} by virtue of A
  • {"x": 1, "y": 1} by virtue of B
  • {"y": 1} by virtue of C
  • {"x": 1, "y": 1} by virtue of B
  • {"y": 1} by virtue of C
  • ...

Is my analysis correct?

seh avatar Feb 17 '22 22:02 seh

Currently we don't allow for cross-field checking, so if you're assigning to field x you can only test x (or its parents). This means Assign A and Assign B can't currently be written.

I think the system above would converge, since convergence is about whether the system eventually reaches a stable value. In this case, the final value after Assign C converges to {"y": 1}

maxsmythe avatar Feb 18 '22 04:02 maxsmythe

Currently we don't allow for cross-field checking, so if you're assigning to field x you can only test x (or its parents). This means Assign A and Assign B can't currently be written.

Oh, I missed that in the documentation. It doesn't mention which fields one can inspect.

I think the system above would converge, since convergence is about whether the system eventually reaches a stable value. In this case, the final value after Assign C converges to {"y": 1}

Would'n Assign B and Assign C keep duking it out, alternately inserting field "x" and then removing it again, or would Assign B not run again after Assign A adds field "x" back in?

seh avatar Feb 18 '22 18:02 seh

If you keep iterating, you'll always get {"y": 1} after the third mutator is applied.

In order to get infinite mutations, you'd need a cycle:

  • A: if x, unset z
  • B: if z, unset y
  • C: if y, unset x
  • D: if z, set x
  • E: if y, set z
  • F: if x, set y

iterations:

  • input: {x, z}
  • 1st output of F: {x, y}
  • 2nd output of F: {y, z}
  • 3rd output of F: {x, z}

Here the output bounces between {x, z}, {x, y}, and {y, z}

the sets are a bit of a metaphor, you can replace "add to set" with set spec.x = 1, or similar, and "unset" with delete spec.x or similar.

maxsmythe avatar Feb 24 '22 02:02 maxsmythe

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jul 23 '22 02:07 stale[bot]

We also have a need for this.

ctrought avatar Sep 23 '22 18:09 ctrought

Does ModifySet work for you?

It can either add or remove strings from a list:

https://open-policy-agent.github.io/gatekeeper/website/docs/mutation#modifyset

maxsmythe avatar Sep 27 '22 02:09 maxsmythe

We looked at it but based on our understanding of the docs it can only remove values from a list, not keys (that are optional) from an object.

ctrought avatar Sep 27 '22 04:09 ctrought

Ah, yeah. The ability to remove keys from an object should be added to Assign

maxsmythe avatar Sep 28 '22 02:09 maxsmythe

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Nov 27 '22 15:11 stale[bot]

/active

ctml91 avatar Nov 27 '22 17:11 ctml91

Looking to use this to delete/remove/null .spec.containers[].resources.limits.cpu

cdenneen avatar Mar 28 '23 21:03 cdenneen

I need this.

kahirokunn avatar May 31 '23 07:05 kahirokunn

+1 Would be helpful for us as well

alex-r-tf avatar Aug 01 '23 15:08 alex-r-tf

+1 Removing the CPU limit is also my use case.

jcdecaux-oss avatar Aug 02 '23 13:08 jcdecaux-oss