Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhancement] Update CEL policies to make use of optionals and variables to remove redundant expressions #1058

Closed
12 of 19 tasks
Chandan-DK opened this issue Jul 1, 2024 · 6 comments · Fixed by #1109
Closed
12 of 19 tasks
Assignees
Labels
sample Sample policy

Comments

@Chandan-DK
Copy link
Contributor

Chandan-DK commented Jul 1, 2024

Problem Statement

There are redundant expressions in CEL policies that are present in the library. For example, here container.securityContext has been repeated multiple times:

object.spec.containers.all(container, has(container.securityContext) &&
has(container.securityContext.allowPrivilegeEscalation) &&
container.securityContext.allowPrivilegeEscalation == false)

Here, we can remove redundant expressions by using optionals:

object.spec.containers.all(container, container.?securityContext.?allowPrivilegeEscalation.orValue(true) == false)

CEL Playground for the above expressions.

Also, we can optimize some CEL policies by using variables. Example

Solution Description

Update the following CEL policies to make use of optionals and variables to remove redundant expressions.

Note:
The below checklist is not exhaustive and more policies will be added here.

pod-security-cel

Other Comments

No response

Slack discussion

No response

Troubleshooting

@Chandan-DK Chandan-DK added the sample Sample policy label Jul 1, 2024
@Chandan-DK
Copy link
Contributor Author

cc @JimBugwadia @MariamFahmy98

@JimBugwadia JimBugwadia added the good first issue Good for newcomers label Jul 27, 2024
@JimBugwadia
Copy link
Member

So, using these techniques we can simply a policy like this:

https://kyverno.io/policies/pod-security-cel/restricted/require-run-as-nonroot/require-run-as-nonroot/

      validate:
        cel:
          expressions:
            - expression: >-
                (
                    (
                      has(object.spec.securityContext) &&
                      has(object.spec.securityContext.runAsNonRoot) &&
                      object.spec.securityContext.runAsNonRoot == true
                    ) && (
                      (
                          object.spec.containers +
                          (has(object.spec.initContainers) ? object.spec.initContainers : []) +
                          (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : [])
                      ).all(container,
                          !has(container.securityContext) ||
                          !has(container.securityContext.runAsNonRoot) ||
                          container.securityContext.runAsNonRoot == true)
                    )
                ) || (
                    (
                        object.spec.containers +
                        (has(object.spec.initContainers) ? object.spec.initContainers : []) +
                        (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : [])
                    ).all(container,
                        has(container.securityContext) &&
                        has(container.securityContext.runAsNonRoot) &&
                        container.securityContext.runAsNonRoot == true)
                )  

to:

      validate:
        cel:
          variables:
          - name: ctnrs
            expression: >-
              object.spec.containers +
              (has(object.spec.initContainers) ? object.spec.initContainers : []) +
              (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : [])
          expressions:
            - expression: >-
                (object.spec.?securityContext.?runAsNonRoot.orValue(false) == true
                  && variables.ctnrs.all(c, c.?securityContext.?runAsNonRoot.orValue(true) == true))
                  || variables.ctnrs.all(c, c.?securityContext.?runAsNonRoot.orValue(false) == true)

@Chandan-DK
Copy link
Contributor Author

Chandan-DK commented Jul 28, 2024

Here are some more examples of simplifying CEL expressions in policies using optionals:

Example 1

has(object.metadata.annotations) && 'pod.kubernetes.io/lifetime' in object.metadata.annotations

Can be written as

object.metadata.?annotations[?'pod.kubernetes.io/lifetime'].orValue(false)

Playground


Example 2

(object.spec.containers + (has(object.spec.initContainers) ? object.spec.initContainers : []) + (has(object.spec.ephemeralContainers) ? object.spec.ephemeralContainers : []))

Can be written as:

object.spec.containers + object.spec.?initContainers.orValue([]) + object.spec.?ephemeralContainers.orValue([])

Playground


Example 3

has(object.spec.template.metadata) && has(object.spec.template.metadata.labels) && 'foo' in object.spec.template.metadata.labels

Can be written as:

object.spec.template.?metadata.?labels.?foo.hasValue()

Playground


Example 4

has(object.metadata.labels) && 'corp.org/version' in object.metadata.labels && object.metadata.labels['corp.org/version'].matches('^v[0-9].[0-9].[0-9]$')

Can be written as:

object.metadata.?labels[?'corp.org/version'].orValue('default').matches('^v[0-9].[0-9].[0-9]$') 

Playground


Example 5

!has(object.spec.volumes) || object.spec.volumes.all(volume, !has(volume.secret))

Can be written as:

object.spec.?volumes.orValue([]).all(volume, !has(volume.secret))

Playground


@lavishpal
Copy link

Hi @JimBugwadia , Could you assign this issue to me, it will be helpful if you provide guidance on how to get started?

@JimBugwadia
Copy link
Member

Hi @lavishpal - lets keep this as tracking issue, as there are many policies to update.

Can you select one of the sub-tasks instead?

#1090
#1091
#1092
#1093
#1094
#1095
#1096
#1097
#1098
#1099
#1100

@lavishpal
Copy link

lavishpal commented Aug 2, 2024

@Chandan-DK , @JimBugwadia Can I raise the pr for all .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sample Sample policy
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants