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

feat: add more container validation models #19

Merged
merged 1 commit into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions examples/mutation/readonly-root-fs/kcl.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[package]
name = "readonly-root-fs"
version = "0.0.1"
9 changes: 9 additions & 0 deletions examples/mutation/readonly-root-fs/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
schema Params:

params: Params = option("params")
items = [item | {
if item.kind == "Pod":
spec.containers: [{
securityContext.readOnlyRootFilesystem = True
} for container in item.spec.containers]
} for item in option("items") or []]
22 changes: 22 additions & 0 deletions examples/mutation/readonly-root-fs/suite/good.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
metadata:
name: readonly-root-fs
annotations:
krm.kcl.dev/version: 0.0.1
krm.kcl.dev/type: mutation
documentation: >-
Set read only root file system for containers
spec:
source: ./examples/mutation/readonly-root-fs/main.k
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Empty file.
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions examples/validation/allowed-image-repos/kcl.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[package]
name = "allowed-image-repos"
version = "0.0.1"
25 changes: 25 additions & 0 deletions examples/validation/allowed-image-repos/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Requires container images to begin with a string from the specified list.

Ref: https://github.com/open-policy-agent/gatekeeper-library/blob/master/src/general/allowedrepos/constraint.tmpl
"""

# The list of prefixes a container image is allowed to have.
repos: [str] = option("params").repos or []

# Define the validation function
validate = lambda item {
containers = []
if item.kind == "Pod" and repos:
containers = (item.spec.containers or []) + (item.spec.phemeralContainers or []) + (item.spec.initContainers or [])
elif item.kind == "Deployment":
containers = (item.spec.template.spec.containers or []) + (item.spec.template.spec.phemeralContainers or []) + (item.spec.template.spec.initContainers or [])
images: [str] = [c.image for c in containers]
assert all image in images {
all repo in repos {
image.startswith(repo)
}
} if images and repos, """Use of image is disallowed for ${item.kind}: ${item.metadata.name}, valid repos ${repos}"""
item
}
# Validate All resource
items = [validate(i) for i in option("items")]
38 changes: 38 additions & 0 deletions examples/validation/allowed-image-repos/suite/bad.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
metadata:
name: allowed-image-repos
annotations:
krm.kcl.dev/version: 0.0.1
krm.kcl.dev/type: validation
documentation: >-
Requires container images to begin with a string from the specified list.

Ref: https://github.com/open-policy-agent/gatekeeper-library/blob/master/src/general/allowedrepos/constraint.tmpl
spec:
params:
repos:
- nginx
source: ./examples/validation/allowed-image-repos/main.k
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deploy
labels:
app: kcl
spec:
replicas: 3
selector:
matchLabels:
app: kcl
template:
metadata:
labels:
app: kcl
spec:
containers:
- name: kcl
image: kcllang/kcl
ports:
- containerPort: 80
38 changes: 38 additions & 0 deletions examples/validation/allowed-image-repos/suite/good.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
metadata:
name: allowed-image-repos
annotations:
krm.kcl.dev/version: 0.0.1
krm.kcl.dev/type: validation
documentation: >-
Requires container images to begin with a string from the specified list.

Ref: https://github.com/open-policy-agent/gatekeeper-library/blob/master/src/general/allowedrepos/constraint.tmpl
spec:
params:
repos:
- nginx
source: ./examples/validation/allowed-image-repos/main.k
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deploy
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
3 changes: 3 additions & 0 deletions examples/validation/deny-all/kcl.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[package]
name = "deny-all"
version = "0.0.1"
1 change: 1 addition & 0 deletions examples/validation/deny-all/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
assert False if option("items"), "Deny all objects and the input object list is ${option('items')}"
26 changes: 26 additions & 0 deletions examples/validation/deny-all/suite/bad.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
metadata:
name: deny-all
annotations:
krm.kcl.dev/version: 0.0.1
krm.kcl.dev/type: validation
documentation: >-
Deny all objects if there are input objects.
spec:
source: ./examples/validation/deny-all/main.k
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
livenessProbe:
exec:
command:
- ps
11 changes: 11 additions & 0 deletions examples/validation/deny-all/suite/good.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
metadata:
name: deny-all
annotations:
krm.kcl.dev/version: 0.0.1
krm.kcl.dev/type: validation
documentation: >-
Deny all objects if there are input objects.
spec:
source: ./examples/validation/deny-all/main.k
Empty file.
3 changes: 3 additions & 0 deletions examples/validation/deny-endpoint-edit-default-role/kcl.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[package]
name = "deny-endpoint-edit-default-role"
version = "0.0.1"
32 changes: 32 additions & 0 deletions examples/validation/deny-endpoint-edit-default-role/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Many Kubernetes installations by default have a system:aggregate-to-edit
ClusterRole which does not properly restrict access to editing Endpoints.
This ConstraintTemplate forbids the system:aggregate-to-edit ClusterRole
from granting permission to create/patch/update Endpoints.

ClusterRole/system:aggregate-to-edit should not allow
Endpoint edit permissions due to CVE-2021-25740, Endpoint & EndpointSlice
permissions allow cross-Namespace forwarding,
https://github.com/kubernetes/kubernetes/issues/103675

Reference: https://github.com/open-policy-agent/gatekeeper-library/blob/master/library/general/block-endpoint-edit-default-role/template.yaml
"""

# Define the validation function
validate = lambda item {
if (item?.metadata?.name or "") == "system:aggregate-to-edit":
rules = item.rules or []
# Check all rules if rules exist
assert all rule in rules {
# Check evrey rule verbs if rule resources exist "endpoints"
all res in rule.resources {
# Check every verbs
all verb in rule.verbs {
verb not in ["create", "patch", "update"]
} if rule.verbs and res == "endpoints"
} if rule.resources
} if rules, "ClusterRole system:aggregate-to-edit should not allow endpoint edit permissions. For k8s version < 1.22, the Cluster Role should be annotated with rbac.authorization.kubernetes.io/autoupdate=false to prevent autoreconciliation back to default permissions for this role."
item
}

# Validate All resource
items = [validate(i) for i in option("items")]
116 changes: 116 additions & 0 deletions examples/validation/deny-endpoint-edit-default-role/suite/bad.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
apiVersion: krm.kcl.dev/v1alpha1
kind: KCLRun
metadata:
name: deny-endpoint-edit-default-role
annotations:
krm.kcl.dev/version: 0.0.1
krm.kcl.dev/type: validation
documentation: >-
Many Kubernetes installations by default have a system:aggregate-to-edit
ClusterRole which does not properly restrict access to editing Endpoints.
This ConstraintTemplate forbids the system:aggregate-to-edit ClusterRole
from granting permission to create/patch/update Endpoints.

ClusterRole/system:aggregate-to-edit should not allow
Endpoint edit permissions due to CVE-2021-25740, Endpoint & EndpointSlice
permissions allow cross-Namespace forwarding,
https://github.com/kubernetes/kubernetes/issues/103675

Reference: https://github.com/open-policy-agent/gatekeeper-library/blob/master/library/general/block-endpoint-edit-default-role/template.yaml
spec:
source: ./examples/validation/deny-endpoint-edit-default-role/main.k
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
livenessProbe:
exec:
command:
- ps
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null
labels:
kubernetes.io/bootstrapping: rbac-defaults
rbac.authorization.k8s.io/aggregate-to-edit: "true"
name: system:aggregate-to-edit
rules:
- apiGroups:
- ""
resources:
- pods/attach
- pods/exec
- pods/portforward
- pods/proxy
- secrets
- services/proxy
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- impersonate
- apiGroups:
- ""
resources:
- pods
- pods/attach
- pods/exec
- pods/portforward
- pods/proxy
verbs:
- create
- delete
- deletecollection
- patch
- update
- apiGroups:
- ""
resources:
- configmaps
- persistentvolumeclaims
- replicationcontrollers
- replicationcontrollers/scale
- secrets
- serviceaccounts
- services
- services/proxy
verbs:
- create
- delete
- deletecollection
- patch
- update
- apiGroups:
- apps
resources:
- daemonsets
- deployments
- deployments/rollback
- deployments/scale
- endpoints
- replicasets
- replicasets/scale
- statefulsets
- statefulsets/scale
verbs:
- create
- delete
- deletecollection
- patch
- update
Loading
Loading