1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-22 07:41:10 +00:00

solves the cronjob autogen nested path issue (#12383)

* solves the cronjob autogen nested path issue

Signed-off-by: Mohd Kamaal <mohdkamaal2019@gmail.com>

* format the file using linter

Signed-off-by: Mohd Kamaal <mohdkamaal2019@gmail.com>

* autogen path change in validating-polcies

Signed-off-by: Mohd Kamaal <mohdcode@MBA.local>

---------

Signed-off-by: Mohd Kamaal <mohdkamaal2019@gmail.com>
Signed-off-by: Mohd Kamaal <mohdcode@MBA.local>
Co-authored-by: Mohd Kamaal <mohdcode@MBA.local>
This commit is contained in:
Mohd Kamaal 2025-03-13 19:52:51 +05:30 committed by GitHub
parent 7e3dfd934e
commit 19b816ba70
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 121 additions and 67 deletions

View file

@ -152,19 +152,6 @@ func convertMatchconditions(conditions []admissionregistrationv1.MatchCondition,
} }
var ( var (
podReplacementRules [][2][]byte = [][2][]byte{
{[]byte("object.spec"), []byte("object.spec.template.spec")},
{[]byte("oldObject.spec"), []byte("oldObject.spec.template.spec")},
{[]byte("object.metadata"), []byte("object.spec.template.metadata")},
{[]byte("oldObject.metadata"), []byte("oldObject.spec.template.metadata")},
}
cronJobReplacementRules [][2][]byte = [][2][]byte{
{[]byte("object.spec"), []byte("object.spec.jobTemplate.spec.template.spec")},
{[]byte("oldObject.spec"), []byte("oldObject.spec.jobTemplate.spec.template.spec")},
{[]byte("object.metadata"), []byte("object.spec.jobTemplate.spec.template.metadata")},
{[]byte("oldObject.metadata"), []byte("oldObject.spec.jobTemplate.spec.template.metadata")},
}
podControllerMatchConditionName = "autogen-" podControllerMatchConditionName = "autogen-"
podControllersMatchConditionExpression = "!(object.kind =='Deployment' || object.kind =='ReplicaSet' || object.kind =='StatefulSet' || object.kind =='DaemonSet') || " podControllersMatchConditionExpression = "!(object.kind =='Deployment' || object.kind =='ReplicaSet' || object.kind =='StatefulSet' || object.kind =='DaemonSet') || "
cronjobMatchConditionName = "autogen-cronjobs-" cronjobMatchConditionName = "autogen-cronjobs-"
@ -172,15 +159,31 @@ var (
) )
func updateFields(data []byte, resource autogencontroller) []byte { func updateFields(data []byte, resource autogencontroller) []byte {
// Define the target prefixes based on resource type
var specPrefix, metadataPrefix []byte
switch resource { switch resource {
case PODS: case PODS:
for _, replacement := range podReplacementRules { specPrefix = []byte("object.spec.template.spec")
data = bytes.ReplaceAll(data, replacement[0], replacement[1]) metadataPrefix = []byte("object.spec.template.metadata")
}
case CRONJOBS: case CRONJOBS:
for _, replacement := range cronJobReplacementRules { specPrefix = []byte("object.spec.jobTemplate.spec.template.spec")
data = bytes.ReplaceAll(data, replacement[0], replacement[1]) metadataPrefix = []byte("object.spec.jobTemplate.spec.template.metadata")
}
} }
// Replace object.spec and oldObject.spec with the correct prefix
data = bytes.ReplaceAll(data, []byte("object.spec"), specPrefix)
data = bytes.ReplaceAll(data, []byte("oldObject.spec"), append([]byte("oldObject"), specPrefix[6:]...)) // Adjust for oldObject
data = bytes.ReplaceAll(data, []byte("object.metadata"), metadataPrefix)
data = bytes.ReplaceAll(data, []byte("oldObject.metadata"), append([]byte("oldObject"), metadataPrefix[6:]...))
// Normalize any over-nested paths remove extra .template.spec
if resource == CRONJOBS {
data = bytes.ReplaceAll(data, []byte("object.spec.jobTemplate.spec.template.spec.template.spec"), specPrefix)
data = bytes.ReplaceAll(data, []byte("oldObject.spec.jobTemplate.spec.template.spec.template.spec"), append([]byte("oldObject"), specPrefix[6:]...))
} else if resource == PODS {
data = bytes.ReplaceAll(data, []byte("object.spec.template.spec.template.spec"), specPrefix)
data = bytes.ReplaceAll(data, []byte("oldObject.spec.template.spec.template.spec"), append([]byte("oldObject"), specPrefix[6:]...))
}
return data return data
} }

View file

@ -22,3 +22,29 @@ spec:
image: nginx:latest image: nginx:latest
securityContext: securityContext:
allowPrivilegeEscalation: true allowPrivilegeEscalation: true
---
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: bad-cronjob
spec:
schedule: "*/5 * * * *"
concurrencyPolicy: Forbid
jobTemplate:
metadata:
labels:
prod: "true"
spec:
template:
metadata:
labels:
prod: "true"
spec:
containers:
- name: secure-container
image: busybox
command: ["echo", "Hello, world"]
securityContext:
allowPrivilegeEscalation: true
restartPolicy: OnFailure

View file

@ -1,51 +1,52 @@
apiVersion: policies.kyverno.io/v1alpha1 apiVersion: policies.kyverno.io/v1alpha1
kind: ValidatingPolicy kind: ValidatingPolicy
metadata: metadata:
name: disallow-privilege-escalation name: disallow-privilege-escalation
status: status:
autogen: autogen:
rules: rules:
- matchConditions: - matchConditions:
- expression: "!(object.kind =='Deployment' || object.kind =='ReplicaSet' || object.kind =='StatefulSet' || object.kind =='DaemonSet') || has(object.spec.template.metadata.labels) && has(object.spec.template.metadata.labels.prod) - expression: '!(object.kind ==''Deployment'' || object.kind ==''ReplicaSet''
&& object.spec.template.metadata.labels.prod == 'true'" || object.kind ==''StatefulSet'' || object.kind ==''DaemonSet'') || has(object.spec.template.metadata.labels)
name: autogen-check-prod-label && has(object.spec.template.metadata.labels.prod) && object.spec.template.metadata.labels.prod
matchConstraints: == ''true'''
resourceRules: name: autogen-check-prod-label
- apiGroups: matchConstraints:
- apps resourceRules:
apiVersions: - apiGroups:
- v1 - apps
operations: apiVersions:
- CREATE - v1
- UPDATE operations:
resources: - CREATE
- deployments - UPDATE
validations: resources:
- expression: object.spec.template.spec.containers.all(container, has(container.securityContext) - deployments
&& has(container.securityContext.allowPrivilegeEscalation) && container.securityContext.allowPrivilegeEscalation validations:
== false) - expression: object.spec.template.spec.containers.all(container, has(container.securityContext)
message: Privilege escalation is disallowed. The field spec.containers[*].securityContext.allowPrivilegeEscalation && has(container.securityContext.allowPrivilegeEscalation) && container.securityContext.allowPrivilegeEscalation
must be set to `false`. == false)
- matchConditions: message: Privilege escalation is disallowed. The field spec.containers[*].securityContext.allowPrivilegeEscalation
- expression: "!(object.kind =='CronJob') || has(object.spec.jobTemplate.spec.template.metadata.labels) must be set to `false`.
&& has(object.spec.jobTemplate.spec.template.metadata.labels.prod) - matchConditions:
&& object.spec.jobTemplate.spec.template.metadata.labels.prod - expression: '!(object.kind ==''CronJob'') || has(object.spec.jobTemplate.spec.template.metadata.labels)
== 'true'" && has(object.spec.jobTemplate.spec.template.metadata.labels.prod) &&
name: autogen-cronjobs-check-prod-label object.spec.jobTemplate.spec.template.metadata.labels.prod == ''true'''
matchConstraints: name: autogen-cronjobs-check-prod-label
resourceRules: matchConstraints:
- apiGroups: resourceRules:
- batch - apiGroups:
apiVersions: - batch
- v1 apiVersions:
operations: - v1
- CREATE operations:
- UPDATE - CREATE
resources: - UPDATE
- cronjobs resources:
validations: - cronjobs
- expression: object.spec.jobTemplate.spec.template.spec.template.spec.containers.all(container, validations:
has(container.securityContext) && has(container.securityContext.allowPrivilegeEscalation) - expression: object.spec.jobTemplate.spec.template.spec.containers.all(container,
&& container.securityContext.allowPrivilegeEscalation == false) has(container.securityContext) && has(container.securityContext.allowPrivilegeEscalation)
message: Privilege escalation is disallowed. The field spec.containers[*].securityContext.allowPrivilegeEscalation && container.securityContext.allowPrivilegeEscalation == false)
must be set to `false`. message: Privilege escalation is disallowed. The field spec.containers[*].securityContext.allowPrivilegeEscalation
must be set to `false`.

View file

@ -22,3 +22,27 @@ spec:
image: nginx:latest image: nginx:latest
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: good-cronjob
spec:
schedule: "*/5 * * * *"
jobTemplate:
metadata:
labels:
prod: "true"
spec:
template:
metadata:
labels:
prod: "true"
spec:
containers:
- name: secure-container
image: busybox
command: ["echo", "Hello, world"]
securityContext:
allowPrivilegeEscalation: false
restartPolicy: OnFailure

View file

@ -56,7 +56,7 @@ status:
resources: resources:
- cronjobs - cronjobs
validations: validations:
- expression: object.spec.jobTemplate.spec.template.spec.template.spec.containers.all(container, - expression: object.spec.jobTemplate.spec.template.spec.containers.all(container,
has(container.securityContext) && has(container.securityContext.allowPrivilegeEscalation) has(container.securityContext) && has(container.securityContext.allowPrivilegeEscalation)
&& container.securityContext.allowPrivilegeEscalation == false) && container.securityContext.allowPrivilegeEscalation == false)
message: Privilege escalation is disallowed. The field spec.containers[*].securityContext.allowPrivilegeEscalation message: Privilege escalation is disallowed. The field spec.containers[*].securityContext.allowPrivilegeEscalation